Rework from previous work by: Sujit Reddy Thumma <sthumma@xxxxxxxxxxxxxx> Override auto suspend tunables for UFS device LUNs during initialization so as to efficiently manage background operations and the power consumption. Signed-off-by: Stanley Chu <stanley.chu@xxxxxxxxxxxx> Reviewed-by: Avri Altman <avri.altman@xxxxxxx> Reviewed-by: Bean Huo <beanhuo@xxxxxxxxxx> --- drivers/scsi/ufs/ufshcd.c | 9 +++++++++ drivers/scsi/ufs/ufshcd.h | 10 ++++++++++ 2 files changed, 19 insertions(+) diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c index 30b752c61b97..60a24fe908e7 100644 --- a/drivers/scsi/ufs/ufshcd.c +++ b/drivers/scsi/ufs/ufshcd.c @@ -88,6 +88,9 @@ /* Interrupt aggregation default timeout, unit: 40us */ #define INT_AGGR_DEF_TO 0x02 +/* default delay of autosuspend: 2000 ms */ +#define RPM_AUTOSUSPEND_DELAY_MS 2000 + #define ufshcd_toggle_vreg(_dev, _vreg, _on) \ ({ \ int _ret; \ @@ -4612,9 +4615,14 @@ static int ufshcd_change_queue_depth(struct scsi_device *sdev, int depth) */ static int ufshcd_slave_configure(struct scsi_device *sdev) { + struct ufs_hba *hba = shost_priv(sdev->host); struct request_queue *q = sdev->request_queue; blk_queue_update_dma_pad(q, PRDT_DATA_BYTE_COUNT_PAD - 1); + + if (ufshcd_is_rpm_autosuspend_allowed(hba)) + sdev->rpm_autosuspend = 1; + return 0; } @@ -7041,6 +7049,7 @@ static struct scsi_host_template ufshcd_driver_template = { .track_queue_depth = 1, .sdev_groups = ufshcd_driver_groups, .dma_boundary = PAGE_SIZE - 1, + .rpm_autosuspend_delay = RPM_AUTOSUSPEND_DELAY_MS, }; static int ufshcd_config_vreg_load(struct device *dev, struct ufs_vreg *vreg, diff --git a/drivers/scsi/ufs/ufshcd.h b/drivers/scsi/ufs/ufshcd.h index a43c7135f33d..99ea416519af 100644 --- a/drivers/scsi/ufs/ufshcd.h +++ b/drivers/scsi/ufs/ufshcd.h @@ -714,6 +714,12 @@ struct ufs_hba { * the performance of ongoing read/write operations. */ #define UFSHCD_CAP_KEEP_AUTO_BKOPS_ENABLED_EXCEPT_SUSPEND (1 << 5) + /* + * This capability allows host controller driver to automatically + * enable runtime power management by itself instead of waiting + * for userspace to control the power management. + */ +#define UFSHCD_CAP_RPM_AUTOSUSPEND (1 << 6) struct devfreq *devfreq; struct ufs_clk_scaling clk_scaling; @@ -747,6 +753,10 @@ static inline bool ufshcd_can_autobkops_during_suspend(struct ufs_hba *hba) { return hba->caps & UFSHCD_CAP_AUTO_BKOPS_SUSPEND; } +static inline bool ufshcd_is_rpm_autosuspend_allowed(struct ufs_hba *hba) +{ + return hba->caps & UFSHCD_CAP_RPM_AUTOSUSPEND; +} static inline bool ufshcd_is_intr_aggr_allowed(struct ufs_hba *hba) { -- 2.18.0