diff options
author | Linus Torvalds <torvalds@g5.osdl.org> | 2006-08-04 09:41:22 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2006-08-04 09:41:22 -0700 |
commit | 12952784e5271374b7cb926501f51b9649bf5a2b (patch) | |
tree | 7e6e16d08df7553f30b345a65d46fdc8b4737a38 /drivers | |
parent | efe78cda3596f8a6d1c2d4a6b1a221bafa3e1a48 (diff) | |
parent | 12e704db809cd4101b7d3594fc9a96f30fe88a31 (diff) |
Merge master.kernel.org:/pub/scm/linux/kernel/git/davej/cpufreq
* master.kernel.org:/pub/scm/linux/kernel/git/davej/cpufreq:
[CPUFREQ] Propagate acpi_processor_preregister_performance return value.
[CPUFREQ] [2/2] demand load governor modules.
[CPUFREQ] [1/2] add __find_governor helper and clean up some error handling.
[CPUFREQ] Longhaul - Rename & fix multipliers table
[CPUFREQ] Longhaul - Fix power state test to do something more useful
[CPUFREQ] Longhaul - Readd accidentally dropped line
[CPUFREQ] Make longhaul_walk_callback() static
[CPUFREQ] X86_GX_SUSPMOD must depend on PCI
[CPUFREQ] Longhaul - Initialise later.
[CPUFREQ] Longhaul - Workaround issues with APIC.
[CPUFREQ] Longhaul - Hook into ACPI C states.
[CPUFREQ] return error when failing to set minfreq
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/cpufreq/cpufreq.c | 75 |
1 files changed, 54 insertions, 21 deletions
diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c index bc1088d9b37..b3df613ae4e 100644 --- a/drivers/cpufreq/cpufreq.c +++ b/drivers/cpufreq/cpufreq.c @@ -284,39 +284,69 @@ EXPORT_SYMBOL_GPL(cpufreq_notify_transition); * SYSFS INTERFACE * *********************************************************************/ +static struct cpufreq_governor *__find_governor(const char *str_governor) +{ + struct cpufreq_governor *t; + + list_for_each_entry(t, &cpufreq_governor_list, governor_list) + if (!strnicmp(str_governor,t->name,CPUFREQ_NAME_LEN)) + return t; + + return NULL; +} + /** * cpufreq_parse_governor - parse a governor string */ static int cpufreq_parse_governor (char *str_governor, unsigned int *policy, struct cpufreq_governor **governor) { + int err = -EINVAL; + if (!cpufreq_driver) - return -EINVAL; + goto out; + if (cpufreq_driver->setpolicy) { if (!strnicmp(str_governor, "performance", CPUFREQ_NAME_LEN)) { *policy = CPUFREQ_POLICY_PERFORMANCE; - return 0; + err = 0; } else if (!strnicmp(str_governor, "powersave", CPUFREQ_NAME_LEN)) { *policy = CPUFREQ_POLICY_POWERSAVE; - return 0; + err = 0; } - return -EINVAL; - } else { + } else if (cpufreq_driver->target) { struct cpufreq_governor *t; + mutex_lock(&cpufreq_governor_mutex); - if (!cpufreq_driver || !cpufreq_driver->target) - goto out; - list_for_each_entry(t, &cpufreq_governor_list, governor_list) { - if (!strnicmp(str_governor,t->name,CPUFREQ_NAME_LEN)) { - *governor = t; + + t = __find_governor(str_governor); + + if (t == NULL) { + char *name = kasprintf(GFP_KERNEL, "cpufreq_%s", str_governor); + + if (name) { + int ret; + mutex_unlock(&cpufreq_governor_mutex); - return 0; + ret = request_module(name); + mutex_lock(&cpufreq_governor_mutex); + + if (ret == 0) + t = __find_governor(str_governor); } + + kfree(name); } -out: + + if (t != NULL) { + *governor = t; + err = 0; + } + mutex_unlock(&cpufreq_governor_mutex); } - return -EINVAL; + out: + return err; } @@ -1265,23 +1295,21 @@ static int __cpufreq_governor(struct cpufreq_policy *policy, unsigned int event) int cpufreq_register_governor(struct cpufreq_governor *governor) { - struct cpufreq_governor *t; + int err; if (!governor) return -EINVAL; mutex_lock(&cpufreq_governor_mutex); - list_for_each_entry(t, &cpufreq_governor_list, governor_list) { - if (!strnicmp(governor->name,t->name,CPUFREQ_NAME_LEN)) { - mutex_unlock(&cpufreq_governor_mutex); - return -EBUSY; - } + err = -EBUSY; + if (__find_governor(governor->name) == NULL) { + err = 0; + list_add(&governor->governor_list, &cpufreq_governor_list); } - list_add(&governor->governor_list, &cpufreq_governor_list); mutex_unlock(&cpufreq_governor_mutex); - return 0; + return err; } EXPORT_SYMBOL_GPL(cpufreq_register_governor); @@ -1343,6 +1371,11 @@ static int __cpufreq_set_policy(struct cpufreq_policy *data, struct cpufreq_poli memcpy(&policy->cpuinfo, &data->cpuinfo, sizeof(struct cpufreq_cpuinfo)); + if (policy->min > data->min && policy->min > policy->max) { + ret = -EINVAL; + goto error_out; + } + /* verify the cpu speed can be set within this limit */ ret = cpufreq_driver->verify(policy); if (ret) |