Merge branch 'for-2.6.27' of git://git.infradead.org/users/dwmw2/firmware-2.6
[linux-2.6.git] / arch / x86 / kernel / microcode.c
index 6ff447f9fda702398aaaaef9aa8f93143c56a12d..56b933119a04f5551094ce08feeb12bf2642aa6b 100644 (file)
@@ -5,13 +5,14 @@
  *                   2006      Shaohua Li <shaohua.li@intel.com>
  *
  *     This driver allows to upgrade microcode on Intel processors
- *     belonging to IA-32 family - PentiumPro, Pentium II, 
+ *     belonging to IA-32 family - PentiumPro, Pentium II,
  *     Pentium III, Xeon, Pentium 4, etc.
  *
- *     Reference: Section 8.10 of Volume III, Intel Pentium 4 Manual, 
- *     Order Number 245472 or free download from:
- *             
- *     http://developer.intel.com/design/pentium4/manuals/245472.htm
+ *     Reference: Section 8.11 of Volume 3a, IA-32 Intel? Architecture
+ *     Software Developer's Manual
+ *     Order Number 253668 or free download from:
+ *
+ *     http://developer.intel.com/design/pentium4/manuals/253668.htm
  *
  *     For more information, go to http://www.urbanmyth.org/microcode
  *
  *             nature of implementation.
  *     1.11    22 Mar 2002 Tigran Aivazian <tigran@veritas.com>
  *             Fix the panic when writing zero-length microcode chunk.
- *     1.12    29 Sep 2003 Nitin Kamble <nitin.a.kamble@intel.com>, 
+ *     1.12    29 Sep 2003 Nitin Kamble <nitin.a.kamble@intel.com>,
  *             Jun Nakajima <jun.nakajima@intel.com>
  *             Support for the microcode updates in the new format.
  *     1.13    10 Oct 2003 Tigran Aivazian <tigran@veritas.com>
  *             Removed ->read() method and obsoleted MICROCODE_IOCFREE ioctl
- *             because we no longer hold a copy of applied microcode 
+ *             because we no longer hold a copy of applied microcode
  *             in kernel memory.
  *     1.14    25 Jun 2004 Tigran Aivazian <tigran@veritas.com>
  *             Fix sigmatch() macro to handle old CPUs with pf == 0.
@@ -75,6 +76,7 @@
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/sched.h>
+#include <linux/smp_lock.h>
 #include <linux/cpumask.h>
 #include <linux/module.h>
 #include <linux/slab.h>
@@ -290,7 +292,7 @@ static int get_maching_microcode(void *mc, int cpu)
        }
        return 0;
 find:
-       pr_debug("microcode: CPU %d found a matching microcode update with"
+       pr_debug("microcode: CPU%d found a matching microcode update with"
                " version 0x%x (current=0x%x)\n", cpu, mc_header->rev,uci->rev);
        new_mc = vmalloc(total_size);
        if (!new_mc) {
@@ -320,11 +322,11 @@ static void apply_microcode(int cpu)
                return;
 
        /* serialize access to the physical write to MSR 0x79 */
-       spin_lock_irqsave(&microcode_update_lock, flags);          
+       spin_lock_irqsave(&microcode_update_lock, flags);
 
        /* write microcode via MSR 0x79 */
        wrmsr(MSR_IA32_UCODE_WRITE,
-               (unsigned long) uci->mc->bits, 
+               (unsigned long) uci->mc->bits,
                (unsigned long) uci->mc->bits >> 16 >> 16);
        wrmsr(MSR_IA32_UCODE_REV, 0, 0);
 
@@ -336,12 +338,12 @@ static void apply_microcode(int cpu)
 
        spin_unlock_irqrestore(&microcode_update_lock, flags);
        if (val[1] != uci->mc->hdr.rev) {
-               printk(KERN_ERR "microcode: CPU%d updated from revision "
+               printk(KERN_ERR "microcode: CPU%d update from revision "
                        "0x%x to 0x%x failed\n", cpu_num, uci->rev, val[1]);
                return;
        }
-       pr_debug("microcode: CPU%d updated from revision "
-              "0x%x to 0x%x, date = %08x \n", 
+       printk(KERN_INFO "microcode: CPU%d updated from revision "
+              "0x%x to 0x%x, date = %08x \n",
               cpu_num, uci->rev, val[1], uci->mc->hdr.date);
        uci->rev = val[1];
 }
@@ -402,7 +404,7 @@ static int do_microcode_update (void)
 
                        if (!uci->valid)
                                continue;
-                       set_cpus_allowed(current, cpumask_of_cpu(cpu));
+                       set_cpus_allowed_ptr(current, &cpumask_of_cpu(cpu));
                        error = get_maching_microcode(new_mc, cpu);
                        if (error < 0)
                                goto out;
@@ -416,12 +418,13 @@ out:
                vfree(new_mc);
        if (cursor < 0)
                error = cursor;
-       set_cpus_allowed(current, old);
+       set_cpus_allowed_ptr(current, &old);
        return error;
 }
 
 static int microcode_open (struct inode *unused1, struct file *unused2)
 {
+       cycle_kernel_lock();
        return capable(CAP_SYS_RAWIO) ? 0 : -EPERM;
 }
 
@@ -488,7 +491,7 @@ MODULE_ALIAS_MISCDEV(MICROCODE_MINOR);
 #define microcode_dev_exit() do { } while(0)
 #endif
 
-static long get_next_ucode_from_buffer(void **mc, void *buf,
+static long get_next_ucode_from_buffer(void **mc, const u8 *buf,
        unsigned long size, long offset)
 {
        microcode_header_t *mc_header;
@@ -522,7 +525,7 @@ static int cpu_request_microcode(int cpu)
        char name[30];
        struct cpuinfo_x86 *c = &cpu_data(cpu);
        const struct firmware *firmware;
-       void *buf;
+       const u8 *buf;
        unsigned long size;
        long offset = 0;
        int error;
@@ -534,7 +537,7 @@ static int cpu_request_microcode(int cpu)
                c->x86, c->x86_model, c->x86_mask);
        error = request_firmware(&firmware, name, &microcode_pdev->dev);
        if (error) {
-               pr_debug("ucode data file %s load failed\n", name);
+               pr_debug("microcode: data file %s load failed\n", name);
                return error;
        }
        buf = firmware->data;
@@ -579,7 +582,7 @@ static int apply_microcode_check_cpu(int cpu)
                return 0;
 
        old = current->cpus_allowed;
-       set_cpus_allowed(current, cpumask_of_cpu(cpu));
+       set_cpus_allowed_ptr(current, &cpumask_of_cpu(cpu));
 
        /* Check if the microcode we have in memory matches the CPU */
        if (c->x86_vendor != X86_VENDOR_INTEL || c->x86 < 6 ||
@@ -610,7 +613,7 @@ static int apply_microcode_check_cpu(int cpu)
                        " sig=0x%x, pf=0x%x, rev=0x%x\n",
                        cpu, uci->sig, uci->pf, uci->rev);
 
-       set_cpus_allowed(current, old);
+       set_cpus_allowed_ptr(current, &old);
        return err;
 }
 
@@ -621,13 +624,13 @@ static void microcode_init_cpu(int cpu, int resume)
 
        old = current->cpus_allowed;
 
-       set_cpus_allowed(current, cpumask_of_cpu(cpu));
+       set_cpus_allowed_ptr(current, &cpumask_of_cpu(cpu));
        mutex_lock(&microcode_mutex);
        collect_cpu_info(cpu);
        if (uci->valid && system_state == SYSTEM_RUNNING && !resume)
                cpu_request_microcode(cpu);
        mutex_unlock(&microcode_mutex);
-       set_cpus_allowed(current, old);
+       set_cpus_allowed_ptr(current, &old);
 }
 
 static void microcode_fini_cpu(int cpu)
@@ -657,14 +660,14 @@ static ssize_t reload_store(struct sys_device *dev, const char *buf, size_t sz)
                old = current->cpus_allowed;
 
                get_online_cpus();
-               set_cpus_allowed(current, cpumask_of_cpu(cpu));
+               set_cpus_allowed_ptr(current, &cpumask_of_cpu(cpu));
 
                mutex_lock(&microcode_mutex);
                if (uci->valid)
                        err = cpu_request_microcode(cpu);
                mutex_unlock(&microcode_mutex);
                put_online_cpus();
-               set_cpus_allowed(current, old);
+               set_cpus_allowed_ptr(current, &old);
        }
        if (err)
                return err;
@@ -709,7 +712,7 @@ static int __mc_sysdev_add(struct sys_device *sys_dev, int resume)
        if (!cpu_online(cpu))
                return 0;
 
-       pr_debug("Microcode:CPU %d added\n", cpu);
+       pr_debug("microcode: CPU%d added\n", cpu);
        memset(uci, 0, sizeof(*uci));
 
        err = sysfs_create_group(&sys_dev->kobj, &mc_attr_group);
@@ -733,7 +736,7 @@ static int mc_sysdev_remove(struct sys_device *sys_dev)
        if (!cpu_online(cpu))
                return 0;
 
-       pr_debug("Microcode:CPU %d removed\n", cpu);
+       pr_debug("microcode: CPU%d removed\n", cpu);
        microcode_fini_cpu(cpu);
        sysfs_remove_group(&sys_dev->kobj, &mc_attr_group);
        return 0;
@@ -745,7 +748,7 @@ static int mc_sysdev_resume(struct sys_device *dev)
 
        if (!cpu_online(cpu))
                return 0;
-       pr_debug("Microcode:CPU %d resumed\n", cpu);
+       pr_debug("microcode: CPU%d resumed\n", cpu);
        /* only CPU 0 will apply ucode here */
        apply_microcode(0);
        return 0;
@@ -783,7 +786,7 @@ mc_cpu_callback(struct notifier_block *nb, unsigned long action, void *hcpu)
                }
        case CPU_DOWN_FAILED_FROZEN:
                if (sysfs_create_group(&sys_dev->kobj, &mc_attr_group))
-                       printk(KERN_ERR "Microcode: Failed to create the sysfs "
+                       printk(KERN_ERR "microcode: Failed to create the sysfs "
                                "group for CPU%d\n", cpu);
                break;
        case CPU_DOWN_PREPARE:
@@ -797,7 +800,7 @@ mc_cpu_callback(struct notifier_block *nb, unsigned long action, void *hcpu)
        return NOTIFY_OK;
 }
 
-static struct notifier_block __cpuinitdata mc_cpu_notifier = {
+static struct notifier_block __refdata mc_cpu_notifier = {
        .notifier_call = mc_cpu_callback,
 };
 
@@ -805,6 +808,9 @@ static int __init microcode_init (void)
 {
        int error;
 
+       printk(KERN_INFO
+               "IA-32 Microcode Update Driver: v" MICROCODE_VERSION " <tigran@aivazian.fsnet.co.uk>\n");
+
        error = microcode_dev_init();
        if (error)
                return error;
@@ -825,9 +831,6 @@ static int __init microcode_init (void)
        }
 
        register_hotcpu_notifier(&mc_cpu_notifier);
-
-       printk(KERN_INFO 
-               "IA-32 Microcode Update Driver: v" MICROCODE_VERSION " <tigran@aivazian.fsnet.co.uk>\n");
        return 0;
 }