x86: cpumask: use work_on_cpu in arch/x86/kernel/microcode_core.c
Impact: don't play with current's cpumask Straightforward indirection through work_on_cpu(). One change is that the error code from microcode_update_cpu() is now actually plumbed back to microcode_init_cpu(), so now we printk if it fails on cpu hotplug. Signed-off-by: Rusty Russell <rusty@rustcorp.com.au> Cc: Andrew Morton <akpm@linux-foundation.org> Cc: Dmitry Adamushko <dmitry.adamushko@gmail.com> Cc: Peter Oruba <peter.oruba@amd.com> LKML-Reference: <200903111632.37279.rusty@rustcorp.com.au> Signed-off-by: Ingo Molnar <mingo@elte.hu>
This commit is contained in:
Родитель
30e1e6d1af
Коммит
af5c820a31
|
@ -108,29 +108,40 @@ struct ucode_cpu_info ucode_cpu_info[NR_CPUS];
|
|||
EXPORT_SYMBOL_GPL(ucode_cpu_info);
|
||||
|
||||
#ifdef CONFIG_MICROCODE_OLD_INTERFACE
|
||||
struct update_for_cpu {
|
||||
const void __user *buf;
|
||||
size_t size;
|
||||
};
|
||||
|
||||
static long update_for_cpu(void *_ufc)
|
||||
{
|
||||
struct update_for_cpu *ufc = _ufc;
|
||||
int error;
|
||||
|
||||
error = microcode_ops->request_microcode_user(smp_processor_id(),
|
||||
ufc->buf, ufc->size);
|
||||
if (error < 0)
|
||||
return error;
|
||||
if (!error)
|
||||
microcode_ops->apply_microcode(smp_processor_id());
|
||||
return error;
|
||||
}
|
||||
|
||||
static int do_microcode_update(const void __user *buf, size_t size)
|
||||
{
|
||||
cpumask_t old;
|
||||
int error = 0;
|
||||
int cpu;
|
||||
|
||||
old = current->cpus_allowed;
|
||||
struct update_for_cpu ufc = { .buf = buf, .size = size };
|
||||
|
||||
for_each_online_cpu(cpu) {
|
||||
struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
|
||||
|
||||
if (!uci->valid)
|
||||
continue;
|
||||
|
||||
set_cpus_allowed_ptr(current, &cpumask_of_cpu(cpu));
|
||||
error = microcode_ops->request_microcode_user(cpu, buf, size);
|
||||
error = work_on_cpu(cpu, update_for_cpu, &ufc);
|
||||
if (error < 0)
|
||||
goto out;
|
||||
if (!error)
|
||||
microcode_ops->apply_microcode(cpu);
|
||||
break;
|
||||
}
|
||||
out:
|
||||
set_cpus_allowed_ptr(current, &old);
|
||||
return error;
|
||||
}
|
||||
|
||||
|
@ -205,11 +216,26 @@ MODULE_ALIAS_MISCDEV(MICROCODE_MINOR);
|
|||
/* fake device for request_firmware */
|
||||
static struct platform_device *microcode_pdev;
|
||||
|
||||
static long reload_for_cpu(void *unused)
|
||||
{
|
||||
struct ucode_cpu_info *uci = ucode_cpu_info + smp_processor_id();
|
||||
int err = 0;
|
||||
|
||||
mutex_lock(µcode_mutex);
|
||||
if (uci->valid) {
|
||||
err = microcode_ops->request_microcode_fw(smp_processor_id(),
|
||||
µcode_pdev->dev);
|
||||
if (!err)
|
||||
microcode_ops->apply_microcode(smp_processor_id());
|
||||
}
|
||||
mutex_unlock(µcode_mutex);
|
||||
return err;
|
||||
}
|
||||
|
||||
static ssize_t reload_store(struct sys_device *dev,
|
||||
struct sysdev_attribute *attr,
|
||||
const char *buf, size_t sz)
|
||||
{
|
||||
struct ucode_cpu_info *uci = ucode_cpu_info + dev->id;
|
||||
char *end;
|
||||
unsigned long val = simple_strtoul(buf, &end, 0);
|
||||
int err = 0;
|
||||
|
@ -218,21 +244,9 @@ static ssize_t reload_store(struct sys_device *dev,
|
|||
if (end == buf)
|
||||
return -EINVAL;
|
||||
if (val == 1) {
|
||||
cpumask_t old = current->cpus_allowed;
|
||||
|
||||
get_online_cpus();
|
||||
if (cpu_online(cpu)) {
|
||||
set_cpus_allowed_ptr(current, &cpumask_of_cpu(cpu));
|
||||
mutex_lock(µcode_mutex);
|
||||
if (uci->valid) {
|
||||
err = microcode_ops->request_microcode_fw(cpu,
|
||||
µcode_pdev->dev);
|
||||
if (!err)
|
||||
microcode_ops->apply_microcode(cpu);
|
||||
}
|
||||
mutex_unlock(µcode_mutex);
|
||||
set_cpus_allowed_ptr(current, &old);
|
||||
}
|
||||
if (cpu_online(cpu))
|
||||
err = work_on_cpu(cpu, reload_for_cpu, NULL);
|
||||
put_online_cpus();
|
||||
}
|
||||
if (err)
|
||||
|
@ -328,9 +342,9 @@ static int microcode_resume_cpu(int cpu)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void microcode_update_cpu(int cpu)
|
||||
static long microcode_update_cpu(void *unused)
|
||||
{
|
||||
struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
|
||||
struct ucode_cpu_info *uci = ucode_cpu_info + smp_processor_id();
|
||||
int err = 0;
|
||||
|
||||
/*
|
||||
|
@ -338,30 +352,27 @@ static void microcode_update_cpu(int cpu)
|
|||
* otherwise just request a firmware:
|
||||
*/
|
||||
if (uci->valid) {
|
||||
err = microcode_resume_cpu(cpu);
|
||||
err = microcode_resume_cpu(smp_processor_id());
|
||||
} else {
|
||||
collect_cpu_info(cpu);
|
||||
collect_cpu_info(smp_processor_id());
|
||||
if (uci->valid && system_state == SYSTEM_RUNNING)
|
||||
err = microcode_ops->request_microcode_fw(cpu,
|
||||
err = microcode_ops->request_microcode_fw(
|
||||
smp_processor_id(),
|
||||
µcode_pdev->dev);
|
||||
}
|
||||
if (!err)
|
||||
microcode_ops->apply_microcode(cpu);
|
||||
microcode_ops->apply_microcode(smp_processor_id());
|
||||
return err;
|
||||
}
|
||||
|
||||
static void microcode_init_cpu(int cpu)
|
||||
static int microcode_init_cpu(int cpu)
|
||||
{
|
||||
cpumask_t old = current->cpus_allowed;
|
||||
|
||||
set_cpus_allowed_ptr(current, &cpumask_of_cpu(cpu));
|
||||
/* We should bind the task to the CPU */
|
||||
BUG_ON(raw_smp_processor_id() != cpu);
|
||||
|
||||
int err;
|
||||
mutex_lock(µcode_mutex);
|
||||
microcode_update_cpu(cpu);
|
||||
err = work_on_cpu(cpu, microcode_update_cpu, NULL);
|
||||
mutex_unlock(µcode_mutex);
|
||||
|
||||
set_cpus_allowed_ptr(current, &old);
|
||||
return err;
|
||||
}
|
||||
|
||||
static int mc_sysdev_add(struct sys_device *sys_dev)
|
||||
|
@ -379,8 +390,11 @@ static int mc_sysdev_add(struct sys_device *sys_dev)
|
|||
if (err)
|
||||
return err;
|
||||
|
||||
microcode_init_cpu(cpu);
|
||||
return 0;
|
||||
err = microcode_init_cpu(cpu);
|
||||
if (err)
|
||||
sysfs_remove_group(&sys_dev->kobj, &mc_attr_group);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static int mc_sysdev_remove(struct sys_device *sys_dev)
|
||||
|
@ -404,7 +418,7 @@ static int mc_sysdev_resume(struct sys_device *dev)
|
|||
return 0;
|
||||
|
||||
/* only CPU 0 will apply ucode here */
|
||||
microcode_update_cpu(0);
|
||||
microcode_update_cpu(NULL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -424,7 +438,9 @@ mc_cpu_callback(struct notifier_block *nb, unsigned long action, void *hcpu)
|
|||
switch (action) {
|
||||
case CPU_ONLINE:
|
||||
case CPU_ONLINE_FROZEN:
|
||||
microcode_init_cpu(cpu);
|
||||
if (microcode_init_cpu(cpu))
|
||||
printk(KERN_ERR "microcode: failed to init CPU%d\n",
|
||||
cpu);
|
||||
case CPU_DOWN_FAILED:
|
||||
case CPU_DOWN_FAILED_FROZEN:
|
||||
pr_debug("microcode: CPU%d added\n", cpu);
|
||||
|
|
Загрузка…
Ссылка в новой задаче