@@ -567,16 +567,17 @@ static int cpu_request_microcode(int cpu)
567567 return error ;
568568}
569569
570- static int apply_microcode_on_cpu (int cpu )
570+ static int apply_microcode_check_cpu (int cpu )
571571{
572572 struct cpuinfo_x86 * c = cpu_data + cpu ;
573573 struct ucode_cpu_info * uci = ucode_cpu_info + cpu ;
574574 cpumask_t old ;
575575 unsigned int val [2 ];
576576 int err = 0 ;
577577
578+ /* Check if the microcode is available */
578579 if (!uci -> mc )
579- return - EINVAL ;
580+ return 0 ;
580581
581582 old = current -> cpus_allowed ;
582583 set_cpus_allowed (current , cpumask_of_cpu (cpu ));
@@ -614,7 +615,7 @@ static int apply_microcode_on_cpu(int cpu)
614615 return err ;
615616}
616617
617- static void microcode_init_cpu (int cpu )
618+ static void microcode_init_cpu (int cpu , int resume )
618619{
619620 cpumask_t old ;
620621 struct ucode_cpu_info * uci = ucode_cpu_info + cpu ;
@@ -624,8 +625,7 @@ static void microcode_init_cpu(int cpu)
624625 set_cpus_allowed (current , cpumask_of_cpu (cpu ));
625626 mutex_lock (& microcode_mutex );
626627 collect_cpu_info (cpu );
627- if (uci -> valid && system_state == SYSTEM_RUNNING &&
628- !suspend_cpu_hotplug )
628+ if (uci -> valid && system_state == SYSTEM_RUNNING && !resume )
629629 cpu_request_microcode (cpu );
630630 mutex_unlock (& microcode_mutex );
631631 set_cpus_allowed (current , old );
@@ -702,7 +702,7 @@ static struct attribute_group mc_attr_group = {
702702 .name = "microcode" ,
703703};
704704
705- static int mc_sysdev_add (struct sys_device * sys_dev )
705+ static int __mc_sysdev_add (struct sys_device * sys_dev , int resume )
706706{
707707 int err , cpu = sys_dev -> id ;
708708 struct ucode_cpu_info * uci = ucode_cpu_info + cpu ;
@@ -711,39 +711,31 @@ static int mc_sysdev_add(struct sys_device *sys_dev)
711711 return 0 ;
712712
713713 pr_debug ("Microcode:CPU %d added\n" , cpu );
714- /* If suspend_cpu_hotplug is set, the system is resuming and we should
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 ));
714+ memset (uci , 0 , sizeof (* uci ));
724715
725716 err = sysfs_create_group (& sys_dev -> kobj , & mc_attr_group );
726717 if (err )
727718 return err ;
728719
729- if (!uci -> valid )
730- microcode_init_cpu (cpu );
720+ microcode_init_cpu (cpu , resume );
731721
732722 return 0 ;
733723}
734724
725+ static int mc_sysdev_add (struct sys_device * sys_dev )
726+ {
727+ return __mc_sysdev_add (sys_dev , 0 );
728+ }
729+
735730static int mc_sysdev_remove (struct sys_device * sys_dev )
736731{
737732 int cpu = sys_dev -> id ;
738733
739734 if (!cpu_online (cpu ))
740735 return 0 ;
736+
741737 pr_debug ("Microcode:CPU %d removed\n" , cpu );
742- /* If suspend_cpu_hotplug is set, the system is suspending and we should
743- * keep the microcode in memory for the resume.
744- */
745- if (!suspend_cpu_hotplug )
746- microcode_fini_cpu (cpu );
738+ microcode_fini_cpu (cpu );
747739 sysfs_remove_group (& sys_dev -> kobj , & mc_attr_group );
748740 return 0 ;
749741}
@@ -774,16 +766,34 @@ mc_cpu_callback(struct notifier_block *nb, unsigned long action, void *hcpu)
774766
775767 sys_dev = get_cpu_sysdev (cpu );
776768 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 ;
777773 case CPU_ONLINE :
778- case CPU_ONLINE_FROZEN :
779774 case CPU_DOWN_FAILED :
780- case CPU_DOWN_FAILED_FROZEN :
781775 mc_sysdev_add (sys_dev );
782776 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 ;
783790 case CPU_DOWN_PREPARE :
784- case CPU_DOWN_PREPARE_FROZEN :
785791 mc_sysdev_remove (sys_dev );
786792 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 ;
787797 }
788798 return NOTIFY_OK ;
789799}
0 commit comments