summaryrefslogtreecommitdiff
path: root/drivers/devfreq
diff options
context:
space:
mode:
authorSaravana Kannan <skannan@codeaurora.org>2015-07-30 17:34:01 -0700
committerDavid Keitel <dkeitel@codeaurora.org>2016-03-23 20:04:32 -0700
commit3dfc05409f19c2f77fd0930518e71372a3795104 (patch)
tree8c0a13bf008555a1784e3d624eb1110675a8ed3a /drivers/devfreq
parent1610191072812d956ea1f45b5bfed16033f5a466 (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.c28
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;