Merge branch 'x86-microcode-for-linus' of git://git.kernel.org/pub/scm/linux/kernel...
authorLinus Torvalds <torvalds@linux-foundation.org>
Tue, 18 May 2010 16:17:17 +0000 (09:17 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Tue, 18 May 2010 16:17:17 +0000 (09:17 -0700)
* 'x86-microcode-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip:
  x86/microcode: Use nonseekable_open()
  x86: Improve Intel microcode loader performance

arch/x86/kernel/microcode_core.c
arch/x86/kernel/microcode_intel.c

index cceb5bc..2cd8c54 100644 (file)
@@ -201,9 +201,9 @@ static int do_microcode_update(const void __user *buf, size_t size)
        return error;
 }
 
-static int microcode_open(struct inode *unused1, struct file *unused2)
+static int microcode_open(struct inode *inode, struct file *file)
 {
-       return capable(CAP_SYS_RAWIO) ? 0 : -EPERM;
+       return capable(CAP_SYS_RAWIO) ? nonseekable_open(inode, file) : -EPERM;
 }
 
 static ssize_t microcode_write(struct file *file, const char __user *buf,
index 85a343e..3561702 100644 (file)
@@ -343,10 +343,11 @@ static enum ucode_state generic_load_microcode(int cpu, void *data, size_t size,
                                int (*get_ucode_data)(void *, const void *, size_t))
 {
        struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
-       u8 *ucode_ptr = data, *new_mc = NULL, *mc;
+       u8 *ucode_ptr = data, *new_mc = NULL, *mc = NULL;
        int new_rev = uci->cpu_sig.rev;
        unsigned int leftover = size;
        enum ucode_state state = UCODE_OK;
+       unsigned int curr_mc_size = 0;
 
        while (leftover) {
                struct microcode_header_intel mc_header;
@@ -361,9 +362,15 @@ static enum ucode_state generic_load_microcode(int cpu, void *data, size_t size,
                        break;
                }
 
-               mc = vmalloc(mc_size);
-               if (!mc)
-                       break;
+               /* For performance reasons, reuse mc area when possible */
+               if (!mc || mc_size > curr_mc_size) {
+                       if (mc)
+                               vfree(mc);
+                       mc = vmalloc(mc_size);
+                       if (!mc)
+                               break;
+                       curr_mc_size = mc_size;
+               }
 
                if (get_ucode_data(mc, ucode_ptr, mc_size) ||
                    microcode_sanity_check(mc) < 0) {
@@ -376,13 +383,16 @@ static enum ucode_state generic_load_microcode(int cpu, void *data, size_t size,
                                vfree(new_mc);
                        new_rev = mc_header.rev;
                        new_mc  = mc;
-               } else
-                       vfree(mc);
+                       mc = NULL;      /* trigger new vmalloc */
+               }
 
                ucode_ptr += mc_size;
                leftover  -= mc_size;
        }
 
+       if (mc)
+               vfree(mc);
+
        if (leftover) {
                if (new_mc)
                        vfree(new_mc);