aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorThomas Renninger <trenn@suse.de>2006-04-13 09:14:04 -0400
committerDave Jones <davej@redhat.com>2006-04-18 18:24:52 -0400
commit7970e08bf066900efcd7794a1a338c11eb8f5141 (patch)
treebde8036f2d2aab1d85e8704bd69bd3f587d407a4 /drivers
parentf1f76afd71e0f17af9a35fcb649f4bab53304a4d (diff)
[CPUFREQ] If max_freq got reduced (e.g. by _PPC) a write to sysfs scaling_governor let cpufreq core stuck at low max_freq for ever
The previous patch had bugs (locking and refcount). This one could also be related to the latest DELL reports. But they only slip into this if a user prog (e.g. powersave daemon does when AC got (un) plugged due to a scheme change) echos something to /sys/../cpufreq/scaling_governor while the frequencies got limited by BIOS. This one works: Subject: Max freq stucks at low freq if reduced by _PPC and sysfs gov access The problem is reproducable by(if machine is limiting freqs via BIOS): - Unplugging AC -> max freq gets limited - echo ${governor} >/sys/.../cpufreq/scaling_governor (policy->user_data.max gets overridden with policy->max and will never come up again.) This patch exchanged the cpufreq_set_policy call to __cpufreq_set_policy and duplicated it's functionality but did not override user_data.max. The same happens with overridding min/max values. If freqs are limited and you override the min freq value, the max freq global value will also get stuck to the limited freq, even if BIOS allows all freqs again. Last scenario does only happen if BIOS does not reduce the frequency to the lowest value (should never happen, just for correctness...) drivers/cpufreq/cpufreq.c | 17 +++++++++++++++-- 1 files changed, 15 insertions(+), 2 deletions(-) Signed-off-by: Thomas Renninger <trenn@suse.de> Signed-off-by: "Pallipadi, Venkatesh" <venkatesh.pallipadi@intel.com> Signed-off-by: Dave Jones <davej@redhat.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/cpufreq/cpufreq.c17
1 files changed, 15 insertions, 2 deletions
diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c
index 3d0430741b5a..12e63642aa0f 100644
--- a/drivers/cpufreq/cpufreq.c
+++ b/drivers/cpufreq/cpufreq.c
@@ -346,6 +346,8 @@ show_one(scaling_min_freq, min);
346show_one(scaling_max_freq, max); 346show_one(scaling_max_freq, max);
347show_one(scaling_cur_freq, cur); 347show_one(scaling_cur_freq, cur);
348 348
349static int __cpufreq_set_policy(struct cpufreq_policy *data, struct cpufreq_policy *policy);
350
349/** 351/**
350 * cpufreq_per_cpu_attr_write() / store_##file_name() - sysfs write access 352 * cpufreq_per_cpu_attr_write() / store_##file_name() - sysfs write access
351 */ 353 */
@@ -364,7 +366,10 @@ static ssize_t store_##file_name \
364 if (ret != 1) \ 366 if (ret != 1) \
365 return -EINVAL; \ 367 return -EINVAL; \
366 \ 368 \
367 ret = cpufreq_set_policy(&new_policy); \ 369 mutex_lock(&policy->lock); \
370 ret = __cpufreq_set_policy(policy, &new_policy); \
371 policy->user_policy.object = policy->object; \
372 mutex_unlock(&policy->lock); \
368 \ 373 \
369 return ret ? ret : count; \ 374 return ret ? ret : count; \
370} 375}
@@ -420,7 +425,15 @@ static ssize_t store_scaling_governor (struct cpufreq_policy * policy,
420 if (cpufreq_parse_governor(str_governor, &new_policy.policy, &new_policy.governor)) 425 if (cpufreq_parse_governor(str_governor, &new_policy.policy, &new_policy.governor))
421 return -EINVAL; 426 return -EINVAL;
422 427
423 ret = cpufreq_set_policy(&new_policy); 428 /* Do not use cpufreq_set_policy here or the user_policy.max
429 will be wrongly overridden */
430 mutex_lock(&policy->lock);
431 ret = __cpufreq_set_policy(policy, &new_policy);
432
433 policy->user_policy.policy = policy->policy;
434 policy->user_policy.governor = policy->governor;
435 mutex_unlock(&policy->lock);
436
424 return ret ? ret : count; 437 return ret ? ret : count;
425} 438}
426 439