forked from Minki/linux
cpu/SMT: Fix x86 link error without CONFIG_SYSFS
When CONFIG_SYSFS is disabled, but CONFIG_HOTPLUG_SMT is enabled,
the kernel fails to link:
arch/x86/power/cpu.o: In function `hibernate_resume_nonboot_cpu_disable':
(.text+0x38d): undefined reference to `cpuhp_smt_enable'
arch/x86/power/hibernate.o: In function `arch_resume_nosmt':
hibernate.c:(.text+0x291): undefined reference to `cpuhp_smt_enable'
hibernate.c:(.text+0x29c): undefined reference to `cpuhp_smt_disable'
Move the exported functions out of the #ifdef section into its
own with the correct conditions.
The patch that caused this is marked for stable backports, so
this one may need to be backported as well.
Fixes: ec527c3180
("x86/power: Fix 'nosmt' vs hibernation triple fault during resume")
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Reviewed-by: Jiri Kosina <jkosina@suse.cz>
Cc: stable@vger.kernel.org
Link: https://lore.kernel.org/r/20191210195614.786555-1-arnd@arndb.de
This commit is contained in:
parent
c79f46a282
commit
dc8d37ed30
143
kernel/cpu.c
143
kernel/cpu.c
@ -1909,6 +1909,78 @@ void __cpuhp_remove_state(enum cpuhp_state state, bool invoke)
|
||||
}
|
||||
EXPORT_SYMBOL(__cpuhp_remove_state);
|
||||
|
||||
#ifdef CONFIG_HOTPLUG_SMT
|
||||
static void cpuhp_offline_cpu_device(unsigned int cpu)
|
||||
{
|
||||
struct device *dev = get_cpu_device(cpu);
|
||||
|
||||
dev->offline = true;
|
||||
/* Tell user space about the state change */
|
||||
kobject_uevent(&dev->kobj, KOBJ_OFFLINE);
|
||||
}
|
||||
|
||||
static void cpuhp_online_cpu_device(unsigned int cpu)
|
||||
{
|
||||
struct device *dev = get_cpu_device(cpu);
|
||||
|
||||
dev->offline = false;
|
||||
/* Tell user space about the state change */
|
||||
kobject_uevent(&dev->kobj, KOBJ_ONLINE);
|
||||
}
|
||||
|
||||
int cpuhp_smt_disable(enum cpuhp_smt_control ctrlval)
|
||||
{
|
||||
int cpu, ret = 0;
|
||||
|
||||
cpu_maps_update_begin();
|
||||
for_each_online_cpu(cpu) {
|
||||
if (topology_is_primary_thread(cpu))
|
||||
continue;
|
||||
ret = cpu_down_maps_locked(cpu, CPUHP_OFFLINE);
|
||||
if (ret)
|
||||
break;
|
||||
/*
|
||||
* As this needs to hold the cpu maps lock it's impossible
|
||||
* to call device_offline() because that ends up calling
|
||||
* cpu_down() which takes cpu maps lock. cpu maps lock
|
||||
* needs to be held as this might race against in kernel
|
||||
* abusers of the hotplug machinery (thermal management).
|
||||
*
|
||||
* So nothing would update device:offline state. That would
|
||||
* leave the sysfs entry stale and prevent onlining after
|
||||
* smt control has been changed to 'off' again. This is
|
||||
* called under the sysfs hotplug lock, so it is properly
|
||||
* serialized against the regular offline usage.
|
||||
*/
|
||||
cpuhp_offline_cpu_device(cpu);
|
||||
}
|
||||
if (!ret)
|
||||
cpu_smt_control = ctrlval;
|
||||
cpu_maps_update_done();
|
||||
return ret;
|
||||
}
|
||||
|
||||
int cpuhp_smt_enable(void)
|
||||
{
|
||||
int cpu, ret = 0;
|
||||
|
||||
cpu_maps_update_begin();
|
||||
cpu_smt_control = CPU_SMT_ENABLED;
|
||||
for_each_present_cpu(cpu) {
|
||||
/* Skip online CPUs and CPUs on offline nodes */
|
||||
if (cpu_online(cpu) || !node_online(cpu_to_node(cpu)))
|
||||
continue;
|
||||
ret = _cpu_up(cpu, 0, CPUHP_ONLINE);
|
||||
if (ret)
|
||||
break;
|
||||
/* See comment in cpuhp_smt_disable() */
|
||||
cpuhp_online_cpu_device(cpu);
|
||||
}
|
||||
cpu_maps_update_done();
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_SYSFS) && defined(CONFIG_HOTPLUG_CPU)
|
||||
static ssize_t show_cpuhp_state(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
@ -2063,77 +2135,6 @@ static const struct attribute_group cpuhp_cpu_root_attr_group = {
|
||||
|
||||
#ifdef CONFIG_HOTPLUG_SMT
|
||||
|
||||
static void cpuhp_offline_cpu_device(unsigned int cpu)
|
||||
{
|
||||
struct device *dev = get_cpu_device(cpu);
|
||||
|
||||
dev->offline = true;
|
||||
/* Tell user space about the state change */
|
||||
kobject_uevent(&dev->kobj, KOBJ_OFFLINE);
|
||||
}
|
||||
|
||||
static void cpuhp_online_cpu_device(unsigned int cpu)
|
||||
{
|
||||
struct device *dev = get_cpu_device(cpu);
|
||||
|
||||
dev->offline = false;
|
||||
/* Tell user space about the state change */
|
||||
kobject_uevent(&dev->kobj, KOBJ_ONLINE);
|
||||
}
|
||||
|
||||
int cpuhp_smt_disable(enum cpuhp_smt_control ctrlval)
|
||||
{
|
||||
int cpu, ret = 0;
|
||||
|
||||
cpu_maps_update_begin();
|
||||
for_each_online_cpu(cpu) {
|
||||
if (topology_is_primary_thread(cpu))
|
||||
continue;
|
||||
ret = cpu_down_maps_locked(cpu, CPUHP_OFFLINE);
|
||||
if (ret)
|
||||
break;
|
||||
/*
|
||||
* As this needs to hold the cpu maps lock it's impossible
|
||||
* to call device_offline() because that ends up calling
|
||||
* cpu_down() which takes cpu maps lock. cpu maps lock
|
||||
* needs to be held as this might race against in kernel
|
||||
* abusers of the hotplug machinery (thermal management).
|
||||
*
|
||||
* So nothing would update device:offline state. That would
|
||||
* leave the sysfs entry stale and prevent onlining after
|
||||
* smt control has been changed to 'off' again. This is
|
||||
* called under the sysfs hotplug lock, so it is properly
|
||||
* serialized against the regular offline usage.
|
||||
*/
|
||||
cpuhp_offline_cpu_device(cpu);
|
||||
}
|
||||
if (!ret)
|
||||
cpu_smt_control = ctrlval;
|
||||
cpu_maps_update_done();
|
||||
return ret;
|
||||
}
|
||||
|
||||
int cpuhp_smt_enable(void)
|
||||
{
|
||||
int cpu, ret = 0;
|
||||
|
||||
cpu_maps_update_begin();
|
||||
cpu_smt_control = CPU_SMT_ENABLED;
|
||||
for_each_present_cpu(cpu) {
|
||||
/* Skip online CPUs and CPUs on offline nodes */
|
||||
if (cpu_online(cpu) || !node_online(cpu_to_node(cpu)))
|
||||
continue;
|
||||
ret = _cpu_up(cpu, 0, CPUHP_ONLINE);
|
||||
if (ret)
|
||||
break;
|
||||
/* See comment in cpuhp_smt_disable() */
|
||||
cpuhp_online_cpu_device(cpu);
|
||||
}
|
||||
cpu_maps_update_done();
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static ssize_t
|
||||
__store_smt_control(struct device *dev, struct device_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
|
Loading…
Reference in New Issue
Block a user