[PATCH v1 9/9] scsi: ufs: enable FASTAUTO mode during low load condition
From: Subhash Jadavani We are currently running UFS link in HS-G3 FAST mode during high load condition for best possible performance and in HS-G2 FAST mode during low load condition to save power. As we are anyway scaling down from HS-G3 to HS-G2, we can also change the mode from FAST to FASTAUTO. So we looked at the performance numbers with HS-G2 FASTAUTO mode and they are good enough for most of the low bandwidth usecases. But Samsung UFS memory devices are exception which has really low sequential read throughput in FAST AUTO mode hence we will only be enabling FAST AUTO mode for other UFS device vendors. Signed-off-by: Subhash Jadavani Signed-off-by: Can Guo Signed-off-by: Asutosh Das --- drivers/scsi/ufs/ufshcd.c | 4 1 file changed, 4 insertions(+) diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c index 50588cf..a6e43f9 100644 --- a/drivers/scsi/ufs/ufshcd.c +++ b/drivers/scsi/ufs/ufshcd.c @@ -1088,6 +1088,10 @@ static int ufshcd_scale_gear(struct ufs_hba *hba, bool scale_up) /* scale down gear */ new_pwr_info.gear_tx = UFS_MIN_GEAR_TO_SCALE_DOWN; new_pwr_info.gear_rx = UFS_MIN_GEAR_TO_SCALE_DOWN; + if (!(hba->dev_quirks & UFS_DEVICE_NO_FASTAUTO)) { + new_pwr_info.pwr_tx = FASTAUTO_MODE; + new_pwr_info.pwr_rx = FASTAUTO_MODE; + } } } -- Qualcomm India Private Limited, on behalf of Qualcomm Innovation Center, Inc. Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, a Linux Foundation Collaborative Project.
[PATCH v1 4/9] scsi: ufs: add option to change default UFS power management level
From: Subhash Jadavani UFS device and link can be put in multiple different low power modes hence UFS driver supports multiple different low power modes. By default UFS driver selects the default (optimal) low power mode (which gives moderate power savings and have relatively less enter and exit latencies) but we might have to tune this default power mode for different chipset platforms to meet the low power requirements/goals. Hence this patch adds option to change default UFS low power mode (level). Signed-off-by: Subhash Jadavani Signed-off-by: Venkat Gopalakrishnan Signed-off-by: Can Guo Signed-off-by: Asutosh Das --- .../devicetree/bindings/ufs/ufshcd-pltfrm.txt | 11 drivers/scsi/ufs/ufshcd-pltfrm.c | 14 +++ drivers/scsi/ufs/ufshcd.c | 29 +++--- drivers/scsi/ufs/ufshcd.h | 4 +-- 4 files changed, 47 insertions(+), 11 deletions(-) diff --git a/Documentation/devicetree/bindings/ufs/ufshcd-pltfrm.txt b/Documentation/devicetree/bindings/ufs/ufshcd-pltfrm.txt index c39dfef..f564d9a 100644 --- a/Documentation/devicetree/bindings/ufs/ufshcd-pltfrm.txt +++ b/Documentation/devicetree/bindings/ufs/ufshcd-pltfrm.txt @@ -38,6 +38,15 @@ Optional properties: defined or a value in the array is "0" then it is assumed that the frequency is set by the parent clock or a fixed rate clock source. +- rpm-level: UFS Runtime power management level. Following PM levels are supported: + 0 - Both UFS device and Link in active state (Highest power consumption) + 1 - UFS device in active state but Link in Hibern8 state + 2 - UFS device in Sleep state but Link in active state + 3 - UFS device in Sleep state and Link in hibern8 state (default PM level) + 4 - UFS device in Power-down state and Link in Hibern8 state + 5 - UFS device in Power-down state and Link in OFF state (Lowest power consumption) +- spm-level: UFS System power management level. Allowed PM levels are same as rpm-level. + -lanes-per-direction : number of lanes available per direction - either 1 or 2. Note that it is assume same number of lanes is used both directions at once. If not specified, default is 2 lanes per direction. @@ -66,4 +75,6 @@ Example: freq-table-hz = <1 2>, <0 0>, <0 0>; phys = <>; phy-names = "ufsphy"; + rpm-level = <3>; + spm-level = <5>; }; diff --git a/drivers/scsi/ufs/ufshcd-pltfrm.c b/drivers/scsi/ufs/ufshcd-pltfrm.c index e82bde0..7dba799 100644 --- a/drivers/scsi/ufs/ufshcd-pltfrm.c +++ b/drivers/scsi/ufs/ufshcd-pltfrm.c @@ -221,6 +221,19 @@ static int ufshcd_parse_regulator_info(struct ufs_hba *hba) return err; } +static void ufshcd_parse_pm_levels(struct ufs_hba *hba) +{ + struct device *dev = hba->dev; + struct device_node *np = dev->of_node; + + if (np) { + if (of_property_read_u32(np, "rpm-level", >rpm_lvl)) + hba->rpm_lvl = -1; + if (of_property_read_u32(np, "spm-level", >spm_lvl)) + hba->spm_lvl = -1; + } +} + #ifdef CONFIG_PM /** * ufshcd_pltfrm_suspend - suspend power management function @@ -340,6 +353,7 @@ int ufshcd_pltfrm_init(struct platform_device *pdev, goto dealloc_host; } + ufshcd_parse_pm_levels(hba); pm_runtime_set_active(>dev); pm_runtime_enable(>dev); diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c index b03f3ea..e950204 100644 --- a/drivers/scsi/ufs/ufshcd.c +++ b/drivers/scsi/ufs/ufshcd.c @@ -192,6 +192,14 @@ struct ufs_pm_lvl_states ufs_pm_lvl_states[] = { return UFS_PM_LVL_0; } +static inline bool ufshcd_is_valid_pm_lvl(int lvl) +{ + if (lvl >= 0 && lvl < ARRAY_SIZE(ufs_pm_lvl_states)) + return true; + else + return false; +} + static struct ufs_dev_fix ufs_fixups[] = { /* UFS cards deviations table */ UFS_FIX(UFS_VENDOR_SAMSUNG, UFS_ANY_MODEL, @@ -8051,16 +8059,19 @@ int ufshcd_init(struct ufs_hba *hba, void __iomem *mmio_base, unsigned int irq) } /* -* Set the default power management level for runtime and system PM. -* Default power saving mode is to keep UFS link in Hibern8 state -* and UFS device in sleep state. +* If rpm_lvl and and spm_lvl are not already set to valid levels, +* set the default power management level for UFS runtime and system +* suspend. Default power saving mode selected is keeping UFS link in +* Hibern8 state and UFS device in sleep state.
[PATCH v1 6/9] scsi: ufs: optimize clock, pm_qos, hibern8 handling in queuecommand
From: Subhash Jadavani ufshcd_queuecommand() vote for the resources in this order: clocks, pm_qos latency, hibern8 exit. If any of these votes are not already applied, each one has to be applied asynchronously and in that case we are releasing all the previously applied resource votes (for example, if hibern8 exit has to be completed asynchronously, we release the votes for pm_qos and clocks as well). This is not a optimal solution instead we should skip scheduling the unvoting work for already voted resources. Signed-off-by: Subhash Jadavani Signed-off-by: Can Guo Signed-off-by: Asutosh Das --- drivers/scsi/ufs/ufs-qcom.c | 2 +- drivers/scsi/ufs/ufshcd.c | 33 + drivers/scsi/ufs/ufshcd.h | 2 +- 3 files changed, 19 insertions(+), 18 deletions(-) diff --git a/drivers/scsi/ufs/ufs-qcom.c b/drivers/scsi/ufs/ufs-qcom.c index 221820a..fa01924 100644 --- a/drivers/scsi/ufs/ufs-qcom.c +++ b/drivers/scsi/ufs/ufs-qcom.c @@ -1605,7 +1605,7 @@ int ufs_qcom_testbus_config(struct ufs_qcom_host *host) * committed before returning. */ mb(); - ufshcd_release(host->hba); + ufshcd_release(host->hba, false); pm_runtime_put_sync(host->hba->dev); return 0; diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c index 8a56ef6..40d9c35 100644 --- a/drivers/scsi/ufs/ufshcd.c +++ b/drivers/scsi/ufs/ufshcd.c @@ -1175,7 +1175,7 @@ static int ufshcd_devfreq_scale(struct ufs_hba *hba, bool scale_up) out: ufshcd_clock_scaling_unprepare(hba); - ufshcd_release(hba); + ufshcd_release_all(hba); return ret; } @@ -1447,7 +1447,7 @@ static ssize_t ufshcd_clkscale_enable_store(struct device *dev, __func__, err); } - ufshcd_release(hba); + ufshcd_release(hba, false); pm_runtime_put_sync(hba->dev); out: return count; @@ -1662,7 +1662,7 @@ static void ufshcd_gate_work(struct work_struct *work) } /* host lock must be held before calling this variant */ -static void __ufshcd_release(struct ufs_hba *hba) +static void __ufshcd_release(struct ufs_hba *hba, bool no_sched) { if (!ufshcd_is_clkgating_allowed(hba)) return; @@ -1673,7 +1673,7 @@ static void __ufshcd_release(struct ufs_hba *hba) || hba->ufshcd_state != UFSHCD_STATE_OPERATIONAL || hba->lrb_in_use || hba->outstanding_tasks || hba->active_uic_cmd || hba->uic_async_done - || ufshcd_eh_in_progress(hba)) + || ufshcd_eh_in_progress(hba) || no_sched) return; hba->clk_gating.state = REQ_CLKS_OFF; @@ -1682,12 +1682,12 @@ static void __ufshcd_release(struct ufs_hba *hba) msecs_to_jiffies(hba->clk_gating.delay_ms)); } -void ufshcd_release(struct ufs_hba *hba) +void ufshcd_release(struct ufs_hba *hba, bool no_sched) { unsigned long flags; spin_lock_irqsave(hba->host->host_lock, flags); - __ufshcd_release(hba); + __ufshcd_release(hba, no_sched); spin_unlock_irqrestore(hba->host->host_lock, flags); } EXPORT_SYMBOL_GPL(ufshcd_release); @@ -1738,7 +1738,7 @@ static ssize_t ufshcd_clkgate_enable_store(struct device *dev, goto out; if (value) { - ufshcd_release(hba); + ufshcd_release(hba, false); } else { spin_lock_irqsave(hba->host->host_lock, flags); hba->clk_gating.active_reqs++; @@ -1870,7 +1870,7 @@ int ufshcd_hibern8_hold(struct ufs_hba *hba, bool async) } /* host lock must be held before calling this variant */ -static void __ufshcd_hibern8_release(struct ufs_hba *hba) +static void __ufshcd_hibern8_release(struct ufs_hba *hba, bool no_sched) { unsigned long delay_in_jiffies; @@ -1884,7 +1884,8 @@ static void __ufshcd_hibern8_release(struct ufs_hba *hba) || hba->hibern8_on_idle.is_suspended || hba->ufshcd_state != UFSHCD_STATE_OPERATIONAL || hba->lrb_in_use || hba->outstanding_tasks - || hba->active_uic_cmd || hba->uic_async_done) + || hba->active_uic_cmd || hba->uic_async_done + || ufshcd_eh_in_progress(hba) || no_sched) return; hba->hibern8_on_idle.state = REQ_HIBERN8_ENTER; @@ -1907,12 +1908,12 @@ static void __ufshcd_hibern8_release(struct ufs_hba *hba) delay_in_jiffies); } -void ufshcd_hibern8_release(struct ufs_hba *hba) +void ufshcd_hibern8_release(struct ufs_hba *hba, bool no_sched) { unsigned long flags; spin_lock_irqsave(hba->host->host_lock, flags); - __ufshcd_hibern8_release(hba); + __ufshcd_hibern8_release(hba, no_sched); spin_unlock_irqrestore(hba->host->host_lock, flags); } @@ -2034,8 +2035,8 @@ static void ufshcd_hold_all(struct ufs_hba *hba) static void
[PATCH v1 2/9] scsi: Allow auto suspend override by low-level driver
From: Sujit Reddy Thumma Until now the scsi mid-layer forbids runtime suspend till userspace enables it. This is mainly to quarantine some disks with broken runtime power management or have high latencies executing suspend resume callbacks. If the userspace doesn't enable the runtime suspend the underlying hardware will be always on even when it is not doing any useful work and thus wasting power. Some low-level drivers for the controllers can efficiently use runtime power management to reduce power consumption and improve battery life. Allow runtime suspend parameters override within the LLD itself instead of waiting for userspace to control the power management. Signed-off-by: Sujit Reddy Thumma Signed-off-by: Subhash Jadavani Signed-off-by: Asutosh Das --- drivers/scsi/scsi_scan.c | 4 drivers/scsi/scsi_sysfs.c | 3 ++- drivers/scsi/sd.c | 2 ++ include/scsi/scsi_device.h | 3 +++ 4 files changed, 11 insertions(+), 1 deletion(-) diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c index 0880d97..5b7232a 100644 --- a/drivers/scsi/scsi_scan.c +++ b/drivers/scsi/scsi_scan.c @@ -969,6 +969,10 @@ static int scsi_add_lun(struct scsi_device *sdev, unsigned char *inq_result, transport_configure_device(>sdev_gendev); + /* The LLD can override auto suspend tunables in ->slave_configure() */ + sdev->use_rpm_auto = 0; + sdev->autosuspend_delay = SCSI_DEFAULT_AUTOSUSPEND_DELAY; + if (sdev->host->hostt->slave_configure) { ret = sdev->host->hostt->slave_configure(sdev); if (ret) { diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c index 7943b76..706e778 100644 --- a/drivers/scsi/scsi_sysfs.c +++ b/drivers/scsi/scsi_sysfs.c @@ -1266,7 +1266,8 @@ int scsi_sysfs_add_sdev(struct scsi_device *sdev) device_enable_async_suspend(>sdev_gendev); scsi_autopm_get_target(starget); pm_runtime_set_active(>sdev_gendev); - pm_runtime_forbid(>sdev_gendev); + if (!sdev->use_rpm_auto) + pm_runtime_forbid(>sdev_gendev); pm_runtime_enable(>sdev_gendev); scsi_autopm_put_target(starget); diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index a6201e6..205624f 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c @@ -3269,6 +3269,8 @@ static void sd_probe_async(void *data, async_cookie_t cookie) } blk_pm_runtime_init(sdp->request_queue, dev); + if (sdp->autosuspend_delay >= 0) + pm_runtime_set_autosuspend_delay(dev, sdp->autosuspend_delay); device_add_disk(dev, gd); if (sdkp->capacity) sd_dif_config_host(sdkp); diff --git a/include/scsi/scsi_device.h b/include/scsi/scsi_device.h index 4c36af6..1d5ae90 100644 --- a/include/scsi/scsi_device.h +++ b/include/scsi/scsi_device.h @@ -197,7 +197,10 @@ struct scsi_device { unsigned broken_fua:1; /* Don't set FUA bit */ unsigned lun_in_cdb:1; /* Store LUN bits in CDB[1] */ unsigned unmap_limit_for_ws:1; /* Use the UNMAP limit for WRITE SAME */ + unsigned use_rpm_auto:1; /* Enable runtime PM auto suspend */ +#define SCSI_DEFAULT_AUTOSUSPEND_DELAY -1 + int autosuspend_delay; atomic_t disk_events_disable_depth; /* disable depth for disk events */ DECLARE_BITMAP(supported_events, SDEV_EVT_MAXBITS); /* supported events */ -- Qualcomm India Private Limited, on behalf of Qualcomm Innovation Center, Inc. Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, a Linux Foundation Collaborative Project.
[PATCH v1 8/9] scsi: ufs: enable runtime pm only after ufshcd init
From: Gilad Broner Previous code enables runtime pm before ufshcd_init() is completed, and before the hba struct is stored in the platform device private data. This means that pm runtime calls will have null hba pointer as well as partially initialized driver. Instead, enable pm runtime only after ufshcd_init() is done and after hba struct is stored in the platform device private data. Signed-off-by: Gilad Broner Signed-off-by: Can Guo Signed-off-by: Asutosh Das --- drivers/scsi/ufs/ufshcd-pltfrm.c | 11 --- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/drivers/scsi/ufs/ufshcd-pltfrm.c b/drivers/scsi/ufs/ufshcd-pltfrm.c index 7dba799..8332d99 100644 --- a/drivers/scsi/ufs/ufshcd-pltfrm.c +++ b/drivers/scsi/ufs/ufshcd-pltfrm.c @@ -354,24 +354,21 @@ int ufshcd_pltfrm_init(struct platform_device *pdev, } ufshcd_parse_pm_levels(hba); - pm_runtime_set_active(>dev); - pm_runtime_enable(>dev); ufshcd_init_lanes_per_dir(hba); err = ufshcd_init(hba, mmio_base, irq); if (err) { dev_err(dev, "Initialization failed\n"); - goto out_disable_rpm; + goto dealloc_host; } platform_set_drvdata(pdev, hba); - return 0; + pm_runtime_set_active(>dev); + pm_runtime_enable(>dev); -out_disable_rpm: - pm_runtime_disable(>dev); - pm_runtime_set_suspended(>dev); + return 0; dealloc_host: ufshcd_dealloc_host(hba); out: -- Qualcomm India Private Limited, on behalf of Qualcomm Innovation Center, Inc. Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, a Linux Foundation Collaborative Project.
[PATCH v1 5/9] scsi: ufs: add support for hibern8 on idle
From: Subhash Jadavani In order to save power we should put the UFS link into hibern8 as soon as UFS link is idle and power measurement of active usecases (like audio/video playback/recording) show that putting UFS link in hibern8 @ 10ms of idle (if not earlier) would save significant power. Our current available solution is to do hibern8 with clock gating @idle timeout of 150ms. As clock gating has huge latencies (7ms each in enter and exit), we cannot bring down the idle timeout to <=10ms without degrading UFS throughput. Hence this change has added support to enter into hibern8 with another idle timer. Signed-off-by: Subhash Jadavani Signed-off-by: Can Guo Signed-off-by: Asutosh Das --- drivers/scsi/ufs/ufshcd.c | 372 - drivers/scsi/ufs/ufshcd.h | 39 + include/trace/events/ufs.h | 20 +++ 3 files changed, 397 insertions(+), 34 deletions(-) diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c index e950204..8a56ef6 100644 --- a/drivers/scsi/ufs/ufshcd.c +++ b/drivers/scsi/ufs/ufshcd.c @@ -246,6 +246,8 @@ static int __ufshcd_setup_clocks(struct ufs_hba *hba, bool on, static irqreturn_t ufshcd_intr(int irq, void *__hba); static int ufshcd_change_power_mode(struct ufs_hba *hba, struct ufs_pa_layer_attr *pwr_mode); +static void ufshcd_hold_all(struct ufs_hba *hba); +static void ufshcd_release_all(struct ufs_hba *hba); static inline bool ufshcd_valid_tag(struct ufs_hba *hba, int tag) { return tag >= 0 && tag < hba->nutrs; @@ -853,6 +855,18 @@ static inline bool ufshcd_is_hba_active(struct ufs_hba *hba) ? false : true; } +static const char *ufshcd_hibern8_on_idle_state_to_string( + enum ufshcd_hibern8_on_idle_state state) +{ + switch (state) { + case HIBERN8_ENTERED: return "HIBERN8_ENTERED"; + case HIBERN8_EXITED:return "HIBERN8_EXITED"; + case REQ_HIBERN8_ENTER: return "REQ_HIBERN8_ENTER"; + case REQ_HIBERN8_EXIT: return "REQ_HIBERN8_EXIT"; + default:return "UNKNOWN_STATE"; + } +} + u32 ufshcd_get_local_unipro_ver(struct ufs_hba *hba) { /* HCI version 1.0 and 1.1 supports UniPro 1.41 */ @@ -993,7 +1007,7 @@ static int ufshcd_wait_for_doorbell_clr(struct ufs_hba *hba, bool timeout = false, do_last_check = false; ktime_t start; - ufshcd_hold(hba, false); + ufshcd_hold_all(hba); spin_lock_irqsave(hba->host->host_lock, flags); /* * Wait for all the outstanding tasks/transfer requests. @@ -1038,7 +1052,7 @@ static int ufshcd_wait_for_doorbell_clr(struct ufs_hba *hba, } out: spin_unlock_irqrestore(hba->host->host_lock, flags); - ufshcd_release(hba); + ufshcd_release_all(hba); return ret; } @@ -1601,8 +1615,16 @@ static void ufshcd_gate_work(struct work_struct *work) spin_unlock_irqrestore(hba->host->host_lock, flags); + if (ufshcd_is_hibern8_on_idle_allowed(hba)) + /* +* Hibern8 enter work (on Idle) needs clocks to be ON hence +* make sure that it is flushed before turning off the clocks. +*/ + flush_delayed_work(>hibern8_on_idle.enter_work); + /* put the link into hibern8 mode before turning off clocks */ - if (ufshcd_can_hibern8_during_gating(hba)) { + if (ufshcd_can_hibern8_during_gating(hba) && + ufshcd_is_link_active(hba)) { if (ufshcd_uic_hibern8_enter(hba)) { hba->clk_gating.state = CLKS_ON; trace_ufshcd_clk_gating(dev_name(hba->dev), @@ -1732,6 +1754,8 @@ static void ufshcd_init_clk_gating(struct ufs_hba *hba) { char wq_name[sizeof("ufs_clk_gating_00")]; + hba->clk_gating.state = CLKS_ON; + if (!ufshcd_is_clkgating_allowed(hba)) return; @@ -1774,6 +1798,246 @@ static void ufshcd_exit_clk_gating(struct ufs_hba *hba) destroy_workqueue(hba->clk_gating.clk_gating_workq); } +/** + * ufshcd_hibern8_hold - Make sure that link is not in hibern8. + * + * @hba: per adapter instance + * @async: This indicates whether caller wants to exit hibern8 asynchronously. + * + * Exit from hibern8 mode and set the link as active. + * + * Return 0 on success, non-zero on failure. + */ +int ufshcd_hibern8_hold(struct ufs_hba *hba, bool async) +{ + int rc = 0; + unsigned long flags; + + if (!ufshcd_is_hibern8_on_idle_allowed(hba)) + goto out; + + spin_lock_irqsave(hba->host->host_lock, flags); + hba->hibern8_on_idle.active_reqs++; + +start: + switch (hba->hibern8_on_idle.state) { + case HIBERN8_EXITED: + break; + case REQ_HIBERN8_ENTER: + if (cancel_delayed_work(>hibern8_on_idle.enter_work)) { +
[PATCH v1 3/9] scsi: ufs: Override auto suspend tunables for ufs
From: Sujit Reddy Thumma Override auto suspend tunables for UFS device LUNs during initialization so as to efficiently manage background operations and the power consumption. Signed-off-by: Sujit Reddy Thumma Signed-off-by: Gilad Broner Signed-off-by: Asutosh Das --- drivers/scsi/ufs/ufshcd.c | 6 ++ 1 file changed, 6 insertions(+) diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c index 77e2b3e..b03f3ea 100644 --- a/drivers/scsi/ufs/ufshcd.c +++ b/drivers/scsi/ufs/ufshcd.c @@ -89,6 +89,9 @@ /* Interrupt aggregation default timeout, unit: 40us */ #define INT_AGGR_DEF_TO0x02 +/* default value of auto suspend is 3 seconds */ +#define UFSHCD_AUTO_SUSPEND_DELAY_MS 3000 /* millisecs */ + #define ufshcd_toggle_vreg(_dev, _vreg, _on) \ ({ \ int _ret; \ @@ -4528,6 +4531,9 @@ static int ufshcd_slave_configure(struct scsi_device *sdev) blk_queue_update_dma_pad(q, PRDT_DATA_BYTE_COUNT_PAD - 1); blk_queue_max_segment_size(q, PRDT_DATA_BYTE_COUNT_MAX); + sdev->autosuspend_delay = UFSHCD_AUTO_SUSPEND_DELAY_MS; + sdev->use_rpm_auto = 1; + return 0; } -- Qualcomm India Private Limited, on behalf of Qualcomm Innovation Center, Inc. Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, a Linux Foundation Collaborative Project.
[PATCH v1 0/9] UFS: Fixes and enhancements
This patch series adds some enhancements and fixes to UFS driver. Gilad Broner (1): scsi: ufs: enable runtime pm only after ufshcd init Subhash Jadavani (6): scsi: ufs: add support to allow non standard behaviours (quirks) scsi: ufs: add option to change default UFS power management level scsi: ufs: add support for hibern8 on idle scsi: ufs: optimize clock, pm_qos, hibern8 handling in queuecommand scsi: ufs: add UFS power collapse support during hibern8 scsi: ufs: enable FASTAUTO mode during low load condition Sujit Reddy Thumma (2): scsi: Allow auto suspend override by low-level driver scsi: ufs: Override auto suspend tunables for ufs .../devicetree/bindings/ufs/ufshcd-pltfrm.txt | 11 + drivers/scsi/scsi_scan.c | 4 + drivers/scsi/scsi_sysfs.c | 3 +- drivers/scsi/sd.c | 2 + drivers/scsi/ufs/ufs-qcom.c| 2 +- drivers/scsi/ufs/ufshcd-pltfrm.c | 25 +- drivers/scsi/ufs/ufshcd.c | 436 ++--- drivers/scsi/ufs/ufshcd.h | 61 ++- include/scsi/scsi_device.h | 3 + include/trace/events/ufs.h | 20 + 10 files changed, 501 insertions(+), 66 deletions(-) -- Qualcomm India Private Limited, on behalf of Qualcomm Innovation Center, Inc. Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, a Linux Foundation Collaborative Project.
[PATCH v1 1/9] scsi: ufs: add support to allow non standard behaviours (quirks)
From: Subhash Jadavani Some implementation of UFS host controller HW might have some non-standard behaviours (quirks) when compared to behaviour specified by UFSHCI specification. This patch adds a quirk for broken hibernate support. Signed-off-by: Subhash Jadavani Signed-off-by: Can Guo Signed-off-by: Asutosh Das --- drivers/scsi/ufs/ufshcd.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/scsi/ufs/ufshcd.h b/drivers/scsi/ufs/ufshcd.h index f51758f..e996a08 100644 --- a/drivers/scsi/ufs/ufshcd.h +++ b/drivers/scsi/ufs/ufshcd.h @@ -613,6 +613,9 @@ struct ufs_hba { * enabled via HCE register. */ #define UFSHCI_QUIRK_BROKEN_HCE 0x400 + + /* HIBERN8 support is broken */ + #define UFSHCD_QUIRK_BROKEN_HIBERN8 0x800 unsigned int quirks;/* Deviations from standard UFSHCI spec. */ /* Device deviations from standard UFS device spec. */ -- Qualcomm India Private Limited, on behalf of Qualcomm Innovation Center, Inc. Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, a Linux Foundation Collaborative Project.
[PATCH v1 7/9] scsi: ufs: add UFS power collapse support during hibern8
From: Subhash Jadavani UFS host controller hardware may allow the host controller to be power collapsed when UFS link is hibern8 state, this change allows the UFS host controller to be power collapsed during hibern8. Signed-off-by: Subhash Jadavani Signed-off-by: Venkat Gopalakrishnan Signed-off-by: Can Guo Signed-off-by: Asutosh Das --- drivers/scsi/ufs/ufshcd.c | 8 ++-- drivers/scsi/ufs/ufshcd.h | 13 - 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c index 40d9c35..50588cf 100644 --- a/drivers/scsi/ufs/ufshcd.c +++ b/drivers/scsi/ufs/ufshcd.c @@ -7673,13 +7673,17 @@ static int ufshcd_vreg_set_hpm(struct ufs_hba *hba) static void ufshcd_hba_vreg_set_lpm(struct ufs_hba *hba) { - if (ufshcd_is_link_off(hba)) + if (ufshcd_is_link_off(hba) || + (ufshcd_is_link_hibern8(hba) +&& ufshcd_is_power_collapse_during_hibern8_allowed(hba))) ufshcd_setup_hba_vreg(hba, false); } static void ufshcd_hba_vreg_set_hpm(struct ufs_hba *hba) { - if (ufshcd_is_link_off(hba)) + if (ufshcd_is_link_off(hba) || + (ufshcd_is_link_hibern8(hba) +&& ufshcd_is_power_collapse_during_hibern8_allowed(hba))) ufshcd_setup_hba_vreg(hba, true); } diff --git a/drivers/scsi/ufs/ufshcd.h b/drivers/scsi/ufs/ufshcd.h index f79a639..8c5f987 100644 --- a/drivers/scsi/ufs/ufshcd.h +++ b/drivers/scsi/ufs/ufshcd.h @@ -728,7 +728,12 @@ struct ufs_hba { * to do background operation when it's active but it might degrade * the performance of ongoing read/write operations. */ -#define UFSHCD_CAP_KEEP_AUTO_BKOPS_ENABLED_EXCEPT_SUSPEND (1 << 5) +#define UFSHCD_CAP_KEEP_AUTO_BKOPS_ENABLED_EXCEPT_SUSPEND (1 << 6) + /* +* If host controller hardware can be power collapsed when UFS link is +* in hibern8 then enable this cap. +*/ +#define UFSHCD_CAP_POWER_COLLAPSE_DURING_HIBERN8 (1 << 7) struct devfreq *devfreq; struct ufs_clk_scaling clk_scaling; @@ -764,6 +769,12 @@ static inline bool ufshcd_is_hibern8_on_idle_allowed(struct ufs_hba *hba) return hba->caps & UFSHCD_CAP_HIBERN8_ENTER_ON_IDLE; } +static inline bool ufshcd_is_power_collapse_during_hibern8_allowed( + struct ufs_hba *hba) +{ + return !!(hba->caps & UFSHCD_CAP_POWER_COLLAPSE_DURING_HIBERN8); +} + static inline bool ufshcd_is_intr_aggr_allowed(struct ufs_hba *hba) { /* DWC UFS Core has the Interrupt aggregation feature but is not detectable*/ -- Qualcomm India Private Limited, on behalf of Qualcomm Innovation Center, Inc. Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, a Linux Foundation Collaborative Project.
[PATCH V5 0/2] Add ufs provisioning support in driver
This patch adds Configfs support to provision ufs device at runtime. This feature can be primarily useful in factory or assembly line as some devices may be required to be configured multiple times during initial system development phase. Configuration Descriptors can be written multiple times until bConfigDescrLock attribute is zero. Configuration descriptor buffer consists of Device and Unit descriptor configurable parameters which are parsed from vendor specific provisioning file and then passed via configfs node at runtime to provision ufs device. Chages since V4: 1)scsi: ufs: set the device reference clock setting Used "assigned-clock-rates" DT property to pass required ref clk frequency. 2)scsi: ufs: Add configfs support for ufs provisioning Combined previous patch(2) and patch(3) into single patch which adds configfs provisioning support in driver. Removed extra sw provisioning related fields (like lun_to_grow, commit) and its related code. Updated Documentation to match configuration descriptor buffer parameters to be passed as per specs. Removed global ufs_hba ptr added in ufs-configfs file and instead passed *hba in ufs configfs init()/store()/show() api's. This is to support embedded as well as removable ufs card provisioning via configfs. Changes since V3: 1)scsi: ufs: set the device reference clock setting Updated logic to retain default ref_clk frequency setting programmed in device in case if invalid value is passed via devicetree setting. Replaced of_property_read_u32() with device_property_read_u32(). Removed invalid checks. 2)scsi: ufs: Add ufs provisioning support Added pm_runtime_get/put_sync and scsi_block/unblock_request in runtime provisioning for stable operation. 3)scsi: ufs: Add configfs support for ufs provisioning Updated Documentation with missing buffer entries required for runtime provisioning. Used config option to support conditional compilation for configfs api's. Changes since V2: Added configfs support for ufs provisioning and removed sysfs support. Changes since V1: Added device tree entry to parse reference clock frequency instead of hardcoding 19.2 MHz, as it can vary for different vendors. Also removed setting ref_clk again during runtime provisioning as it will be already set during probe. Used get_unaligned_be*/put_unaligned_be* where applicable. Changes since RFC: Added check to avoid ufs runtime provisioning if Configuration decriptor lock attribute is set to one. Instead of parsing ref_clk frequency via device tree, used correct enum ref_clk_freq value(19.2 Mhz for proviosioning). Added config_descriptor sysfs entry to provision ufs and also updated documentation for its correct usage. Added more protection against bad data handling in sysfs code. Sayali Lokhande (1): scsi: ufs: Add configfs support for ufs provisioning Subhash Jadavani (1): scsi: ufs: set the device reference clock setting Documentation/ABI/testing/configfs-driver-ufs | 18 +++ .../devicetree/bindings/ufs/ufshcd-pltfrm.txt | 7 + drivers/scsi/ufs/Makefile | 1 + drivers/scsi/ufs/ufs-configfs.c| 172 + drivers/scsi/ufs/ufs.h | 9 ++ drivers/scsi/ufs/ufshcd-pltfrm.c | 2 + drivers/scsi/ufs/ufshcd.c | 64 drivers/scsi/ufs/ufshcd.h | 21 +++ 8 files changed, 294 insertions(+) create mode 100644 Documentation/ABI/testing/configfs-driver-ufs create mode 100644 drivers/scsi/ufs/ufs-configfs.c -- The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, a Linux Foundation Collaborative Project