aboutsummaryrefslogtreecommitdiffstats
path: root/arch/i386/kernel/microcode.c
diff options
context:
space:
mode:
authorRafael J. Wysocki <rjw@sisk.pl>2007-05-09 05:35:11 -0400
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-05-09 15:30:56 -0400
commit455c017ae3934797653549704c286e7bcc3a9397 (patch)
tree7b5b67916b064e3ce7868082e0915f37b437aeb8 /arch/i386/kernel/microcode.c
parent8bb7844286fb8c9fce6f65d8288aeb09d03a5e0d (diff)
microcode: use suspend-related CPU hotplug notifications
Make the microcode driver use the suspend-related CPU hotplug notifications to handle the CPU hotplug events occuring during system-wide suspend and resume transitions. Remove the global variable suspend_cpu_hotplug previously used for this purpose. Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl> Cc: Gautham R Shenoy <ego@in.ibm.com> Cc: Pavel Machek <pavel@ucw.cz> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'arch/i386/kernel/microcode.c')
-rw-r--r--arch/i386/kernel/microcode.c62
1 files changed, 36 insertions, 26 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
570static int apply_microcode_on_cpu(int cpu) 570static 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
617static void microcode_init_cpu(int cpu) 618static 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(&microcode_mutex); 626 mutex_lock(&microcode_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(&microcode_mutex); 630 mutex_unlock(&microcode_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
705static int mc_sysdev_add(struct sys_device *sys_dev) 705static 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
725static int mc_sysdev_add(struct sys_device *sys_dev)
726{
727 return __mc_sysdev_add(sys_dev, 0);
728}
729
735static int mc_sysdev_remove(struct sys_device *sys_dev) 730static 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}