From 709dd09c020aa08bc9f17e5f835fe06b34d0d11a Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Fri, 23 Nov 2007 15:31:53 -0500 Subject: [PATCH] Import 2.3.47pre6 --- arch/i386/kernel/microcode.c | 74 +++++++++++++++++++++++++++----------------- drivers/net/tulip.c | 3 +- 2 files changed, 48 insertions(+), 29 deletions(-) diff --git a/arch/i386/kernel/microcode.c b/arch/i386/kernel/microcode.c index 906d82bcf..26b6525d8 100644 --- a/arch/i386/kernel/microcode.c +++ b/arch/i386/kernel/microcode.c @@ -88,7 +88,7 @@ static int __init microcode_init(void) mc_applied = kmalloc(size, GFP_KERNEL); if (!mc_applied) { remove_proc_entry("microcode", proc_root_driver); - printk(KERN_ERR "microcode: can't allocate memory to hold applied microcode\n"); + printk(KERN_ERR "microcode: can't allocate memory for saved microcode\n"); return -ENOMEM; } memset(mc_applied, 0, size); /* so that reading from offsets corresponding to failed @@ -132,28 +132,46 @@ static int microcode_release(struct inode *inode, struct file *file) return 0; } +/* a pointer to 'struct update_req' is passed to the IPI hanlder = do_update_one() + * update_req[cpu].err is set to 1 if update failed on 'cpu', 0 otherwise + * if err==0, microcode[update_req[cpu].slot] points to applied block of microcode + */ +struct update_req { + int err; + int slot; +} update_req[NR_CPUS]; static int do_microcode_update(void) { - int err; + int i, error = 0, err; + struct microcode *m; - if (smp_call_function(do_update_one, &err, 1, 1) != 0) + if (smp_call_function(do_update_one, (void *)update_req, 1, 1) != 0) panic("do_microcode_update(): timed out waiting for other CPUs\n"); - do_update_one(&err); - - return err; + do_update_one((void *)update_req); + + for (i=0; ierr = 1; /* be pessimistic */ if (c->x86_vendor != X86_VENDOR_INTEL || c->x86 < 6) return; @@ -174,29 +192,29 @@ static void do_update_one(void *arg) if (microcode[i].rev <= rev) { printk(KERN_ERR "microcode: CPU%d not 'upgrading' to earlier revision" - " %d (current=%d)\n", id, microcode[i].rev, rev); + " %d (current=%d)\n", cpu_num, microcode[i].rev, rev); } else { int sum = 0; - struct microcode *m, *mcslot; - unsigned int *sump; + struct microcode *m = µcode[i]; + unsigned int *sump = (unsigned int *)(m+1); - m = µcode[i]; - sump = (unsigned int *)(m+1); while (--sump >= (unsigned int *)m) sum += *sump; if (sum != 0) { printk(KERN_ERR "microcode: CPU%d aborting, " - "bad checksum\n", id); + "bad checksum\n", cpu_num); break; } + wrmsr(0x79, (unsigned int)(m->bits), 0); __asm__ __volatile__ ("cpuid"); rdmsr(0x8B, val[0], val[1]); - *err = 0; - mcslot = (struct microcode *)mc_applied + id; - memcpy(mcslot, m, sizeof(struct microcode)); - printk(KERN_ERR "microcode: CPU%d updated from revision " - "%d to %d, date=%08x\n", id, rev, val[1], m->date); + + req->err = 0; + req->slot = i; + printk(KERN_ERR "microcode: CPU%d microcode updated " + "from revision %d to %d, date=%08x\n", + cpu_num, rev, val[1], m->date); } break; } @@ -218,7 +236,7 @@ static ssize_t microcode_read(struct file *file, char *buf, size_t len, loff_t * static ssize_t microcode_write(struct file *file, const char *buf, size_t len, loff_t *ppos) { - int err; + ssize_t ret; if (len % sizeof(struct microcode) != 0) { printk(KERN_ERR "microcode: can only write in N*%d bytes units\n", @@ -237,12 +255,12 @@ static ssize_t microcode_write(struct file *file, const char *buf, size_t len, l unlock_kernel(); return -EFAULT; } - err = do_microcode_update(); - if (err) - len = (size_t)err; - else + ret = do_microcode_update(); + if (!ret) { proc_microcode->size = smp_num_cpus * sizeof(struct microcode); + ret = (ssize_t)len; + } vfree(microcode); unlock_kernel(); - return len; + return ret; } diff --git a/drivers/net/tulip.c b/drivers/net/tulip.c index a20d34cec..c4391741d 100644 --- a/drivers/net/tulip.c +++ b/drivers/net/tulip.c @@ -2717,7 +2717,8 @@ static int __devinit tulip_init_one (struct pci_dev *pdev, if (!request_region (ioaddr, tulip_tbl[chip_idx].io_size, dev->name)) goto err_out_free_netdev; - pci_enable_device (pdev); + pci_enable_device(pdev); + pci_set_master(pdev); tp = dev->priv; memset(tp, 0, sizeof(*tp)); -- 2.11.4.GIT