summaryrefslogtreecommitdiff
path: root/drivers/gpu/drm/amd/amdkfd
diff options
context:
space:
mode:
authorOak Zeng <Oak.Zeng@amd.com>2019-06-06 13:19:06 -0500
committerAlex Deucher <alexander.deucher@amd.com>2019-06-11 12:57:18 -0500
commitf77dac6cd62e5d4bcadd740620af1218bfb54cc6 (patch)
tree6967d9f4ca95c2d04a80fa905d7c68a628758371 /drivers/gpu/drm/amd/amdkfd
parent06b89b38f3cc518a761164f9f958a9607bbb3587 (diff)
drm/amdkfd: Fix sdma queue allocate race condition
SDMA queue allocation requires the dqm lock at it modify the global dqm members. Move up the dqm_lock so sdma queue allocation is enclosed in the critical section. Move mqd allocation out of critical section to avoid circular lock dependency. Signed-off-by: Oak Zeng <Oak.Zeng@amd.com> Reviewed-by: Felix Kuehling <Felix.Kuehling@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Diffstat (limited to 'drivers/gpu/drm/amd/amdkfd')
-rw-r--r--drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c26
1 files changed, 12 insertions, 14 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 3ac9e58b8328..e5c6db1a2c19 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c
@@ -1133,23 +1133,27 @@ static int create_queue_cpsch(struct device_queue_manager *dqm, struct queue *q,
if (dqm->total_queue_count >= max_num_of_queues_per_device) {
pr_warn("Can't create new usermode queue because %d queues were already created\n",
dqm->total_queue_count);
- retval = -EPERM;
- goto out;
+ return -EPERM;
}
+ mqd_mgr = dqm->mqd_mgrs[get_mqd_type_from_queue_type(
+ q->properties.type)];
+ q->mqd_mem_obj = mqd_mgr->allocate_mqd(mqd_mgr->dev, &q->properties);
+ if (!q->mqd_mem_obj)
+ return -ENOMEM;
+
+ dqm_lock(dqm);
if (q->properties.type == KFD_QUEUE_TYPE_SDMA ||
q->properties.type == KFD_QUEUE_TYPE_SDMA_XGMI) {
retval = allocate_sdma_queue(dqm, q);
if (retval)
- goto out;
+ goto out_unlock;
}
retval = allocate_doorbell(qpd, q);
if (retval)
goto out_deallocate_sdma_queue;
- mqd_mgr = dqm->mqd_mgrs[get_mqd_type_from_queue_type(
- q->properties.type)];
/*
* Eviction state logic: mark all queues as evicted, even ones
* not currently active. Restoring inactive queues later only
@@ -1161,14 +1165,8 @@ static int create_queue_cpsch(struct device_queue_manager *dqm, struct queue *q,
dqm->asic_ops.init_sdma_vm(dqm, q, qpd);
q->properties.tba_addr = qpd->tba_addr;
q->properties.tma_addr = qpd->tma_addr;
- q->mqd_mem_obj = mqd_mgr->allocate_mqd(mqd_mgr->dev, &q->properties);
- if (!q->mqd_mem_obj) {
- retval = -ENOMEM;
- goto out_deallocate_doorbell;
- }
mqd_mgr->init_mqd(mqd_mgr, &q->mqd, q->mqd_mem_obj,
&q->gart_mqd_addr, &q->properties);
- dqm_lock(dqm);
list_add(&q->list, &qpd->queues_list);
qpd->queue_count++;
@@ -1194,13 +1192,13 @@ static int create_queue_cpsch(struct device_queue_manager *dqm, struct queue *q,
dqm_unlock(dqm);
return retval;
-out_deallocate_doorbell:
- deallocate_doorbell(qpd, q);
out_deallocate_sdma_queue:
if (q->properties.type == KFD_QUEUE_TYPE_SDMA ||
q->properties.type == KFD_QUEUE_TYPE_SDMA_XGMI)
deallocate_sdma_queue(dqm, q);
-out:
+out_unlock:
+ dqm_unlock(dqm);
+ mqd_mgr->free_mqd(mqd_mgr, q->mqd, q->mqd_mem_obj);
return retval;
}