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

Commit ba2a4ddd authored by Nitin Rawat's avatar Nitin Rawat
Browse files

scsi: ufs: fix race b/w resume and err_handler



In some rare scenario, race condition is observed between
eh_work handler and ufshcd_resume operation.
Sequence of events:

1. SSU command is send as a part of ufshcd_resume.

2. ufshcd_rls_handler waits on pm_runtime_get_sync
   because runtime_status was RPM_RESUMING.

3. After SSU timeout, as a part of abort work, err_handler
   scccessfully runs and recovers dev state as active and
   uic link as active.
4. In ufshcd_resume, after ssu return failure,
   it moved the link state as hibern8 and disabled the
   interrupt leaving dev state as active and link as
   hibernate and hence the inconsistency.

5. Later rls_handler acquired pm_runtime_get_sync and as a part
   of power change command , uic command is sent and but since
   interrupt is disabled uic command timeout happended.

Also when start stop failed runtime_error was set to
DID_TIME_OUT >> 16. and since runtime error is only cleared
at initialization in the normal case, device can't resume
and watch dog expired happended .
scsi 0:0:0:49488: START_STOP failed for power mode: 1, result 30000.

Fix this by checking the device state and link state after
ssu return failure with reason as DID_TIME_OUT.If
current dev and link state is active, dont return
error as dev and link state is in correct state and
hence proceed with the resume.

Change-Id: I32cdcbd00cf7e39af14d44c81b181b276183f54a
Signed-off-by: default avatarNitin Rawat <nitirawa@codeaurora.org>
parent 82e0a0f5
Loading
Loading
Loading
Loading
+14 −3
Original line number Diff line number Diff line
@@ -10543,10 +10543,21 @@ static int ufshcd_resume(struct ufs_hba *hba, enum ufs_pm_op pm_op)
	ufshcd_wb_buf_flush_disable(hba);
	if (!ufshcd_is_ufs_dev_active(hba)) {
		ret = ufshcd_set_dev_pwr_mode(hba, UFS_ACTIVE_PWR_MODE);
		if (ret)
		if (ret) {
			/*
			 * In the case of SSU timeout, err_handler must have
			 * recovered the uic link and dev state to active so
			 * we can proceed after checking the link and
			 * dev state.
			 */
			if ((host_byte(ret) == DID_TIME_OUT) &&
			    ufshcd_is_ufs_dev_active(hba) &&
			    ufshcd_is_link_active(hba))
				ret = 0;
			else
				goto set_old_link_state;
		}

	}
	if (ufshcd_keep_autobkops_enabled_except_suspend(hba))
		ufshcd_enable_auto_bkops(hba);
	else