aboutsummaryrefslogtreecommitdiffstats
path: root/common/recipes-kernel/linux/linux-yocto-4.14.71/1438-drm-amdkfd-Fix-leaking-HQD-in-SW-scheduler.patch
diff options
context:
space:
mode:
Diffstat (limited to 'common/recipes-kernel/linux/linux-yocto-4.14.71/1438-drm-amdkfd-Fix-leaking-HQD-in-SW-scheduler.patch')
-rw-r--r--common/recipes-kernel/linux/linux-yocto-4.14.71/1438-drm-amdkfd-Fix-leaking-HQD-in-SW-scheduler.patch176
1 files changed, 176 insertions, 0 deletions
diff --git a/common/recipes-kernel/linux/linux-yocto-4.14.71/1438-drm-amdkfd-Fix-leaking-HQD-in-SW-scheduler.patch b/common/recipes-kernel/linux/linux-yocto-4.14.71/1438-drm-amdkfd-Fix-leaking-HQD-in-SW-scheduler.patch
new file mode 100644
index 00000000..e29f7f71
--- /dev/null
+++ b/common/recipes-kernel/linux/linux-yocto-4.14.71/1438-drm-amdkfd-Fix-leaking-HQD-in-SW-scheduler.patch
@@ -0,0 +1,176 @@
+From 32bb38a1781929b7f724a5824d1ed74f53b9dced 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 1438/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
+