]> nv-tegra.nvidia Code Review - linux-3.10.git/blobdiff - arch/x86/kernel/microcode_core.c
x86: fix microcode driver newly spewing warnings
[linux-3.10.git] / arch / x86 / kernel / microcode_core.c
index c9b721ba968c8f779a253919b2c7c046542ea974..4d420de9ac61653f9e7fd0fb8ec89ab63213ce52 100644 (file)
  *             Fix sigmatch() macro to handle old CPUs with pf == 0.
  *             Thanks to Stuart Swales for pointing out this bug.
  */
+#include <linux/platform_device.h>
 #include <linux/capability.h>
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/sched.h>
+#include <linux/miscdevice.h>
+#include <linux/firmware.h>
 #include <linux/smp_lock.h>
+#include <linux/spinlock.h>
 #include <linux/cpumask.h>
-#include <linux/module.h>
-#include <linux/slab.h>
+#include <linux/uaccess.h>
 #include <linux/vmalloc.h>
-#include <linux/miscdevice.h>
-#include <linux/spinlock.h>
-#include <linux/mm.h>
-#include <linux/fs.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
 #include <linux/mutex.h>
+#include <linux/sched.h>
+#include <linux/init.h>
+#include <linux/slab.h>
 #include <linux/cpu.h>
-#include <linux/firmware.h>
-#include <linux/platform_device.h>
+#include <linux/fs.h>
+#include <linux/mm.h>
 
-#include <asm/msr.h>
-#include <asm/uaccess.h>
-#include <asm/processor.h>
 #include <asm/microcode.h>
+#include <asm/processor.h>
+#include <asm/msr.h>
 
 MODULE_DESCRIPTION("Microcode Update Driver");
 MODULE_AUTHOR("Tigran Aivazian <tigran@aivazian.fsnet.co.uk>");
 MODULE_LICENSE("GPL");
 
-#define MICROCODE_VERSION      "2.00"
+#define MICROCODE_VERSION      "2.00"
 
-static struct microcode_ops *microcode_ops;
+static struct microcode_ops    *microcode_ops;
 
 /* no concurrent ->write()s are allowed on /dev/cpu/microcode */
 static DEFINE_MUTEX(microcode_mutex);
 
-struct ucode_cpu_info ucode_cpu_info[NR_CPUS];
+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;
 }
 
@@ -198,18 +209,33 @@ static void microcode_dev_exit(void)
 
 MODULE_ALIAS_MISCDEV(MICROCODE_MINOR);
 #else
-#define microcode_dev_init() 0
-#define microcode_dev_exit() do { } while (0)
+#define microcode_dev_init()   0
+#define microcode_dev_exit()   do { } while (0)
 #endif
 
 /* fake device for request_firmware */
-static struct platform_device *microcode_pdev;
+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)
@@ -268,8 +282,8 @@ static struct attribute *mc_default_attrs[] = {
 };
 
 static struct attribute_group mc_attr_group = {
-       .attrs = mc_default_attrs,
-       .name = "microcode",
+       .attrs          = mc_default_attrs,
+       .name           = "microcode",
 };
 
 static void __microcode_fini_cpu(int cpu)
@@ -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);
-       } else {        
-               collect_cpu_info(cpu);
+               err = microcode_resume_cpu(smp_processor_id());
+       } else {
+               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,9 @@ 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);
+
+       return err;
 }
 
 static int mc_sysdev_remove(struct sys_device *sys_dev)
@@ -404,14 +416,14 @@ 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;
 }
 
 static struct sysdev_driver mc_sysdev_driver = {
-       .add = mc_sysdev_add,
-       .remove = mc_sysdev_remove,
-       .resume = mc_sysdev_resume,
+       .add            = mc_sysdev_add,
+       .remove         = mc_sysdev_remove,
+       .resume         = mc_sysdev_resume,
 };
 
 static __cpuinit int
@@ -424,7 +436,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);
@@ -448,7 +462,7 @@ mc_cpu_callback(struct notifier_block *nb, unsigned long action, void *hcpu)
 }
 
 static struct notifier_block __refdata mc_cpu_notifier = {
-       .notifier_call = mc_cpu_callback,
+       .notifier_call  = mc_cpu_callback,
 };
 
 static int __init microcode_init(void)