scsi: ufs: Fix race condition in rls_work and ufshcd_resume

In some rare scenario, race condition is observed between
rls_work handler and ufshcd_resume operation.
Sequence of events:
1.rls_work is scheduled due to UIC error.
2.ufshcd_rls_handler sets host_self_blocked to 1 and then
invokes pm_runtime_get_sync
3. pm_runtime_get_sync is not yet completed because
runtime_status was RPM_RESUMING.
4.pm_runtime_work schedules at almost same time of rls_work.

Here ufshcd_resume schedules out as host_self_blocked
was set to 1 by rls_work.

Call stacks:

-006|wait_for_completion_io(?)
-007|blk_execute_rq()
-008|scsi_execute()
-009|scsi_execute_req_flags()
-010|ufshcd_set_dev_pwr_mode()
-011|ufshcd_resume()
-012|ufshcd_runtime_resume(hba)
-013|ufshcd_pltfrm_runtime_resume(?)
-014|pm_generic_runtime_resume(?)
-015|__rpm_callback(inline)

-003|schedule()
-004|spin_lock_irq(inline)
-004|rpm_resume()
-005|__pm_runtime_resume()
-006|ufshcd_rls_handler()

Fix this by calling pm_runtime_get_sync before setting
host_self_blocked to 1 during rls_work.

Change-Id: I69f23c169ac8a9eb59062b461302f5521cd57ebc
Signed-off-by: Sayali Lokhande <sayalil@codeaurora.org>
This commit is contained in:
Sayali Lokhande 2018-06-12 16:15:02 +05:30
parent 2a61e30d44
commit 1fc3a7badb

View file

@ -6289,8 +6289,8 @@ static void ufshcd_rls_handler(struct work_struct *work)
u32 mode; u32 mode;
hba = container_of(work, struct ufs_hba, rls_work); hba = container_of(work, struct ufs_hba, rls_work);
ufshcd_scsi_block_requests(hba);
pm_runtime_get_sync(hba->dev); pm_runtime_get_sync(hba->dev);
ufshcd_scsi_block_requests(hba);
ret = ufshcd_wait_for_doorbell_clr(hba, U64_MAX); ret = ufshcd_wait_for_doorbell_clr(hba, U64_MAX);
if (ret) { if (ret) {
dev_err(hba->dev, dev_err(hba->dev,