From e2bb35c426fdf1b757f2002cb11a472bb539f2e6 Mon Sep 17 00:00:00 2001 From: Can Guo Date: Wed, 25 Mar 2020 18:09:59 -0700 Subject: [PATCH] FROMGIT: scsi: ufs: 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 not being enabled for the well-known SCSI devices, the HBA, which is at the top of a SCSI device's parent chain, will not be resumed. 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. Reviewed-by: Avri Altman Reviewed-by: Stanley Chu Signed-off-by: Can Guo Signed-off-by: Martin K. Petersen Bug: 152930830 Change-Id: Id5cc396a1d072eff5d55080f097c2f8d3c60b58f (cherry picked from commit fb276f770118ac1464316231868e711e04218d53 https://git.kernel.org/pub/scm/linux/kernel/git/mkp/scsi.git 5.7/scsi-queue) Signed-off-by: Can Guo --- drivers/scsi/ufs/ufshcd.c | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c index 1c90a3d651bc..bb96e082f6a7 100644 --- a/drivers/scsi/ufs/ufshcd.c +++ b/drivers/scsi/ufs/ufshcd.c @@ -42,6 +42,7 @@ #include #include #include +#include #include "ufshcd.h" #include "ufs_quirks.h" #include "unipro.h" @@ -6682,6 +6683,16 @@ out: kfree(desc_buf); } +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, + RPM_AUTOSUSPEND_DELAY_MS); + scsi_autopm_put_device(sdev); +} + /** * ufshcd_scsi_add_wlus - Adds required W-LUs * @hba: per-adapter instance @@ -6721,6 +6732,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, @@ -6729,14 +6741,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: