diff options
author | Dmitry Adamushko <dmitry.adamushko@gmail.com> | 2008-09-11 17:27:52 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2008-09-12 06:20:27 -0400 |
commit | a0a29b62a9cac6b7d83b7514679f2ed8d33d4372 (patch) | |
tree | e07ab66cbe3c90da70a7195104413cae00104de6 /arch/x86/kernel/microcode.c | |
parent | 5b792d320f28ff83dd4c13f984807e26235f7703 (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.c | 84 |
1 files changed, 34 insertions, 50 deletions
diff --git a/arch/x86/kernel/microcode.c b/arch/x86/kernel/microcode.c index b2f84ce5eed3..902dada2eb6d 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]; | |||
110 | EXPORT_SYMBOL_GPL(ucode_cpu_info); | 110 | EXPORT_SYMBOL_GPL(ucode_cpu_info); |
111 | 111 | ||
112 | #ifdef CONFIG_MICROCODE_OLD_INTERFACE | 112 | #ifdef CONFIG_MICROCODE_OLD_INTERFACE |
113 | void __user *user_buffer; /* user area microcode data buffer */ | 113 | static int do_microcode_update(const void __user *buf, size_t size) |
114 | EXPORT_SYMBOL_GPL(user_buffer); | ||
115 | unsigned int user_buffer_size; /* it's size */ | ||
116 | EXPORT_SYMBOL_GPL(user_buffer_size); | ||
117 | |||
118 | static 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 | } |
152 | out: | 134 | out: |
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(µcode_mutex); | 157 | mutex_lock(µcode_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 */ |
233 | struct platform_device *microcode_pdev; | 208 | struct platform_device *microcode_pdev; |
234 | EXPORT_SYMBOL_GPL(microcode_pdev); | ||
235 | 209 | ||
236 | static ssize_t reload_store(struct sys_device *dev, | 210 | static 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(µcode_mutex); | 228 | mutex_lock(µcode_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 | µcode_pdev->dev); | ||
232 | if (!err) | ||
233 | microcode_ops->apply_microcode(cpu); | ||
234 | } | ||
257 | mutex_unlock(µcode_mutex); | 235 | mutex_unlock(µcode_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 | ||
318 | static void microcode_resume_cpu(int cpu) | 296 | static 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 | ||
346 | void microcode_update_cpu(int cpu) | 324 | void 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 | µcode_pdev->dev); | ||
364 | } | 344 | } |
345 | |||
346 | if (!err) | ||
347 | microcode_ops->apply_microcode(cpu); | ||
348 | |||
365 | mutex_unlock(µcode_mutex); | 349 | mutex_unlock(µcode_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 | ||