[PATCH 5/8] cpumask: use work_on_cpu in some other places.

From: Mike Travis
Date: Fri Dec 19 2008 - 20:03:35 EST


Impact: remove potential problem with cpus_allowed, use new API

Replace cpumask_t's used by set_cpus_allowed_ptr() to use
work_on_cpu instead.

Signed-off-by: Mike Travis <travis@xxxxxxx>
Cc: Rusty Russell <rusty@xxxxxxxxxxxxxxx>
Cc: Andreas Herrmann <andreas.herrmann3@xxxxxxx>
Cc: Dave Jones <davej@xxxxxxxxxx>
Cc: Len Brown <len.brown@xxxxxxxxx>
---
arch/x86/kernel/acpi/cstate.c | 70 ++++----
arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c | 160 +++++++++---------
arch/x86/kernel/cpu/cpufreq/powernow-k8.c | 195 ++++++++++++++---------
arch/x86/kernel/cpu/cpufreq/speedstep-centrino.c | 34 ++--
arch/x86/kernel/cpu/mcheck/mce_amd_64.c | 2
5 files changed, 264 insertions(+), 197 deletions(-)

--- linux-2.6-for-ingo.orig/arch/x86/kernel/acpi/cstate.c
+++ linux-2.6-for-ingo/arch/x86/kernel/acpi/cstate.c
@@ -66,35 +66,15 @@ static short mwait_supported[ACPI_PROCES

#define NATIVE_CSTATE_BEYOND_HALT (2)

-int acpi_processor_ffh_cstate_probe(unsigned int cpu,
- struct acpi_processor_cx *cx, struct acpi_power_register *reg)
+static long acpi_processor_ffh_cstate_probe_cpu(void *_cx)
{
- struct cstate_entry *percpu_entry;
- struct cpuinfo_x86 *c = &cpu_data(cpu);
-
- cpumask_t saved_mask;
- int retval;
+ struct acpi_processor_cx *cx = _cx;
+ long retval;
unsigned int eax, ebx, ecx, edx;
unsigned int edx_part;
unsigned int cstate_type; /* C-state type and not ACPI C-state type */
unsigned int num_cstate_subtype;

- if (!cpu_cstate_entry || c->cpuid_level < CPUID_MWAIT_LEAF )
- return -1;
-
- if (reg->bit_offset != NATIVE_CSTATE_BEYOND_HALT)
- return -1;
-
- percpu_entry = per_cpu_ptr(cpu_cstate_entry, cpu);
- percpu_entry->states[cx->index].eax = 0;
- percpu_entry->states[cx->index].ecx = 0;
-
- /* Make sure we are running on right CPU */
- saved_mask = current->cpus_allowed;
- retval = set_cpus_allowed_ptr(current, &cpumask_of_cpu(cpu));
- if (retval)
- return -1;
-
cpuid(CPUID_MWAIT_LEAF, &eax, &ebx, &ecx, &edx);

/* Check whether this particular cx_type (in CST) is supported or not */
@@ -114,21 +94,45 @@ int acpi_processor_ffh_cstate_probe(unsi
retval = -1;
goto out;
}
- percpu_entry->states[cx->index].ecx = MWAIT_ECX_INTERRUPT_BREAK;
-
- /* Use the hint in CST */
- percpu_entry->states[cx->index].eax = cx->address;

if (!mwait_supported[cstate_type]) {
mwait_supported[cstate_type] = 1;
- printk(KERN_DEBUG "Monitor-Mwait will be used to enter C-%d "
- "state\n", cx->type);
+ printk(KERN_DEBUG
+ "Monitor-Mwait will be used to enter C-%d "
+ "state\n", cx->type);
}
- snprintf(cx->desc, ACPI_CX_DESC_LEN, "ACPI FFH INTEL MWAIT 0x%x",
- cx->address);
-
+ snprintf(cx->desc,
+ ACPI_CX_DESC_LEN, "ACPI FFH INTEL MWAIT 0x%x",
+ cx->address);
out:
- set_cpus_allowed_ptr(current, &saved_mask);
+ return retval;
+}
+
+int acpi_processor_ffh_cstate_probe(unsigned int cpu,
+ struct acpi_processor_cx *cx, struct acpi_power_register *reg)
+{
+ struct cstate_entry *percpu_entry;
+ struct cpuinfo_x86 *c = &cpu_data(cpu);
+ long retval;
+
+ if (!cpu_cstate_entry || c->cpuid_level < CPUID_MWAIT_LEAF)
+ return -1;
+
+ if (reg->bit_offset != NATIVE_CSTATE_BEYOND_HALT)
+ return -1;
+
+ percpu_entry = per_cpu_ptr(cpu_cstate_entry, cpu);
+ percpu_entry->states[cx->index].eax = 0;
+ percpu_entry->states[cx->index].ecx = 0;
+
+ /* Make sure we are running on right CPU */
+
+ retval = work_on_cpu(cpu, acpi_processor_ffh_cstate_probe_cpu, cx);
+ if (retval == 0) {
+ /* Use the hint in CST */
+ percpu_entry->states[cx->index].eax = cx->address;
+ percpu_entry->states[cx->index].ecx = MWAIT_ECX_INTERRUPT_BREAK;
+ }
return retval;
}
EXPORT_SYMBOL_GPL(acpi_processor_ffh_cstate_probe);
--- linux-2.6-for-ingo.orig/arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c
+++ linux-2.6-for-ingo/arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c
@@ -145,13 +145,14 @@ typedef union {

struct drv_cmd {
unsigned int type;
- cpumask_t mask;
+ cpumask_var_t mask;
drv_addr_union addr;
u32 val;
};

-static void do_drv_read(struct drv_cmd *cmd)
+static long do_drv_read(void *_cmd)
{
+ struct drv_cmd *cmd = _cmd;
u32 h;

switch (cmd->type) {
@@ -166,10 +167,12 @@ static void do_drv_read(struct drv_cmd *
default:
break;
}
+ return 0;
}

-static void do_drv_write(struct drv_cmd *cmd)
+static long do_drv_write(void *_cmd)
{
+ struct drv_cmd *cmd = _cmd;
u32 lo, hi;

switch (cmd->type) {
@@ -186,41 +189,34 @@ static void do_drv_write(struct drv_cmd
default:
break;
}
+ return 0;
}

static void drv_read(struct drv_cmd *cmd)
{
- cpumask_t saved_mask = current->cpus_allowed;
cmd->val = 0;

- set_cpus_allowed_ptr(current, &cmd->mask);
- do_drv_read(cmd);
- set_cpus_allowed_ptr(current, &saved_mask);
+ work_on_cpu(cpumask_any(cmd->mask), do_drv_read, cmd);
}

static void drv_write(struct drv_cmd *cmd)
{
- cpumask_t saved_mask = current->cpus_allowed;
unsigned int i;

- for_each_cpu_mask_nr(i, cmd->mask) {
- set_cpus_allowed_ptr(current, &cpumask_of_cpu(i));
- do_drv_write(cmd);
+ for_each_cpu(i, cmd->mask) {
+ work_on_cpu(i, do_drv_write, cmd);
}
-
- set_cpus_allowed_ptr(current, &saved_mask);
- return;
}

-static u32 get_cur_val(const cpumask_t *mask)
+static u32 get_cur_val(const struct cpumask *mask)
{
struct acpi_processor_performance *perf;
struct drv_cmd cmd;

- if (unlikely(cpus_empty(*mask)))
+ if (unlikely(cpumask_empty(mask)))
return 0;

- switch (per_cpu(drv_data, first_cpu(*mask))->cpu_feature) {
+ switch (per_cpu(drv_data, cpumask_first(mask))->cpu_feature) {
case SYSTEM_INTEL_MSR_CAPABLE:
cmd.type = SYSTEM_INTEL_MSR_CAPABLE;
cmd.addr.msr.reg = MSR_IA32_PERF_STATUS;
@@ -235,15 +231,44 @@ static u32 get_cur_val(const cpumask_t *
return 0;
}

- cmd.mask = *mask;
+ if (unlikely(!alloc_cpumask_var(&cmd.mask, GFP_KERNEL)))
+ return 0;
+
+ cpumask_copy(cmd.mask, mask);

drv_read(&cmd);

+ free_cpumask_var(cmd.mask);
+
dprintk("get_cur_val = %u\n", cmd.val);

return cmd.val;
}

+struct perf_cur {
+ union {
+ struct {
+ u32 lo;
+ u32 hi;
+ } split;
+ u64 whole;
+ } aperf_cur, mperf_cur;
+};
+
+
+static long read_measured_perf_ctrs(void *_cur)
+{
+ struct perf_cur *cur = _cur;
+
+ rdmsr(MSR_IA32_APERF, cur->aperf_cur.split.lo, cur->aperf_cur.split.hi);
+ rdmsr(MSR_IA32_MPERF, cur->mperf_cur.split.lo, cur->mperf_cur.split.hi);
+
+ wrmsr(MSR_IA32_APERF, 0, 0);
+ wrmsr(MSR_IA32_MPERF, 0, 0);
+
+ return 0;
+}
+
/*
* Return the measured active (C0) frequency on this CPU since last call
* to this function.
@@ -260,31 +285,12 @@ static u32 get_cur_val(const cpumask_t *
static unsigned int get_measured_perf(struct cpufreq_policy *policy,
unsigned int cpu)
{
- union {
- struct {
- u32 lo;
- u32 hi;
- } split;
- u64 whole;
- } aperf_cur, mperf_cur;
-
- cpumask_t saved_mask;
+ struct perf_cur cur;
unsigned int perf_percent;
unsigned int retval;

- saved_mask = current->cpus_allowed;
- set_cpus_allowed_ptr(current, &cpumask_of_cpu(cpu));
- if (get_cpu() != cpu) {
- /* We were not able to run on requested processor */
- put_cpu();
+ if (!work_on_cpu(cpu, read_measured_perf_ctrs, &cur))
return 0;
- }
-
- rdmsr(MSR_IA32_APERF, aperf_cur.split.lo, aperf_cur.split.hi);
- rdmsr(MSR_IA32_MPERF, mperf_cur.split.lo, mperf_cur.split.hi);
-
- wrmsr(MSR_IA32_APERF, 0,0);
- wrmsr(MSR_IA32_MPERF, 0,0);

#ifdef __i386__
/*
@@ -292,37 +298,39 @@ static unsigned int get_measured_perf(st
* Get an approximate value. Return failure in case we cannot get
* an approximate value.
*/
- if (unlikely(aperf_cur.split.hi || mperf_cur.split.hi)) {
+ if (unlikely(cur.aperf_cur.split.hi || cur.mperf_cur.split.hi)) {
int shift_count;
u32 h;

- h = max_t(u32, aperf_cur.split.hi, mperf_cur.split.hi);
+ h = max_t(u32, cur.aperf_cur.split.hi, cur.mperf_cur.split.hi);
shift_count = fls(h);

- aperf_cur.whole >>= shift_count;
- mperf_cur.whole >>= shift_count;
+ cur.aperf_cur.whole >>= shift_count;
+ cur.mperf_cur.whole >>= shift_count;
}

- if (((unsigned long)(-1) / 100) < aperf_cur.split.lo) {
+ if (((unsigned long)(-1) / 100) < cur.aperf_cur.split.lo) {
int shift_count = 7;
- aperf_cur.split.lo >>= shift_count;
- mperf_cur.split.lo >>= shift_count;
+ cur.aperf_cur.split.lo >>= shift_count;
+ cur.mperf_cur.split.lo >>= shift_count;
}

- if (aperf_cur.split.lo && mperf_cur.split.lo)
- perf_percent = (aperf_cur.split.lo * 100) / mperf_cur.split.lo;
+ if (cur.aperf_cur.split.lo && cur.mperf_cur.split.lo)
+ perf_percent = (cur.aperf_cur.split.lo * 100) /
+ cur.mperf_cur.split.lo;
else
perf_percent = 0;

#else
- if (unlikely(((unsigned long)(-1) / 100) < aperf_cur.whole)) {
+ if (unlikely(((unsigned long)(-1) / 100) < cur.aperf_cur.whole)) {
int shift_count = 7;
- aperf_cur.whole >>= shift_count;
- mperf_cur.whole >>= shift_count;
+ cur.aperf_cur.whole >>= shift_count;
+ cur.mperf_cur.whole >>= shift_count;
}

- if (aperf_cur.whole && mperf_cur.whole)
- perf_percent = (aperf_cur.whole * 100) / mperf_cur.whole;
+ if (cur.aperf_cur.whole && cur.mperf_cur.whole)
+ perf_percent = (cur.aperf_cur.whole * 100) /
+ cur.mperf_cur.whole;
else
perf_percent = 0;

@@ -330,10 +338,6 @@ static unsigned int get_measured_perf(st

retval = per_cpu(drv_data, policy->cpu)->max_freq * perf_percent / 100;

- put_cpu();
- set_cpus_allowed_ptr(current, &saved_mask);
-
- dprintk("cpu %d: performance percent %d\n", cpu, perf_percent);
return retval;
}

@@ -351,7 +355,7 @@ static unsigned int get_cur_freq_on_cpu(
}

cached_freq = data->freq_table[data->acpi_data->state].frequency;
- freq = extract_freq(get_cur_val(&cpumask_of_cpu(cpu)), data);
+ freq = extract_freq(get_cur_val(cpumask_of(cpu)), data);
if (freq != cached_freq) {
/*
* The dreaded BIOS frequency change behind our back.
@@ -386,7 +390,6 @@ static int acpi_cpufreq_target(struct cp
struct acpi_cpufreq_data *data = per_cpu(drv_data, policy->cpu);
struct acpi_processor_performance *perf;
struct cpufreq_freqs freqs;
- cpumask_t online_policy_cpus;
struct drv_cmd cmd;
unsigned int next_state = 0; /* Index into freq_table */
unsigned int next_perf_state = 0; /* Index into perf table */
@@ -401,20 +404,18 @@ static int acpi_cpufreq_target(struct cp
return -ENODEV;
}

+ if (unlikely(!alloc_cpumask_var(&cmd.mask, GFP_KERNEL)))
+ return -ENOMEM;
+
perf = data->acpi_data;
result = cpufreq_frequency_table_target(policy,
data->freq_table,
target_freq,
relation, &next_state);
- if (unlikely(result))
- return -ENODEV;
-
-#ifdef CONFIG_HOTPLUG_CPU
- /* cpufreq holds the hotplug lock, so we are safe from here on */
- cpumask_and(&online_policy_cpus, cpu_online_mask, policy->cpus);
-#else
- online_policy_cpus = policy->cpus;
-#endif
+ if (unlikely(result)) {
+ result = -ENODEV;
+ goto out;
+ }

next_perf_state = data->freq_table[next_state].index;
if (perf->state == next_perf_state) {
@@ -425,7 +426,7 @@ static int acpi_cpufreq_target(struct cp
} else {
dprintk("Already at target state (P%d)\n",
next_perf_state);
- return 0;
+ goto out;
}
}

@@ -444,19 +445,19 @@ static int acpi_cpufreq_target(struct cp
cmd.val = (u32) perf->states[next_perf_state].control;
break;
default:
- return -ENODEV;
+ result = -ENODEV;
+ goto out;
}

- cpus_clear(cmd.mask);
-
+ /* cpufreq holds the hotplug lock, so we are safe from here on */
if (policy->shared_type != CPUFREQ_SHARED_TYPE_ANY)
- cmd.mask = online_policy_cpus;
+ cpumask_and(cmd.mask, cpu_online_mask, policy->cpus);
else
- cpu_set(policy->cpu, cmd.mask);
+ cpumask_copy(cmd.mask, cpumask_of(policy->cpu));

freqs.old = perf->states[perf->state].core_frequency * 1000;
freqs.new = data->freq_table[next_state].frequency;
- for_each_cpu_mask_nr(i, cmd.mask) {
+ for_each_cpu(i, cmd.mask) {
freqs.cpu = i;
cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
}
@@ -464,19 +465,22 @@ static int acpi_cpufreq_target(struct cp
drv_write(&cmd);

if (acpi_pstate_strict) {
- if (!check_freqs(&cmd.mask, freqs.new, data)) {
+ if (!check_freqs(cmd.mask, freqs.new, data)) {
dprintk("acpi_cpufreq_target failed (%d)\n",
policy->cpu);
- return -EAGAIN;
+ result = -EAGAIN;
+ goto out;
}
}

- for_each_cpu_mask_nr(i, cmd.mask) {
+ for_each_cpu(i, cmd.mask) {
freqs.cpu = i;
cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
}
perf->state = next_perf_state;

+out:
+ free_cpumask_var(cmd.mask);
return result;
}

--- linux-2.6-for-ingo.orig/arch/x86/kernel/cpu/cpufreq/powernow-k8.c
+++ linux-2.6-for-ingo/arch/x86/kernel/cpu/cpufreq/powernow-k8.c
@@ -483,60 +483,56 @@ static int core_voltage_post_transition(
return 0;
}

-static int check_supported_cpu(unsigned int cpu)
+static long read_cpuid_fields(void *unused)
{
- cpumask_t oldmask;
u32 eax, ebx, ecx, edx;
- unsigned int rc = 0;
-
- oldmask = current->cpus_allowed;
- set_cpus_allowed_ptr(current, &cpumask_of_cpu(cpu));
-
- if (smp_processor_id() != cpu) {
- printk(KERN_ERR PFX "limiting to cpu %u failed\n", cpu);
- goto out;
- }

if (current_cpu_data.x86_vendor != X86_VENDOR_AMD)
- goto out;
+ return -ENODEV;

eax = cpuid_eax(CPUID_PROCESSOR_SIGNATURE);
if (((eax & CPUID_XFAM) != CPUID_XFAM_K8) &&
((eax & CPUID_XFAM) < CPUID_XFAM_10H))
- goto out;
+ return -ENODEV;

if ((eax & CPUID_XFAM) == CPUID_XFAM_K8) {
if (((eax & CPUID_USE_XFAM_XMOD) != CPUID_USE_XFAM_XMOD) ||
((eax & CPUID_XMOD) > CPUID_XMOD_REV_MASK)) {
- printk(KERN_INFO PFX "Processor cpuid %x not supported\n", eax);
- goto out;
+ printk(KERN_INFO PFX
+ "Processor cpuid %x not supported\n", eax);
+ return -ENODEV;
}

eax = cpuid_eax(CPUID_GET_MAX_CAPABILITIES);
if (eax < CPUID_FREQ_VOLT_CAPABILITIES) {
printk(KERN_INFO PFX
"No frequency change capabilities detected\n");
- goto out;
+ return -ENODEV;
}

cpuid(CPUID_FREQ_VOLT_CAPABILITIES, &eax, &ebx, &ecx, &edx);
- if ((edx & P_STATE_TRANSITION_CAPABLE) != P_STATE_TRANSITION_CAPABLE) {
- printk(KERN_INFO PFX "Power state transitions not supported\n");
- goto out;
+ if ((edx & P_STATE_TRANSITION_CAPABLE)
+ != P_STATE_TRANSITION_CAPABLE) {
+ printk(KERN_INFO PFX
+ "Power state transitions not supported\n");
+ return -ENODEV;
}
} else { /* must be a HW Pstate capable processor */
cpuid(CPUID_FREQ_VOLT_CAPABILITIES, &eax, &ebx, &ecx, &edx);
if ((edx & USE_HW_PSTATE) == USE_HW_PSTATE)
cpu_family = CPU_HW_PSTATE;
else
- goto out;
+ return -ENODEV;
}

- rc = 1;
+ return 0;
+}

-out:
- set_cpus_allowed_ptr(current, &oldmask);
- return rc;
+static int check_supported_cpu(unsigned int cpu)
+{
+ if (work_on_cpu(cpu, read_cpuid_fields, NULL))
+ return 0;
+ return 1;
}

static int check_pst_table(struct powernow_k8_data *data, struct pst_s *pst, u8 maxvid)
@@ -654,7 +650,7 @@ static int fill_powernow_table(struct po

dprintk("cfid 0x%x, cvid 0x%x\n", data->currfid, data->currvid);
data->powernow_table = powernow_table;
- if (first_cpu(per_cpu(cpu_core_map, data->cpu)) == data->cpu)
+ if (cpumask_first(&per_cpu(cpu_core_map, data->cpu)) == data->cpu)
print_basics(data);

for (j = 0; j < data->numps; j++)
@@ -808,7 +804,7 @@ static int powernow_k8_cpu_init_acpi(str

/* fill in data */
data->numps = data->acpi_data.state_count;
- if (first_cpu(per_cpu(cpu_core_map, data->cpu)) == data->cpu)
+ if (cpumask_first(&per_cpu(cpu_core_map, data->cpu)) == data->cpu)
print_basics(data);
powernow_k8_acpi_pst_values(data, 0);

@@ -1025,25 +1021,27 @@ static int transition_frequency_pstate(s
}

/* Driver entry point to switch to the target frequency */
-static int powernowk8_target(struct cpufreq_policy *pol, unsigned targfreq, unsigned relation)
+struct powernowk8_target_args {
+ struct cpufreq_policy *pol;
+ unsigned targfreq;
+ unsigned relation;
+};
+
+static long powernowk8_target_on_cpu(void *_args)
{
- cpumask_t oldmask;
+ struct powernowk8_target_args *args = _args;
+ struct cpufreq_policy *pol = args->pol;
+ unsigned targfreq = args->targfreq;
+ unsigned relation = args->relation;
struct powernow_k8_data *data = per_cpu(powernow_data, pol->cpu);
u32 checkfid;
u32 checkvid;
unsigned int newstate;
int ret = -EIO;

- if (!data)
- return -EINVAL;
-
checkfid = data->currfid;
checkvid = data->currvid;

- /* only run on specific CPU from here on */
- oldmask = current->cpus_allowed;
- set_cpus_allowed_ptr(current, &cpumask_of_cpu(pol->cpu));
-
if (smp_processor_id() != pol->cpu) {
printk(KERN_ERR PFX "limiting to cpu %u failed\n", pol->cpu);
goto err_out;
@@ -1097,10 +1095,26 @@ static int powernowk8_target(struct cpuf
ret = 0;

err_out:
- set_cpus_allowed_ptr(current, &oldmask);
return ret;
}

+static int powernowk8_target(struct cpufreq_policy *pol, unsigned targfreq,
+ unsigned relation)
+{
+ struct powernow_k8_data *data = per_cpu(powernow_data, pol->cpu);
+ struct powernowk8_target_args args;
+
+ if (!data)
+ return -EINVAL;
+
+ args.pol = pol;
+ args.targfreq = targfreq;
+ args.relation = relation;
+
+ /* only run on specific CPU from here on */
+ return work_on_cpu(pol->cpu, powernowk8_target_on_cpu, &args);
+}
+
/* Driver entry point to verify the policy and range of frequencies */
static int powernowk8_verify(struct cpufreq_policy *pol)
{
@@ -1113,10 +1127,39 @@ static int powernowk8_verify(struct cpuf
}

/* per CPU init entry point to the driver */
+struct powernowk8_cpu_init_args {
+ struct cpufreq_policy *pol;
+ struct powernow_k8_data *data;
+};
+
+static long __cpuinit powernowk8_cpu_init_on_cpu(void *_args)
+{
+ struct powernowk8_cpu_init_args *args = _args;
+ struct cpufreq_policy *pol = args->pol;
+ struct powernow_k8_data *data = args->data;
+
+ if (smp_processor_id() != pol->cpu) {
+ printk(KERN_ERR PFX "limiting to cpu %u failed\n", pol->cpu);
+ return -ENODEV;
+ }
+
+ if (pending_bit_stuck()) {
+ printk(KERN_ERR PFX "failing init, change pending bit set\n");
+ return -EBUSY;
+ }
+
+ if (query_current_values_with_pending_wait(data))
+ return -EBUSY;
+
+ if (cpu_family == CPU_OPTERON)
+ fidvid_msr_init();
+
+ return 0;
+}
+
static int __cpuinit powernowk8_cpu_init(struct cpufreq_policy *pol)
{
struct powernow_k8_data *data;
- cpumask_t oldmask;
int rc;

if (!cpu_online(pol->cpu))
@@ -1170,27 +1213,17 @@ static int __cpuinit powernowk8_cpu_init
}

/* only run on specific CPU from here on */
- oldmask = current->cpus_allowed;
- set_cpus_allowed_ptr(current, &cpumask_of_cpu(pol->cpu));
+ {
+ struct powernowk8_cpu_init_args args;

- if (smp_processor_id() != pol->cpu) {
- printk(KERN_ERR PFX "limiting to cpu %u failed\n", pol->cpu);
- goto err_out;
- }
+ args.pol = pol;
+ args.data = data;

- if (pending_bit_stuck()) {
- printk(KERN_ERR PFX "failing init, change pending bit set\n");
- goto err_out;
+ rc = work_on_cpu(pol->cpu, powernowk8_cpu_init_on_cpu, &args);
+ if (rc)
+ goto err_out;
}
-
- if (query_current_values_with_pending_wait(data))
- goto err_out;
-
- if (cpu_family == CPU_OPTERON)
- fidvid_msr_init();
-
/* run on any CPU again */
- set_cpus_allowed_ptr(current, &oldmask);

if (cpu_family == CPU_HW_PSTATE)
cpumask_copy(pol->cpus, cpumask_of(pol->cpu));
@@ -1231,7 +1264,6 @@ static int __cpuinit powernowk8_cpu_init
return 0;

err_out:
- set_cpus_allowed_ptr(current, &oldmask);
powernow_k8_cpu_exit_acpi(data);

kfree(data);
@@ -1255,39 +1287,54 @@ static int __devexit powernowk8_cpu_exit
return 0;
}

-static unsigned int powernowk8_get (unsigned int cpu)
-{
+struct powernowk8_get_args {
struct powernow_k8_data *data;
- cpumask_t oldmask = current->cpus_allowed;
- unsigned int khz = 0;
- unsigned int first;
-
- first = first_cpu(per_cpu(cpu_core_map, cpu));
- data = per_cpu(powernow_data, first);
+ unsigned int cpu;
+ unsigned int *khz;
+};

- if (!data)
- return -EINVAL;
+static long powernowk8_get_on_cpu(void *_args)
+{
+ struct powernowk8_get_args *args = _args;
+ struct powernow_k8_data *data = args->data;
+ unsigned int cpu = args->cpu;

- set_cpus_allowed_ptr(current, &cpumask_of_cpu(cpu));
if (smp_processor_id() != cpu) {
printk(KERN_ERR PFX
"limiting to CPU %d failed in powernowk8_get\n", cpu);
- set_cpus_allowed_ptr(current, &oldmask);
- return 0;
+ return -ENODEV;
}

if (query_current_values_with_pending_wait(data))
- goto out;
+ return -EBUSY;

if (cpu_family == CPU_HW_PSTATE)
- khz = find_khz_freq_from_pstate(data->powernow_table,
- data->currpstate);
+ *(args->khz) = find_khz_freq_from_pstate(data->powernow_table,
+ data->currpstate);
else
- khz = find_khz_freq_from_fid(data->currfid);
+ *(args->khz) = find_khz_freq_from_fid(data->currfid);
+
+ return 0;
+}
+
+static unsigned int powernowk8_get(unsigned int cpu)
+{
+ struct powernow_k8_data *data;
+ struct powernowk8_get_args args;
+ unsigned int khz = 0;
+ unsigned int first;
+
+ first = cpumask_first(&per_cpu(cpu_core_map, cpu));
+ data = per_cpu(powernow_data, first);
+
+ if (!data)
+ return -EINVAL;

+ args.data = data;
+ args.cpu = cpu;
+ args.khz = &khz;
+ work_on_cpu(cpu, powernowk8_get_on_cpu, &args);

-out:
- set_cpus_allowed_ptr(current, &oldmask);
return khz;
}

--- linux-2.6-for-ingo.orig/arch/x86/kernel/cpu/cpufreq/speedstep-centrino.c
+++ linux-2.6-for-ingo/arch/x86/kernel/cpu/cpufreq/speedstep-centrino.c
@@ -319,21 +319,23 @@ static unsigned extract_clock(unsigned m
}

/* Return the current CPU frequency in kHz */
-static unsigned int get_cur_freq(unsigned int cpu)
+struct get_cur_freq_args {
+ unsigned int cpu;
+ unsigned int *clock_freq;
+};
+
+static long get_cur_freq_on_cpu(void *_args)
{
+ struct get_cur_freq_args *args = _args;
unsigned l, h;
- unsigned clock_freq;
- cpumask_t saved_mask;

- saved_mask = current->cpus_allowed;
- set_cpus_allowed_ptr(current, &cpumask_of_cpu(cpu));
- if (smp_processor_id() != cpu)
+ if (smp_processor_id() != args->cpu)
return 0;

rdmsr(MSR_IA32_PERF_STATUS, l, h);
- clock_freq = extract_clock(l, cpu, 0);
+ *(args->clock_freq) = extract_clock(l, args->cpu, 0);

- if (unlikely(clock_freq == 0)) {
+ if (unlikely(*(args->clock_freq) == 0)) {
/*
* On some CPUs, we can see transient MSR values (which are
* not present in _PSS), while CPU is doing some automatic
@@ -341,13 +343,23 @@ static unsigned int get_cur_freq(unsigne
* in PERF_CTL.
*/
rdmsr(MSR_IA32_PERF_CTL, l, h);
- clock_freq = extract_clock(l, cpu, 1);
+ *(args->clock_freq) = extract_clock(l, args->cpu, 1);
}

- set_cpus_allowed_ptr(current, &saved_mask);
- return clock_freq;
+ return 0;
}

+static unsigned int get_cur_freq(unsigned int cpu)
+{
+ struct get_cur_freq_args args;
+ unsigned clock_freq = 0;
+
+ args.cpu = cpu;
+ args.clock_freq = &clock_freq;
+ work_on_cpu(cpu, get_cur_freq_on_cpu, &args);
+
+ return clock_freq;
+}

static int centrino_cpu_init(struct cpufreq_policy *policy)
{
--- linux-2.6-for-ingo.orig/arch/x86/kernel/cpu/mcheck/mce_amd_64.c
+++ linux-2.6-for-ingo/arch/x86/kernel/cpu/mcheck/mce_amd_64.c
@@ -398,7 +398,7 @@ static __cpuinit int allocate_threshold_
if ((bank >= NR_BANKS) || (block >= NR_BLOCKS))
return 0;

- if (rdmsr_safe(address, &low, &high))
+ if (rdmsr_safe_on_cpu(cpu, address, &low, &high))
return 0;

if (!(high & MASK_VALID_HI)) {

--
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/