Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 52de3d30 authored by Sayali Lokhande's avatar Sayali Lokhande
Browse files

scsi: ufs: Avoid deadlock in suspend and eeh_work



In case of an exception, there could be a deadlock:

eeh_work:
-002|schedule()
-003|spin_lock_irq()
-003|rpm_resume << pm_runtime_get_sync(hba->dev);
-004|__pm_runtime_resume()
-005|ufshcd_scsi_block_requests()
-005|ufshcd_exception_event_handler()

ufshcd_suspend:
-002|schedule()
-003|schedule_timeout()
-004|do_wait_for_common()
-004|__wait_for_common()
-004|wait_for_common()
-005|wait_for_completion()
-006|destroy_work_on_stack()
-006|flush_work(?) << eeh_work
-007|ufshcd_suspend()
-008|ufshcd_runtime_suspend()
-009|ufshcd_pltfrm_runtime_suspend()
-010|pm_generic_runtime_suspend()
-011|__rpm_callback()

Scenario looks like :
1.Hba->eeh_work starts to work and at the almost same
time ufshcd_runtime_suspend start to work by rpm core.
2.pm_runtime_get_sync in eeh_work remains pending as
rpm_status is RPM_SUSPENDING due to ufshcd_runtime_suspend.

To fix this, call pm_runtime_get_noresume() once eeh_work
is scheduled so that suspend cannot be invoked during
exception work.

Change-Id: Ib212f71e22f063dad9c6ccca4aa8f7261e568b51
Signed-off-by: default avatarAsutosh Das <asutoshd@codeaurora.org>
Signed-off-by: default avatarSayali Lokhande <sayalil@codeaurora.org>
parent 21a1b0f4
Loading
Loading
Loading
Loading
+16 −2
Original line number Diff line number Diff line
@@ -5561,8 +5561,15 @@ ufshcd_transfer_rsp_status(struct ufs_hba *hba, struct ufshcd_lrb *lrbp)
			 * UFS device needs urgent BKOPs.
			 */
			if (!hba->pm_op_in_progress &&
			    ufshcd_is_exception_event(lrbp->ucd_rsp_ptr))
				schedule_work(&hba->eeh_work);
			    ufshcd_is_exception_event(lrbp->ucd_rsp_ptr)) {
				/*
				 * Prevent suspend once eeh_work is scheduled
				 * to avoid deadlock between ufshcd_suspend
				 * and exception event handler.
				 */
				if (schedule_work(&hba->eeh_work))
					pm_runtime_get_noresume(hba->dev);
			}
			break;
		case UPIU_TRANSACTION_REJECT_UPIU:
			/* TODO: handle Reject UPIU Response */
@@ -6146,6 +6153,13 @@ static void ufshcd_exception_event_handler(struct work_struct *work)

out:
	ufshcd_scsi_unblock_requests(hba);
	/*
	 * pm_runtime_get_noresume is called while scheduling
	 * eeh_work to avoid suspend racing with exception work.
	 * Hence decrement usage counter using pm_runtime_put_noidle
	 * to allow suspend on completion of exception event handler.
	 */
	pm_runtime_put_noidle(hba->dev);
	pm_runtime_put(hba->dev);
	return;
}