diff options
-rw-r--r-- | arch/i386/kernel/microcode.c | 62 | ||||
-rw-r--r-- | kernel/cpu.c | 10 |
2 files changed, 36 insertions, 36 deletions
diff --git a/arch/i386/kernel/microcode.c b/arch/i386/kernel/microcode.c index 7d934e493e74..83f825f2e2d7 100644 --- a/arch/i386/kernel/microcode.c +++ b/arch/i386/kernel/microcode.c | |||
@@ -567,7 +567,7 @@ static int cpu_request_microcode(int cpu) | |||
567 | return error; | 567 | return error; |
568 | } | 568 | } |
569 | 569 | ||
570 | static int apply_microcode_on_cpu(int cpu) | 570 | static int apply_microcode_check_cpu(int cpu) |
571 | { | 571 | { |
572 | struct cpuinfo_x86 *c = cpu_data + cpu; | 572 | struct cpuinfo_x86 *c = cpu_data + cpu; |
573 | struct ucode_cpu_info *uci = ucode_cpu_info + cpu; | 573 | struct ucode_cpu_info *uci = ucode_cpu_info + cpu; |
@@ -575,8 +575,9 @@ static int apply_microcode_on_cpu(int cpu) | |||
575 | unsigned int val[2]; | 575 | unsigned int val[2]; |
576 | int err = 0; | 576 | int err = 0; |
577 | 577 | ||
578 | /* Check if the microcode is available */ | ||
578 | if (!uci->mc) | 579 | if (!uci->mc) |
579 | return -EINVAL; | 580 | return 0; |
580 | 581 | ||
581 | old = current->cpus_allowed; | 582 | old = current->cpus_allowed; |
582 | set_cpus_allowed(current, cpumask_of_cpu(cpu)); | 583 | set_cpus_allowed(current, cpumask_of_cpu(cpu)); |
@@ -614,7 +615,7 @@ static int apply_microcode_on_cpu(int cpu) | |||
614 | return err; | 615 | return err; |
615 | } | 616 | } |
616 | 617 | ||
617 | static void microcode_init_cpu(int cpu) | 618 | static void microcode_init_cpu(int cpu, int resume) |
618 | { | 619 | { |
619 | cpumask_t old; | 620 | cpumask_t old; |
620 | struct ucode_cpu_info *uci = ucode_cpu_info + cpu; | 621 | struct ucode_cpu_info *uci = ucode_cpu_info + cpu; |
@@ -624,8 +625,7 @@ static void microcode_init_cpu(int cpu) | |||
624 | set_cpus_allowed(current, cpumask_of_cpu(cpu)); | 625 | set_cpus_allowed(current, cpumask_of_cpu(cpu)); |
625 | mutex_lock(µcode_mutex); | 626 | mutex_lock(µcode_mutex); |
626 | collect_cpu_info(cpu); | 627 | collect_cpu_info(cpu); |
627 | if (uci->valid && system_state == SYSTEM_RUNNING && | 628 | if (uci->valid && system_state == SYSTEM_RUNNING && !resume) |
628 | !suspend_cpu_hotplug) | ||
629 | cpu_request_microcode(cpu); | 629 | cpu_request_microcode(cpu); |
630 | mutex_unlock(µcode_mutex); | 630 | mutex_unlock(µcode_mutex); |
631 | set_cpus_allowed(current, old); | 631 | set_cpus_allowed(current, old); |
@@ -702,7 +702,7 @@ static struct attribute_group mc_attr_group = { | |||
702 | .name = "microcode", | 702 | .name = "microcode", |
703 | }; | 703 | }; |
704 | 704 | ||
705 | static int mc_sysdev_add(struct sys_device *sys_dev) | 705 | static int __mc_sysdev_add(struct sys_device *sys_dev, int resume) |
706 | { | 706 | { |
707 | int err, cpu = sys_dev->id; | 707 | int err, cpu = sys_dev->id; |
708 | struct ucode_cpu_info *uci = ucode_cpu_info + cpu; | 708 | struct ucode_cpu_info *uci = ucode_cpu_info + cpu; |
@@ -711,39 +711,31 @@ static int mc_sysdev_add(struct sys_device *sys_dev) | |||
711 | return 0; | 711 | return 0; |
712 | 712 | ||
713 | pr_debug("Microcode:CPU %d added\n", cpu); | 713 | pr_debug("Microcode:CPU %d added\n", cpu); |
714 | /* If suspend_cpu_hotplug is set, the system is resuming and we should | 714 | memset(uci, 0, sizeof(*uci)); |
715 | * use the data from before the suspend. | ||
716 | */ | ||
717 | if (suspend_cpu_hotplug) { | ||
718 | err = apply_microcode_on_cpu(cpu); | ||
719 | if (err) | ||
720 | microcode_fini_cpu(cpu); | ||
721 | } | ||
722 | if (!uci->valid) | ||
723 | memset(uci, 0, sizeof(*uci)); | ||
724 | 715 | ||
725 | err = sysfs_create_group(&sys_dev->kobj, &mc_attr_group); | 716 | err = sysfs_create_group(&sys_dev->kobj, &mc_attr_group); |
726 | if (err) | 717 | if (err) |
727 | return err; | 718 | return err; |
728 | 719 | ||
729 | if (!uci->valid) | 720 | microcode_init_cpu(cpu, resume); |
730 | microcode_init_cpu(cpu); | ||
731 | 721 | ||
732 | return 0; | 722 | return 0; |
733 | } | 723 | } |
734 | 724 | ||
725 | static int mc_sysdev_add(struct sys_device *sys_dev) | ||
726 | { | ||
727 | return __mc_sysdev_add(sys_dev, 0); | ||
728 | } | ||
729 | |||
735 | static int mc_sysdev_remove(struct sys_device *sys_dev) | 730 | static int mc_sysdev_remove(struct sys_device *sys_dev) |
736 | { | 731 | { |
737 | int cpu = sys_dev->id; | 732 | int cpu = sys_dev->id; |
738 | 733 | ||
739 | if (!cpu_online(cpu)) | 734 | if (!cpu_online(cpu)) |
740 | return 0; | 735 | return 0; |
736 | |||
741 | pr_debug("Microcode:CPU %d removed\n", cpu); | 737 | pr_debug("Microcode:CPU %d removed\n", cpu); |
742 | /* If suspend_cpu_hotplug is set, the system is suspending and we should | 738 | microcode_fini_cpu(cpu); |
743 | * keep the microcode in memory for the resume. | ||
744 | */ | ||
745 | if (!suspend_cpu_hotplug) | ||
746 | microcode_fini_cpu(cpu); | ||
747 | sysfs_remove_group(&sys_dev->kobj, &mc_attr_group); | 739 | sysfs_remove_group(&sys_dev->kobj, &mc_attr_group); |
748 | return 0; | 740 | return 0; |
749 | } | 741 | } |
@@ -774,16 +766,34 @@ mc_cpu_callback(struct notifier_block *nb, unsigned long action, void *hcpu) | |||
774 | 766 | ||
775 | sys_dev = get_cpu_sysdev(cpu); | 767 | sys_dev = get_cpu_sysdev(cpu); |
776 | switch (action) { | 768 | switch (action) { |
769 | case CPU_UP_CANCELED_FROZEN: | ||
770 | /* The CPU refused to come up during a system resume */ | ||
771 | microcode_fini_cpu(cpu); | ||
772 | break; | ||
777 | case CPU_ONLINE: | 773 | case CPU_ONLINE: |
778 | case CPU_ONLINE_FROZEN: | ||
779 | case CPU_DOWN_FAILED: | 774 | case CPU_DOWN_FAILED: |
780 | case CPU_DOWN_FAILED_FROZEN: | ||
781 | mc_sysdev_add(sys_dev); | 775 | mc_sysdev_add(sys_dev); |
782 | break; | 776 | break; |
777 | case CPU_ONLINE_FROZEN: | ||
778 | /* System-wide resume is in progress, try to apply microcode */ | ||
779 | if (apply_microcode_check_cpu(cpu)) { | ||
780 | /* The application of microcode failed */ | ||
781 | microcode_fini_cpu(cpu); | ||
782 | __mc_sysdev_add(sys_dev, 1); | ||
783 | break; | ||
784 | } | ||
785 | case CPU_DOWN_FAILED_FROZEN: | ||
786 | if (sysfs_create_group(&sys_dev->kobj, &mc_attr_group)) | ||
787 | printk(KERN_ERR "Microcode: Failed to create the sysfs " | ||
788 | "group for CPU%d\n", cpu); | ||
789 | break; | ||
783 | case CPU_DOWN_PREPARE: | 790 | case CPU_DOWN_PREPARE: |
784 | case CPU_DOWN_PREPARE_FROZEN: | ||
785 | mc_sysdev_remove(sys_dev); | 791 | mc_sysdev_remove(sys_dev); |
786 | break; | 792 | break; |
793 | case CPU_DOWN_PREPARE_FROZEN: | ||
794 | /* Suspend is in progress, only remove the interface */ | ||
795 | sysfs_remove_group(&sys_dev->kobj, &mc_attr_group); | ||
796 | break; | ||
787 | } | 797 | } |
788 | return NOTIFY_OK; | 798 | return NOTIFY_OK; |
789 | } | 799 | } |
diff --git a/kernel/cpu.c b/kernel/cpu.c index 369d2892687d..208cf3497c10 100644 --- a/kernel/cpu.c +++ b/kernel/cpu.c | |||
@@ -262,12 +262,6 @@ int __cpuinit cpu_up(unsigned int cpu) | |||
262 | } | 262 | } |
263 | 263 | ||
264 | #ifdef CONFIG_SUSPEND_SMP | 264 | #ifdef CONFIG_SUSPEND_SMP |
265 | /* Needed to prevent the microcode driver from requesting firmware in its CPU | ||
266 | * hotplug notifier during the suspend/resume. | ||
267 | */ | ||
268 | int suspend_cpu_hotplug; | ||
269 | EXPORT_SYMBOL(suspend_cpu_hotplug); | ||
270 | |||
271 | static cpumask_t frozen_cpus; | 265 | static cpumask_t frozen_cpus; |
272 | 266 | ||
273 | int disable_nonboot_cpus(void) | 267 | int disable_nonboot_cpus(void) |
@@ -275,7 +269,6 @@ int disable_nonboot_cpus(void) | |||
275 | int cpu, first_cpu, error = 0; | 269 | int cpu, first_cpu, error = 0; |
276 | 270 | ||
277 | mutex_lock(&cpu_add_remove_lock); | 271 | mutex_lock(&cpu_add_remove_lock); |
278 | suspend_cpu_hotplug = 1; | ||
279 | first_cpu = first_cpu(cpu_online_map); | 272 | first_cpu = first_cpu(cpu_online_map); |
280 | /* We take down all of the non-boot CPUs in one shot to avoid races | 273 | /* We take down all of the non-boot CPUs in one shot to avoid races |
281 | * with the userspace trying to use the CPU hotplug at the same time | 274 | * with the userspace trying to use the CPU hotplug at the same time |
@@ -302,7 +295,6 @@ int disable_nonboot_cpus(void) | |||
302 | } else { | 295 | } else { |
303 | printk(KERN_ERR "Non-boot CPUs are not disabled\n"); | 296 | printk(KERN_ERR "Non-boot CPUs are not disabled\n"); |
304 | } | 297 | } |
305 | suspend_cpu_hotplug = 0; | ||
306 | mutex_unlock(&cpu_add_remove_lock); | 298 | mutex_unlock(&cpu_add_remove_lock); |
307 | return error; | 299 | return error; |
308 | } | 300 | } |
@@ -317,7 +309,6 @@ void enable_nonboot_cpus(void) | |||
317 | if (cpus_empty(frozen_cpus)) | 309 | if (cpus_empty(frozen_cpus)) |
318 | goto out; | 310 | goto out; |
319 | 311 | ||
320 | suspend_cpu_hotplug = 1; | ||
321 | printk("Enabling non-boot CPUs ...\n"); | 312 | printk("Enabling non-boot CPUs ...\n"); |
322 | for_each_cpu_mask(cpu, frozen_cpus) { | 313 | for_each_cpu_mask(cpu, frozen_cpus) { |
323 | error = _cpu_up(cpu, 1); | 314 | error = _cpu_up(cpu, 1); |
@@ -328,7 +319,6 @@ void enable_nonboot_cpus(void) | |||
328 | printk(KERN_WARNING "Error taking CPU%d up: %d\n", cpu, error); | 319 | printk(KERN_WARNING "Error taking CPU%d up: %d\n", cpu, error); |
329 | } | 320 | } |
330 | cpus_clear(frozen_cpus); | 321 | cpus_clear(frozen_cpus); |
331 | suspend_cpu_hotplug = 0; | ||
332 | out: | 322 | out: |
333 | mutex_unlock(&cpu_add_remove_lock); | 323 | mutex_unlock(&cpu_add_remove_lock); |
334 | } | 324 | } |