From 32bb38a1781929b7f724a5824d1ed74f53b9dced Mon Sep 17 00:00:00 2001 From: Amber Lin 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 --- .../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