drm/amdkfd: Allocate doorbells only when needed
authorFelix Kuehling <Felix.Kuehling@amd.com>
Wed, 3 Aug 2022 18:45:45 +0000 (14:45 -0400)
committerAlex Deucher <alexander.deucher@amd.com>
Thu, 25 Aug 2022 17:35:17 +0000 (13:35 -0400)
Only allocate doorbells when the first queue is created on a GPU or the
doorbells need to be mapped into CPU or GPU virtual address space. This
avoids allocating doorbells unnecessarily and can allow more processes
to use KFD on multi-GPU systems.

Signed-off-by: Felix Kuehling <Felix.Kuehling@amd.com>
Reviewed-by: Kent Russell <kent.Russell@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
drivers/gpu/drm/amd/amdkfd/kfd_chardev.c
drivers/gpu/drm/amd/amdkfd/kfd_doorbell.c
drivers/gpu/drm/amd/amdkfd/kfd_process.c

index dc774ddf34456461a0818c4cb0955efadfdc566c..664e8b5d82c0eec437ec6295fd68062af05493f6 100644 (file)
@@ -327,6 +327,12 @@ static int kfd_ioctl_create_queue(struct file *filep, struct kfd_process *p,
                goto err_bind_process;
        }
 
+       if (!pdd->doorbell_index &&
+           kfd_alloc_process_doorbells(dev, &pdd->doorbell_index) < 0) {
+               err = -ENOMEM;
+               goto err_alloc_doorbells;
+       }
+
        /* Starting with GFX11, wptr BOs must be mapped to GART for MES to determine work
         * on unmapped queues for usermode queue oversubscription (no aggregated doorbell)
         */
@@ -404,6 +410,7 @@ err_create_queue:
        if (wptr_bo)
                amdgpu_amdkfd_free_gtt_mem(dev->adev, wptr_bo);
 err_wptr_map_gart:
+err_alloc_doorbells:
 err_bind_process:
 err_pdd:
        mutex_unlock(&p->mutex);
@@ -1092,6 +1099,10 @@ static int kfd_ioctl_alloc_memory_of_gpu(struct file *filep,
                        goto err_unlock;
                }
                offset = kfd_get_process_doorbells(pdd);
+               if (!offset) {
+                       err = -ENOMEM;
+                       goto err_unlock;
+               }
        } else if (flags & KFD_IOC_ALLOC_MEM_FLAGS_MMIO_REMAP) {
                if (args->size != PAGE_SIZE) {
                        err = -EINVAL;
@@ -2173,6 +2184,8 @@ static int criu_restore_memory_of_gpu(struct kfd_process_device *pdd,
                        return -EINVAL;
 
                offset = kfd_get_process_doorbells(pdd);
+               if (!offset)
+                       return -ENOMEM;
        } else if (bo_bucket->alloc_flags & KFD_IOC_ALLOC_MEM_FLAGS_MMIO_REMAP) {
                /* MMIO BOs need remapped bus address */
                if (bo_bucket->size != PAGE_SIZE) {
index cb3d2ccc51007ac8c3903d1294d3c18fe86e7abb..b33798f89ef09517ab110657f275e9a22f6bb74f 100644 (file)
@@ -157,6 +157,8 @@ int kfd_doorbell_mmap(struct kfd_dev *dev, struct kfd_process *process,
 
        /* Calculate physical address of doorbell */
        address = kfd_get_process_doorbells(pdd);
+       if (!address)
+               return -ENOMEM;
        vma->vm_flags |= VM_IO | VM_DONTCOPY | VM_DONTEXPAND | VM_NORESERVE |
                                VM_DONTDUMP | VM_PFNMAP;
 
@@ -275,6 +277,13 @@ uint64_t kfd_get_number_elems(struct kfd_dev *kfd)
 
 phys_addr_t kfd_get_process_doorbells(struct kfd_process_device *pdd)
 {
+       if (!pdd->doorbell_index) {
+               int r = kfd_alloc_process_doorbells(pdd->dev,
+                                                   &pdd->doorbell_index);
+               if (r)
+                       return 0;
+       }
+
        return pdd->dev->doorbell_base +
                pdd->doorbell_index * kfd_doorbell_process_slice(pdd->dev);
 }
index 6c83a519b3a1bd70157e293dcc01ca64d7448bb0..951b636772484304a06b32fed2a5f48c852b09ed 100644 (file)
@@ -1499,11 +1499,6 @@ struct kfd_process_device *kfd_create_process_device_data(struct kfd_dev *dev,
        if (!pdd)
                return NULL;
 
-       if (kfd_alloc_process_doorbells(dev, &pdd->doorbell_index) < 0) {
-               pr_err("Failed to alloc doorbell for pdd\n");
-               goto err_free_pdd;
-       }
-
        if (init_doorbell_bitmap(&pdd->qpd, dev)) {
                pr_err("Failed to init doorbell for process\n");
                goto err_free_pdd;