Messages in this thread Patch in this message | | | Date | Fri, 18 Feb 2000 23:22:39 +0000 (GMT) | From | Tigran Aivazian <> | Subject | [patch-2.3.47-p3] small improvement of microcode driver |
| |
Hi Linus
a) made error handling robust, i.e. independent of which of N cpus failed the update - the entire transaction is failed if at least one cpu failed.
b) reduced the amount of work (greatly!) done inside IPI handler, namely got rid of memcpy() by having an abstract 'update request' structure.
regards, Tigran.
--- microcode.c.0 Fri Feb 18 22:55:18 2000 +++ microcode.c Fri Feb 18 23:16:52 2000 @@ -88,7 +88,7 @@ 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 @@ 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); + do_update_one((void *)update_req); - return err; + for (i=0; i<smp_num_cpus; i++) { + err = update_req[i].err; + error += err; + if (!err) { + m = (struct microcode *)mc_applied + i; + memcpy(m, µcode[update_req[i].slot], sizeof(struct microcode)); + } + } + return error ? -EIO : 0; } static void do_update_one(void *arg) { - int *err = (int *)arg; + struct update_req *req; struct cpuinfo_x86 * c; unsigned int pf = 0, val[2], rev, sig; - int i, id; + int i, cpu_num; - id = smp_processor_id(); - c = cpu_data + id; - *err = 1; /* be pessimistic */ + cpu_num = smp_processor_id(); + c = cpu_data + cpu_num; + req = (struct update_req *)arg + cpu_num; + req->err = 1; /* be pessimistic */ if (c->x86_vendor != X86_VENDOR_INTEL || c->x86 < 6) return; @@ -174,29 +192,29 @@ 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_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 @@ 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; }
- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.rutgers.edu Please read the FAQ at http://www.tux.org/lkml/
| |