From af21fb73ee028ca95222005904de7c653a0f7371 Mon Sep 17 00:00:00 2001 From: YuanShang Date: Fri, 28 Aug 2026 15:30:50 +0800 Subject: [PATCH] drm/amdkfd: mark queues as reset after a full GPU reset During a GPU reset, evict_process_queues_cpsch() calls remove_queue_mes() per queue, which fails with -EIO because the recovery path already holds the reset domain write lock. The loop aborts on the first queue, leaving the rest with is_active still set while the reset wipes the MES queue table. When the process later exits, process_termination_cpsch() sends REMOVE_QUEUE for doorbells MES no longer knows about. MES rejects them, the driver reports it as a timeout and concludes MES is unrecoverable, so it requests another GPU reset. Failed to evict queue 2 GPU reset(1) succeeded! failed to remove queue from MES, doorbell=0x1002 MES might be in unrecoverable state, issue a GPU reset GPU reset begin!. Source: 3 Mark every queue as reset in kgd2kfd_post_reset(). This clears is_active, corrects the queue counts and sets is_reset so the queue is skipped later. Add a verbose argument to set_queue_as_reset() so the full reset path does not log a message for every queue. Change-Id: I08cf7404caacaf9fd458c028e3f6219375482b61 Signed-off-by: YuanShang Acked-by: Alex Deucher --- drivers/gpu/drm/amd/amdkfd/kfd_device.c | 3 ++ .../drm/amd/amdkfd/kfd_device_queue_manager.c | 36 +++++++++++++++---- .../drm/amd/amdkfd/kfd_device_queue_manager.h | 1 + 3 files changed, 33 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_device.c b/drivers/gpu/drm/amd/amdkfd/kfd_device.c index 23db8dcb076dd..bb4c6695f3cf9 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_device.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_device.c @@ -1040,6 +1040,9 @@ int kgd2kfd_post_reset(struct kfd_dev *kfd) if (!kfd->init_complete) return 0; + for (i = 0; i < kfd->num_nodes; i++) + kfd_dqm_set_queues_as_reset(kfd->nodes[i]->dqm); + for (i = 0; i < kfd->num_nodes; i++) { ret = kfd_resume(kfd->nodes[i]); if (ret) 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 ace5609fbb4b0..6d12f9dc7f04d 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c @@ -78,7 +78,7 @@ static int reset_queues_on_hws_hang(struct device_queue_manager *dqm, bool is_sd static struct queue *find_queue_by_doorbell_offset(struct device_queue_manager *dqm, u32 doorbell_offset); static void set_queue_as_reset(struct device_queue_manager *dqm, struct queue *q, - struct qcm_process_device *qpd); + struct qcm_process_device *qpd, bool verbose); static int reset_queues_mes(struct device_queue_manager *dqm, struct queue *q); static inline @@ -460,7 +460,7 @@ static int reset_queue_mes(struct device_queue_manager *dqm, struct queue *q, return r; /* Proceed remove_queue with reset=true */ remove_queue_mes_on_reset_option(dqm, q, &pdd->qpd, true, true); - set_queue_as_reset(dqm, q, &pdd->qpd); + set_queue_as_reset(dqm, q, &pdd->qpd, true); return 0; } @@ -2518,12 +2518,14 @@ static int map_queues_cpsch(struct device_queue_manager *dqm) } static void set_queue_as_reset(struct device_queue_manager *dqm, struct queue *q, - struct qcm_process_device *qpd) + struct qcm_process_device *qpd, bool verbose) { struct kfd_process_device *pdd = qpd_to_pdd(qpd); - dev_err(dqm->dev->adev->dev, "queue id 0x%0x at pasid %d is reset\n", - q->properties.queue_id, pdd->process->lead_thread->pid); + if (verbose) + dev_err(dqm->dev->adev->dev, + "queue id 0x%0x at pasid %d is reset\n", + q->properties.queue_id, pdd->process->lead_thread->pid); pdd->has_reset_queue = true; q->properties.is_reset = true; @@ -2533,6 +2535,26 @@ static void set_queue_as_reset(struct device_queue_manager *dqm, struct queue *q } } +void kfd_dqm_set_queues_as_reset(struct device_queue_manager *dqm) +{ + struct device_process_node *cur; + struct qcm_process_device *qpd; + struct queue *q; + + dqm_lock(dqm); + if (dqm->processes_count) + dev_warn(dqm->dev->adev->dev, + "GPU reset: queues of %d process(es) are no longer usable\n", + dqm->processes_count); + + list_for_each_entry(cur, &dqm->queues, list) { + qpd = cur->qpd; + list_for_each_entry(q, &qpd->queues_list, list) + set_queue_as_reset(dqm, q, qpd, false); + } + dqm_unlock(dqm); +} + static int detect_queue_hang(struct device_queue_manager *dqm) { int i; @@ -2648,7 +2670,7 @@ static int reset_hung_queues(struct device_queue_manager *dqm) goto reset_fail; } - set_queue_as_reset(dqm, q, &pdd->qpd); + set_queue_as_reset(dqm, q, &pdd->qpd, true); reset_count++; } @@ -2695,7 +2717,7 @@ static bool set_sdma_queue_as_reset(struct device_queue_manager *dqm, if ((q->properties.type == KFD_QUEUE_TYPE_SDMA || q->properties.type == KFD_QUEUE_TYPE_SDMA_XGMI) && q->properties.doorbell_off == doorbell_off) { - set_queue_as_reset(dqm, q, qpd); + set_queue_as_reset(dqm, q, qpd, true); return true; } } diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.h b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.h index f55f313d6cc28..c21da12d3f384 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.h +++ b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.h @@ -336,6 +336,7 @@ int debug_refresh_runlist(struct device_queue_manager *dqm); bool kfd_dqm_is_queue_in_process(struct device_queue_manager *dqm, struct qcm_process_device *qpd, int doorbell_off, u32 *queue_format); +void kfd_dqm_set_queues_as_reset(struct device_queue_manager *dqm); int kfd_reset_queue_mes(struct device_queue_manager *dqm, int queue_type, int pipe, int queue, unsigned int db); size_t mqd_size_from_queue_type(struct device_queue_manager *dqm, -- GitLab