]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
scsi: core: ufs: Fix a hang in the error handler
authorSanjeev Yadav <sanjeev.y@mediatek.com>
Fri, 23 May 2025 20:14:01 +0000 (13:14 -0700)
committerMartin K. Petersen <martin.petersen@oracle.com>
Wed, 4 Jun 2025 02:00:13 +0000 (22:00 -0400)
ufshcd_err_handling_prepare() calls ufshcd_rpm_get_sync(). The latter
function can only succeed if UFSHCD_EH_IN_PROGRESS is not set because
resuming involves submitting a SCSI command and ufshcd_queuecommand()
returns SCSI_MLQUEUE_HOST_BUSY if UFSHCD_EH_IN_PROGRESS is set. Fix this
hang by setting UFSHCD_EH_IN_PROGRESS after ufshcd_rpm_get_sync() has
been called instead of before.

Backtrace:
__switch_to+0x174/0x338
__schedule+0x600/0x9e4
schedule+0x7c/0xe8
schedule_timeout+0xa4/0x1c8
io_schedule_timeout+0x48/0x70
wait_for_common_io+0xa8/0x160 //waiting on START_STOP
wait_for_completion_io_timeout+0x10/0x20
blk_execute_rq+0xe4/0x1e4
scsi_execute_cmd+0x108/0x244
ufshcd_set_dev_pwr_mode+0xe8/0x250
__ufshcd_wl_resume+0x94/0x354
ufshcd_wl_runtime_resume+0x3c/0x174
scsi_runtime_resume+0x64/0xa4
rpm_resume+0x15c/0xa1c
__pm_runtime_resume+0x4c/0x90 // Runtime resume ongoing
ufshcd_err_handler+0x1a0/0xd08
process_one_work+0x174/0x808
worker_thread+0x15c/0x490
kthread+0xf4/0x1ec
ret_from_fork+0x10/0x20

Signed-off-by: Sanjeev Yadav <sanjeev.y@mediatek.com>
[ bvanassche: rewrote patch description ]
Fixes: 62694735ca95 ("[SCSI] ufs: Add runtime PM support for UFS host controller driver")
Signed-off-by: Bart Van Assche <bvanassche@acm.org>
Link: https://lore.kernel.org/r/20250523201409.1676055-1-bvanassche@acm.org
Reviewed-by: Peter Wang <peter.wang@mediatek.com>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
drivers/ufs/core/ufshcd.c

index a7513f256057b78771d2b8ac69d085d36a4aac2b..a1d7c8660c1bf915f67388ab430c08b8f8c2da96 100644 (file)
@@ -6623,9 +6623,14 @@ static void ufshcd_err_handler(struct work_struct *work)
                up(&hba->host_sem);
                return;
        }
-       ufshcd_set_eh_in_progress(hba);
        spin_unlock_irqrestore(hba->host->host_lock, flags);
+
        ufshcd_err_handling_prepare(hba);
+
+       spin_lock_irqsave(hba->host->host_lock, flags);
+       ufshcd_set_eh_in_progress(hba);
+       spin_unlock_irqrestore(hba->host->host_lock, flags);
+
        /* Complete requests that have door-bell cleared by h/w */
        ufshcd_complete_requests(hba, false);
        spin_lock_irqsave(hba->host->host_lock, flags);