diff options
author | Chanwoo Choi <cw00.choi@samsung.com> | 2017-10-22 21:32:08 -0400 |
---|---|---|
committer | MyungJoo Ham <myungjoo.ham@samsung.com> | 2017-10-26 04:08:40 -0400 |
commit | f1d981eaecf8ace68ec1d15bf05f28a4887ea6fb (patch) | |
tree | 0304a9e1ca1740a05b0bc36a06de56105a6950fb /drivers/devfreq/devfreq.c | |
parent | 1051e2c304b5cf17d4117505985f8128c5c64fd9 (diff) |
PM / devfreq: Use the available min/max frequency
The commit a76caf55e5b35 ("thermal: Add devfreq cooling") is able
to disable OPP as a cooling device. In result, both update_devfreq()
and {min|max}_freq_show() have to consider the 'opp->available'
status of each OPP.
So, this patch adds the 'scaling_{min|max}_freq' to struct devfreq
in order to indicate the available mininum and maximum frequency
by adjusting OPP interface such as dev_pm_opp_{disable|enable}().
The 'scaling_{min|max}_freq' are used for on both update_devfreq()
and {min|max}_freq_show().
Signed-off-by: Chanwoo Choi <cw00.choi@samsung.com>
Signed-off-by: MyungJoo Ham <myungjoo.ham@samsung.com>
Diffstat (limited to 'drivers/devfreq/devfreq.c')
-rw-r--r-- | drivers/devfreq/devfreq.c | 40 |
1 files changed, 32 insertions, 8 deletions
diff --git a/drivers/devfreq/devfreq.c b/drivers/devfreq/devfreq.c index b6ba24e5db0d..ee3e7cee30b6 100644 --- a/drivers/devfreq/devfreq.c +++ b/drivers/devfreq/devfreq.c | |||
@@ -28,6 +28,9 @@ | |||
28 | #include <linux/of.h> | 28 | #include <linux/of.h> |
29 | #include "governor.h" | 29 | #include "governor.h" |
30 | 30 | ||
31 | #define MAX(a,b) ((a > b) ? a : b) | ||
32 | #define MIN(a,b) ((a < b) ? a : b) | ||
33 | |||
31 | static struct class *devfreq_class; | 34 | static struct class *devfreq_class; |
32 | 35 | ||
33 | /* | 36 | /* |
@@ -255,7 +258,7 @@ static int devfreq_notify_transition(struct devfreq *devfreq, | |||
255 | int update_devfreq(struct devfreq *devfreq) | 258 | int update_devfreq(struct devfreq *devfreq) |
256 | { | 259 | { |
257 | struct devfreq_freqs freqs; | 260 | struct devfreq_freqs freqs; |
258 | unsigned long freq, cur_freq; | 261 | unsigned long freq, cur_freq, min_freq, max_freq; |
259 | int err = 0; | 262 | int err = 0; |
260 | u32 flags = 0; | 263 | u32 flags = 0; |
261 | 264 | ||
@@ -273,19 +276,21 @@ int update_devfreq(struct devfreq *devfreq) | |||
273 | return err; | 276 | return err; |
274 | 277 | ||
275 | /* | 278 | /* |
276 | * Adjust the frequency with user freq and QoS. | 279 | * Adjust the frequency with user freq, QoS and available freq. |
277 | * | 280 | * |
278 | * List from the highest priority | 281 | * List from the highest priority |
279 | * max_freq | 282 | * max_freq |
280 | * min_freq | 283 | * min_freq |
281 | */ | 284 | */ |
285 | max_freq = MIN(devfreq->scaling_max_freq, devfreq->max_freq); | ||
286 | min_freq = MAX(devfreq->scaling_min_freq, devfreq->min_freq); | ||
282 | 287 | ||
283 | if (devfreq->min_freq && freq < devfreq->min_freq) { | 288 | if (min_freq && freq < min_freq) { |
284 | freq = devfreq->min_freq; | 289 | freq = min_freq; |
285 | flags &= ~DEVFREQ_FLAG_LEAST_UPPER_BOUND; /* Use GLB */ | 290 | flags &= ~DEVFREQ_FLAG_LEAST_UPPER_BOUND; /* Use GLB */ |
286 | } | 291 | } |
287 | if (devfreq->max_freq && freq > devfreq->max_freq) { | 292 | if (max_freq && freq > max_freq) { |
288 | freq = devfreq->max_freq; | 293 | freq = max_freq; |
289 | flags |= DEVFREQ_FLAG_LEAST_UPPER_BOUND; /* Use LUB */ | 294 | flags |= DEVFREQ_FLAG_LEAST_UPPER_BOUND; /* Use LUB */ |
290 | } | 295 | } |
291 | 296 | ||
@@ -494,6 +499,19 @@ static int devfreq_notifier_call(struct notifier_block *nb, unsigned long type, | |||
494 | int ret; | 499 | int ret; |
495 | 500 | ||
496 | mutex_lock(&devfreq->lock); | 501 | mutex_lock(&devfreq->lock); |
502 | |||
503 | devfreq->scaling_min_freq = find_available_min_freq(devfreq); | ||
504 | if (!devfreq->scaling_min_freq) { | ||
505 | mutex_unlock(&devfreq->lock); | ||
506 | return -EINVAL; | ||
507 | } | ||
508 | |||
509 | devfreq->scaling_max_freq = find_available_max_freq(devfreq); | ||
510 | if (!devfreq->scaling_max_freq) { | ||
511 | mutex_unlock(&devfreq->lock); | ||
512 | return -EINVAL; | ||
513 | } | ||
514 | |||
497 | ret = update_devfreq(devfreq); | 515 | ret = update_devfreq(devfreq); |
498 | mutex_unlock(&devfreq->lock); | 516 | mutex_unlock(&devfreq->lock); |
499 | 517 | ||
@@ -593,6 +611,7 @@ struct devfreq *devfreq_add_device(struct device *dev, | |||
593 | err = -EINVAL; | 611 | err = -EINVAL; |
594 | goto err_dev; | 612 | goto err_dev; |
595 | } | 613 | } |
614 | devfreq->scaling_min_freq = devfreq->min_freq; | ||
596 | 615 | ||
597 | devfreq->max_freq = find_available_max_freq(devfreq); | 616 | devfreq->max_freq = find_available_max_freq(devfreq); |
598 | if (!devfreq->max_freq) { | 617 | if (!devfreq->max_freq) { |
@@ -600,6 +619,7 @@ struct devfreq *devfreq_add_device(struct device *dev, | |||
600 | err = -EINVAL; | 619 | err = -EINVAL; |
601 | goto err_dev; | 620 | goto err_dev; |
602 | } | 621 | } |
622 | devfreq->scaling_max_freq = devfreq->max_freq; | ||
603 | 623 | ||
604 | dev_set_name(&devfreq->dev, "devfreq%d", | 624 | dev_set_name(&devfreq->dev, "devfreq%d", |
605 | atomic_inc_return(&devfreq_no)); | 625 | atomic_inc_return(&devfreq_no)); |
@@ -1127,7 +1147,9 @@ unlock: | |||
1127 | static ssize_t min_freq_show(struct device *dev, struct device_attribute *attr, | 1147 | static ssize_t min_freq_show(struct device *dev, struct device_attribute *attr, |
1128 | char *buf) | 1148 | char *buf) |
1129 | { | 1149 | { |
1130 | return sprintf(buf, "%lu\n", to_devfreq(dev)->min_freq); | 1150 | struct devfreq *df = to_devfreq(dev); |
1151 | |||
1152 | return sprintf(buf, "%lu\n", MAX(df->scaling_min_freq, df->min_freq)); | ||
1131 | } | 1153 | } |
1132 | 1154 | ||
1133 | static ssize_t max_freq_store(struct device *dev, struct device_attribute *attr, | 1155 | static ssize_t max_freq_store(struct device *dev, struct device_attribute *attr, |
@@ -1161,7 +1183,9 @@ static DEVICE_ATTR_RW(min_freq); | |||
1161 | static ssize_t max_freq_show(struct device *dev, struct device_attribute *attr, | 1183 | static ssize_t max_freq_show(struct device *dev, struct device_attribute *attr, |
1162 | char *buf) | 1184 | char *buf) |
1163 | { | 1185 | { |
1164 | return sprintf(buf, "%lu\n", to_devfreq(dev)->max_freq); | 1186 | struct devfreq *df = to_devfreq(dev); |
1187 | |||
1188 | return sprintf(buf, "%lu\n", MIN(df->scaling_max_freq, df->max_freq)); | ||
1165 | } | 1189 | } |
1166 | static DEVICE_ATTR_RW(max_freq); | 1190 | static DEVICE_ATTR_RW(max_freq); |
1167 | 1191 | ||