summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/x86/lib/msr-smp.c32
1 files changed, 24 insertions, 8 deletions
diff --git a/arch/x86/lib/msr-smp.c b/arch/x86/lib/msr-smp.c
index 693cce0be82d..761ba062afda 100644
--- a/arch/x86/lib/msr-smp.c
+++ b/arch/x86/lib/msr-smp.c
@@ -2,6 +2,7 @@
2#include <linux/export.h> 2#include <linux/export.h>
3#include <linux/preempt.h> 3#include <linux/preempt.h>
4#include <linux/smp.h> 4#include <linux/smp.h>
5#include <linux/completion.h>
5#include <asm/msr.h> 6#include <asm/msr.h>
6 7
7static void __rdmsr_on_cpu(void *info) 8static void __rdmsr_on_cpu(void *info)
@@ -143,13 +144,19 @@ void wrmsr_on_cpus(const struct cpumask *mask, u32 msr_no, struct msr *msrs)
143} 144}
144EXPORT_SYMBOL(wrmsr_on_cpus); 145EXPORT_SYMBOL(wrmsr_on_cpus);
145 146
147struct msr_info_completion {
148 struct msr_info msr;
149 struct completion done;
150};
151
146/* These "safe" variants are slower and should be used when the target MSR 152/* These "safe" variants are slower and should be used when the target MSR
147 may not actually exist. */ 153 may not actually exist. */
148static void __rdmsr_safe_on_cpu(void *info) 154static void __rdmsr_safe_on_cpu(void *info)
149{ 155{
150 struct msr_info *rv = info; 156 struct msr_info_completion *rv = info;
151 157
152 rv->err = rdmsr_safe(rv->msr_no, &rv->reg.l, &rv->reg.h); 158 rv->msr.err = rdmsr_safe(rv->msr.msr_no, &rv->msr.reg.l, &rv->msr.reg.h);
159 complete(&rv->done);
153} 160}
154 161
155static void __wrmsr_safe_on_cpu(void *info) 162static void __wrmsr_safe_on_cpu(void *info)
@@ -161,17 +168,26 @@ static void __wrmsr_safe_on_cpu(void *info)
161 168
162int rdmsr_safe_on_cpu(unsigned int cpu, u32 msr_no, u32 *l, u32 *h) 169int rdmsr_safe_on_cpu(unsigned int cpu, u32 msr_no, u32 *l, u32 *h)
163{ 170{
171 struct msr_info_completion rv;
172 call_single_data_t csd = {
173 .func = __rdmsr_safe_on_cpu,
174 .info = &rv,
175 };
164 int err; 176 int err;
165 struct msr_info rv;
166 177
167 memset(&rv, 0, sizeof(rv)); 178 memset(&rv, 0, sizeof(rv));
179 init_completion(&rv.done);
180 rv.msr.msr_no = msr_no;
168 181
169 rv.msr_no = msr_no; 182 err = smp_call_function_single_async(cpu, &csd);
170 err = smp_call_function_single(cpu, __rdmsr_safe_on_cpu, &rv, 1); 183 if (!err) {
171 *l = rv.reg.l; 184 wait_for_completion(&rv.done);
172 *h = rv.reg.h; 185 err = rv.msr.err;
186 }
187 *l = rv.msr.reg.l;
188 *h = rv.msr.reg.h;
173 189
174 return err ? err : rv.err; 190 return err;
175} 191}
176EXPORT_SYMBOL(rdmsr_safe_on_cpu); 192EXPORT_SYMBOL(rdmsr_safe_on_cpu);
177 193