Commit 934a3595 authored by Linus Torvalds's avatar Linus Torvalds

Merge master.kernel.org:/pub/scm/linux/kernel/git/davej/cpufreq

parents b4d9eda0 7d5e350f
...@@ -282,6 +282,10 @@ time_cpufreq_notifier(struct notifier_block *nb, unsigned long val, ...@@ -282,6 +282,10 @@ time_cpufreq_notifier(struct notifier_block *nb, unsigned long val,
if (val != CPUFREQ_RESUMECHANGE) if (val != CPUFREQ_RESUMECHANGE)
write_seqlock_irq(&xtime_lock); write_seqlock_irq(&xtime_lock);
if (!ref_freq) { if (!ref_freq) {
if (!freq->old){
ref_freq = freq->new;
goto end;
}
ref_freq = freq->old; ref_freq = freq->old;
loops_per_jiffy_ref = cpu_data[freq->cpu].loops_per_jiffy; loops_per_jiffy_ref = cpu_data[freq->cpu].loops_per_jiffy;
#ifndef CONFIG_SMP #ifndef CONFIG_SMP
...@@ -307,6 +311,7 @@ time_cpufreq_notifier(struct notifier_block *nb, unsigned long val, ...@@ -307,6 +311,7 @@ time_cpufreq_notifier(struct notifier_block *nb, unsigned long val,
#endif #endif
} }
end:
if (val != CPUFREQ_RESUMECHANGE) if (val != CPUFREQ_RESUMECHANGE)
write_sequnlock_irq(&xtime_lock); write_sequnlock_irq(&xtime_lock);
......
...@@ -35,8 +35,8 @@ ...@@ -35,8 +35,8 @@
* level driver of CPUFreq support, and its spinlock. This lock * level driver of CPUFreq support, and its spinlock. This lock
* also protects the cpufreq_cpu_data array. * also protects the cpufreq_cpu_data array.
*/ */
static struct cpufreq_driver *cpufreq_driver; static struct cpufreq_driver *cpufreq_driver;
static struct cpufreq_policy *cpufreq_cpu_data[NR_CPUS]; static struct cpufreq_policy *cpufreq_cpu_data[NR_CPUS];
static DEFINE_SPINLOCK(cpufreq_driver_lock); static DEFINE_SPINLOCK(cpufreq_driver_lock);
/* internal prototypes */ /* internal prototypes */
...@@ -50,15 +50,15 @@ static void handle_update(void *data); ...@@ -50,15 +50,15 @@ static void handle_update(void *data);
* changes to devices when the CPU clock speed changes. * changes to devices when the CPU clock speed changes.
* The mutex locks both lists. * The mutex locks both lists.
*/ */
static struct notifier_block *cpufreq_policy_notifier_list; static struct notifier_block *cpufreq_policy_notifier_list;
static struct notifier_block *cpufreq_transition_notifier_list; static struct notifier_block *cpufreq_transition_notifier_list;
static DECLARE_RWSEM (cpufreq_notifier_rwsem); static DECLARE_RWSEM (cpufreq_notifier_rwsem);
static LIST_HEAD(cpufreq_governor_list); static LIST_HEAD(cpufreq_governor_list);
static DEFINE_MUTEX (cpufreq_governor_mutex); static DEFINE_MUTEX (cpufreq_governor_mutex);
struct cpufreq_policy * cpufreq_cpu_get(unsigned int cpu) struct cpufreq_policy *cpufreq_cpu_get(unsigned int cpu)
{ {
struct cpufreq_policy *data; struct cpufreq_policy *data;
unsigned long flags; unsigned long flags;
...@@ -85,20 +85,19 @@ struct cpufreq_policy * cpufreq_cpu_get(unsigned int cpu) ...@@ -85,20 +85,19 @@ struct cpufreq_policy * cpufreq_cpu_get(unsigned int cpu)
if (!kobject_get(&data->kobj)) if (!kobject_get(&data->kobj))
goto err_out_put_module; goto err_out_put_module;
spin_unlock_irqrestore(&cpufreq_driver_lock, flags); spin_unlock_irqrestore(&cpufreq_driver_lock, flags);
return data; return data;
err_out_put_module: err_out_put_module:
module_put(cpufreq_driver->owner); module_put(cpufreq_driver->owner);
err_out_unlock: err_out_unlock:
spin_unlock_irqrestore(&cpufreq_driver_lock, flags); spin_unlock_irqrestore(&cpufreq_driver_lock, flags);
err_out: err_out:
return NULL; return NULL;
} }
EXPORT_SYMBOL_GPL(cpufreq_cpu_get); EXPORT_SYMBOL_GPL(cpufreq_cpu_get);
void cpufreq_cpu_put(struct cpufreq_policy *data) void cpufreq_cpu_put(struct cpufreq_policy *data)
{ {
kobject_put(&data->kobj); kobject_put(&data->kobj);
...@@ -229,44 +228,53 @@ static inline void adjust_jiffies(unsigned long val, struct cpufreq_freqs *ci) { ...@@ -229,44 +228,53 @@ static inline void adjust_jiffies(unsigned long val, struct cpufreq_freqs *ci) {
/** /**
* cpufreq_notify_transition - call notifier chain and adjust_jiffies on frequency transition * cpufreq_notify_transition - call notifier chain and adjust_jiffies
* on frequency transition.
* *
* This function calls the transition notifiers and the "adjust_jiffies" function. It is called * This function calls the transition notifiers and the "adjust_jiffies"
* twice on all CPU frequency changes that have external effects. * function. It is called twice on all CPU frequency changes that have
* external effects.
*/ */
void cpufreq_notify_transition(struct cpufreq_freqs *freqs, unsigned int state) void cpufreq_notify_transition(struct cpufreq_freqs *freqs, unsigned int state)
{ {
struct cpufreq_policy *policy;
BUG_ON(irqs_disabled()); BUG_ON(irqs_disabled());
freqs->flags = cpufreq_driver->flags; freqs->flags = cpufreq_driver->flags;
dprintk("notification %u of frequency transition to %u kHz\n", state, freqs->new); dprintk("notification %u of frequency transition to %u kHz\n",
state, freqs->new);
down_read(&cpufreq_notifier_rwsem); down_read(&cpufreq_notifier_rwsem);
policy = cpufreq_cpu_data[freqs->cpu];
switch (state) { switch (state) {
case CPUFREQ_PRECHANGE: case CPUFREQ_PRECHANGE:
/* detect if the driver reported a value as "old frequency" which /* detect if the driver reported a value as "old frequency"
* is not equal to what the cpufreq core thinks is "old frequency". * which is not equal to what the cpufreq core thinks is
* "old frequency".
*/ */
if (!(cpufreq_driver->flags & CPUFREQ_CONST_LOOPS)) { if (!(cpufreq_driver->flags & CPUFREQ_CONST_LOOPS)) {
if ((likely(cpufreq_cpu_data[freqs->cpu])) && if ((policy) && (policy->cpu == freqs->cpu) &&
(likely(cpufreq_cpu_data[freqs->cpu]->cpu == freqs->cpu)) && (policy->cur) && (policy->cur != freqs->old)) {
(likely(cpufreq_cpu_data[freqs->cpu]->cur)) && dprintk(KERN_WARNING "Warning: CPU frequency is"
(unlikely(freqs->old != cpufreq_cpu_data[freqs->cpu]->cur))) " %u, cpufreq assumed %u kHz.\n",
{ freqs->old, policy->cur);
dprintk(KERN_WARNING "Warning: CPU frequency is %u, " freqs->old = policy->cur;
"cpufreq assumed %u kHz.\n", freqs->old, cpufreq_cpu_data[freqs->cpu]->cur);
freqs->old = cpufreq_cpu_data[freqs->cpu]->cur;
} }
} }
notifier_call_chain(&cpufreq_transition_notifier_list, CPUFREQ_PRECHANGE, freqs); notifier_call_chain(&cpufreq_transition_notifier_list,
CPUFREQ_PRECHANGE, freqs);
adjust_jiffies(CPUFREQ_PRECHANGE, freqs); adjust_jiffies(CPUFREQ_PRECHANGE, freqs);
break; break;
case CPUFREQ_POSTCHANGE: case CPUFREQ_POSTCHANGE:
adjust_jiffies(CPUFREQ_POSTCHANGE, freqs); adjust_jiffies(CPUFREQ_POSTCHANGE, freqs);
notifier_call_chain(&cpufreq_transition_notifier_list, CPUFREQ_POSTCHANGE, freqs); notifier_call_chain(&cpufreq_transition_notifier_list,
if ((likely(cpufreq_cpu_data[freqs->cpu])) && CPUFREQ_POSTCHANGE, freqs);
(likely(cpufreq_cpu_data[freqs->cpu]->cpu == freqs->cpu))) if (likely(policy) && likely(policy->cpu == freqs->cpu))
cpufreq_cpu_data[freqs->cpu]->cur = freqs->new; policy->cur = freqs->new;
break; break;
} }
up_read(&cpufreq_notifier_rwsem); up_read(&cpufreq_notifier_rwsem);
...@@ -308,7 +316,7 @@ static int cpufreq_parse_governor (char *str_governor, unsigned int *policy, ...@@ -308,7 +316,7 @@ static int cpufreq_parse_governor (char *str_governor, unsigned int *policy,
return 0; return 0;
} }
} }
out: out:
mutex_unlock(&cpufreq_governor_mutex); mutex_unlock(&cpufreq_governor_mutex);
} }
return -EINVAL; return -EINVAL;
...@@ -415,7 +423,6 @@ static ssize_t store_scaling_governor (struct cpufreq_policy * policy, ...@@ -415,7 +423,6 @@ static ssize_t store_scaling_governor (struct cpufreq_policy * policy,
return -EINVAL; return -EINVAL;
ret = cpufreq_set_policy(&new_policy); ret = cpufreq_set_policy(&new_policy);
return ret ? ret : count; return ret ? ret : count;
} }
...@@ -446,7 +453,7 @@ static ssize_t show_scaling_available_governors (struct cpufreq_policy * policy, ...@@ -446,7 +453,7 @@ static ssize_t show_scaling_available_governors (struct cpufreq_policy * policy,
goto out; goto out;
i += scnprintf(&buf[i], CPUFREQ_NAME_LEN, "%s ", t->name); i += scnprintf(&buf[i], CPUFREQ_NAME_LEN, "%s ", t->name);
} }
out: out:
i += sprintf(&buf[i], "\n"); i += sprintf(&buf[i], "\n");
return i; return i;
} }
...@@ -789,7 +796,6 @@ static int cpufreq_remove_dev (struct sys_device * sys_dev) ...@@ -789,7 +796,6 @@ static int cpufreq_remove_dev (struct sys_device * sys_dev)
kfree(data); kfree(data);
cpufreq_debug_enable_ratelimit(); cpufreq_debug_enable_ratelimit();
return 0; return 0;
} }
...@@ -870,8 +876,7 @@ unsigned int cpufreq_get(unsigned int cpu) ...@@ -870,8 +876,7 @@ unsigned int cpufreq_get(unsigned int cpu)
ret = cpufreq_driver->get(cpu); ret = cpufreq_driver->get(cpu);
if (ret && policy->cur && !(cpufreq_driver->flags & CPUFREQ_CONST_LOOPS)) if (ret && policy->cur && !(cpufreq_driver->flags & CPUFREQ_CONST_LOOPS)) {
{
/* verify no discrepancy between actual and saved value exists */ /* verify no discrepancy between actual and saved value exists */
if (unlikely(ret != policy->cur)) { if (unlikely(ret != policy->cur)) {
cpufreq_out_of_sync(cpu, policy->cur, ret); cpufreq_out_of_sync(cpu, policy->cur, ret);
...@@ -881,7 +886,7 @@ unsigned int cpufreq_get(unsigned int cpu) ...@@ -881,7 +886,7 @@ unsigned int cpufreq_get(unsigned int cpu)
mutex_unlock(&policy->lock); mutex_unlock(&policy->lock);
out: out:
cpufreq_cpu_put(policy); cpufreq_cpu_put(policy);
return (ret); return (ret);
...@@ -962,7 +967,7 @@ static int cpufreq_suspend(struct sys_device * sysdev, pm_message_t pmsg) ...@@ -962,7 +967,7 @@ static int cpufreq_suspend(struct sys_device * sysdev, pm_message_t pmsg)
cpu_policy->cur = cur_freq; cpu_policy->cur = cur_freq;
} }
out: out:
cpufreq_cpu_put(cpu_policy); cpufreq_cpu_put(cpu_policy);
return 0; return 0;
} }
...@@ -1169,7 +1174,6 @@ int cpufreq_driver_target(struct cpufreq_policy *policy, ...@@ -1169,7 +1174,6 @@ int cpufreq_driver_target(struct cpufreq_policy *policy,
mutex_unlock(&policy->lock); mutex_unlock(&policy->lock);
cpufreq_cpu_put(policy); cpufreq_cpu_put(policy);
return ret; return ret;
} }
EXPORT_SYMBOL_GPL(cpufreq_driver_target); EXPORT_SYMBOL_GPL(cpufreq_driver_target);
...@@ -1208,7 +1212,6 @@ int cpufreq_governor(unsigned int cpu, unsigned int event) ...@@ -1208,7 +1212,6 @@ int cpufreq_governor(unsigned int cpu, unsigned int event)
mutex_unlock(&policy->lock); mutex_unlock(&policy->lock);
cpufreq_cpu_put(policy); cpufreq_cpu_put(policy);
return ret; return ret;
} }
EXPORT_SYMBOL_GPL(cpufreq_governor); EXPORT_SYMBOL_GPL(cpufreq_governor);
...@@ -1232,7 +1235,6 @@ int cpufreq_register_governor(struct cpufreq_governor *governor) ...@@ -1232,7 +1235,6 @@ int cpufreq_register_governor(struct cpufreq_governor *governor)
list_add(&governor->governor_list, &cpufreq_governor_list); list_add(&governor->governor_list, &cpufreq_governor_list);
mutex_unlock(&cpufreq_governor_mutex); mutex_unlock(&cpufreq_governor_mutex);
return 0; return 0;
} }
EXPORT_SYMBOL_GPL(cpufreq_register_governor); EXPORT_SYMBOL_GPL(cpufreq_register_governor);
...@@ -1277,7 +1279,6 @@ int cpufreq_get_policy(struct cpufreq_policy *policy, unsigned int cpu) ...@@ -1277,7 +1279,6 @@ int cpufreq_get_policy(struct cpufreq_policy *policy, unsigned int cpu)
mutex_unlock(&cpu_policy->lock); mutex_unlock(&cpu_policy->lock);
cpufreq_cpu_put(cpu_policy); cpufreq_cpu_put(cpu_policy);
return 0; return 0;
} }
EXPORT_SYMBOL(cpufreq_get_policy); EXPORT_SYMBOL(cpufreq_get_policy);
...@@ -1291,9 +1292,7 @@ static int __cpufreq_set_policy(struct cpufreq_policy *data, struct cpufreq_poli ...@@ -1291,9 +1292,7 @@ static int __cpufreq_set_policy(struct cpufreq_policy *data, struct cpufreq_poli
dprintk("setting new policy for CPU %u: %u - %u kHz\n", policy->cpu, dprintk("setting new policy for CPU %u: %u - %u kHz\n", policy->cpu,
policy->min, policy->max); policy->min, policy->max);
memcpy(&policy->cpuinfo, memcpy(&policy->cpuinfo, &data->cpuinfo, sizeof(struct cpufreq_cpuinfo));
&data->cpuinfo,
sizeof(struct cpufreq_cpuinfo));
/* verify the cpu speed can be set within this limit */ /* verify the cpu speed can be set within this limit */
ret = cpufreq_driver->verify(policy); ret = cpufreq_driver->verify(policy);
...@@ -1324,8 +1323,8 @@ static int __cpufreq_set_policy(struct cpufreq_policy *data, struct cpufreq_poli ...@@ -1324,8 +1323,8 @@ static int __cpufreq_set_policy(struct cpufreq_policy *data, struct cpufreq_poli
up_read(&cpufreq_notifier_rwsem); up_read(&cpufreq_notifier_rwsem);
data->min = policy->min; data->min = policy->min;
data->max = policy->max; data->max = policy->max;
dprintk("new min and max freqs are %u - %u kHz\n", data->min, data->max); dprintk("new min and max freqs are %u - %u kHz\n", data->min, data->max);
...@@ -1362,7 +1361,7 @@ static int __cpufreq_set_policy(struct cpufreq_policy *data, struct cpufreq_poli ...@@ -1362,7 +1361,7 @@ static int __cpufreq_set_policy(struct cpufreq_policy *data, struct cpufreq_poli
__cpufreq_governor(data, CPUFREQ_GOV_LIMITS); __cpufreq_governor(data, CPUFREQ_GOV_LIMITS);
} }
error_out: error_out:
cpufreq_debug_enable_ratelimit(); cpufreq_debug_enable_ratelimit();
return ret; return ret;
} }
...@@ -1421,9 +1420,7 @@ int cpufreq_update_policy(unsigned int cpu) ...@@ -1421,9 +1420,7 @@ int cpufreq_update_policy(unsigned int cpu)
mutex_lock(&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, data, sizeof(struct cpufreq_policy));
data,
sizeof(struct cpufreq_policy));
policy.min = data->user_policy.min; policy.min = data->user_policy.min;
policy.max = data->user_policy.max; policy.max = data->user_policy.max;
policy.policy = data->user_policy.policy; policy.policy = data->user_policy.policy;
...@@ -1433,8 +1430,13 @@ int cpufreq_update_policy(unsigned int cpu) ...@@ -1433,8 +1430,13 @@ int cpufreq_update_policy(unsigned int cpu)
-> ask driver for current freq and notify governors about a change */ -> ask driver for current freq and notify governors about a change */
if (cpufreq_driver->get) { if (cpufreq_driver->get) {
policy.cur = cpufreq_driver->get(cpu); policy.cur = cpufreq_driver->get(cpu);
if (data->cur != policy.cur) if (!data->cur) {
cpufreq_out_of_sync(cpu, data->cur, policy.cur); dprintk("Driver did not initialize current freq");
data->cur = policy.cur;
} else {
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);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment