diff options
| author | Saravana Kannan <skannan@codeaurora.org> | 2015-07-30 17:34:01 -0700 |
|---|---|---|
| committer | David Keitel <dkeitel@codeaurora.org> | 2016-03-23 20:04:32 -0700 |
| commit | 3dfc05409f19c2f77fd0930518e71372a3795104 (patch) | |
| tree | 8c0a13bf008555a1784e3d624eb1110675a8ed3a /drivers/devfreq | |
| parent | 1610191072812d956ea1f45b5bfed16033f5a466 (diff) | |
PM / devfreq: bw_hwmon: Take at least one sample per decision window
Due to the way the short samples are triggered, when the traffic is very
low, we could have a decision window where no sample is taken. Fix this by
forcing a sample at the end of every decision window as long as that is the
first sample for that decision window or the sample window won't be smaller
than the sample_ms tunable.
Change-Id: Ia33b59fbff9ff4058c06e24208d1e037d6e9eda9
Signed-off-by: Saravana Kannan <skannan@codeaurora.org>
Diffstat (limited to 'drivers/devfreq')
| -rw-r--r-- | drivers/devfreq/governor_bw_hwmon.c | 28 |
1 files changed, 24 insertions, 4 deletions
diff --git a/drivers/devfreq/governor_bw_hwmon.c b/drivers/devfreq/governor_bw_hwmon.c index a53334489348..9f153fdd13dd 100644 --- a/drivers/devfreq/governor_bw_hwmon.c +++ b/drivers/devfreq/governor_bw_hwmon.c @@ -73,6 +73,7 @@ struct hwmon_node { unsigned int down_cnt; ktime_t prev_ts; ktime_t hist_max_ts; + bool sampled; bool mon_started; struct list_head list; void *orig_data; @@ -190,19 +191,18 @@ static unsigned int mbps_to_bytes(unsigned long mbps, unsigned int ms) return mbps; } -int bw_hwmon_sample_end(struct bw_hwmon *hwmon) +static int __bw_hwmon_sample_end(struct bw_hwmon *hwmon) { struct devfreq *df; struct hwmon_node *node; ktime_t ts; - unsigned long bytes, mbps, flags; + unsigned long bytes, mbps; unsigned int us; int wake = 0; df = hwmon->df; node = df->data; - spin_lock_irqsave(&irq_lock, flags); ts = ktime_get(); us = ktime_to_us(ktime_sub(ts, node->prev_ts)); @@ -230,7 +230,7 @@ int bw_hwmon_sample_end(struct bw_hwmon *hwmon) node->prev_ts = ts; node->wake = wake; - spin_unlock_irqrestore(&irq_lock, flags); + node->sampled = true; trace_bw_hwmon_meas(dev_name(df->dev.parent), mbps, @@ -243,6 +243,18 @@ int bw_hwmon_sample_end(struct bw_hwmon *hwmon) return wake; } +int bw_hwmon_sample_end(struct bw_hwmon *hwmon) +{ + unsigned long flags; + int wake; + + spin_lock_irqsave(&irq_lock, flags); + wake = __bw_hwmon_sample_end(hwmon); + spin_unlock_irqrestore(&irq_lock, flags); + + return wake; +} + unsigned long to_mbps_zone(struct hwmon_node *node, unsigned long mbps) { int i; @@ -264,9 +276,17 @@ static unsigned long get_bw_and_set_irq(struct hwmon_node *node, unsigned long hist_lo_tol, hyst_lo_tol; struct bw_hwmon *hw = node->hw; unsigned int new_bw, io_percent; + ktime_t ts; + unsigned int ms; spin_lock_irqsave(&irq_lock, flags); + ts = ktime_get(); + ms = ktime_to_ms(ktime_sub(ts, node->prev_ts)); + if (!node->sampled || ms >= node->sample_ms) + __bw_hwmon_sample_end(node->hw); + node->sampled = false; + req_mbps = meas_mbps = node->max_mbps; node->max_mbps = 0; |
