aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/kernel/microcode.c
diff options
context:
space:
mode:
authorDmitry Adamushko <dmitry.adamushko@gmail.com>2008-09-11 17:27:52 -0400
committerIngo Molnar <mingo@elte.hu>2008-09-12 06:20:27 -0400
commita0a29b62a9cac6b7d83b7514679f2ed8d33d4372 (patch)
treee07ab66cbe3c90da70a7195104413cae00104de6 /arch/x86/kernel/microcode.c
parent5b792d320f28ff83dd4c13f984807e26235f7703 (diff)
x86, microcode rework, v2
this is a rework of the microcode splitup in tip/x86/microcode (1) I think this new interface is cleaner (look at the changes in 'struct microcode_ops' in microcode.h); (2) it's -64 lines of code; Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'arch/x86/kernel/microcode.c')
-rw-r--r--arch/x86/kernel/microcode.c84
1 files changed, 34 insertions, 50 deletions
diff --git a/arch/x86/kernel/microcode.c b/arch/x86/kernel/microcode.c
index b2f84ce5eed..902dada2eb6 100644
--- a/arch/x86/kernel/microcode.c
+++ b/arch/x86/kernel/microcode.c
@@ -110,50 +110,28 @@ struct ucode_cpu_info ucode_cpu_info[NR_CPUS];
110EXPORT_SYMBOL_GPL(ucode_cpu_info); 110EXPORT_SYMBOL_GPL(ucode_cpu_info);
111 111
112#ifdef CONFIG_MICROCODE_OLD_INTERFACE 112#ifdef CONFIG_MICROCODE_OLD_INTERFACE
113void __user *user_buffer; /* user area microcode data buffer */ 113static int do_microcode_update(const void __user *buf, size_t size)
114EXPORT_SYMBOL_GPL(user_buffer);
115unsigned int user_buffer_size; /* it's size */
116EXPORT_SYMBOL_GPL(user_buffer_size);
117
118static int do_microcode_update(void)
119{ 114{
120 long cursor = 0; 115 cpumask_t old;
121 int error = 0; 116 int error = 0;
122 void *new_mc = NULL;
123 int cpu; 117 int cpu;
124 cpumask_t old;
125 118
126 old = current->cpus_allowed; 119 old = current->cpus_allowed;
127 120
128 while ((cursor = microcode_ops->get_next_ucode(&new_mc, cursor)) > 0) { 121 for_each_online_cpu(cpu) {
129 if (microcode_ops->microcode_sanity_check != NULL) 122 struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
130 error = microcode_ops->microcode_sanity_check(new_mc); 123
131 if (error) 124 if (!uci->valid)
125 continue;
126
127 set_cpus_allowed_ptr(current, &cpumask_of_cpu(cpu));
128 error = microcode_ops->request_microcode_user(cpu, buf, size);
129 if (error < 0)
132 goto out; 130 goto out;
133 /* 131 if (!error)
134 * It's possible the data file has multiple matching ucode, 132 microcode_ops->apply_microcode(cpu);
135 * lets keep searching till the latest version
136 */
137 for_each_online_cpu(cpu) {
138 struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
139
140 if (!uci->valid)
141 continue;
142 set_cpus_allowed_ptr(current, &cpumask_of_cpu(cpu));
143 error = microcode_ops->get_matching_microcode(new_mc,
144 cpu);
145 if (error < 0)
146 goto out;
147 if (error == 1)
148 microcode_ops->apply_microcode(cpu);
149 }
150 vfree(new_mc);
151 } 133 }
152out: 134out:
153 if (cursor > 0)
154 vfree(new_mc);
155 if (cursor < 0)
156 error = cursor;
157 set_cpus_allowed_ptr(current, &old); 135 set_cpus_allowed_ptr(current, &old);
158 return error; 136 return error;
159} 137}
@@ -178,10 +156,7 @@ static ssize_t microcode_write(struct file *file, const char __user *buf,
178 get_online_cpus(); 156 get_online_cpus();
179 mutex_lock(&microcode_mutex); 157 mutex_lock(&microcode_mutex);
180 158
181 user_buffer = (void __user *) buf; 159 ret = do_microcode_update(buf, len);
182 user_buffer_size = (int) len;
183
184 ret = do_microcode_update();
185 if (!ret) 160 if (!ret)
186 ret = (ssize_t)len; 161 ret = (ssize_t)len;
187 162
@@ -231,7 +206,6 @@ MODULE_ALIAS_MISCDEV(MICROCODE_MINOR);
231 206
232/* fake device for request_firmware */ 207/* fake device for request_firmware */
233struct platform_device *microcode_pdev; 208struct platform_device *microcode_pdev;
234EXPORT_SYMBOL_GPL(microcode_pdev);
235 209
236static ssize_t reload_store(struct sys_device *dev, 210static ssize_t reload_store(struct sys_device *dev,
237 struct sysdev_attribute *attr, 211 struct sysdev_attribute *attr,
@@ -252,8 +226,12 @@ static ssize_t reload_store(struct sys_device *dev,
252 if (cpu_online(cpu)) { 226 if (cpu_online(cpu)) {
253 set_cpus_allowed_ptr(current, &cpumask_of_cpu(cpu)); 227 set_cpus_allowed_ptr(current, &cpumask_of_cpu(cpu));
254 mutex_lock(&microcode_mutex); 228 mutex_lock(&microcode_mutex);
255 if (uci->valid) 229 if (uci->valid) {
256 err = microcode_ops->cpu_request_microcode(cpu); 230 err = microcode_ops->request_microcode_fw(cpu,
231 &microcode_pdev->dev);
232 if (!err)
233 microcode_ops->apply_microcode(cpu);
234 }
257 mutex_unlock(&microcode_mutex); 235 mutex_unlock(&microcode_mutex);
258 set_cpus_allowed_ptr(current, &old); 236 set_cpus_allowed_ptr(current, &old);
259 } 237 }
@@ -315,7 +293,7 @@ static void collect_cpu_info(int cpu)
315 uci->valid = 1; 293 uci->valid = 1;
316} 294}
317 295
318static void microcode_resume_cpu(int cpu) 296static int microcode_resume_cpu(int cpu)
319{ 297{
320 struct ucode_cpu_info *uci = ucode_cpu_info + cpu; 298 struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
321 struct cpu_signature nsig; 299 struct cpu_signature nsig;
@@ -323,7 +301,7 @@ static void microcode_resume_cpu(int cpu)
323 pr_debug("microcode: CPU%d resumed\n", cpu); 301 pr_debug("microcode: CPU%d resumed\n", cpu);
324 302
325 if (!uci->mc.valid_mc) 303 if (!uci->mc.valid_mc)
326 return; 304 return 1;
327 305
328 /* 306 /*
329 * Let's verify that the 'cached' ucode does belong 307 * Let's verify that the 'cached' ucode does belong
@@ -331,21 +309,22 @@ static void microcode_resume_cpu(int cpu)
331 */ 309 */
332 if (microcode_ops->collect_cpu_info(cpu, &nsig)) { 310 if (microcode_ops->collect_cpu_info(cpu, &nsig)) {
333 microcode_fini_cpu(cpu); 311 microcode_fini_cpu(cpu);
334 return; 312 return -1;
335 } 313 }
336 314
337 if (memcmp(&nsig, &uci->cpu_sig, sizeof(nsig))) { 315 if (memcmp(&nsig, &uci->cpu_sig, sizeof(nsig))) {
338 microcode_fini_cpu(cpu); 316 microcode_fini_cpu(cpu);
339 /* Should we look for a new ucode here? */ 317 /* Should we look for a new ucode here? */
340 return; 318 return 1;
341 } 319 }
342 320
343 microcode_ops->apply_microcode(cpu); 321 return 0;
344} 322}
345 323
346void microcode_update_cpu(int cpu) 324void microcode_update_cpu(int cpu)
347{ 325{
348 struct ucode_cpu_info *uci = ucode_cpu_info + cpu; 326 struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
327 int err = 0;
349 328
350 /* We should bind the task to the CPU */ 329 /* We should bind the task to the CPU */
351 BUG_ON(raw_smp_processor_id() != cpu); 330 BUG_ON(raw_smp_processor_id() != cpu);
@@ -356,12 +335,17 @@ void microcode_update_cpu(int cpu)
356 * otherwise just request a firmware: 335 * otherwise just request a firmware:
357 */ 336 */
358 if (uci->valid) { 337 if (uci->valid) {
359 microcode_resume_cpu(cpu); 338 err = microcode_resume_cpu(cpu);
360 } else { 339 } else {
361 collect_cpu_info(cpu); 340 collect_cpu_info(cpu);
362 if (uci->valid && system_state == SYSTEM_RUNNING) 341 if (uci->valid && system_state == SYSTEM_RUNNING)
363 microcode_ops->cpu_request_microcode(cpu); 342 err = microcode_ops->request_microcode_fw(cpu,
343 &microcode_pdev->dev);
364 } 344 }
345
346 if (!err)
347 microcode_ops->apply_microcode(cpu);
348
365 mutex_unlock(&microcode_mutex); 349 mutex_unlock(&microcode_mutex);
366} 350}
367 351
@@ -414,7 +398,7 @@ static int mc_sysdev_resume(struct sys_device *dev)
414 return 0; 398 return 0;
415 pr_debug("microcode: CPU%d resumed\n", cpu); 399 pr_debug("microcode: CPU%d resumed\n", cpu);
416 /* only CPU 0 will apply ucode here */ 400 /* only CPU 0 will apply ucode here */
417 microcode_ops->apply_microcode(0); 401 microcode_update_cpu(0);
418 return 0; 402 return 0;
419} 403}
420 404