aboutsummaryrefslogtreecommitdiffstats
path: root/meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.14.71/1279-drm-amdkfd-Move-doorbell_bitmap-to-per-process-struc.patch
diff options
context:
space:
mode:
Diffstat (limited to 'meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.14.71/1279-drm-amdkfd-Move-doorbell_bitmap-to-per-process-struc.patch')
-rw-r--r--meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.14.71/1279-drm-amdkfd-Move-doorbell_bitmap-to-per-process-struc.patch378
1 files changed, 378 insertions, 0 deletions
diff --git a/meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.14.71/1279-drm-amdkfd-Move-doorbell_bitmap-to-per-process-struc.patch b/meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.14.71/1279-drm-amdkfd-Move-doorbell_bitmap-to-per-process-struc.patch
new file mode 100644
index 00000000..42da61a3
--- /dev/null
+++ b/meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.14.71/1279-drm-amdkfd-Move-doorbell_bitmap-to-per-process-struc.patch
@@ -0,0 +1,378 @@
+From b453a28cec2c23798add20268437be07e437c81c Mon Sep 17 00:00:00 2001
+From: Shaoyun Liu <Shaoyun.Liu@amd.com>
+Date: Thu, 4 May 2017 17:39:58 -0400
+Subject: [PATCH 1279/4131] drm/amdkfd: Move doorbell_bitmap to per process
+ structure
+
+The original DQM structure is not per process, so when process
+terminated, the doorbell_bitmap will not be cleared. If user
+didn't destroy the queue correctly, driver will run out of
+the resource eventually.
+
+Change-Id: Ifb5b0b5b9745f79730be9b730bf0be5b5c3c37d2
+Signed-off-by: Shaoyun Liu <Shaoyun.Liu@amd.com>
+---
+ .../gpu/drm/amd/amdkfd/kfd_device_queue_manager.c | 78 +++++---------------
+ .../gpu/drm/amd/amdkfd/kfd_device_queue_manager.h | 1 -
+ drivers/gpu/drm/amd/amdkfd/kfd_priv.h | 3 +
+ drivers/gpu/drm/amd/amdkfd/kfd_process.c | 85 ++++++++++++++++------
+ 4 files changed, 84 insertions(+), 83 deletions(-)
+
+diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c
+index 702fc4a..2a4a556 100644
+--- a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c
++++ b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c
+@@ -111,38 +111,11 @@ void program_sh_mem_settings(struct device_queue_manager *dqm,
+ qpd->sh_mem_bases);
+ }
+
+-static int init_doorbell_bitmap(struct device_queue_manager *dqm)
++static int allocate_doorbell(struct qcm_process_device *qpd, struct queue *q)
+ {
+- unsigned int i;
+-
+- if (!KFD_IS_SOC15(dqm->dev->device_info->asic_family))
+- return 0;
+-
+- dqm->doorbell_bitmap =
+- kzalloc(DIV_ROUND_UP(KFD_MAX_NUM_OF_QUEUES_PER_PROCESS,
+- BITS_PER_BYTE), GFP_KERNEL);
+- if (dqm->doorbell_bitmap == NULL)
+- return -ENOMEM;
+-
+- /* Mask out any reserved doorbells */
+- for (i = 0; i < KFD_MAX_NUM_OF_QUEUES_PER_PROCESS; i++)
+- if ((dqm->dev->shared_resources.reserved_doorbell_mask & i) ==
+- dqm->dev->shared_resources.reserved_doorbell_val) {
+- set_bit(i, dqm->doorbell_bitmap);
+- pr_debug("reserved doorbell 0x%03x\n", i);
+- }
+-
+- return 0;
+-}
++ struct kfd_dev *dev = qpd->dqm->dev;
+
+-static void uninit_doorbell_bitmap(struct device_queue_manager *dqm)
+-{
+- kfree(dqm->doorbell_bitmap);
+-}
+-
+-static int allocate_doorbell(struct device_queue_manager *dqm, struct queue *q)
+-{
+- if (!KFD_IS_SOC15(dqm->dev->device_info->asic_family)) {
++ if (!KFD_IS_SOC15(dev->device_info->asic_family)) {
+ /* On pre-SOC15 chips we need to use the queue ID to
+ * preserve the user mode ABI.
+ */
+@@ -151,40 +124,41 @@ static int allocate_doorbell(struct device_queue_manager *dqm, struct queue *q)
+ /* For SDMA queues on SOC15, use static doorbell
+ * assignments based on the engine and queue.
+ */
+- q->doorbell_id = dqm->dev->shared_resources.sdma_doorbell
++ q->doorbell_id = dev->shared_resources.sdma_doorbell
+ [q->properties.sdma_engine_id]
+ [q->properties.sdma_queue_id];
+ } else {
+ /* For CP queues on SOC15 reserve a free doorbell ID */
+ unsigned int found;
+
+- found = find_first_zero_bit(dqm->doorbell_bitmap,
++ found = find_first_zero_bit(qpd->doorbell_bitmap,
+ KFD_MAX_NUM_OF_QUEUES_PER_PROCESS);
+ if (found >= KFD_MAX_NUM_OF_QUEUES_PER_PROCESS) {
+ pr_debug("amdkfd: No doorbells available");
+ return -EBUSY;
+ }
+- set_bit(found, dqm->doorbell_bitmap);
++ set_bit(found, qpd->doorbell_bitmap);
+ q->doorbell_id = found;
+ }
+
+ q->properties.doorbell_off =
+- kfd_doorbell_id_to_offset(dqm->dev, q->process,
++ kfd_doorbell_id_to_offset(dev, q->process,
+ q->doorbell_id);
+
+ return 0;
+ }
+
+-static void deallocate_doorbell(struct device_queue_manager *dqm,
++static void deallocate_doorbell(struct qcm_process_device *qpd,
+ struct queue *q)
+ {
+ unsigned int old;
++ struct kfd_dev *dev = qpd->dqm->dev;
+
+- if (!KFD_IS_SOC15(dqm->dev->device_info->asic_family) ||
++ if (!KFD_IS_SOC15(dev->device_info->asic_family) ||
+ q->properties.type == KFD_QUEUE_TYPE_SDMA)
+ return;
+
+- old = test_and_clear_bit(q->doorbell_id, dqm->doorbell_bitmap);
++ old = test_and_clear_bit(q->doorbell_id, qpd->doorbell_bitmap);
+ WARN_ON(!old);
+ }
+
+@@ -386,7 +360,7 @@ static int create_compute_queue_nocpsch(struct device_queue_manager *dqm,
+ if (retval != 0)
+ return retval;
+
+- retval = allocate_doorbell(dqm, q);
++ retval = allocate_doorbell(qpd, q);
+ if (retval)
+ goto out_deallocate_hqd;
+
+@@ -415,7 +389,7 @@ static int create_compute_queue_nocpsch(struct device_queue_manager *dqm,
+ out_uninit_mqd:
+ mqd->uninit_mqd(mqd, q->mqd, q->mqd_mem_obj);
+ out_deallocate_doorbell:
+- deallocate_doorbell(dqm, q);
++ deallocate_doorbell(qpd, q);
+ out_deallocate_hqd:
+ deallocate_hqd(dqm, q);
+
+@@ -441,7 +415,7 @@ static int destroy_queue_nocpsch_locked(struct device_queue_manager *dqm,
+ goto out;
+ }
+
+- deallocate_doorbell(dqm, q);
++ deallocate_doorbell(qpd, q);
+
+ if (q->properties.type == KFD_QUEUE_TYPE_COMPUTE)
+ deallocate_hqd(dqm, q);
+@@ -826,7 +800,7 @@ static int init_scheduler(struct device_queue_manager *dqm)
+
+ static int initialize_nocpsch(struct device_queue_manager *dqm)
+ {
+- int i, ret;
++ int i;
+
+ BUG_ON(!dqm);
+
+@@ -838,12 +812,6 @@ static int initialize_nocpsch(struct device_queue_manager *dqm)
+ if (!dqm->allocated_queues)
+ return -ENOMEM;
+
+- ret = init_doorbell_bitmap(dqm);
+- if (ret) {
+- kfree(dqm->allocated_queues);
+- return ret;
+- }
+-
+ mutex_init(&dqm->lock);
+ INIT_LIST_HEAD(&dqm->queues);
+ dqm->queue_count = dqm->next_pipe_to_allocate = 0;
+@@ -867,7 +835,6 @@ static void uninitialize_nocpsch(struct device_queue_manager *dqm)
+
+ BUG_ON(dqm->queue_count > 0 || dqm->processes_count > 0);
+
+- uninit_doorbell_bitmap(dqm);
+ kfree(dqm->allocated_queues);
+ for (i = 0 ; i < KFD_MQD_TYPE_MAX ; i++)
+ kfree(dqm->mqds[i]);
+@@ -928,7 +895,7 @@ static int create_sdma_queue_nocpsch(struct device_queue_manager *dqm,
+ q->properties.sdma_queue_id = q->sdma_id / CIK_SDMA_QUEUES_PER_ENGINE;
+ q->properties.sdma_engine_id = q->sdma_id % CIK_SDMA_QUEUES_PER_ENGINE;
+
+- retval = allocate_doorbell(dqm, q);
++ retval = allocate_doorbell(qpd, q);
+ if (retval)
+ goto out_deallocate_sdma_queue;
+
+@@ -951,7 +918,7 @@ static int create_sdma_queue_nocpsch(struct device_queue_manager *dqm,
+ out_uninit_mqd:
+ mqd->uninit_mqd(mqd, q->mqd, q->mqd_mem_obj);
+ out_deallocate_doorbell:
+- deallocate_doorbell(dqm, q);
++ deallocate_doorbell(qpd, q);
+ out_deallocate_sdma_queue:
+ deallocate_sdma_queue(dqm, q->sdma_id);
+
+@@ -1015,10 +982,6 @@ static int initialize_cpsch(struct device_queue_manager *dqm)
+ pr_debug("kfd: In func %s num of pipes: %d\n",
+ __func__, get_pipes_per_mec(dqm));
+
+- retval = init_doorbell_bitmap(dqm);
+- if (retval)
+- return retval;
+-
+ mutex_init(&dqm->lock);
+ INIT_LIST_HEAD(&dqm->queues);
+ dqm->queue_count = dqm->processes_count = 0;
+@@ -1032,7 +995,6 @@ static int initialize_cpsch(struct device_queue_manager *dqm)
+ return 0;
+
+ fail_init_pipelines:
+- uninit_doorbell_bitmap(dqm);
+ mutex_destroy(&dqm->lock);
+ return retval;
+ }
+@@ -1184,7 +1146,7 @@ static int create_queue_cpsch(struct device_queue_manager *dqm, struct queue *q,
+ q->sdma_id % CIK_SDMA_QUEUES_PER_ENGINE;
+ }
+
+- retval = allocate_doorbell(dqm, q);
++ retval = allocate_doorbell(qpd, q);
+ if (retval)
+ goto out_deallocate_sdma_queue;
+
+@@ -1234,7 +1196,7 @@ static int create_queue_cpsch(struct device_queue_manager *dqm, struct queue *q,
+ return retval;
+
+ out_deallocate_doorbell:
+- deallocate_doorbell(dqm, q);
++ deallocate_doorbell(qpd, q);
+ out_deallocate_sdma_queue:
+ if (q->properties.type == KFD_QUEUE_TYPE_SDMA)
+ deallocate_sdma_queue(dqm, q->sdma_id);
+@@ -1402,7 +1364,7 @@ static int destroy_queue_cpsch(struct device_queue_manager *dqm,
+ goto failed;
+ }
+
+- deallocate_doorbell(dqm, q);
++ deallocate_doorbell(qpd, q);
+
+ if (q->properties.type == KFD_QUEUE_TYPE_SDMA) {
+ dqm->sdma_queue_count--;
+diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.h b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.h
+index c269e5e..113ac1f 100644
+--- a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.h
++++ b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.h
+@@ -182,7 +182,6 @@ struct device_queue_manager {
+ unsigned int *allocated_queues;
+ unsigned int sdma_bitmap;
+ unsigned int vmid_bitmap;
+- unsigned long *doorbell_bitmap;
+ uint64_t pipelines_addr;
+ struct kfd_mem_obj *pipeline_mem;
+ uint64_t fence_gpu_addr;
+diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_priv.h b/drivers/gpu/drm/amd/amdkfd/kfd_priv.h
+index 7bdddab..a81dfe7 100644
+--- a/drivers/gpu/drm/amd/amdkfd/kfd_priv.h
++++ b/drivers/gpu/drm/amd/amdkfd/kfd_priv.h
+@@ -577,6 +577,9 @@ struct qcm_process_device {
+ /* IB memory */
+ uint64_t ib_base; /* ib_base+ib_size must be below cwsr_base */
+ void *ib_kaddr;
++
++ /*doorbell resources per process per device*/
++ unsigned long *doorbell_bitmap;
+ };
+
+ /* KFD Memory Eviction */
+diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_process.c b/drivers/gpu/drm/amd/amdkfd/kfd_process.c
+index 5343dad..601e551 100644
+--- a/drivers/gpu/drm/amd/amdkfd/kfd_process.c
++++ b/drivers/gpu/drm/amd/amdkfd/kfd_process.c
+@@ -356,6 +356,9 @@ static void kfd_process_destroy_pdds(struct kfd_process *p)
+ get_order(pdd->dev->cwsr_size));
+ }
+
++ kfree(pdd->qpd.doorbell_bitmap);
++ idr_destroy(&pdd->alloc_idr);
++
+ kfree(pdd);
+ }
+ }
+@@ -633,6 +636,31 @@ static struct kfd_process *create_process(const struct task_struct *thread,
+ return ERR_PTR(err);
+ }
+
++static int init_doorbell_bitmap(struct qcm_process_device *qpd,
++ struct kfd_dev *dev)
++{
++ unsigned int i;
++
++ if (!KFD_IS_SOC15(dev->device_info->asic_family))
++ return 0;
++
++ qpd->doorbell_bitmap =
++ kzalloc(DIV_ROUND_UP(KFD_MAX_NUM_OF_QUEUES_PER_PROCESS,
++ BITS_PER_BYTE), GFP_KERNEL);
++ if (qpd->doorbell_bitmap == NULL)
++ return -ENOMEM;
++
++ /* Mask out any reserved doorbells */
++ for (i = 0; i < KFD_MAX_NUM_OF_QUEUES_PER_PROCESS; i++)
++ if ((dev->shared_resources.reserved_doorbell_mask & i) ==
++ dev->shared_resources.reserved_doorbell_val) {
++ set_bit(i, qpd->doorbell_bitmap);
++ pr_debug("reserved doorbell 0x%03x\n", i);
++ }
++
++ return 0;
++}
++
+ struct kfd_process_device *kfd_get_process_device_data(struct kfd_dev *dev,
+ struct kfd_process *p)
+ {
+@@ -651,33 +679,42 @@ struct kfd_process_device *kfd_create_process_device_data(struct kfd_dev *dev,
+ struct kfd_process_device *pdd = NULL;
+
+ pdd = kzalloc(sizeof(*pdd), GFP_KERNEL);
+- if (pdd != NULL) {
+- pdd->dev = dev;
+- INIT_LIST_HEAD(&pdd->qpd.queues_list);
+- INIT_LIST_HEAD(&pdd->qpd.priv_queue_list);
+- pdd->qpd.dqm = dev->dqm;
+- pdd->qpd.pqm = &p->pqm;
+- pdd->qpd.evicted = 0;
+- pdd->reset_wavefronts = false;
+- pdd->process = p;
+- pdd->bound = PDD_UNBOUND;
+- pdd->already_dequeued = false;
+- list_add(&pdd->per_device_list, &p->per_device_data);
+-
+- /* Init idr used for memory handle translation */
+- idr_init(&pdd->alloc_idr);
+-
+- /* Create the GPUVM context for this specific device */
+- if (dev->kfd2kgd->create_process_vm(dev->kgd, &pdd->vm,
+- &p->process_info)) {
+- pr_err("Failed to create process VM object\n");
+- list_del(&pdd->per_device_list);
+- kfree(pdd);
+- pdd = NULL;
+- }
++ if (!pdd)
++ return NULL;
++
++ pdd->dev = dev;
++ INIT_LIST_HEAD(&pdd->qpd.queues_list);
++ INIT_LIST_HEAD(&pdd->qpd.priv_queue_list);
++ pdd->qpd.dqm = dev->dqm;
++ pdd->qpd.pqm = &p->pqm;
++ pdd->qpd.evicted = 0;
++ pdd->reset_wavefronts = false;
++ pdd->process = p;
++ pdd->bound = PDD_UNBOUND;
++ pdd->already_dequeued = false;
++ list_add(&pdd->per_device_list, &p->per_device_data);
++
++ /* Init idr used for memory handle translation */
++ idr_init(&pdd->alloc_idr);
++ if (init_doorbell_bitmap(&pdd->qpd, dev)) {
++ pr_err("Failed to init doorbell for process\n");
++ goto err_create_pdd;
+ }
+
++ /* Create the GPUVM context for this specific device */
++ if (dev->kfd2kgd->create_process_vm(dev->kgd, &pdd->vm,
++ &p->process_info)) {
++ pr_err("Failed to create process VM object\n");
++ goto err_create_pdd;
++ }
+ return pdd;
++
++err_create_pdd:
++ kfree(pdd->qpd.doorbell_bitmap);
++ idr_destroy(&pdd->alloc_idr);
++ list_del(&pdd->per_device_list);
++ kfree(pdd);
++ return NULL;
+ }
+
+ /*
+--
+2.7.4
+