Commit fb276f77 authored by Can Guo's avatar Can Guo Committed by Martin K. Petersen

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: default avatarAvri Altman <avri.altman@wdc.com>
Reviewed-by: default avatarStanley Chu <stanley.chu@mediatek.com>
Signed-off-by: default avatarCan Guo <cang@codeaurora.org>
Signed-off-by: default avatarMartin K. Petersen <martin.petersen@oracle.com>
parent 80b21006
...@@ -42,6 +42,7 @@ ...@@ -42,6 +42,7 @@
#include <linux/nls.h> #include <linux/nls.h>
#include <linux/of.h> #include <linux/of.h>
#include <linux/bitfield.h> #include <linux/bitfield.h>
#include <linux/blk-pm.h>
#include "ufshcd.h" #include "ufshcd.h"
#include "ufs_quirks.h" #include "ufs_quirks.h"
#include "unipro.h" #include "unipro.h"
...@@ -6512,6 +6513,16 @@ static void ufshcd_init_icc_levels(struct ufs_hba *hba) ...@@ -6512,6 +6513,16 @@ static void ufshcd_init_icc_levels(struct ufs_hba *hba)
kfree(desc_buf); 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 * ufshcd_scsi_add_wlus - Adds required W-LUs
* @hba: per-adapter instance * @hba: per-adapter instance
...@@ -6551,6 +6562,7 @@ static int ufshcd_scsi_add_wlus(struct ufs_hba *hba) ...@@ -6551,6 +6562,7 @@ static int ufshcd_scsi_add_wlus(struct ufs_hba *hba)
hba->sdev_ufs_device = NULL; hba->sdev_ufs_device = NULL;
goto out; goto out;
} }
ufshcd_blk_pm_runtime_init(hba->sdev_ufs_device);
scsi_device_put(hba->sdev_ufs_device); scsi_device_put(hba->sdev_ufs_device);
sdev_rpmb = __scsi_add_device(hba->host, 0, 0, sdev_rpmb = __scsi_add_device(hba->host, 0, 0,
...@@ -6559,14 +6571,17 @@ static int ufshcd_scsi_add_wlus(struct ufs_hba *hba) ...@@ -6559,14 +6571,17 @@ static int ufshcd_scsi_add_wlus(struct ufs_hba *hba)
ret = PTR_ERR(sdev_rpmb); ret = PTR_ERR(sdev_rpmb);
goto remove_sdev_ufs_device; goto remove_sdev_ufs_device;
} }
ufshcd_blk_pm_runtime_init(sdev_rpmb);
scsi_device_put(sdev_rpmb); scsi_device_put(sdev_rpmb);
sdev_boot = __scsi_add_device(hba->host, 0, 0, sdev_boot = __scsi_add_device(hba->host, 0, 0,
ufshcd_upiu_wlun_to_scsi_wlun(UFS_UPIU_BOOT_WLUN), NULL); 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__); 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); scsi_device_put(sdev_boot);
}
goto out; goto out;
remove_sdev_ufs_device: remove_sdev_ufs_device:
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment