[PATCH 1/9] scsi: ufs: core: Do not poll unconfigured MCQ queues in the error handler

From: Stanley Jhu

Date: Thu Nov 12 2026 - 00:17:50 EST


In MCQ mode, ufshcd_err_handler() can poll completion queues that a
failed reset left unconfigured:

1. The UFS device W-LUN is runtime suspended with the link in hibern8.
The device stops responding and the host reports a fatal UIC error,
so the interrupt handler schedules ufshcd_err_handler().
2. ufshcd_err_handler() passes its first stop check and calls
ufshcd_err_handling_prepare(), which resumes the W-LUN through
ufshcd_rpm_get_sync().
3. The resume fails to exit hibern8 and calls ufshcd_link_recovery().
The reset completes all outstanding requests, but link startup fails
before the MCQ queues are configured, leaving UFSHCD_STATE_ERROR.
4. ufshcd_err_handler() calls ufshcd_complete_requests(), which logs
"Abnormal CQ entry!" for each empty slot and writes the head pointer
of each unconfigured queue.
5. Only the second stop check sees UFSHCD_STATE_ERROR and gives up.

Check the stop condition under host_lock right after preparation and
skip ufshcd_complete_requests() when error handling is going to stop.
The failed reset has already completed every outstanding request
and has not set up the completion queues again, so there is nothing
to poll.

Fixes: ab248643d3d6 ("scsi: ufs: core: Add error handling for MCQ mode")
Cc: stable@xxxxxxxxxxxxxxx
Signed-off-by: Stanley Jhu <stanleyjhu@xxxxxxxxxx>
---
drivers/ufs/core/ufshcd.c | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/drivers/ufs/core/ufshcd.c b/drivers/ufs/core/ufshcd.c
index 96e25a0a1dbe..e9dcab35a4cd 100644
--- a/drivers/ufs/core/ufshcd.c
+++ b/drivers/ufs/core/ufshcd.c
@@ -7093,6 +7093,7 @@ static void ufshcd_err_handler(struct work_struct *work)
unsigned long flags;
bool needs_restore;
bool needs_reset;
+ bool stop;
int pmc_err;

hba = container_of(work, struct ufs_hba, eh_work);
@@ -7141,10 +7142,13 @@ static void ufshcd_err_handler(struct work_struct *work)

spin_lock_irqsave(&hba->host->host_lock, flags);
ufshcd_set_eh_in_progress(hba);
+ /* A PM callback in the preparation above may have reset the host. */
+ stop = ufshcd_err_handling_should_stop(hba);
spin_unlock_irqrestore(&hba->host->host_lock, flags);

/* Complete requests that have door-bell cleared by h/w */
- ufshcd_complete_requests(hba, false);
+ if (!stop)
+ ufshcd_complete_requests(hba, false);
spin_lock_irqsave(&hba->host->host_lock, flags);
again:
needs_restore = false;
--
2.56.0.567.gdb80ae8cd5-goog