scsi: ufs: Enable block layer runtime PM for well-known logical units
authorCan Guo <cang@codeaurora.org>
Thu, 26 Mar 2020 01:09:59 +0000 (18:09 -0700)
committerMartin K. Petersen <martin.petersen@oracle.com>
Fri, 27 Mar 2020 02:30:44 +0000 (22:30 -0400)
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 <avri.altman@wdc.com>
Reviewed-by: Stanley Chu <stanley.chu@mediatek.com>
Signed-off-by: Can Guo <cang@codeaurora.org>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
drivers/scsi/ufs/ufshcd.c

index 145b67f..a3bcf9f 100644 (file)
@@ -42,6 +42,7 @@
 #include <linux/nls.h>
 #include <linux/of.h>
 #include <linux/bitfield.h>
+#include <linux/blk-pm.h>
 #include "ufshcd.h"
 #include "ufs_quirks.h"
 #include "unipro.h"
@@ -6512,6 +6513,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
@@ -6551,6 +6562,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,
@@ -6559,14 +6571,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: