From bb45ad80bd11c6b763bc8f45ffb0511dc5bb0481 Mon Sep 17 00:00:00 2001 From: Can Guo Date: Tue, 24 Mar 2020 19:33:29 -0700 Subject: [PATCH] scsi: ufs-qti: Enable block layer runtime PM for well-known logical units Block layer RPM is enabled for the genernal UFS SCSI devices when they are probed by their driver. However block layer RPM is not enabled for UFS well-known SCSI devices. As UFS SCSI devices have their corresponding BSG char devices, accessing a BSG char device via IOCTL may send requests to its corresponding SCSI device through its request queue. If BSG IOCTL sends a request to a well-known SCSI device when hba is not runtime active, due to block layer RPM is not eanbled for the well-known SCSI devices, hba, which is at the top of a scsi device's parent chain, shall not be resumed, then unexpected error would happen. This change enables block layer RPM for the well-known SCSI devices, so that block layer can handle RPM for the well-known SCSI devices just like for the general SCSI devices. Change-Id: Ie4c5c4876f8500c285166a5f7be87a2157a12df3 Signed-off-by: Can Guo --- drivers/scsi/ufs/ufshcd-qti.c | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/ufs/ufshcd-qti.c b/drivers/scsi/ufs/ufshcd-qti.c index d60520426f62..dfbaa0518647 100644 --- a/drivers/scsi/ufs/ufshcd-qti.c +++ b/drivers/scsi/ufs/ufshcd-qti.c @@ -8,6 +8,7 @@ #include #include #include +#include #include #include #include @@ -7686,6 +7687,16 @@ static int ufshcd_set_low_vcc_level(struct ufs_hba *hba, return ret; } +static inline void ufshcd_blk_pm_runtime_init(struct scsi_device *sdev) +{ + scsi_autopm_get_device(sdev); + blk_pm_runtime_init(sdev->request_queue, &sdev->sdev_gendev); + if (sdev->rpm_autosuspend) + pm_runtime_set_autosuspend_delay(&sdev->sdev_gendev, + UFSHCD_AUTO_SUSPEND_DELAY_MS); + scsi_autopm_put_device(sdev); +} + /** * ufshcd_scsi_add_wlus - Adds required W-LUs * @hba: per-adapter instance @@ -7725,6 +7736,7 @@ static int ufshcd_scsi_add_wlus(struct ufs_hba *hba) hba->sdev_ufs_device = NULL; goto out; } + ufshcd_blk_pm_runtime_init(hba->sdev_ufs_device); scsi_device_put(hba->sdev_ufs_device); sdev_rpmb = __scsi_add_device(hba->host, 0, 0, @@ -7733,14 +7745,17 @@ static int ufshcd_scsi_add_wlus(struct ufs_hba *hba) ret = PTR_ERR(sdev_rpmb); goto remove_sdev_ufs_device; } + ufshcd_blk_pm_runtime_init(sdev_rpmb); scsi_device_put(sdev_rpmb); sdev_boot = __scsi_add_device(hba->host, 0, 0, ufshcd_upiu_wlun_to_scsi_wlun(UFS_UPIU_BOOT_WLUN), NULL); - if (IS_ERR(sdev_boot)) + if (IS_ERR(sdev_boot)) { dev_err(hba->dev, "%s: BOOT WLUN not found\n", __func__); - else + } else { + ufshcd_blk_pm_runtime_init(sdev_boot); scsi_device_put(sdev_boot); + } goto out; remove_sdev_ufs_device: