The ufs driver calls scsi_device_get() in ufshcd_set_dev_pwr_mode() in order to avoid manual delete of UFS device W-LUN by holding the reference. But scsi_device_get() has been changed to fail when the LLD module is in the process of being unloaded. So it no longer doesn't work if the module is unloaded while the device is runtime suspended. (i.e. driver_detach -> ... pm_runtime_get_sync() ... -> ufshcd_runtime_resume -> ufshcd_resume -> ufshcd_set_dev_pwr_mode -> scsi_device_get -> try_module_get -> return -ENXIO) As the reason for scsi_device_get() is to avoid manual delete of UFS device W-LUN, this acquires shost->scan_mutex lock instead of scsi_device_get() to work around the problem. Signed-off-by: Akinobu Mita <akinobu.mita@xxxxxxxxx> Cc: Vinayak Holikatti <vinholikatti@xxxxxxxxx> Cc: "James E.J. Bottomley" <JBottomley@xxxxxxxx> Cc: Christoph Hellwig <hch@xxxxxx> Cc: Dolev Raviv <draviv@xxxxxxxxxxxxxx> Cc: Sujit Reddy Thumma <sthumma@xxxxxxxxxxxxxx> Cc: Akinobu Mita <akinobu.mita@xxxxxxxxx> Cc: Subhash Jadavani <subhashj@xxxxxxxxxxxxxx> Cc: Sahitya Tummala <stummala@xxxxxxxxxxxxxx> Cc: Yaniv Gardi <ygardi@xxxxxxxxxxxxxx> Cc: linux-scsi@xxxxxxxxxxxxxxx --- drivers/scsi/ufs/ufshcd.c | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c index d425816..d287207 100644 --- a/drivers/scsi/ufs/ufshcd.c +++ b/drivers/scsi/ufs/ufshcd.c @@ -4792,23 +4792,19 @@ static int ufshcd_set_dev_pwr_mode(struct ufs_hba *hba, struct scsi_sense_hdr sshdr; struct scsi_device *sdp; unsigned long flags; - int ret; + int ret = 0; + mutex_lock(&hba->host->scan_mutex); spin_lock_irqsave(hba->host->host_lock, flags); sdp = hba->sdev_ufs_device; - if (sdp) { - ret = scsi_device_get(sdp); - if (!ret && !scsi_device_online(sdp)) { - ret = -ENODEV; - scsi_device_put(sdp); - } - } else { + if (!sdp || !scsi_device_online(sdp)) ret = -ENODEV; - } spin_unlock_irqrestore(hba->host->host_lock, flags); - if (ret) + if (ret) { + mutex_unlock(&hba->host->scan_mutex); return ret; + } /* * If scsi commands fail, the scsi mid-layer schedules scsi error- @@ -4845,7 +4841,7 @@ static int ufshcd_set_dev_pwr_mode(struct ufs_hba *hba, if (!ret) hba->curr_dev_pwr_mode = pwr_mode; out: - scsi_device_put(sdp); + mutex_unlock(&hba->host->scan_mutex); hba->host->eh_noresume = 0; return ret; } -- 1.9.1 -- To unsubscribe from this list: send the line "unsubscribe linux-scsi" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html