Skip to content

Commit 455c017

Browse files
rjwysockiLinus Torvalds
authored andcommitted
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>
1 parent 8bb7844 commit 455c017

File tree

2 files changed

+36
-36
lines changed

2 files changed

+36
-36
lines changed

arch/i386/kernel/microcode.c

Lines changed: 36 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -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+
735730
static 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
}

kernel/cpu.c

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -262,20 +262,13 @@ int __cpuinit cpu_up(unsigned int cpu)
262262
}
263263

264264
#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-
271265
static cpumask_t frozen_cpus;
272266

273267
int disable_nonboot_cpus(void)
274268
{
275269
int cpu, first_cpu, error = 0;
276270

277271
mutex_lock(&cpu_add_remove_lock);
278-
suspend_cpu_hotplug = 1;
279272
first_cpu = first_cpu(cpu_online_map);
280273
/* We take down all of the non-boot CPUs in one shot to avoid races
281274
* with the userspace trying to use the CPU hotplug at the same time
@@ -302,7 +295,6 @@ int disable_nonboot_cpus(void)
302295
} else {
303296
printk(KERN_ERR "Non-boot CPUs are not disabled\n");
304297
}
305-
suspend_cpu_hotplug = 0;
306298
mutex_unlock(&cpu_add_remove_lock);
307299
return error;
308300
}
@@ -317,7 +309,6 @@ void enable_nonboot_cpus(void)
317309
if (cpus_empty(frozen_cpus))
318310
goto out;
319311

320-
suspend_cpu_hotplug = 1;
321312
printk("Enabling non-boot CPUs ...\n");
322313
for_each_cpu_mask(cpu, frozen_cpus) {
323314
error = _cpu_up(cpu, 1);
@@ -328,7 +319,6 @@ void enable_nonboot_cpus(void)
328319
printk(KERN_WARNING "Error taking CPU%d up: %d\n", cpu, error);
329320
}
330321
cpus_clear(frozen_cpus);
331-
suspend_cpu_hotplug = 0;
332322
out:
333323
mutex_unlock(&cpu_add_remove_lock);
334324
}

0 commit comments

Comments
 (0)