include cleanup: Update gfp.h and slab.h includes to prepare for breaking implicit...
[safe/jmp/linux-2.6] / arch / x86 / kernel / cpu / cpufreq / speedstep-ich.c
index 8bbb11a..561758e 100644 (file)
@@ -23,7 +23,6 @@
 #include <linux/init.h>
 #include <linux/cpufreq.h>
 #include <linux/pci.h>
-#include <linux/slab.h>
 #include <linux/sched.h>
 
 #include "speedstep-lib.h"
@@ -39,7 +38,7 @@ static struct pci_dev *speedstep_chipset_dev;
 
 /* speedstep_processor
  */
-static unsigned int speedstep_processor;
+static enum speedstep_processor speedstep_processor;
 
 static u32 pmbase;
 
@@ -89,7 +88,8 @@ static int speedstep_find_register(void)
  * speedstep_set_state - set the SpeedStep state
  * @state: new processor frequency state (SPEEDSTEP_LOW or SPEEDSTEP_HIGH)
  *
- *   Tries to change the SpeedStep state.
+ *   Tries to change the SpeedStep state.  Can be called from
+ *   smp_call_function_single.
  */
 static void speedstep_set_state(unsigned int state)
 {
@@ -143,6 +143,11 @@ static void speedstep_set_state(unsigned int state)
        return;
 }
 
+/* Wrapper for smp_call_function_single. */
+static void _speedstep_set_state(void *_state)
+{
+       speedstep_set_state(*(unsigned int *)_state);
+}
 
 /**
  * speedstep_activate - activate SpeedStep control in the chipset
@@ -226,22 +231,23 @@ static unsigned int speedstep_detect_chipset(void)
        return 0;
 }
 
-static unsigned int _speedstep_get(const struct cpumask *cpus)
+static void get_freq_data(void *_speed)
 {
-       unsigned int speed;
-       cpumask_t cpus_allowed;
+       unsigned int *speed = _speed;
 
-       cpus_allowed = current->cpus_allowed;
-       set_cpus_allowed_ptr(current, cpus);
-       speed = speedstep_get_frequency(speedstep_processor);
-       set_cpus_allowed_ptr(current, &cpus_allowed);
-       dprintk("detected %u kHz as current frequency\n", speed);
-       return speed;
+       *speed = speedstep_get_frequency(speedstep_processor);
 }
 
 static unsigned int speedstep_get(unsigned int cpu)
 {
-       return _speedstep_get(cpumask_of(cpu));
+       unsigned int speed;
+
+       /* You're supposed to ensure CPU is online. */
+       if (smp_call_function_single(cpu, get_freq_data, &speed, 1) != 0)
+               BUG();
+
+       dprintk("detected %u kHz as current frequency\n", speed);
+       return speed;
 }
 
 /**
@@ -257,16 +263,16 @@ static int speedstep_target(struct cpufreq_policy *policy,
                             unsigned int target_freq,
                             unsigned int relation)
 {
-       unsigned int newstate = 0;
+       unsigned int newstate = 0, policy_cpu;
        struct cpufreq_freqs freqs;
-       cpumask_t cpus_allowed;
        int i;
 
        if (cpufreq_frequency_table_target(policy, &speedstep_freqs[0],
                                target_freq, relation, &newstate))
                return -EINVAL;
 
-       freqs.old = _speedstep_get(policy->cpus);
+       policy_cpu = cpumask_any_and(policy->cpus, cpu_online_mask);
+       freqs.old = speedstep_get(policy_cpu);
        freqs.new = speedstep_freqs[newstate].frequency;
        freqs.cpu = policy->cpu;
 
@@ -276,20 +282,13 @@ static int speedstep_target(struct cpufreq_policy *policy,
        if (freqs.old == freqs.new)
                return 0;
 
-       cpus_allowed = current->cpus_allowed;
-
        for_each_cpu(i, policy->cpus) {
                freqs.cpu = i;
                cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
        }
 
-       /* switch to physical CPU where state is to be changed */
-       set_cpus_allowed_ptr(current, policy->cpus);
-
-       speedstep_set_state(newstate);
-
-       /* allow to be run on all CPUs */
-       set_cpus_allowed_ptr(current, &cpus_allowed);
+       smp_call_function_single(policy_cpu, _speedstep_set_state, &newstate,
+                                true);
 
        for_each_cpu(i, policy->cpus) {
                freqs.cpu = i;
@@ -312,33 +311,43 @@ static int speedstep_verify(struct cpufreq_policy *policy)
        return cpufreq_frequency_table_verify(policy, &speedstep_freqs[0]);
 }
 
+struct get_freqs {
+       struct cpufreq_policy *policy;
+       int ret;
+};
+
+static void get_freqs_on_cpu(void *_get_freqs)
+{
+       struct get_freqs *get_freqs = _get_freqs;
+
+       get_freqs->ret =
+               speedstep_get_freqs(speedstep_processor,
+                           &speedstep_freqs[SPEEDSTEP_LOW].frequency,
+                           &speedstep_freqs[SPEEDSTEP_HIGH].frequency,
+                           &get_freqs->policy->cpuinfo.transition_latency,
+                           &speedstep_set_state);
+}
 
 static int speedstep_cpu_init(struct cpufreq_policy *policy)
 {
-       int result = 0;
-       unsigned int speed;
-       cpumask_t cpus_allowed;
+       int result;
+       unsigned int policy_cpu, speed;
+       struct get_freqs gf;
 
        /* only run on CPU to be set, or on its sibling */
 #ifdef CONFIG_SMP
-       cpumask_copy(policy->cpus, &per_cpu(cpu_sibling_map, policy->cpu));
+       cpumask_copy(policy->cpus, cpu_sibling_mask(policy->cpu));
 #endif
-
-       cpus_allowed = current->cpus_allowed;
-       set_cpus_allowed_ptr(current, policy->cpus);
+       policy_cpu = cpumask_any_and(policy->cpus, cpu_online_mask);
 
        /* detect low and high frequency and transition latency */
-       result = speedstep_get_freqs(speedstep_processor,
-                                    &speedstep_freqs[SPEEDSTEP_LOW].frequency,
-                                    &speedstep_freqs[SPEEDSTEP_HIGH].frequency,
-                                    &policy->cpuinfo.transition_latency,
-                                    &speedstep_set_state);
-       set_cpus_allowed_ptr(current, &cpus_allowed);
-       if (result)
-               return result;
+       gf.policy = policy;
+       smp_call_function_single(policy_cpu, get_freqs_on_cpu, &gf, 1);
+       if (gf.ret)
+               return gf.ret;
 
        /* get current speed setting */
-       speed = _speedstep_get(policy->cpus);
+       speed = speedstep_get(policy_cpu);
        if (!speed)
                return -EIO;