diff options
Diffstat (limited to 'arch/x86/kernel/microcode_amd.c')
| -rw-r--r-- | arch/x86/kernel/microcode_amd.c | 232 |
1 files changed, 86 insertions, 146 deletions
diff --git a/arch/x86/kernel/microcode_amd.c b/arch/x86/kernel/microcode_amd.c index 5f8e5d75a254..c25fdb382292 100644 --- a/arch/x86/kernel/microcode_amd.c +++ b/arch/x86/kernel/microcode_amd.c | |||
| @@ -10,7 +10,7 @@ | |||
| 10 | * This driver allows to upgrade microcode on AMD | 10 | * This driver allows to upgrade microcode on AMD |
| 11 | * family 0x10 and 0x11 processors. | 11 | * family 0x10 and 0x11 processors. |
| 12 | * | 12 | * |
| 13 | * Licensed unter the terms of the GNU General Public | 13 | * Licensed under the terms of the GNU General Public |
| 14 | * License version 2. See file COPYING for details. | 14 | * License version 2. See file COPYING for details. |
| 15 | */ | 15 | */ |
| 16 | 16 | ||
| @@ -32,9 +32,9 @@ | |||
| 32 | #include <linux/platform_device.h> | 32 | #include <linux/platform_device.h> |
| 33 | #include <linux/pci.h> | 33 | #include <linux/pci.h> |
| 34 | #include <linux/pci_ids.h> | 34 | #include <linux/pci_ids.h> |
| 35 | #include <linux/uaccess.h> | ||
| 35 | 36 | ||
| 36 | #include <asm/msr.h> | 37 | #include <asm/msr.h> |
| 37 | #include <asm/uaccess.h> | ||
| 38 | #include <asm/processor.h> | 38 | #include <asm/processor.h> |
| 39 | #include <asm/microcode.h> | 39 | #include <asm/microcode.h> |
| 40 | 40 | ||
| @@ -47,43 +47,38 @@ MODULE_LICENSE("GPL v2"); | |||
| 47 | #define UCODE_UCODE_TYPE 0x00000001 | 47 | #define UCODE_UCODE_TYPE 0x00000001 |
| 48 | 48 | ||
| 49 | struct equiv_cpu_entry { | 49 | struct equiv_cpu_entry { |
| 50 | unsigned int installed_cpu; | 50 | u32 installed_cpu; |
| 51 | unsigned int fixed_errata_mask; | 51 | u32 fixed_errata_mask; |
| 52 | unsigned int fixed_errata_compare; | 52 | u32 fixed_errata_compare; |
| 53 | unsigned int equiv_cpu; | 53 | u16 equiv_cpu; |
| 54 | }; | 54 | u16 res; |
| 55 | } __attribute__((packed)); | ||
| 55 | 56 | ||
| 56 | struct microcode_header_amd { | 57 | struct microcode_header_amd { |
| 57 | unsigned int data_code; | 58 | u32 data_code; |
| 58 | unsigned int patch_id; | 59 | u32 patch_id; |
| 59 | unsigned char mc_patch_data_id[2]; | 60 | u16 mc_patch_data_id; |
| 60 | unsigned char mc_patch_data_len; | 61 | u8 mc_patch_data_len; |
| 61 | unsigned char init_flag; | 62 | u8 init_flag; |
| 62 | unsigned int mc_patch_data_checksum; | 63 | u32 mc_patch_data_checksum; |
| 63 | unsigned int nb_dev_id; | 64 | u32 nb_dev_id; |
| 64 | unsigned int sb_dev_id; | 65 | u32 sb_dev_id; |
| 65 | unsigned char processor_rev_id[2]; | 66 | u16 processor_rev_id; |
| 66 | unsigned char nb_rev_id; | 67 | u8 nb_rev_id; |
| 67 | unsigned char sb_rev_id; | 68 | u8 sb_rev_id; |
| 68 | unsigned char bios_api_rev; | 69 | u8 bios_api_rev; |
| 69 | unsigned char reserved1[3]; | 70 | u8 reserved1[3]; |
| 70 | unsigned int match_reg[8]; | 71 | u32 match_reg[8]; |
| 71 | }; | 72 | } __attribute__((packed)); |
| 72 | 73 | ||
| 73 | struct microcode_amd { | 74 | struct microcode_amd { |
| 74 | struct microcode_header_amd hdr; | 75 | struct microcode_header_amd hdr; |
| 75 | unsigned int mpb[0]; | 76 | unsigned int mpb[0]; |
| 76 | }; | 77 | }; |
| 77 | 78 | ||
| 78 | #define UCODE_MAX_SIZE (2048) | 79 | #define UCODE_MAX_SIZE 2048 |
| 79 | #define DEFAULT_UCODE_DATASIZE (896) | 80 | #define UCODE_CONTAINER_SECTION_HDR 8 |
| 80 | #define MC_HEADER_SIZE (sizeof(struct microcode_header_amd)) | 81 | #define UCODE_CONTAINER_HEADER_SIZE 12 |
| 81 | #define DEFAULT_UCODE_TOTALSIZE (DEFAULT_UCODE_DATASIZE + MC_HEADER_SIZE) | ||
| 82 | #define DWSIZE (sizeof(u32)) | ||
| 83 | /* For now we support a fixed ucode total size only */ | ||
| 84 | #define get_totalsize(mc) \ | ||
| 85 | ((((struct microcode_amd *)mc)->hdr.mc_patch_data_len * 28) \ | ||
| 86 | + MC_HEADER_SIZE) | ||
| 87 | 82 | ||
| 88 | /* serialize access to the physical write */ | 83 | /* serialize access to the physical write */ |
| 89 | static DEFINE_SPINLOCK(microcode_update_lock); | 84 | static DEFINE_SPINLOCK(microcode_update_lock); |
| @@ -93,31 +88,24 @@ static struct equiv_cpu_entry *equiv_cpu_table; | |||
| 93 | static int collect_cpu_info_amd(int cpu, struct cpu_signature *csig) | 88 | static int collect_cpu_info_amd(int cpu, struct cpu_signature *csig) |
| 94 | { | 89 | { |
| 95 | struct cpuinfo_x86 *c = &cpu_data(cpu); | 90 | struct cpuinfo_x86 *c = &cpu_data(cpu); |
| 91 | u32 dummy; | ||
| 96 | 92 | ||
| 97 | memset(csig, 0, sizeof(*csig)); | 93 | memset(csig, 0, sizeof(*csig)); |
| 98 | |||
| 99 | if (c->x86_vendor != X86_VENDOR_AMD || c->x86 < 0x10) { | 94 | if (c->x86_vendor != X86_VENDOR_AMD || c->x86 < 0x10) { |
| 100 | printk(KERN_ERR "microcode: CPU%d not a capable AMD processor\n", | 95 | printk(KERN_WARNING "microcode: CPU%d: AMD CPU family 0x%x not " |
| 101 | cpu); | 96 | "supported\n", cpu, c->x86); |
| 102 | return -1; | 97 | return -1; |
| 103 | } | 98 | } |
| 104 | 99 | rdmsr(MSR_AMD64_PATCH_LEVEL, csig->rev, dummy); | |
| 105 | asm volatile("movl %1, %%ecx; rdmsr" | 100 | printk(KERN_INFO "microcode: CPU%d: patch_level=0x%x\n", cpu, csig->rev); |
| 106 | : "=a" (csig->rev) | ||
| 107 | : "i" (0x0000008B) : "ecx"); | ||
| 108 | |||
| 109 | printk(KERN_INFO "microcode: collect_cpu_info_amd : patch_id=0x%x\n", | ||
| 110 | csig->rev); | ||
| 111 | |||
| 112 | return 0; | 101 | return 0; |
| 113 | } | 102 | } |
| 114 | 103 | ||
| 115 | static int get_matching_microcode(int cpu, void *mc, int rev) | 104 | static int get_matching_microcode(int cpu, void *mc, int rev) |
| 116 | { | 105 | { |
| 117 | struct microcode_header_amd *mc_header = mc; | 106 | struct microcode_header_amd *mc_header = mc; |
| 118 | struct pci_dev *nb_pci_dev, *sb_pci_dev; | ||
| 119 | unsigned int current_cpu_id; | 107 | unsigned int current_cpu_id; |
| 120 | unsigned int equiv_cpu_id = 0x00; | 108 | u16 equiv_cpu_id = 0; |
| 121 | unsigned int i = 0; | 109 | unsigned int i = 0; |
| 122 | 110 | ||
| 123 | BUG_ON(equiv_cpu_table == NULL); | 111 | BUG_ON(equiv_cpu_table == NULL); |
| @@ -132,57 +120,25 @@ static int get_matching_microcode(int cpu, void *mc, int rev) | |||
| 132 | } | 120 | } |
| 133 | 121 | ||
| 134 | if (!equiv_cpu_id) { | 122 | if (!equiv_cpu_id) { |
| 135 | printk(KERN_ERR "microcode: CPU%d cpu_id " | 123 | printk(KERN_WARNING "microcode: CPU%d: cpu revision " |
| 136 | "not found in equivalent cpu table \n", cpu); | 124 | "not listed in equivalent cpu table\n", cpu); |
| 137 | return 0; | 125 | return 0; |
| 138 | } | 126 | } |
| 139 | 127 | ||
| 140 | if ((mc_header->processor_rev_id[0]) != (equiv_cpu_id & 0xff)) { | 128 | if (mc_header->processor_rev_id != equiv_cpu_id) { |
| 141 | printk(KERN_ERR | 129 | printk(KERN_ERR "microcode: CPU%d: patch mismatch " |
| 142 | "microcode: CPU%d patch does not match " | 130 | "(processor_rev_id: %x, equiv_cpu_id: %x)\n", |
| 143 | "(patch is %x, cpu extended is %x) \n", | 131 | cpu, mc_header->processor_rev_id, equiv_cpu_id); |
| 144 | cpu, mc_header->processor_rev_id[0], | ||
| 145 | (equiv_cpu_id & 0xff)); | ||
| 146 | return 0; | 132 | return 0; |
| 147 | } | 133 | } |
| 148 | 134 | ||
| 149 | if ((mc_header->processor_rev_id[1]) != ((equiv_cpu_id >> 16) & 0xff)) { | 135 | /* ucode might be chipset specific -- currently we don't support this */ |
| 150 | printk(KERN_ERR "microcode: CPU%d patch does not match " | 136 | if (mc_header->nb_dev_id || mc_header->sb_dev_id) { |
| 151 | "(patch is %x, cpu base id is %x) \n", | 137 | printk(KERN_ERR "microcode: CPU%d: loading of chipset " |
| 152 | cpu, mc_header->processor_rev_id[1], | 138 | "specific code not yet supported\n", cpu); |
| 153 | ((equiv_cpu_id >> 16) & 0xff)); | ||
| 154 | |||
| 155 | return 0; | 139 | return 0; |
| 156 | } | 140 | } |
| 157 | 141 | ||
| 158 | /* ucode may be northbridge specific */ | ||
| 159 | if (mc_header->nb_dev_id) { | ||
| 160 | nb_pci_dev = pci_get_device(PCI_VENDOR_ID_AMD, | ||
| 161 | (mc_header->nb_dev_id & 0xff), | ||
| 162 | NULL); | ||
| 163 | if ((!nb_pci_dev) || | ||
| 164 | (mc_header->nb_rev_id != nb_pci_dev->revision)) { | ||
| 165 | printk(KERN_ERR "microcode: CPU%d NB mismatch \n", cpu); | ||
| 166 | pci_dev_put(nb_pci_dev); | ||
| 167 | return 0; | ||
| 168 | } | ||
| 169 | pci_dev_put(nb_pci_dev); | ||
| 170 | } | ||
| 171 | |||
| 172 | /* ucode may be southbridge specific */ | ||
| 173 | if (mc_header->sb_dev_id) { | ||
| 174 | sb_pci_dev = pci_get_device(PCI_VENDOR_ID_AMD, | ||
| 175 | (mc_header->sb_dev_id & 0xff), | ||
| 176 | NULL); | ||
| 177 | if ((!sb_pci_dev) || | ||
| 178 | (mc_header->sb_rev_id != sb_pci_dev->revision)) { | ||
| 179 | printk(KERN_ERR "microcode: CPU%d SB mismatch \n", cpu); | ||
| 180 | pci_dev_put(sb_pci_dev); | ||
| 181 | return 0; | ||
| 182 | } | ||
| 183 | pci_dev_put(sb_pci_dev); | ||
| 184 | } | ||
| 185 | |||
| 186 | if (mc_header->patch_id <= rev) | 142 | if (mc_header->patch_id <= rev) |
| 187 | return 0; | 143 | return 0; |
| 188 | 144 | ||
| @@ -192,12 +148,10 @@ static int get_matching_microcode(int cpu, void *mc, int rev) | |||
| 192 | static void apply_microcode_amd(int cpu) | 148 | static void apply_microcode_amd(int cpu) |
| 193 | { | 149 | { |
| 194 | unsigned long flags; | 150 | unsigned long flags; |
| 195 | unsigned int eax, edx; | 151 | u32 rev, dummy; |
| 196 | unsigned int rev; | ||
| 197 | int cpu_num = raw_smp_processor_id(); | 152 | int cpu_num = raw_smp_processor_id(); |
| 198 | struct ucode_cpu_info *uci = ucode_cpu_info + cpu_num; | 153 | struct ucode_cpu_info *uci = ucode_cpu_info + cpu_num; |
| 199 | struct microcode_amd *mc_amd = uci->mc; | 154 | struct microcode_amd *mc_amd = uci->mc; |
| 200 | unsigned long addr; | ||
| 201 | 155 | ||
| 202 | /* We should bind the task to the CPU */ | 156 | /* We should bind the task to the CPU */ |
| 203 | BUG_ON(cpu_num != cpu); | 157 | BUG_ON(cpu_num != cpu); |
| @@ -206,42 +160,34 @@ static void apply_microcode_amd(int cpu) | |||
| 206 | return; | 160 | return; |
| 207 | 161 | ||
| 208 | spin_lock_irqsave(µcode_update_lock, flags); | 162 | spin_lock_irqsave(µcode_update_lock, flags); |
| 209 | 163 | wrmsrl(MSR_AMD64_PATCH_LOADER, (u64)(long)&mc_amd->hdr.data_code); | |
| 210 | addr = (unsigned long)&mc_amd->hdr.data_code; | ||
| 211 | edx = (unsigned int)(((unsigned long)upper_32_bits(addr))); | ||
| 212 | eax = (unsigned int)(((unsigned long)lower_32_bits(addr))); | ||
| 213 | |||
| 214 | asm volatile("movl %0, %%ecx; wrmsr" : | ||
| 215 | : "i" (0xc0010020), "a" (eax), "d" (edx) : "ecx"); | ||
| 216 | |||
| 217 | /* get patch id after patching */ | 164 | /* get patch id after patching */ |
| 218 | asm volatile("movl %1, %%ecx; rdmsr" | 165 | rdmsr(MSR_AMD64_PATCH_LEVEL, rev, dummy); |
| 219 | : "=a" (rev) | ||
| 220 | : "i" (0x0000008B) : "ecx"); | ||
| 221 | |||
| 222 | spin_unlock_irqrestore(µcode_update_lock, flags); | 166 | spin_unlock_irqrestore(µcode_update_lock, flags); |
| 223 | 167 | ||
| 224 | /* check current patch id and patch's id for match */ | 168 | /* check current patch id and patch's id for match */ |
| 225 | if (rev != mc_amd->hdr.patch_id) { | 169 | if (rev != mc_amd->hdr.patch_id) { |
| 226 | printk(KERN_ERR "microcode: CPU%d update from revision " | 170 | printk(KERN_ERR "microcode: CPU%d: update failed " |
| 227 | "0x%x to 0x%x failed\n", cpu_num, | 171 | "(for patch_level=0x%x)\n", cpu, mc_amd->hdr.patch_id); |
| 228 | mc_amd->hdr.patch_id, rev); | ||
| 229 | return; | 172 | return; |
| 230 | } | 173 | } |
| 231 | 174 | ||
| 232 | printk(KERN_INFO "microcode: CPU%d updated from revision " | 175 | printk(KERN_INFO "microcode: CPU%d: updated (new patch_level=0x%x)\n", |
| 233 | "0x%x to 0x%x \n", | 176 | cpu, rev); |
| 234 | cpu_num, uci->cpu_sig.rev, mc_amd->hdr.patch_id); | ||
| 235 | 177 | ||
| 236 | uci->cpu_sig.rev = rev; | 178 | uci->cpu_sig.rev = rev; |
| 237 | } | 179 | } |
| 238 | 180 | ||
| 239 | static void * get_next_ucode(u8 *buf, unsigned int size, | 181 | static int get_ucode_data(void *to, const u8 *from, size_t n) |
| 240 | int (*get_ucode_data)(void *, const void *, size_t), | 182 | { |
| 241 | unsigned int *mc_size) | 183 | memcpy(to, from, n); |
| 184 | return 0; | ||
| 185 | } | ||
| 186 | |||
| 187 | static void *get_next_ucode(const u8 *buf, unsigned int size, | ||
| 188 | unsigned int *mc_size) | ||
| 242 | { | 189 | { |
| 243 | unsigned int total_size; | 190 | unsigned int total_size; |
| 244 | #define UCODE_CONTAINER_SECTION_HDR 8 | ||
| 245 | u8 section_hdr[UCODE_CONTAINER_SECTION_HDR]; | 191 | u8 section_hdr[UCODE_CONTAINER_SECTION_HDR]; |
| 246 | void *mc; | 192 | void *mc; |
| 247 | 193 | ||
| @@ -249,39 +195,37 @@ static void * get_next_ucode(u8 *buf, unsigned int size, | |||
| 249 | return NULL; | 195 | return NULL; |
| 250 | 196 | ||
| 251 | if (section_hdr[0] != UCODE_UCODE_TYPE) { | 197 | if (section_hdr[0] != UCODE_UCODE_TYPE) { |
| 252 | printk(KERN_ERR "microcode: error! " | 198 | printk(KERN_ERR "microcode: error: invalid type field in " |
| 253 | "Wrong microcode payload type field\n"); | 199 | "container file section header\n"); |
| 254 | return NULL; | 200 | return NULL; |
| 255 | } | 201 | } |
| 256 | 202 | ||
| 257 | total_size = (unsigned long) (section_hdr[4] + (section_hdr[5] << 8)); | 203 | total_size = (unsigned long) (section_hdr[4] + (section_hdr[5] << 8)); |
| 258 | 204 | ||
| 259 | printk(KERN_INFO "microcode: size %u, total_size %u\n", | 205 | printk(KERN_DEBUG "microcode: size %u, total_size %u\n", |
| 260 | size, total_size); | 206 | size, total_size); |
| 261 | 207 | ||
| 262 | if (total_size > size || total_size > UCODE_MAX_SIZE) { | 208 | if (total_size > size || total_size > UCODE_MAX_SIZE) { |
| 263 | printk(KERN_ERR "microcode: error! Bad data in microcode data file\n"); | 209 | printk(KERN_ERR "microcode: error: size mismatch\n"); |
| 264 | return NULL; | 210 | return NULL; |
| 265 | } | 211 | } |
| 266 | 212 | ||
| 267 | mc = vmalloc(UCODE_MAX_SIZE); | 213 | mc = vmalloc(UCODE_MAX_SIZE); |
| 268 | if (mc) { | 214 | if (mc) { |
| 269 | memset(mc, 0, UCODE_MAX_SIZE); | 215 | memset(mc, 0, UCODE_MAX_SIZE); |
| 270 | if (get_ucode_data(mc, buf + UCODE_CONTAINER_SECTION_HDR, total_size)) { | 216 | if (get_ucode_data(mc, buf + UCODE_CONTAINER_SECTION_HDR, |
| 217 | total_size)) { | ||
| 271 | vfree(mc); | 218 | vfree(mc); |
| 272 | mc = NULL; | 219 | mc = NULL; |
| 273 | } else | 220 | } else |
| 274 | *mc_size = total_size + UCODE_CONTAINER_SECTION_HDR; | 221 | *mc_size = total_size + UCODE_CONTAINER_SECTION_HDR; |
| 275 | } | 222 | } |
| 276 | #undef UCODE_CONTAINER_SECTION_HDR | ||
| 277 | return mc; | 223 | return mc; |
| 278 | } | 224 | } |
| 279 | 225 | ||
| 280 | 226 | ||
| 281 | static int install_equiv_cpu_table(u8 *buf, | 227 | static int install_equiv_cpu_table(const u8 *buf) |
| 282 | int (*get_ucode_data)(void *, const void *, size_t)) | ||
| 283 | { | 228 | { |
| 284 | #define UCODE_CONTAINER_HEADER_SIZE 12 | ||
| 285 | u8 *container_hdr[UCODE_CONTAINER_HEADER_SIZE]; | 229 | u8 *container_hdr[UCODE_CONTAINER_HEADER_SIZE]; |
| 286 | unsigned int *buf_pos = (unsigned int *)container_hdr; | 230 | unsigned int *buf_pos = (unsigned int *)container_hdr; |
| 287 | unsigned long size; | 231 | unsigned long size; |
| @@ -292,14 +236,15 @@ static int install_equiv_cpu_table(u8 *buf, | |||
| 292 | size = buf_pos[2]; | 236 | size = buf_pos[2]; |
| 293 | 237 | ||
| 294 | if (buf_pos[1] != UCODE_EQUIV_CPU_TABLE_TYPE || !size) { | 238 | if (buf_pos[1] != UCODE_EQUIV_CPU_TABLE_TYPE || !size) { |
| 295 | printk(KERN_ERR "microcode: error! " | 239 | printk(KERN_ERR "microcode: error: invalid type field in " |
| 296 | "Wrong microcode equivalnet cpu table\n"); | 240 | "container file section header\n"); |
| 297 | return 0; | 241 | return 0; |
| 298 | } | 242 | } |
| 299 | 243 | ||
| 300 | equiv_cpu_table = (struct equiv_cpu_entry *) vmalloc(size); | 244 | equiv_cpu_table = (struct equiv_cpu_entry *) vmalloc(size); |
| 301 | if (!equiv_cpu_table) { | 245 | if (!equiv_cpu_table) { |
| 302 | printk(KERN_ERR "microcode: error, can't allocate memory for equiv CPU table\n"); | 246 | printk(KERN_ERR "microcode: failed to allocate " |
| 247 | "equivalent CPU table\n"); | ||
| 303 | return 0; | 248 | return 0; |
| 304 | } | 249 | } |
| 305 | 250 | ||
| @@ -310,7 +255,6 @@ static int install_equiv_cpu_table(u8 *buf, | |||
| 310 | } | 255 | } |
| 311 | 256 | ||
| 312 | return size + UCODE_CONTAINER_HEADER_SIZE; /* add header length */ | 257 | return size + UCODE_CONTAINER_HEADER_SIZE; /* add header length */ |
| 313 | #undef UCODE_CONTAINER_HEADER_SIZE | ||
| 314 | } | 258 | } |
| 315 | 259 | ||
| 316 | static void free_equiv_cpu_table(void) | 260 | static void free_equiv_cpu_table(void) |
| @@ -321,18 +265,20 @@ static void free_equiv_cpu_table(void) | |||
| 321 | } | 265 | } |
| 322 | } | 266 | } |
| 323 | 267 | ||
| 324 | static int generic_load_microcode(int cpu, void *data, size_t size, | 268 | static int generic_load_microcode(int cpu, const u8 *data, size_t size) |
| 325 | int (*get_ucode_data)(void *, const void *, size_t)) | ||
| 326 | { | 269 | { |
| 327 | struct ucode_cpu_info *uci = ucode_cpu_info + cpu; | 270 | struct ucode_cpu_info *uci = ucode_cpu_info + cpu; |
| 328 | u8 *ucode_ptr = data, *new_mc = NULL, *mc; | 271 | const u8 *ucode_ptr = data; |
| 272 | void *new_mc = NULL; | ||
| 273 | void *mc; | ||
| 329 | int new_rev = uci->cpu_sig.rev; | 274 | int new_rev = uci->cpu_sig.rev; |
| 330 | unsigned int leftover; | 275 | unsigned int leftover; |
| 331 | unsigned long offset; | 276 | unsigned long offset; |
| 332 | 277 | ||
| 333 | offset = install_equiv_cpu_table(ucode_ptr, get_ucode_data); | 278 | offset = install_equiv_cpu_table(ucode_ptr); |
| 334 | if (!offset) { | 279 | if (!offset) { |
| 335 | printk(KERN_ERR "microcode: installing equivalent cpu table failed\n"); | 280 | printk(KERN_ERR "microcode: failed to create " |
| 281 | "equivalent cpu table\n"); | ||
| 336 | return -EINVAL; | 282 | return -EINVAL; |
| 337 | } | 283 | } |
| 338 | 284 | ||
| @@ -343,7 +289,7 @@ static int generic_load_microcode(int cpu, void *data, size_t size, | |||
| 343 | unsigned int uninitialized_var(mc_size); | 289 | unsigned int uninitialized_var(mc_size); |
| 344 | struct microcode_header_amd *mc_header; | 290 | struct microcode_header_amd *mc_header; |
| 345 | 291 | ||
| 346 | mc = get_next_ucode(ucode_ptr, leftover, get_ucode_data, &mc_size); | 292 | mc = get_next_ucode(ucode_ptr, leftover, &mc_size); |
| 347 | if (!mc) | 293 | if (!mc) |
| 348 | break; | 294 | break; |
| 349 | 295 | ||
| @@ -353,7 +299,7 @@ static int generic_load_microcode(int cpu, void *data, size_t size, | |||
| 353 | vfree(new_mc); | 299 | vfree(new_mc); |
| 354 | new_rev = mc_header->patch_id; | 300 | new_rev = mc_header->patch_id; |
| 355 | new_mc = mc; | 301 | new_mc = mc; |
| 356 | } else | 302 | } else |
| 357 | vfree(mc); | 303 | vfree(mc); |
| 358 | 304 | ||
| 359 | ucode_ptr += mc_size; | 305 | ucode_ptr += mc_size; |
| @@ -365,9 +311,9 @@ static int generic_load_microcode(int cpu, void *data, size_t size, | |||
| 365 | if (uci->mc) | 311 | if (uci->mc) |
| 366 | vfree(uci->mc); | 312 | vfree(uci->mc); |
| 367 | uci->mc = new_mc; | 313 | uci->mc = new_mc; |
| 368 | pr_debug("microcode: CPU%d found a matching microcode update with" | 314 | pr_debug("microcode: CPU%d found a matching microcode " |
| 369 | " version 0x%x (current=0x%x)\n", | 315 | "update with version 0x%x (current=0x%x)\n", |
| 370 | cpu, new_rev, uci->cpu_sig.rev); | 316 | cpu, new_rev, uci->cpu_sig.rev); |
| 371 | } else | 317 | } else |
| 372 | vfree(new_mc); | 318 | vfree(new_mc); |
| 373 | } | 319 | } |
| @@ -377,12 +323,6 @@ static int generic_load_microcode(int cpu, void *data, size_t size, | |||
| 377 | return (int)leftover; | 323 | return (int)leftover; |
| 378 | } | 324 | } |
| 379 | 325 | ||
| 380 | static int get_ucode_fw(void *to, const void *from, size_t n) | ||
| 381 | { | ||
| 382 | memcpy(to, from, n); | ||
| 383 | return 0; | ||
| 384 | } | ||
| 385 | |||
| 386 | static int request_microcode_fw(int cpu, struct device *device) | 326 | static int request_microcode_fw(int cpu, struct device *device) |
| 387 | { | 327 | { |
| 388 | const char *fw_name = "amd-ucode/microcode_amd.bin"; | 328 | const char *fw_name = "amd-ucode/microcode_amd.bin"; |
| @@ -394,12 +334,11 @@ static int request_microcode_fw(int cpu, struct device *device) | |||
| 394 | 334 | ||
| 395 | ret = request_firmware(&firmware, fw_name, device); | 335 | ret = request_firmware(&firmware, fw_name, device); |
| 396 | if (ret) { | 336 | if (ret) { |
| 397 | printk(KERN_ERR "microcode: ucode data file %s load failed\n", fw_name); | 337 | printk(KERN_ERR "microcode: failed to load file %s\n", fw_name); |
| 398 | return ret; | 338 | return ret; |
| 399 | } | 339 | } |
| 400 | 340 | ||
| 401 | ret = generic_load_microcode(cpu, (void*)firmware->data, firmware->size, | 341 | ret = generic_load_microcode(cpu, firmware->data, firmware->size); |
| 402 | &get_ucode_fw); | ||
| 403 | 342 | ||
| 404 | release_firmware(firmware); | 343 | release_firmware(firmware); |
| 405 | 344 | ||
| @@ -408,8 +347,8 @@ static int request_microcode_fw(int cpu, struct device *device) | |||
| 408 | 347 | ||
| 409 | static int request_microcode_user(int cpu, const void __user *buf, size_t size) | 348 | static int request_microcode_user(int cpu, const void __user *buf, size_t size) |
| 410 | { | 349 | { |
| 411 | printk(KERN_WARNING "microcode: AMD microcode update via /dev/cpu/microcode" | 350 | printk(KERN_INFO "microcode: AMD microcode update via " |
| 412 | "is not supported\n"); | 351 | "/dev/cpu/microcode not supported\n"); |
| 413 | return -1; | 352 | return -1; |
| 414 | } | 353 | } |
| 415 | 354 | ||
| @@ -433,3 +372,4 @@ struct microcode_ops * __init init_amd_microcode(void) | |||
| 433 | { | 372 | { |
| 434 | return µcode_amd_ops; | 373 | return µcode_amd_ops; |
| 435 | } | 374 | } |
| 375 | |||
