diff options
| author | Subhash Jadavani <subhashj@codeaurora.org> | 2014-10-08 19:08:10 -0700 |
|---|---|---|
| committer | David Keitel <dkeitel@codeaurora.org> | 2016-03-22 10:57:36 -0700 |
| commit | ab18ee44ce262018da8bf4c18b8e642e152dac89 (patch) | |
| tree | 6fca7665bffbd26b4cee103ce1a2e41692c770df /include/linux | |
| parent | cfd27bd4b766d785ce70cf4b1e1ace84c7e3c7a9 (diff) | |
scsi: ufs: add support for hibern8 on idle
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.
Change-Id: I5a31f18fc21015d4a68236da9fd94f3f016e1d44
Signed-off-by: Subhash Jadavani <subhashj@codeaurora.org>
[subhashj@codeaurora.org: resolved trivial merge conflicts]
Signed-off-by: Subhash Jadavani <subhashj@codeaurora.org>
Diffstat (limited to 'include/linux')
| -rw-r--r-- | include/linux/scsi/ufs/ufshcd.h | 38 |
1 files changed, 38 insertions, 0 deletions
diff --git a/include/linux/scsi/ufs/ufshcd.h b/include/linux/scsi/ufs/ufshcd.h index 7109f59f9e80..a80130c959eb 100644 --- a/include/linux/scsi/ufs/ufshcd.h +++ b/include/linux/scsi/ufs/ufshcd.h @@ -343,6 +343,35 @@ struct ufs_clk_gating { int active_reqs; }; +/* Hibern8 state */ +enum ufshcd_hibern8_on_idle_state { + HIBERN8_ENTERED, + HIBERN8_EXITED, + REQ_HIBERN8_ENTER, + REQ_HIBERN8_EXIT, +}; + +/** + * struct ufs_hibern8_on_idle - UFS Hibern8 on idle related data + * @enter_work: worker to put UFS link in hibern8 after some delay as + * specified in delay_ms + * @exit_work: worker to bring UFS link out of hibern8 + * @state: the current hibern8 state + * @delay_ms: hibern8 enter delay in ms + * @is_suspended: hibern8 enter is suspended when set to 1 which can be used + * during suspend/resume + * @active_reqs: number of requests that are pending and should be waited for + * completion before scheduling delayed "enter_work". + */ +struct ufs_hibern8_on_idle { + struct delayed_work enter_work; + struct work_struct exit_work; + enum ufshcd_hibern8_on_idle_state state; + unsigned long delay_ms; + bool is_suspended; + int active_reqs; +}; + struct ufs_clk_scaling { ktime_t busy_start_t; bool is_busy_started; @@ -450,6 +479,7 @@ enum ts_types { * @clk_list_head: UFS host controller clocks list node head * @pwr_info: holds current power mode * @max_pwr_info: keeps the device max valid pwm + * @hibern8_on_idle: UFS Hibern8 on idle related data */ struct ufs_hba { void __iomem *mmio_base; @@ -591,6 +621,8 @@ struct ufs_hba { struct ufs_pwr_mode_info max_pwr_info; struct ufs_clk_gating clk_gating; + struct ufs_hibern8_on_idle hibern8_on_idle; + /* Control to enable/disable host capabilities */ u32 caps; /* Allow dynamic clk gating */ @@ -607,6 +639,8 @@ struct ufs_hba { * CAUTION: Enabling this might reduce overall UFS throughput. */ #define UFSHCD_CAP_INTR_AGGR (1 << 4) + /* Allow standalone Hibern8 enter on idle */ +#define UFSHCD_CAP_HIBERN8_ENTER_ON_IDLE (1 << 5) struct devfreq *devfreq; struct ufs_clk_scaling clk_scaling; @@ -630,6 +664,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_hibern8_on_idle_allowed(struct ufs_hba *hba) +{ + return hba->caps & UFSHCD_CAP_HIBERN8_ENTER_ON_IDLE; +} static inline bool ufshcd_is_intr_aggr_allowed(struct ufs_hba *hba) { |
