mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-10 14:19:09 -04:00
scsi: ufs: Fix some racing problems in ufshcd_shutdown()
Currently I/O requests could be still submitted to UFS device while UFS is working on shutdown flow. This may lead to racing as below scenarios and finally system may crash due to unclocked register accesses. To fix this kind of issues, in ufshcd_shutdown(), 1. Use pm_runtime_get_sync() instead of resuming UFS device by ufshcd_runtime_resume() "internally" to let runtime PM framework manage and prevent concurrent runtime operations by incoming I/O requests. 2. Specifically quiesce the SCSI device of UFS Device well known LU so that ufshcd_suspend() can still send the SSU cmd, and remove all the other SCSI devices to block all I/O requests to those SCSI devices. Example of racing scenario: While UFS device is runtime-suspended Thread #1: Executing UFS shutdown flow, e.g., ufshcd_suspend(UFS_SHUTDOWN_PM) Thread #2: Executing runtime resume flow triggered by I/O request, e.g., ufshcd_resume(UFS_RUNTIME_PM) This breaks the assumption that UFS PM flows can not be running concurrently and some unexpected racing behavior may happen. Change-Id: I83345e6b48a832ec7962fc016f4fdf128c9a5bd1 Signed-off-by: Can Guo <cang@codeaurora.org>
This commit is contained in:
parent
0e2097ce85
commit
a24461d3b1
1 changed files with 26 additions and 0 deletions
|
|
@ -4943,6 +4943,10 @@ static void ufshcd_slave_destroy(struct scsi_device *sdev)
|
|||
spin_unlock_irqrestore(hba->host->host_lock, flags);
|
||||
}
|
||||
|
||||
#if defined(CONFIG_SCSI_UFSHCD_QTI)
|
||||
return;
|
||||
#endif
|
||||
|
||||
ufshcd_crypto_destroy_rq_keyslot_manager(hba, q);
|
||||
}
|
||||
|
||||
|
|
@ -8954,6 +8958,9 @@ EXPORT_SYMBOL(ufshcd_runtime_idle);
|
|||
int ufshcd_shutdown(struct ufs_hba *hba)
|
||||
{
|
||||
int ret = 0;
|
||||
#if defined(CONFIG_SCSI_UFSHCD_QTI)
|
||||
struct scsi_device *sdev;
|
||||
#endif
|
||||
|
||||
if (!hba->is_powered)
|
||||
goto out;
|
||||
|
|
@ -8961,11 +8968,30 @@ int ufshcd_shutdown(struct ufs_hba *hba)
|
|||
if (ufshcd_is_ufs_dev_poweroff(hba) && ufshcd_is_link_off(hba))
|
||||
goto out;
|
||||
|
||||
#if defined(CONFIG_SCSI_UFSHCD_QTI)
|
||||
pm_runtime_get_sync(hba->dev);
|
||||
|
||||
/*
|
||||
* I/O requests could be still submitted to SCSI devices
|
||||
* when we are here. Quiesce the scsi device of UFS Device
|
||||
* well known LU but remove all the other scsi devices.
|
||||
* After the scsi device is quiesced, only PM requests can
|
||||
* pass through SCSI layer, which well serves the purpose
|
||||
* of sending the SSU cmd during ufshcd_suspend().
|
||||
*/
|
||||
shost_for_each_device(sdev, hba->host) {
|
||||
if (sdev == hba->sdev_ufs_device)
|
||||
scsi_device_quiesce(sdev);
|
||||
else
|
||||
scsi_remove_device(sdev);
|
||||
}
|
||||
#else
|
||||
if (pm_runtime_suspended(hba->dev)) {
|
||||
ret = ufshcd_runtime_resume(hba);
|
||||
if (ret)
|
||||
goto out;
|
||||
}
|
||||
#endif
|
||||
|
||||
ret = ufshcd_suspend(hba, UFS_SHUTDOWN_PM);
|
||||
out:
|
||||
|
|
|
|||
Loading…
Reference in a new issue