|
@@ -26,6 +26,7 @@
|
|
#include <linux/slab.h>
|
|
#include <linux/slab.h>
|
|
#include <linux/cpu.h>
|
|
#include <linux/cpu.h>
|
|
#include <linux/completion.h>
|
|
#include <linux/completion.h>
|
|
|
|
+#include <linux/mutex.h>
|
|
|
|
|
|
#define dprintk(msg...) cpufreq_debug_printk(CPUFREQ_DEBUG_CORE, "cpufreq-core", msg)
|
|
#define dprintk(msg...) cpufreq_debug_printk(CPUFREQ_DEBUG_CORE, "cpufreq-core", msg)
|
|
|
|
|
|
@@ -55,7 +56,7 @@ static DECLARE_RWSEM (cpufreq_notifier_rwsem);
|
|
|
|
|
|
|
|
|
|
static LIST_HEAD(cpufreq_governor_list);
|
|
static LIST_HEAD(cpufreq_governor_list);
|
|
-static DECLARE_MUTEX (cpufreq_governor_sem);
|
|
|
|
|
|
+static DEFINE_MUTEX (cpufreq_governor_mutex);
|
|
|
|
|
|
struct cpufreq_policy * cpufreq_cpu_get(unsigned int cpu)
|
|
struct cpufreq_policy * cpufreq_cpu_get(unsigned int cpu)
|
|
{
|
|
{
|
|
@@ -297,18 +298,18 @@ static int cpufreq_parse_governor (char *str_governor, unsigned int *policy,
|
|
return -EINVAL;
|
|
return -EINVAL;
|
|
} else {
|
|
} else {
|
|
struct cpufreq_governor *t;
|
|
struct cpufreq_governor *t;
|
|
- down(&cpufreq_governor_sem);
|
|
|
|
|
|
+ mutex_lock(&cpufreq_governor_mutex);
|
|
if (!cpufreq_driver || !cpufreq_driver->target)
|
|
if (!cpufreq_driver || !cpufreq_driver->target)
|
|
goto out;
|
|
goto out;
|
|
list_for_each_entry(t, &cpufreq_governor_list, governor_list) {
|
|
list_for_each_entry(t, &cpufreq_governor_list, governor_list) {
|
|
if (!strnicmp(str_governor,t->name,CPUFREQ_NAME_LEN)) {
|
|
if (!strnicmp(str_governor,t->name,CPUFREQ_NAME_LEN)) {
|
|
*governor = t;
|
|
*governor = t;
|
|
- up(&cpufreq_governor_sem);
|
|
|
|
|
|
+ mutex_unlock(&cpufreq_governor_mutex);
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
out:
|
|
out:
|
|
- up(&cpufreq_governor_sem);
|
|
|
|
|
|
+ mutex_unlock(&cpufreq_governor_mutex);
|
|
}
|
|
}
|
|
return -EINVAL;
|
|
return -EINVAL;
|
|
}
|
|
}
|
|
@@ -600,7 +601,8 @@ static int cpufreq_add_dev (struct sys_device * sys_dev)
|
|
policy->cpu = cpu;
|
|
policy->cpu = cpu;
|
|
policy->cpus = cpumask_of_cpu(cpu);
|
|
policy->cpus = cpumask_of_cpu(cpu);
|
|
|
|
|
|
- init_MUTEX_LOCKED(&policy->lock);
|
|
|
|
|
|
+ mutex_init(&policy->lock);
|
|
|
|
+ mutex_lock(&policy->lock);
|
|
init_completion(&policy->kobj_unregister);
|
|
init_completion(&policy->kobj_unregister);
|
|
INIT_WORK(&policy->update, handle_update, (void *)(long)cpu);
|
|
INIT_WORK(&policy->update, handle_update, (void *)(long)cpu);
|
|
|
|
|
|
@@ -610,6 +612,7 @@ static int cpufreq_add_dev (struct sys_device * sys_dev)
|
|
ret = cpufreq_driver->init(policy);
|
|
ret = cpufreq_driver->init(policy);
|
|
if (ret) {
|
|
if (ret) {
|
|
dprintk("initialization failed\n");
|
|
dprintk("initialization failed\n");
|
|
|
|
+ mutex_unlock(&policy->lock);
|
|
goto err_out;
|
|
goto err_out;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -621,9 +624,10 @@ static int cpufreq_add_dev (struct sys_device * sys_dev)
|
|
strlcpy(policy->kobj.name, "cpufreq", KOBJ_NAME_LEN);
|
|
strlcpy(policy->kobj.name, "cpufreq", KOBJ_NAME_LEN);
|
|
|
|
|
|
ret = kobject_register(&policy->kobj);
|
|
ret = kobject_register(&policy->kobj);
|
|
- if (ret)
|
|
|
|
|
|
+ if (ret) {
|
|
|
|
+ mutex_unlock(&policy->lock);
|
|
goto err_out_driver_exit;
|
|
goto err_out_driver_exit;
|
|
-
|
|
|
|
|
|
+ }
|
|
/* set up files for this cpu device */
|
|
/* set up files for this cpu device */
|
|
drv_attr = cpufreq_driver->attr;
|
|
drv_attr = cpufreq_driver->attr;
|
|
while ((drv_attr) && (*drv_attr)) {
|
|
while ((drv_attr) && (*drv_attr)) {
|
|
@@ -641,7 +645,7 @@ static int cpufreq_add_dev (struct sys_device * sys_dev)
|
|
spin_unlock_irqrestore(&cpufreq_driver_lock, flags);
|
|
spin_unlock_irqrestore(&cpufreq_driver_lock, flags);
|
|
policy->governor = NULL; /* to assure that the starting sequence is
|
|
policy->governor = NULL; /* to assure that the starting sequence is
|
|
* run in cpufreq_set_policy */
|
|
* run in cpufreq_set_policy */
|
|
- up(&policy->lock);
|
|
|
|
|
|
+ mutex_unlock(&policy->lock);
|
|
|
|
|
|
/* set default policy */
|
|
/* set default policy */
|
|
|
|
|
|
@@ -762,10 +766,10 @@ static int cpufreq_remove_dev (struct sys_device * sys_dev)
|
|
spin_unlock_irqrestore(&cpufreq_driver_lock, flags);
|
|
spin_unlock_irqrestore(&cpufreq_driver_lock, flags);
|
|
#endif
|
|
#endif
|
|
|
|
|
|
- down(&data->lock);
|
|
|
|
|
|
+ mutex_lock(&data->lock);
|
|
if (cpufreq_driver->target)
|
|
if (cpufreq_driver->target)
|
|
__cpufreq_governor(data, CPUFREQ_GOV_STOP);
|
|
__cpufreq_governor(data, CPUFREQ_GOV_STOP);
|
|
- up(&data->lock);
|
|
|
|
|
|
+ mutex_unlock(&data->lock);
|
|
|
|
|
|
kobject_unregister(&data->kobj);
|
|
kobject_unregister(&data->kobj);
|
|
|
|
|
|
@@ -834,9 +838,9 @@ unsigned int cpufreq_quick_get(unsigned int cpu)
|
|
unsigned int ret = 0;
|
|
unsigned int ret = 0;
|
|
|
|
|
|
if (policy) {
|
|
if (policy) {
|
|
- down(&policy->lock);
|
|
|
|
|
|
+ mutex_lock(&policy->lock);
|
|
ret = policy->cur;
|
|
ret = policy->cur;
|
|
- up(&policy->lock);
|
|
|
|
|
|
+ mutex_unlock(&policy->lock);
|
|
cpufreq_cpu_put(policy);
|
|
cpufreq_cpu_put(policy);
|
|
}
|
|
}
|
|
|
|
|
|
@@ -862,7 +866,7 @@ unsigned int cpufreq_get(unsigned int cpu)
|
|
if (!cpufreq_driver->get)
|
|
if (!cpufreq_driver->get)
|
|
goto out;
|
|
goto out;
|
|
|
|
|
|
- down(&policy->lock);
|
|
|
|
|
|
+ mutex_lock(&policy->lock);
|
|
|
|
|
|
ret = cpufreq_driver->get(cpu);
|
|
ret = cpufreq_driver->get(cpu);
|
|
|
|
|
|
@@ -875,7 +879,7 @@ unsigned int cpufreq_get(unsigned int cpu)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
- up(&policy->lock);
|
|
|
|
|
|
+ mutex_unlock(&policy->lock);
|
|
|
|
|
|
out:
|
|
out:
|
|
cpufreq_cpu_put(policy);
|
|
cpufreq_cpu_put(policy);
|
|
@@ -1158,11 +1162,11 @@ int cpufreq_driver_target(struct cpufreq_policy *policy,
|
|
if (!policy)
|
|
if (!policy)
|
|
return -EINVAL;
|
|
return -EINVAL;
|
|
|
|
|
|
- down(&policy->lock);
|
|
|
|
|
|
+ mutex_lock(&policy->lock);
|
|
|
|
|
|
ret = __cpufreq_driver_target(policy, target_freq, relation);
|
|
ret = __cpufreq_driver_target(policy, target_freq, relation);
|
|
|
|
|
|
- up(&policy->lock);
|
|
|
|
|
|
+ mutex_unlock(&policy->lock);
|
|
|
|
|
|
cpufreq_cpu_put(policy);
|
|
cpufreq_cpu_put(policy);
|
|
|
|
|
|
@@ -1199,9 +1203,9 @@ int cpufreq_governor(unsigned int cpu, unsigned int event)
|
|
if (!policy)
|
|
if (!policy)
|
|
return -EINVAL;
|
|
return -EINVAL;
|
|
|
|
|
|
- down(&policy->lock);
|
|
|
|
|
|
+ mutex_lock(&policy->lock);
|
|
ret = __cpufreq_governor(policy, event);
|
|
ret = __cpufreq_governor(policy, event);
|
|
- up(&policy->lock);
|
|
|
|
|
|
+ mutex_unlock(&policy->lock);
|
|
|
|
|
|
cpufreq_cpu_put(policy);
|
|
cpufreq_cpu_put(policy);
|
|
|
|
|
|
@@ -1217,17 +1221,17 @@ int cpufreq_register_governor(struct cpufreq_governor *governor)
|
|
if (!governor)
|
|
if (!governor)
|
|
return -EINVAL;
|
|
return -EINVAL;
|
|
|
|
|
|
- down(&cpufreq_governor_sem);
|
|
|
|
|
|
+ mutex_lock(&cpufreq_governor_mutex);
|
|
|
|
|
|
list_for_each_entry(t, &cpufreq_governor_list, governor_list) {
|
|
list_for_each_entry(t, &cpufreq_governor_list, governor_list) {
|
|
if (!strnicmp(governor->name,t->name,CPUFREQ_NAME_LEN)) {
|
|
if (!strnicmp(governor->name,t->name,CPUFREQ_NAME_LEN)) {
|
|
- up(&cpufreq_governor_sem);
|
|
|
|
|
|
+ mutex_unlock(&cpufreq_governor_mutex);
|
|
return -EBUSY;
|
|
return -EBUSY;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
list_add(&governor->governor_list, &cpufreq_governor_list);
|
|
list_add(&governor->governor_list, &cpufreq_governor_list);
|
|
|
|
|
|
- up(&cpufreq_governor_sem);
|
|
|
|
|
|
+ mutex_unlock(&cpufreq_governor_mutex);
|
|
|
|
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
@@ -1239,9 +1243,9 @@ void cpufreq_unregister_governor(struct cpufreq_governor *governor)
|
|
if (!governor)
|
|
if (!governor)
|
|
return;
|
|
return;
|
|
|
|
|
|
- down(&cpufreq_governor_sem);
|
|
|
|
|
|
+ mutex_lock(&cpufreq_governor_mutex);
|
|
list_del(&governor->governor_list);
|
|
list_del(&governor->governor_list);
|
|
- up(&cpufreq_governor_sem);
|
|
|
|
|
|
+ mutex_unlock(&cpufreq_governor_mutex);
|
|
return;
|
|
return;
|
|
}
|
|
}
|
|
EXPORT_SYMBOL_GPL(cpufreq_unregister_governor);
|
|
EXPORT_SYMBOL_GPL(cpufreq_unregister_governor);
|
|
@@ -1268,9 +1272,9 @@ int cpufreq_get_policy(struct cpufreq_policy *policy, unsigned int cpu)
|
|
if (!cpu_policy)
|
|
if (!cpu_policy)
|
|
return -EINVAL;
|
|
return -EINVAL;
|
|
|
|
|
|
- down(&cpu_policy->lock);
|
|
|
|
|
|
+ mutex_lock(&cpu_policy->lock);
|
|
memcpy(policy, cpu_policy, sizeof(struct cpufreq_policy));
|
|
memcpy(policy, cpu_policy, sizeof(struct cpufreq_policy));
|
|
- up(&cpu_policy->lock);
|
|
|
|
|
|
+ mutex_unlock(&cpu_policy->lock);
|
|
|
|
|
|
cpufreq_cpu_put(cpu_policy);
|
|
cpufreq_cpu_put(cpu_policy);
|
|
|
|
|
|
@@ -1382,7 +1386,7 @@ int cpufreq_set_policy(struct cpufreq_policy *policy)
|
|
return -EINVAL;
|
|
return -EINVAL;
|
|
|
|
|
|
/* lock this CPU */
|
|
/* lock this CPU */
|
|
- down(&data->lock);
|
|
|
|
|
|
+ mutex_lock(&data->lock);
|
|
|
|
|
|
ret = __cpufreq_set_policy(data, policy);
|
|
ret = __cpufreq_set_policy(data, policy);
|
|
data->user_policy.min = data->min;
|
|
data->user_policy.min = data->min;
|
|
@@ -1390,7 +1394,7 @@ int cpufreq_set_policy(struct cpufreq_policy *policy)
|
|
data->user_policy.policy = data->policy;
|
|
data->user_policy.policy = data->policy;
|
|
data->user_policy.governor = data->governor;
|
|
data->user_policy.governor = data->governor;
|
|
|
|
|
|
- up(&data->lock);
|
|
|
|
|
|
+ mutex_unlock(&data->lock);
|
|
cpufreq_cpu_put(data);
|
|
cpufreq_cpu_put(data);
|
|
|
|
|
|
return ret;
|
|
return ret;
|
|
@@ -1414,7 +1418,7 @@ int cpufreq_update_policy(unsigned int cpu)
|
|
if (!data)
|
|
if (!data)
|
|
return -ENODEV;
|
|
return -ENODEV;
|
|
|
|
|
|
- down(&data->lock);
|
|
|
|
|
|
+ mutex_lock(&data->lock);
|
|
|
|
|
|
dprintk("updating policy for CPU %u\n", cpu);
|
|
dprintk("updating policy for CPU %u\n", cpu);
|
|
memcpy(&policy,
|
|
memcpy(&policy,
|
|
@@ -1425,9 +1429,17 @@ int cpufreq_update_policy(unsigned int cpu)
|
|
policy.policy = data->user_policy.policy;
|
|
policy.policy = data->user_policy.policy;
|
|
policy.governor = data->user_policy.governor;
|
|
policy.governor = data->user_policy.governor;
|
|
|
|
|
|
|
|
+ /* BIOS might change freq behind our back
|
|
|
|
+ -> ask driver for current freq and notify governors about a change */
|
|
|
|
+ if (cpufreq_driver->get) {
|
|
|
|
+ policy.cur = cpufreq_driver->get(cpu);
|
|
|
|
+ if (data->cur != policy.cur)
|
|
|
|
+ cpufreq_out_of_sync(cpu, data->cur, policy.cur);
|
|
|
|
+ }
|
|
|
|
+
|
|
ret = __cpufreq_set_policy(data, &policy);
|
|
ret = __cpufreq_set_policy(data, &policy);
|
|
|
|
|
|
- up(&data->lock);
|
|
|
|
|
|
+ mutex_unlock(&data->lock);
|
|
|
|
|
|
cpufreq_cpu_put(data);
|
|
cpufreq_cpu_put(data);
|
|
return ret;
|
|
return ret;
|