diff options
| author | Yadwinder Singh Brar <yadi.brar@samsung.com> | 2014-11-07 08:42:29 -0500 |
|---|---|---|
| committer | Eduardo Valentin <edubezval@gmail.com> | 2014-11-20 17:17:11 -0500 |
| commit | 2dcd851fe4b4fe60c2f8520bf7668d7e9b2dd76b (patch) | |
| tree | e420c0d47716705eb3c76663f524938918fbb2d3 /drivers | |
| parent | fc14f9c1272f62c3e8d01300f52467c0d9af50f9 (diff) | |
thermal: cpu_cooling: Update always cpufreq policy with thermal constraints
Existing code updates cupfreq policy only while executing
cpufreq_apply_cooling() function (i.e. when notify_device != NOTIFY_INVALID).
It doesn't apply constraints when cpufreq policy update happens from any other
place but it should update the cpufreq policy with thermal constraints every
time when there is a cpufreq policy update, to keep state of
cpufreq_cooling_device and max_feq of cpufreq policy in sync. For instance
while resuming cpufreq updates cpufreq_policy and it restores default
policy->usr_policy values irrespective of cooling device's cpufreq_state since
notification gets missed because (notify_device == NOTIFY_INVALID).
Another problem, is that userspace is able to change max_freq irrespective of
cooling device's state, as notification gets missed.
This patch modifies code to maintain a global cpufreq_dev_list and applies
constraints of all matching cooling devices for policy's cpu when there is any
policy update(ends up applying the lowest max_freq among the matching cpu
cooling devices).
This patch also removes redundant check (max_freq > policy->user_policy.max),
as cpufreq framework takes care of user_policy constraints already where ever
required, otherwise its causing an issue while increasing max_freq in normal
scenerio as it restores max_freq with policy->user_policy.max which is old
(smaller) value.
Signed-off-by: Yadwinder Singh Brar <yadi.brar@samsung.com>
Signed-off-by: Eduardo Valentin <edubezval@gmail.com>
Diffstat (limited to 'drivers')
| -rw-r--r-- | drivers/thermal/cpu_cooling.c | 37 |
1 files changed, 21 insertions, 16 deletions
diff --git a/drivers/thermal/cpu_cooling.c b/drivers/thermal/cpu_cooling.c index 1ab0018271c5..ad09e51ffae4 100644 --- a/drivers/thermal/cpu_cooling.c +++ b/drivers/thermal/cpu_cooling.c | |||
| @@ -50,15 +50,14 @@ struct cpufreq_cooling_device { | |||
| 50 | unsigned int cpufreq_state; | 50 | unsigned int cpufreq_state; |
| 51 | unsigned int cpufreq_val; | 51 | unsigned int cpufreq_val; |
| 52 | struct cpumask allowed_cpus; | 52 | struct cpumask allowed_cpus; |
| 53 | struct list_head node; | ||
| 53 | }; | 54 | }; |
| 54 | static DEFINE_IDR(cpufreq_idr); | 55 | static DEFINE_IDR(cpufreq_idr); |
| 55 | static DEFINE_MUTEX(cooling_cpufreq_lock); | 56 | static DEFINE_MUTEX(cooling_cpufreq_lock); |
| 56 | 57 | ||
| 57 | static unsigned int cpufreq_dev_count; | 58 | static unsigned int cpufreq_dev_count; |
| 58 | 59 | ||
| 59 | /* notify_table passes value to the CPUFREQ_ADJUST callback function. */ | 60 | static LIST_HEAD(cpufreq_dev_list); |
| 60 | #define NOTIFY_INVALID NULL | ||
| 61 | static struct cpufreq_cooling_device *notify_device; | ||
| 62 | 61 | ||
| 63 | /** | 62 | /** |
| 64 | * get_idr - function to get a unique id. | 63 | * get_idr - function to get a unique id. |
| @@ -287,15 +286,12 @@ static int cpufreq_apply_cooling(struct cpufreq_cooling_device *cpufreq_device, | |||
| 287 | 286 | ||
| 288 | cpufreq_device->cpufreq_state = cooling_state; | 287 | cpufreq_device->cpufreq_state = cooling_state; |
| 289 | cpufreq_device->cpufreq_val = clip_freq; | 288 | cpufreq_device->cpufreq_val = clip_freq; |
| 290 | notify_device = cpufreq_device; | ||
| 291 | 289 | ||
| 292 | for_each_cpu(cpuid, mask) { | 290 | for_each_cpu(cpuid, mask) { |
| 293 | if (is_cpufreq_valid(cpuid)) | 291 | if (is_cpufreq_valid(cpuid)) |
| 294 | cpufreq_update_policy(cpuid); | 292 | cpufreq_update_policy(cpuid); |
| 295 | } | 293 | } |
| 296 | 294 | ||
| 297 | notify_device = NOTIFY_INVALID; | ||
| 298 | |||
| 299 | return 0; | 295 | return 0; |
| 300 | } | 296 | } |
| 301 | 297 | ||
| @@ -316,21 +312,28 @@ static int cpufreq_thermal_notifier(struct notifier_block *nb, | |||
| 316 | { | 312 | { |
| 317 | struct cpufreq_policy *policy = data; | 313 | struct cpufreq_policy *policy = data; |
| 318 | unsigned long max_freq = 0; | 314 | unsigned long max_freq = 0; |
| 315 | struct cpufreq_cooling_device *cpufreq_dev; | ||
| 319 | 316 | ||
| 320 | if (event != CPUFREQ_ADJUST || notify_device == NOTIFY_INVALID) | 317 | if (event != CPUFREQ_ADJUST) |
| 321 | return 0; | 318 | return 0; |
| 322 | 319 | ||
| 323 | if (cpumask_test_cpu(policy->cpu, ¬ify_device->allowed_cpus)) | 320 | mutex_lock(&cooling_cpufreq_lock); |
| 324 | max_freq = notify_device->cpufreq_val; | 321 | list_for_each_entry(cpufreq_dev, &cpufreq_dev_list, node) { |
| 325 | else | 322 | if (!cpumask_test_cpu(policy->cpu, |
| 326 | return 0; | 323 | &cpufreq_dev->allowed_cpus)) |
| 324 | continue; | ||
| 325 | |||
| 326 | if (!cpufreq_dev->cpufreq_val) | ||
| 327 | cpufreq_dev->cpufreq_val = get_cpu_frequency( | ||
| 328 | cpumask_any(&cpufreq_dev->allowed_cpus), | ||
| 329 | cpufreq_dev->cpufreq_state); | ||
| 327 | 330 | ||
| 328 | /* Never exceed user_policy.max */ | 331 | max_freq = cpufreq_dev->cpufreq_val; |
| 329 | if (max_freq > policy->user_policy.max) | ||
| 330 | max_freq = policy->user_policy.max; | ||
| 331 | 332 | ||
| 332 | if (policy->max != max_freq) | 333 | if (policy->max != max_freq) |
| 333 | cpufreq_verify_within_limits(policy, 0, max_freq); | 334 | cpufreq_verify_within_limits(policy, 0, max_freq); |
| 335 | } | ||
| 336 | mutex_unlock(&cooling_cpufreq_lock); | ||
| 334 | 337 | ||
| 335 | return 0; | 338 | return 0; |
| 336 | } | 339 | } |
| @@ -486,6 +489,7 @@ __cpufreq_cooling_register(struct device_node *np, | |||
| 486 | cpufreq_register_notifier(&thermal_cpufreq_notifier_block, | 489 | cpufreq_register_notifier(&thermal_cpufreq_notifier_block, |
| 487 | CPUFREQ_POLICY_NOTIFIER); | 490 | CPUFREQ_POLICY_NOTIFIER); |
| 488 | cpufreq_dev_count++; | 491 | cpufreq_dev_count++; |
| 492 | list_add(&cpufreq_dev->node, &cpufreq_dev_list); | ||
| 489 | 493 | ||
| 490 | mutex_unlock(&cooling_cpufreq_lock); | 494 | mutex_unlock(&cooling_cpufreq_lock); |
| 491 | 495 | ||
| @@ -549,6 +553,7 @@ void cpufreq_cooling_unregister(struct thermal_cooling_device *cdev) | |||
| 549 | 553 | ||
| 550 | cpufreq_dev = cdev->devdata; | 554 | cpufreq_dev = cdev->devdata; |
| 551 | mutex_lock(&cooling_cpufreq_lock); | 555 | mutex_lock(&cooling_cpufreq_lock); |
| 556 | list_del(&cpufreq_dev->node); | ||
| 552 | cpufreq_dev_count--; | 557 | cpufreq_dev_count--; |
| 553 | 558 | ||
| 554 | /* Unregister the notifier for the last cpufreq cooling device */ | 559 | /* Unregister the notifier for the last cpufreq cooling device */ |
