diff options
author | Arto Merilainen <amerilainen@nvidia.com> | 2013-09-12 11:02:04 +0300 |
---|---|---|
committer | Dan Willemsen <dwillemsen@nvidia.com> | 2013-09-16 17:42:36 -0700 |
commit | d5003fb2bbe7d352de0690a2adc2e69f6c41201e (patch) | |
tree | 19c9f1a7316c9d3fe879b9caaa4675e51a1373de /drivers/devfreq | |
parent | dc7d35b32856d9dfcc56a08c6d104b36d5a008f1 (diff) |
devfreq: Round frequencies in transition stats
Transition statistics required that the new frequency was *exactly*
as it was in the table. However, we may unexpectedly select a
frequency that is not in the table (i.e. thermal limit forces us to
select a bit lower frequency, the original DVFS table does not hold
for the current PLL for some reason, etc.)
This patch modifies transition table to select the best candidate
from the frequency table.
Bug 1366760
Change-Id: I4329f77e733f5f1d39b9d9c3aebe3681a0760d90
Signed-off-by: Arto Merilainen <amerilainen@nvidia.com>
Reviewed-on: http://git-master/r/273596
Reviewed-by: Automatic_Commit_Validation_User
GVS: Gerrit_Virtual_Submit
Reviewed-by: Terje Bergstrom <tbergstrom@nvidia.com>
Diffstat (limited to 'drivers/devfreq')
-rw-r--r-- | drivers/devfreq/devfreq.c | 38 |
1 files changed, 32 insertions, 6 deletions
diff --git a/drivers/devfreq/devfreq.c b/drivers/devfreq/devfreq.c index 73f363234253..2ff0106e4fb3 100644 --- a/drivers/devfreq/devfreq.c +++ b/drivers/devfreq/devfreq.c @@ -78,11 +78,27 @@ static int devfreq_get_freq_level(struct devfreq *devfreq, unsigned long freq) { int lev; - for (lev = 0; lev < devfreq->profile->max_state; lev++) - if (freq == devfreq->profile->freq_table[lev]) - return lev; + if (!devfreq->profile->max_state) + return -EINVAL; + + for (lev = 0; lev < devfreq->profile->max_state; lev++) { + if (devfreq->profile->freq_table[lev] >= freq) { + /* below minimum frequency? just return zero level */ + if (lev == 0) + return 0; + + /* select high freq if the freq is closer to that */ + if ((devfreq->profile->freq_table[lev] - freq) < + (freq - devfreq->profile->freq_table[lev - 1])) + return lev; + + /* ..otherwise return the low freq */ + return lev - 1; + } + } - return -EINVAL; + /* above max freq */ + return devfreq->profile->max_state - 1; } /** @@ -920,11 +936,22 @@ static ssize_t show_trans_table(struct device *dev, struct device_attribute *att ssize_t len; int i, j, err; unsigned int max_state = devfreq->profile->max_state; + int prev_freq_level; + unsigned long prev_freq; err = devfreq_update_status(devfreq, devfreq->previous_freq); if (err) return 0; + /* round the current frequency */ + prev_freq_level = devfreq_get_freq_level(devfreq, + devfreq->previous_freq); + + if (prev_freq_level < 0) + prev_freq = devfreq->previous_freq; + else + prev_freq = devfreq->profile->freq_table[prev_freq_level]; + len = sprintf(buf, " From : To\n"); len += sprintf(buf + len, " :"); for (i = 0; i < max_state; i++) @@ -934,8 +961,7 @@ static ssize_t show_trans_table(struct device *dev, struct device_attribute *att len += sprintf(buf + len, " time(ms)\n"); for (i = 0; i < max_state; i++) { - if (devfreq->profile->freq_table[i] - == devfreq->previous_freq) { + if (devfreq->profile->freq_table[i] == prev_freq) { len += sprintf(buf + len, "*"); } else { len += sprintf(buf + len, " "); |