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:
Rusty Russell 2009-03-11 16:32:36 +10:30 коммит произвёл Ingo Molnar
Родитель 30e1e6d1af
Коммит af5c820a31
1 изменённых файлов: 61 добавлений и 45 удалений

Просмотреть файл

@ -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(&microcode_mutex);
if (uci->valid) {
err = microcode_ops->request_microcode_fw(smp_processor_id(),
&microcode_pdev->dev);
if (!err)
microcode_ops->apply_microcode(smp_processor_id());
}
mutex_unlock(&microcode_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(&microcode_mutex);
if (uci->valid) {
err = microcode_ops->request_microcode_fw(cpu,
&microcode_pdev->dev);
if (!err)
microcode_ops->apply_microcode(cpu);
}
mutex_unlock(&microcode_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(),
&microcode_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(&microcode_mutex);
microcode_update_cpu(cpu);
err = work_on_cpu(cpu, microcode_update_cpu, NULL);
mutex_unlock(&microcode_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);