Commit e23ef4f2 authored by Peter Wang's avatar Peter Wang Committed by Martin K. Petersen
Browse files

scsi: ufs: core: Fix error handler host_sem issue



Fix the issue where host_sem is not released due to a new return path in
commit f966e02a ("scsi: ufs: core: Fix runtime suspend error
deadlock").

Check pm_op_in_progress before acquiring hba->host_sem to prevent
deadlocks and ensure proper resource management during error
handling. Add comment for use ufshcd_rpm_get_noresume() to safely
perform link recovery without interfering with ongoing PM operations.

Fixes: f966e02a ("scsi: ufs: core: Fix runtime suspend error deadlock")
Reported-by: default avatarDan Carpenter <dan.carpenter@linaro.org>
Signed-off-by: default avatarPeter Wang <peter.wang@mediatek.com>
Reviewed-by: default avatarBart Van Assche <bvanassche@acm.org>
Link: https://patch.msgid.link/20251008065651.1589614-2-peter.wang@mediatek.com


Signed-off-by: default avatarMartin K. Petersen <martin.petersen@oracle.com>
parent a0b77806
Loading
Loading
Loading
Loading
+14 −8
Original line number Diff line number Diff line
@@ -6673,6 +6673,20 @@ static void ufshcd_err_handler(struct work_struct *work)
		 hba->saved_uic_err, hba->force_reset,
		 ufshcd_is_link_broken(hba) ? "; link is broken" : "");

	/*
	 * Use ufshcd_rpm_get_noresume() here to safely perform link recovery
	 * even if an error occurs during runtime suspend or runtime resume.
	 * This avoids potential deadlocks that could happen if we tried to
	 * resume the device while a PM operation is already in progress.
	 */
	ufshcd_rpm_get_noresume(hba);
	if (hba->pm_op_in_progress) {
		ufshcd_link_recovery(hba);
		ufshcd_rpm_put(hba);
		return;
	}
	ufshcd_rpm_put(hba);

	down(&hba->host_sem);
	spin_lock_irqsave(hba->host->host_lock, flags);
	if (ufshcd_err_handling_should_stop(hba)) {
@@ -6684,14 +6698,6 @@ static void ufshcd_err_handler(struct work_struct *work)
	}
	spin_unlock_irqrestore(hba->host->host_lock, flags);

	ufshcd_rpm_get_noresume(hba);
	if (hba->pm_op_in_progress) {
		ufshcd_link_recovery(hba);
		ufshcd_rpm_put(hba);
		return;
	}
	ufshcd_rpm_put(hba);

	ufshcd_err_handling_prepare(hba);

	spin_lock_irqsave(hba->host->host_lock, flags);