diff options
Diffstat (limited to 'common/recipes-kernel/linux/linux-yocto-4.14.71/1139-drm-amdkfd-Fix-leaking-HQD-in-SW-scheduler.patch')
-rw-r--r-- | common/recipes-kernel/linux/linux-yocto-4.14.71/1139-drm-amdkfd-Fix-leaking-HQD-in-SW-scheduler.patch | 176 |
1 files changed, 176 insertions, 0 deletions
diff --git a/common/recipes-kernel/linux/linux-yocto-4.14.71/1139-drm-amdkfd-Fix-leaking-HQD-in-SW-scheduler.patch b/common/recipes-kernel/linux/linux-yocto-4.14.71/1139-drm-amdkfd-Fix-leaking-HQD-in-SW-scheduler.patch new file mode 100644 index 00000000..ba6715f9 --- /dev/null +++ b/common/recipes-kernel/linux/linux-yocto-4.14.71/1139-drm-amdkfd-Fix-leaking-HQD-in-SW-scheduler.patch @@ -0,0 +1,176 @@ +From 898601bab9aa0bba8cb3bd4e8ed2a75aab7d3b86 Mon Sep 17 00:00:00 2001 +From: Amber Lin <Amber.Lin@amd.com> +Date: Fri, 27 May 2016 15:48:34 -0400 +Subject: [PATCH 1139/4131] drm/amdkfd: Fix leaking HQD in SW scheduler + +With software scheduler, process_termination_nocpsch doesn't deallocate HQD +when destroing the CP queue. However this is done properly in +destroy_queue_nocpsch. In order to avoid errors like this, this patch +factors out duplicated code in process_termination_nocpsch and +destroy_queue_nocpsch into destroy_queue_nocpsch_locked. + +BUG: SWDEV-93672 + +Change-Id: I626dcef388b1ce91f159b1497d82c41630660ee8 +Signed-off-by: Amber Lin <Amber.Lin@amd.com> +--- + .../gpu/drm/amd/amdkfd/kfd_device_queue_manager.c | 94 +++++++++------------- + 1 file changed, 36 insertions(+), 58 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 e04832f..c973a3a 100644 +--- a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c ++++ b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c +@@ -314,48 +314,41 @@ static int create_compute_queue_nocpsch(struct device_queue_manager *dqm, + return 0; + } + +-static int destroy_queue_nocpsch(struct device_queue_manager *dqm, ++/* Access to DQM has to be locked before calling destroy_queue_nocpsch_locked ++ * to avoid asynchronized access ++ */ ++static int destroy_queue_nocpsch_locked(struct device_queue_manager *dqm, + struct qcm_process_device *qpd, + struct queue *q) + { +- int retval; ++ int retval = 0; + struct mqd_manager *mqd; + +- BUG_ON(!dqm || !q || !q->mqd || !qpd); ++ WARN_ON(!dqm || !q || !q->mqd || !qpd); + +- retval = 0; +- +- pr_debug("kfd: In Func %s\n", __func__); +- +- mutex_lock(&dqm->lock); ++ mqd = dqm->ops.get_mqd_manager(dqm, ++ get_mqd_type_from_queue_type(q->properties.type)); ++ if (!mqd) { ++ retval = -ENOMEM; ++ goto out; ++ } + +- if (q->properties.type == KFD_QUEUE_TYPE_COMPUTE) { +- mqd = dqm->ops.get_mqd_manager(dqm, KFD_MQD_TYPE_COMPUTE); +- if (mqd == NULL) { +- retval = -ENOMEM; +- goto out; +- } ++ if (q->properties.type == KFD_QUEUE_TYPE_COMPUTE) + deallocate_hqd(dqm, q); +- } else if (q->properties.type == KFD_QUEUE_TYPE_SDMA) { +- mqd = dqm->ops.get_mqd_manager(dqm, KFD_MQD_TYPE_SDMA); +- if (mqd == NULL) { +- retval = -ENOMEM; +- goto out; +- } ++ else if (q->properties.type == KFD_QUEUE_TYPE_SDMA) { + dqm->sdma_queue_count--; + deallocate_sdma_queue(dqm, q->sdma_id); + } else { + pr_debug("q->properties.type is invalid (%d)\n", +- q->properties.type); ++ q->properties.type); + retval = -EINVAL; +- goto out; + } ++ dqm->total_queue_count--; + + retval = mqd->destroy_mqd(mqd, q->mqd, + KFD_PREEMPT_TYPE_WAVEFRONT_RESET, + KFD_HIQ_TIMEOUT, + q->pipe, q->queue); +- + if (retval != 0) + goto out; + +@@ -367,16 +360,22 @@ static int destroy_queue_nocpsch(struct device_queue_manager *dqm, + if (q->properties.is_active) + dqm->queue_count--; + +- /* +- * Unconditionally decrement this counter, regardless of the queue's +- * type +- */ +- dqm->total_queue_count--; +- pr_debug("Total of %d queues are accountable so far\n", +- dqm->total_queue_count); +- + out: ++ return retval; ++} ++ ++static int destroy_queue_nocpsch(struct device_queue_manager *dqm, ++ struct qcm_process_device *qpd, ++ struct queue *q) ++{ ++ int retval; ++ ++ BUG_ON(!dqm || !q || !q->mqd || !qpd); ++ ++ mutex_lock(&dqm->lock); ++ retval = destroy_queue_nocpsch_locked(dqm, qpd, q); + mutex_unlock(&dqm->lock); ++ + return retval; + } + +@@ -1376,37 +1375,16 @@ static int process_termination_nocpsch(struct device_queue_manager *dqm, + struct qcm_process_device *qpd) + { + struct queue *q, *next; +- struct mqd_manager *mqd; + struct device_process_node *cur, *next_dpn; ++ int retval = 0; + + mutex_lock(&dqm->lock); + + /* Clear all user mode queues */ + list_for_each_entry_safe(q, next, &qpd->queues_list, list) { +- mqd = dqm->ops.get_mqd_manager(dqm, +- get_mqd_type_from_queue_type(q->properties.type)); +- if (!mqd) { +- mutex_unlock(&dqm->lock); +- return -ENOMEM; +- } +- +- if (q->properties.type == KFD_QUEUE_TYPE_SDMA) { +- dqm->sdma_queue_count--; +- deallocate_sdma_queue(dqm, q->sdma_id); +- } +- +- list_del(&q->list); +- if (q->properties.is_active) +- dqm->queue_count--; +- +- dqm->total_queue_count--; +- mqd->destroy_mqd(mqd, q->mqd, +- KFD_PREEMPT_TYPE_WAVEFRONT_RESET, +- KFD_HIQ_TIMEOUT, +- q->pipe, q->queue); +- mqd->uninit_mqd(mqd, q->mqd, q->mqd_mem_obj); +- if (list_empty(&qpd->queues_list)) +- deallocate_vmid(dqm, qpd, q); ++ retval = destroy_queue_nocpsch_locked(dqm, qpd, q); ++ if (retval) ++ goto out; + } + + /* Unregister process */ +@@ -1419,9 +1397,9 @@ static int process_termination_nocpsch(struct device_queue_manager *dqm, + } + } + ++out: + mutex_unlock(&dqm->lock); +- +- return 0; ++ return retval; + } + + +-- +2.7.4 + |