summaryrefslogtreecommitdiff
path: root/drivers/devfreq
diff options
context:
space:
mode:
authorArto Merilainen <amerilainen@nvidia.com>2013-09-12 11:02:04 +0300
committerDan Willemsen <dwillemsen@nvidia.com>2013-09-16 17:42:36 -0700
commitd5003fb2bbe7d352de0690a2adc2e69f6c41201e (patch)
tree19c9f1a7316c9d3fe879b9caaa4675e51a1373de /drivers/devfreq
parentdc7d35b32856d9dfcc56a08c6d104b36d5a008f1 (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.c38
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, " ");