drm/amdkfd: avoid race condition of mqd when reading sdma counter

MQD used outside of dpm_lock is unsafe because the queue could be
destroyed during the window of dqm_unlock, moving into dqm_lock
range is the best practice.

Signed-off-by: Eric Huang <jinhuieric.huang@amd.com>
Reviewed-by: Harish Kasiviswanathan <Harish.Kasiviswanathan@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
This commit is contained in:
Eric Huang 2026-06-11 11:39:33 -04:00 committed by Alex Deucher
parent 272e584fc0
commit cc80854eda

View File

@ -91,7 +91,6 @@ struct kfd_sdma_activity_handler_workarea {
struct temp_sdma_queue_list {
uint64_t __user *rptr;
void *mqd;
uint64_t sdma_val;
unsigned int queue_id;
struct list_head list;
@ -154,6 +153,21 @@ static void kfd_sdma_activity_worker(struct work_struct *work)
(q->properties.type != KFD_QUEUE_TYPE_SDMA_XGMI))
continue;
if (dqm->dev->kfd2kgd->hqd_sdma_get_counter) {
val = 0;
ret = dqm->dev->kfd2kgd->hqd_sdma_get_counter(
dqm->dev->adev, q->mqd,
dqm->dev->kfd->device_info.num_sdma_queues_per_engine,
&val);
if (ret)
pr_debug("Failed to read SDMA queue active counter %i\n", ret);
else
workarea->sdma_activity_counter += val;
continue;
}
sdma_q = kzalloc_obj(struct temp_sdma_queue_list);
if (!sdma_q) {
dqm_unlock(dqm);
@ -162,7 +176,6 @@ static void kfd_sdma_activity_worker(struct work_struct *work)
INIT_LIST_HEAD(&sdma_q->list);
sdma_q->rptr = (uint64_t __user *)q->properties.read_ptr;
sdma_q->mqd = q->mqd;
sdma_q->queue_id = q->properties.queue_id;
list_add_tail(&sdma_q->list, &sdma_q_list.list);
}
@ -173,7 +186,7 @@ static void kfd_sdma_activity_worker(struct work_struct *work)
* count
*/
if (list_empty(&sdma_q_list.list)) {
workarea->sdma_activity_counter = pdd->sdma_past_activity_counter;
workarea->sdma_activity_counter += pdd->sdma_past_activity_counter;
dqm_unlock(dqm);
return;
}
@ -191,15 +204,7 @@ static void kfd_sdma_activity_worker(struct work_struct *work)
list_for_each_entry(sdma_q, &sdma_q_list.list, list) {
val = 0;
if (dqm->dev->kfd2kgd->hqd_sdma_get_counter)
ret = dqm->dev->kfd2kgd->hqd_sdma_get_counter(
dqm->dev->adev, sdma_q->mqd,
dqm->dev->kfd->device_info.num_sdma_queues_per_engine,
&val);
else
ret = read_sdma_queue_counter(sdma_q->rptr, &val);
ret = read_sdma_queue_counter(sdma_q->rptr, &val);
if (ret) {
pr_debug("Failed to read SDMA queue active counter for queue id: %d",
sdma_q->queue_id);