diff options
Diffstat (limited to 'drivers/devfreq/devfreq.c')
-rw-r--r-- | drivers/devfreq/devfreq.c | 47 |
1 files changed, 39 insertions, 8 deletions
diff --git a/drivers/devfreq/devfreq.c b/drivers/devfreq/devfreq.c index ca848cc6a8fd..bc1c5f6dd4bd 100644 --- a/drivers/devfreq/devfreq.c +++ b/drivers/devfreq/devfreq.c @@ -69,11 +69,34 @@ static struct devfreq *find_device_devfreq(struct device *dev) } /** + * devfreq_set_freq_limits() - Set min and max frequency from freq_table + * @devfreq: the devfreq instance + */ +static void devfreq_set_freq_limits(struct devfreq *devfreq) +{ + int idx; + unsigned long min = ~0, max = 0; + + if (!devfreq->profile->freq_table) + return; + + for (idx = 0; idx < devfreq->profile->max_state; idx++) { + if (min > devfreq->profile->freq_table[idx]) + min = devfreq->profile->freq_table[idx]; + if (max < devfreq->profile->freq_table[idx]) + max = devfreq->profile->freq_table[idx]; + } + + devfreq->min_freq = min; + devfreq->max_freq = max; +} + +/** * devfreq_get_freq_level() - Lookup freq_table for the frequency * @devfreq: the devfreq instance * @freq: the target frequency */ -static int devfreq_get_freq_level(struct devfreq *devfreq, unsigned long freq) +int devfreq_get_freq_level(struct devfreq *devfreq, unsigned long freq) { int lev; @@ -83,6 +106,7 @@ static int devfreq_get_freq_level(struct devfreq *devfreq, unsigned long freq) return -EINVAL; } +EXPORT_SYMBOL(devfreq_get_freq_level); /** * devfreq_update_status() - Update statistics of devfreq behavior @@ -172,7 +196,7 @@ int update_devfreq(struct devfreq *devfreq) return -EINVAL; /* Reevaluate the proper frequency */ - err = devfreq->governor->get_target_freq(devfreq, &freq); + err = devfreq->governor->get_target_freq(devfreq, &freq, &flags); if (err) return err; @@ -486,6 +510,7 @@ struct devfreq *devfreq_add_device(struct device *dev, devfreq->profile->max_state, GFP_KERNEL); devfreq->last_stat_updated = jiffies; + devfreq_set_freq_limits(devfreq); dev_set_name(&devfreq->dev, "%s", dev_name(dev)); err = device_register(&devfreq->dev); @@ -536,7 +561,6 @@ int devfreq_remove_device(struct devfreq *devfreq) return -EINVAL; device_unregister(&devfreq->dev); - put_device(&devfreq->dev); return 0; } @@ -969,19 +993,26 @@ static ssize_t available_frequencies_show(struct device *d, struct devfreq *df = to_devfreq(d); struct device *dev = df->dev.parent; struct dev_pm_opp *opp; + unsigned int i = 0, max_state = df->profile->max_state; + bool use_opp; ssize_t count = 0; unsigned long freq = 0; rcu_read_lock(); - do { - opp = dev_pm_opp_find_freq_ceil(dev, &freq); - if (IS_ERR(opp)) - break; + use_opp = dev_pm_opp_get_opp_count(dev) > 0; + while (use_opp || (!use_opp && i < max_state)) { + if (use_opp) { + opp = dev_pm_opp_find_freq_ceil(dev, &freq); + if (IS_ERR(opp)) + break; + } else { + freq = df->profile->freq_table[i++]; + } count += scnprintf(&buf[count], (PAGE_SIZE - count - 2), "%lu ", freq); freq++; - } while (1); + } rcu_read_unlock(); /* Truncate the trailing space */ |