diff options
| author | Sebastian Andrzej Siewior <bigeasy@linutronix.de> | 2016-09-07 12:45:23 -0400 |
|---|---|---|
| committer | Thomas Gleixner <tglx@linutronix.de> | 2016-09-19 15:44:27 -0400 |
| commit | 29bd7fbc071598e939526f782293dbe137be3768 (patch) | |
| tree | 6545bc71f1e17acf4088c95deb83ffb048fcd597 /arch/x86/kernel/cpu/microcode | |
| parent | 515332336be71d014bca1d29369c5d72baa38f71 (diff) | |
x86/microcode: Convert to hotplug state machine
Install the callbacks via the state machine.
CPU_UP_CANCELED_FROZEN() is not preserved: It is only there to free memory in an
error case because it is assumed if the CPU does show up on resume it won't be
seen ever again. As per Borislav:
|IOW, you don't need mc_cpu_dead().
Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Borislav Petkov <bp@alien8.de>
Cc: rt@linutronix.de
Link: http://lkml.kernel.org/r/20160907164523.46a2xnffha4bv63g@linutronix.de
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Diffstat (limited to 'arch/x86/kernel/cpu/microcode')
| -rw-r--r-- | arch/x86/kernel/cpu/microcode/core.c | 52 |
1 files changed, 17 insertions, 35 deletions
diff --git a/arch/x86/kernel/cpu/microcode/core.c b/arch/x86/kernel/cpu/microcode/core.c index df04b2d033f6..5ce5155f0695 100644 --- a/arch/x86/kernel/cpu/microcode/core.c +++ b/arch/x86/kernel/cpu/microcode/core.c | |||
| @@ -558,55 +558,36 @@ static struct syscore_ops mc_syscore_ops = { | |||
| 558 | .resume = mc_bp_resume, | 558 | .resume = mc_bp_resume, |
| 559 | }; | 559 | }; |
| 560 | 560 | ||
| 561 | static int | 561 | static int mc_cpu_online(unsigned int cpu) |
| 562 | mc_cpu_callback(struct notifier_block *nb, unsigned long action, void *hcpu) | ||
| 563 | { | 562 | { |
| 564 | unsigned int cpu = (unsigned long)hcpu; | ||
| 565 | struct device *dev; | 563 | struct device *dev; |
| 566 | 564 | ||
| 567 | dev = get_cpu_device(cpu); | 565 | dev = get_cpu_device(cpu); |
| 566 | microcode_update_cpu(cpu); | ||
| 567 | pr_debug("CPU%d added\n", cpu); | ||
| 568 | 568 | ||
| 569 | switch (action & ~CPU_TASKS_FROZEN) { | 569 | if (sysfs_create_group(&dev->kobj, &mc_attr_group)) |
| 570 | case CPU_ONLINE: | 570 | pr_err("Failed to create group for CPU%d\n", cpu); |
| 571 | microcode_update_cpu(cpu); | 571 | return 0; |
| 572 | pr_debug("CPU%d added\n", cpu); | 572 | } |
| 573 | /* | ||
| 574 | * "break" is missing on purpose here because we want to fall | ||
| 575 | * through in order to create the sysfs group. | ||
| 576 | */ | ||
| 577 | |||
| 578 | case CPU_DOWN_FAILED: | ||
| 579 | if (sysfs_create_group(&dev->kobj, &mc_attr_group)) | ||
| 580 | pr_err("Failed to create group for CPU%d\n", cpu); | ||
| 581 | break; | ||
| 582 | 573 | ||
| 583 | case CPU_DOWN_PREPARE: | 574 | static int mc_cpu_down_prep(unsigned int cpu) |
| 584 | /* Suspend is in progress, only remove the interface */ | 575 | { |
| 585 | sysfs_remove_group(&dev->kobj, &mc_attr_group); | 576 | struct device *dev; |
| 586 | pr_debug("CPU%d removed\n", cpu); | ||
| 587 | break; | ||
| 588 | 577 | ||
| 578 | dev = get_cpu_device(cpu); | ||
| 579 | /* Suspend is in progress, only remove the interface */ | ||
| 580 | sysfs_remove_group(&dev->kobj, &mc_attr_group); | ||
| 581 | pr_debug("CPU%d removed\n", cpu); | ||
| 589 | /* | 582 | /* |
| 590 | * case CPU_DEAD: | ||
| 591 | * | ||
| 592 | * When a CPU goes offline, don't free up or invalidate the copy of | 583 | * When a CPU goes offline, don't free up or invalidate the copy of |
| 593 | * the microcode in kernel memory, so that we can reuse it when the | 584 | * the microcode in kernel memory, so that we can reuse it when the |
| 594 | * CPU comes back online without unnecessarily requesting the userspace | 585 | * CPU comes back online without unnecessarily requesting the userspace |
| 595 | * for it again. | 586 | * for it again. |
| 596 | */ | 587 | */ |
| 597 | } | 588 | return 0; |
| 598 | |||
| 599 | /* The CPU refused to come up during a system resume */ | ||
| 600 | if (action == CPU_UP_CANCELED_FROZEN) | ||
| 601 | microcode_fini_cpu(cpu); | ||
| 602 | |||
| 603 | return NOTIFY_OK; | ||
| 604 | } | 589 | } |
| 605 | 590 | ||
| 606 | static struct notifier_block mc_cpu_notifier = { | ||
| 607 | .notifier_call = mc_cpu_callback, | ||
| 608 | }; | ||
| 609 | |||
| 610 | static struct attribute *cpu_root_microcode_attrs[] = { | 591 | static struct attribute *cpu_root_microcode_attrs[] = { |
| 611 | &dev_attr_reload.attr, | 592 | &dev_attr_reload.attr, |
| 612 | NULL | 593 | NULL |
| @@ -665,7 +646,8 @@ int __init microcode_init(void) | |||
| 665 | goto out_ucode_group; | 646 | goto out_ucode_group; |
| 666 | 647 | ||
| 667 | register_syscore_ops(&mc_syscore_ops); | 648 | register_syscore_ops(&mc_syscore_ops); |
| 668 | register_hotcpu_notifier(&mc_cpu_notifier); | 649 | cpuhp_setup_state_nocalls(CPUHP_AP_ONLINE_DYN, "x86/microcode:online", |
| 650 | mc_cpu_online, mc_cpu_down_prep); | ||
| 669 | 651 | ||
| 670 | pr_info("Microcode Update Driver: v" MICROCODE_VERSION | 652 | pr_info("Microcode Update Driver: v" MICROCODE_VERSION |
| 671 | " <tigran@aivazian.fsnet.co.uk>, Peter Oruba\n"); | 653 | " <tigran@aivazian.fsnet.co.uk>, Peter Oruba\n"); |
