Updates for the CPU hotplug core:
- Support partial SMT enablement. So far the sysfs SMT control only allows to toggle between SMT on and off. That's sufficient for x86 which usually has at max two threads except for the Xeon PHI platform which has four threads per core. Though PowerPC has up to 16 threads per core and so far it's only possible to control the number of enabled threads per core via a command line option. There is some way to control this at runtime, but that lacks enforcement and the usability is awkward. This update expands the sysfs interface and the core infrastructure to accept numerical values so PowerPC can build SMT runtime control for partial SMT enablement on top. The core support has also been provided to the PowerPC maintainers who added the PowerPC related changes on top. - Minor cleanups and documentation updates. -----BEGIN PGP SIGNATURE----- iQJHBAABCgAxFiEEQp8+kY+LLUocC4bMphj1TA10mKEFAmTsj4wTHHRnbHhAbGlu dXRyb25peC5kZQAKCRCmGPVMDXSYoaszEADKMd/6m7/Bq7RU2OJ+IXw8yfMEF9nS 6HPrFu71a4cDufb/G8UckQOvkwdTFWD7bZ0snJe2sBDFTOtzK/inYkgPZTxlm7si JcJmFnHKUM7OTwNZb7Tv1bd9Csz4JhggAYUw6P8CqsCmhQ+p6ECemx3bHDlYiywm 5eW2yzI9EM4dbsHPwUOvjI0WazGvAf0esSDAS8JTnhBXbd8FAckbMV+xuRPcCUK+ dBqbqr+3Nf4/wcXTro/gZIc7sEATAHH6m7zHlLVBSyVPnBxre8NLz6KciW4SezyJ GWFnDV03mmG2KxQ2ugwI8n6M3zDJQtfEJFwW/x4t2M5RK+ka2a6G6GtCLHYOXLWR akIuBXtTAC57BgpqzBihGej9eiC1BJ1QMa9ZK+6WDXSZtMTFOLlbwdY2/qyfxpfw LfepWb+UMtFy5YyW84S1O5/AqpOtKD2kPTqfDjvDxWIAigispU+qwAKxcMzMjtwz aAlf2Z/iX0R9DkRzGD2gaFG5AUsRich8RtVO7u+WDwYSsi8ywrvryiPlZrDDBkSQ sRzdoHeXNGVY/FgkbZmEyBj4udrypymkR6ivqn6C2OrysgznSiv5NC983uS6TfJX cVqdUv6CNYYNiNu0x0Qf0MluYT2s5c1Fa4bjCBJL+KwORwjM3+TCN9RA1KtFrW2T G3Ta1KqI6wRonA== =JQRJ -----END PGP SIGNATURE----- Merge tag 'smp-core-2023-08-28' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip Pull CPU hotplug updates from Thomas Gleixner: "Updates for the CPU hotplug core: - Support partial SMT enablement. So far the sysfs SMT control only allows to toggle between SMT on and off. That's sufficient for x86 which usually has at max two threads except for the Xeon PHI platform which has four threads per core Though PowerPC has up to 16 threads per core and so far it's only possible to control the number of enabled threads per core via a command line option. There is some way to control this at runtime, but that lacks enforcement and the usability is awkward This update expands the sysfs interface and the core infrastructure to accept numerical values so PowerPC can build SMT runtime control for partial SMT enablement on top The core support has also been provided to the PowerPC maintainers who added the PowerPC related changes on top - Minor cleanups and documentation updates" * tag 'smp-core-2023-08-28' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: Documentation: core-api/cpuhotplug: Fix state names cpu/hotplug: Remove unused function declaration cpu_set_state_online() cpu/SMT: Fix cpu_smt_possible() comment cpu/SMT: Allow enabling partial SMT states via sysfs cpu/SMT: Create topology_smt_thread_allowed() cpu/SMT: Remove topology_smt_supported() cpu/SMT: Store the current/max number of threads cpu/SMT: Move smt/control simple exit cases earlier cpu/SMT: Move SMT prototypes into cpu_smt.h cpu/hotplug: Remove dependancy against cpu_primary_thread_mask
This commit is contained in:
commit
6f49693a6c
@ -556,6 +556,7 @@ Description: Control Symmetric Multi Threading (SMT)
|
||||
================ =========================================
|
||||
"on" SMT is enabled
|
||||
"off" SMT is disabled
|
||||
"<N>" SMT is enabled with N threads per core.
|
||||
"forceoff" SMT is force disabled. Cannot be changed.
|
||||
"notsupported" SMT is not supported by the CPU
|
||||
"notimplemented" SMT runtime toggling is not
|
||||
|
@ -395,8 +395,8 @@ multi-instance state the following function is available:
|
||||
* cpuhp_setup_state_multi(state, name, startup, teardown)
|
||||
|
||||
The @state argument is either a statically allocated state or one of the
|
||||
constants for dynamically allocated states - CPUHP_PREPARE_DYN,
|
||||
CPUHP_ONLINE_DYN - depending on the state section (PREPARE, ONLINE) for
|
||||
constants for dynamically allocated states - CPUHP_BP_PREPARE_DYN,
|
||||
CPUHP_AP_ONLINE_DYN - depending on the state section (PREPARE, ONLINE) for
|
||||
which a dynamic state should be allocated.
|
||||
|
||||
The @name argument is used for sysfs output and for instrumentation. The
|
||||
@ -588,7 +588,7 @@ notifications on online and offline operations::
|
||||
Setup and teardown a dynamically allocated state in the ONLINE section
|
||||
for notifications on offline operations::
|
||||
|
||||
state = cpuhp_setup_state(CPUHP_ONLINE_DYN, "subsys:offline", NULL, subsys_cpu_offline);
|
||||
state = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "subsys:offline", NULL, subsys_cpu_offline);
|
||||
if (state < 0)
|
||||
return state;
|
||||
....
|
||||
@ -597,7 +597,7 @@ for notifications on offline operations::
|
||||
Setup and teardown a dynamically allocated state in the ONLINE section
|
||||
for notifications on online operations without invoking the callbacks::
|
||||
|
||||
state = cpuhp_setup_state_nocalls(CPUHP_ONLINE_DYN, "subsys:online", subsys_cpu_online, NULL);
|
||||
state = cpuhp_setup_state_nocalls(CPUHP_AP_ONLINE_DYN, "subsys:online", subsys_cpu_online, NULL);
|
||||
if (state < 0)
|
||||
return state;
|
||||
....
|
||||
@ -606,7 +606,7 @@ for notifications on online operations without invoking the callbacks::
|
||||
Setup, use and teardown a dynamically allocated multi-instance state in the
|
||||
ONLINE section for notifications on online and offline operation::
|
||||
|
||||
state = cpuhp_setup_state_multi(CPUHP_ONLINE_DYN, "subsys:online", subsys_cpu_online, subsys_cpu_offline);
|
||||
state = cpuhp_setup_state_multi(CPUHP_AP_ONLINE_DYN, "subsys:online", subsys_cpu_online, subsys_cpu_offline);
|
||||
if (state < 0)
|
||||
return state;
|
||||
....
|
||||
|
@ -34,6 +34,9 @@ config ARCH_HAS_SUBPAGE_FAULTS
|
||||
config HOTPLUG_SMT
|
||||
bool
|
||||
|
||||
config SMT_NUM_THREADS_DYNAMIC
|
||||
bool
|
||||
|
||||
# Selected by HOTPLUG_CORE_SYNC_DEAD or HOTPLUG_CORE_SYNC_FULL
|
||||
config HOTPLUG_CORE_SYNC
|
||||
bool
|
||||
|
@ -136,10 +136,11 @@ static inline int topology_max_smt_threads(void)
|
||||
return __max_smt_threads;
|
||||
}
|
||||
|
||||
#include <linux/cpu_smt.h>
|
||||
|
||||
int topology_update_package_map(unsigned int apicid, unsigned int cpu);
|
||||
int topology_update_die_map(unsigned int dieid, unsigned int cpu);
|
||||
int topology_phys_to_logical_pkg(unsigned int pkg);
|
||||
bool topology_smt_supported(void);
|
||||
|
||||
extern struct cpumask __cpu_primary_thread_mask;
|
||||
#define cpu_primary_thread_mask ((const struct cpumask *)&__cpu_primary_thread_mask)
|
||||
@ -162,7 +163,6 @@ static inline int topology_phys_to_logical_pkg(unsigned int pkg) { return 0; }
|
||||
static inline int topology_max_die_per_package(void) { return 1; }
|
||||
static inline int topology_max_smt_threads(void) { return 1; }
|
||||
static inline bool topology_is_primary_thread(unsigned int cpu) { return true; }
|
||||
static inline bool topology_smt_supported(void) { return false; }
|
||||
#endif /* !CONFIG_SMP */
|
||||
|
||||
static inline void arch_fix_phys_package_id(int num, u32 slot)
|
||||
|
@ -2343,7 +2343,7 @@ void __init arch_cpu_finalize_init(void)
|
||||
* identify_boot_cpu() initialized SMT support information, let the
|
||||
* core code know.
|
||||
*/
|
||||
cpu_smt_check_topology();
|
||||
cpu_smt_set_num_threads(smp_num_siblings, smp_num_siblings);
|
||||
|
||||
if (!IS_ENABLED(CONFIG_SMP)) {
|
||||
pr_info("CPU: ");
|
||||
|
@ -326,14 +326,6 @@ static void notrace start_secondary(void *unused)
|
||||
cpu_startup_entry(CPUHP_AP_ONLINE_IDLE);
|
||||
}
|
||||
|
||||
/**
|
||||
* topology_smt_supported - Check whether SMT is supported by the CPUs
|
||||
*/
|
||||
bool topology_smt_supported(void)
|
||||
{
|
||||
return smp_num_siblings > 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* topology_phys_to_logical_pkg - Map a physical package id to a logical
|
||||
* @phys_pkg: The physical package id to map
|
||||
|
@ -18,6 +18,7 @@
|
||||
#include <linux/compiler.h>
|
||||
#include <linux/cpumask.h>
|
||||
#include <linux/cpuhotplug.h>
|
||||
#include <linux/cpu_smt.h>
|
||||
|
||||
struct device;
|
||||
struct device_node;
|
||||
@ -194,7 +195,6 @@ void arch_cpu_finalize_init(void);
|
||||
static inline void arch_cpu_finalize_init(void) { }
|
||||
#endif
|
||||
|
||||
void cpu_set_state_online(int cpu);
|
||||
void play_idle_precise(u64 duration_ns, u64 latency_ns);
|
||||
|
||||
static inline void play_idle(unsigned long duration_us)
|
||||
@ -208,30 +208,6 @@ void cpuhp_report_idle_dead(void);
|
||||
static inline void cpuhp_report_idle_dead(void) { }
|
||||
#endif /* #ifdef CONFIG_HOTPLUG_CPU */
|
||||
|
||||
enum cpuhp_smt_control {
|
||||
CPU_SMT_ENABLED,
|
||||
CPU_SMT_DISABLED,
|
||||
CPU_SMT_FORCE_DISABLED,
|
||||
CPU_SMT_NOT_SUPPORTED,
|
||||
CPU_SMT_NOT_IMPLEMENTED,
|
||||
};
|
||||
|
||||
#if defined(CONFIG_SMP) && defined(CONFIG_HOTPLUG_SMT)
|
||||
extern enum cpuhp_smt_control cpu_smt_control;
|
||||
extern void cpu_smt_disable(bool force);
|
||||
extern void cpu_smt_check_topology(void);
|
||||
extern bool cpu_smt_possible(void);
|
||||
extern int cpuhp_smt_enable(void);
|
||||
extern int cpuhp_smt_disable(enum cpuhp_smt_control ctrlval);
|
||||
#else
|
||||
# define cpu_smt_control (CPU_SMT_NOT_IMPLEMENTED)
|
||||
static inline void cpu_smt_disable(bool force) { }
|
||||
static inline void cpu_smt_check_topology(void) { }
|
||||
static inline bool cpu_smt_possible(void) { return false; }
|
||||
static inline int cpuhp_smt_enable(void) { return 0; }
|
||||
static inline int cpuhp_smt_disable(enum cpuhp_smt_control ctrlval) { return 0; }
|
||||
#endif
|
||||
|
||||
extern bool cpu_mitigations_off(void);
|
||||
extern bool cpu_mitigations_auto_nosmt(void);
|
||||
|
||||
|
33
include/linux/cpu_smt.h
Normal file
33
include/linux/cpu_smt.h
Normal file
@ -0,0 +1,33 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
#ifndef _LINUX_CPU_SMT_H_
|
||||
#define _LINUX_CPU_SMT_H_
|
||||
|
||||
enum cpuhp_smt_control {
|
||||
CPU_SMT_ENABLED,
|
||||
CPU_SMT_DISABLED,
|
||||
CPU_SMT_FORCE_DISABLED,
|
||||
CPU_SMT_NOT_SUPPORTED,
|
||||
CPU_SMT_NOT_IMPLEMENTED,
|
||||
};
|
||||
|
||||
#if defined(CONFIG_SMP) && defined(CONFIG_HOTPLUG_SMT)
|
||||
extern enum cpuhp_smt_control cpu_smt_control;
|
||||
extern unsigned int cpu_smt_num_threads;
|
||||
extern void cpu_smt_disable(bool force);
|
||||
extern void cpu_smt_set_num_threads(unsigned int num_threads,
|
||||
unsigned int max_threads);
|
||||
extern bool cpu_smt_possible(void);
|
||||
extern int cpuhp_smt_enable(void);
|
||||
extern int cpuhp_smt_disable(enum cpuhp_smt_control ctrlval);
|
||||
#else
|
||||
# define cpu_smt_control (CPU_SMT_NOT_IMPLEMENTED)
|
||||
# define cpu_smt_num_threads 1
|
||||
static inline void cpu_smt_disable(bool force) { }
|
||||
static inline void cpu_smt_set_num_threads(unsigned int num_threads,
|
||||
unsigned int max_threads) { }
|
||||
static inline bool cpu_smt_possible(void) { return false; }
|
||||
static inline int cpuhp_smt_enable(void) { return 0; }
|
||||
static inline int cpuhp_smt_disable(enum cpuhp_smt_control ctrlval) { return 0; }
|
||||
#endif
|
||||
|
||||
#endif /* _LINUX_CPU_SMT_H_ */
|
@ -48,7 +48,7 @@
|
||||
* same section.
|
||||
*
|
||||
* If neither #1 nor #2 apply, please use the dynamic state space when
|
||||
* setting up a state by using CPUHP_PREPARE_DYN or CPUHP_PREPARE_ONLINE
|
||||
* setting up a state by using CPUHP_BP_PREPARE_DYN or CPUHP_AP_ONLINE_DYN
|
||||
* for the @state argument of the setup function.
|
||||
*
|
||||
* See Documentation/core-api/cpu_hotplug.rst for further information and
|
||||
|
144
kernel/cpu.c
144
kernel/cpu.c
@ -592,7 +592,10 @@ static void lockdep_release_cpus_lock(void)
|
||||
void __weak arch_smt_update(void) { }
|
||||
|
||||
#ifdef CONFIG_HOTPLUG_SMT
|
||||
|
||||
enum cpuhp_smt_control cpu_smt_control __read_mostly = CPU_SMT_ENABLED;
|
||||
static unsigned int cpu_smt_max_threads __ro_after_init;
|
||||
unsigned int cpu_smt_num_threads __read_mostly = UINT_MAX;
|
||||
|
||||
void __init cpu_smt_disable(bool force)
|
||||
{
|
||||
@ -606,16 +609,33 @@ void __init cpu_smt_disable(bool force)
|
||||
pr_info("SMT: disabled\n");
|
||||
cpu_smt_control = CPU_SMT_DISABLED;
|
||||
}
|
||||
cpu_smt_num_threads = 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* The decision whether SMT is supported can only be done after the full
|
||||
* CPU identification. Called from architecture code.
|
||||
*/
|
||||
void __init cpu_smt_check_topology(void)
|
||||
void __init cpu_smt_set_num_threads(unsigned int num_threads,
|
||||
unsigned int max_threads)
|
||||
{
|
||||
if (!topology_smt_supported())
|
||||
WARN_ON(!num_threads || (num_threads > max_threads));
|
||||
|
||||
if (max_threads == 1)
|
||||
cpu_smt_control = CPU_SMT_NOT_SUPPORTED;
|
||||
|
||||
cpu_smt_max_threads = max_threads;
|
||||
|
||||
/*
|
||||
* If SMT has been disabled via the kernel command line or SMT is
|
||||
* not supported, set cpu_smt_num_threads to 1 for consistency.
|
||||
* If enabled, take the architecture requested number of threads
|
||||
* to bring up into account.
|
||||
*/
|
||||
if (cpu_smt_control != CPU_SMT_ENABLED)
|
||||
cpu_smt_num_threads = 1;
|
||||
else if (num_threads < cpu_smt_num_threads)
|
||||
cpu_smt_num_threads = num_threads;
|
||||
}
|
||||
|
||||
static int __init smt_cmdline_disable(char *str)
|
||||
@ -625,9 +645,23 @@ static int __init smt_cmdline_disable(char *str)
|
||||
}
|
||||
early_param("nosmt", smt_cmdline_disable);
|
||||
|
||||
/*
|
||||
* For Archicture supporting partial SMT states check if the thread is allowed.
|
||||
* Otherwise this has already been checked through cpu_smt_max_threads when
|
||||
* setting the SMT level.
|
||||
*/
|
||||
static inline bool cpu_smt_thread_allowed(unsigned int cpu)
|
||||
{
|
||||
#ifdef CONFIG_SMT_NUM_THREADS_DYNAMIC
|
||||
return topology_smt_thread_allowed(cpu);
|
||||
#else
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline bool cpu_smt_allowed(unsigned int cpu)
|
||||
{
|
||||
if (cpu_smt_control == CPU_SMT_ENABLED)
|
||||
if (cpu_smt_control == CPU_SMT_ENABLED && cpu_smt_thread_allowed(cpu))
|
||||
return true;
|
||||
|
||||
if (topology_is_primary_thread(cpu))
|
||||
@ -642,7 +676,7 @@ static inline bool cpu_smt_allowed(unsigned int cpu)
|
||||
return !cpumask_test_cpu(cpu, &cpus_booted_once_mask);
|
||||
}
|
||||
|
||||
/* Returns true if SMT is not supported of forcefully (irreversibly) disabled */
|
||||
/* Returns true if SMT is supported and not forcefully (irreversibly) disabled */
|
||||
bool cpu_smt_possible(void)
|
||||
{
|
||||
return cpu_smt_control != CPU_SMT_FORCE_DISABLED &&
|
||||
@ -650,22 +684,8 @@ bool cpu_smt_possible(void)
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(cpu_smt_possible);
|
||||
|
||||
static inline bool cpuhp_smt_aware(void)
|
||||
{
|
||||
return topology_smt_supported();
|
||||
}
|
||||
|
||||
static inline const struct cpumask *cpuhp_get_primary_thread_mask(void)
|
||||
{
|
||||
return cpu_primary_thread_mask;
|
||||
}
|
||||
#else
|
||||
static inline bool cpu_smt_allowed(unsigned int cpu) { return true; }
|
||||
static inline bool cpuhp_smt_aware(void) { return false; }
|
||||
static inline const struct cpumask *cpuhp_get_primary_thread_mask(void)
|
||||
{
|
||||
return cpu_present_mask;
|
||||
}
|
||||
#endif
|
||||
|
||||
static inline enum cpuhp_state
|
||||
@ -1793,6 +1813,16 @@ static int __init parallel_bringup_parse_param(char *arg)
|
||||
}
|
||||
early_param("cpuhp.parallel", parallel_bringup_parse_param);
|
||||
|
||||
static inline bool cpuhp_smt_aware(void)
|
||||
{
|
||||
return cpu_smt_max_threads > 1;
|
||||
}
|
||||
|
||||
static inline const struct cpumask *cpuhp_get_primary_thread_mask(void)
|
||||
{
|
||||
return cpu_primary_thread_mask;
|
||||
}
|
||||
|
||||
/*
|
||||
* On architectures which have enabled parallel bringup this invokes all BP
|
||||
* prepare states for each of the to be onlined APs first. The last state
|
||||
@ -2626,6 +2656,12 @@ int cpuhp_smt_disable(enum cpuhp_smt_control ctrlval)
|
||||
for_each_online_cpu(cpu) {
|
||||
if (topology_is_primary_thread(cpu))
|
||||
continue;
|
||||
/*
|
||||
* Disable can be called with CPU_SMT_ENABLED when changing
|
||||
* from a higher to lower number of SMT threads per core.
|
||||
*/
|
||||
if (ctrlval == CPU_SMT_ENABLED && cpu_smt_thread_allowed(cpu))
|
||||
continue;
|
||||
ret = cpu_down_maps_locked(cpu, CPUHP_OFFLINE);
|
||||
if (ret)
|
||||
break;
|
||||
@ -2660,6 +2696,8 @@ int cpuhp_smt_enable(void)
|
||||
/* Skip online CPUs and CPUs on offline nodes */
|
||||
if (cpu_online(cpu) || !node_online(cpu_to_node(cpu)))
|
||||
continue;
|
||||
if (!cpu_smt_thread_allowed(cpu))
|
||||
continue;
|
||||
ret = _cpu_up(cpu, 0, CPUHP_ONLINE);
|
||||
if (ret)
|
||||
break;
|
||||
@ -2838,20 +2876,19 @@ static const struct attribute_group cpuhp_cpu_root_attr_group = {
|
||||
|
||||
#ifdef CONFIG_HOTPLUG_SMT
|
||||
|
||||
static bool cpu_smt_num_threads_valid(unsigned int threads)
|
||||
{
|
||||
if (IS_ENABLED(CONFIG_SMT_NUM_THREADS_DYNAMIC))
|
||||
return threads >= 1 && threads <= cpu_smt_max_threads;
|
||||
return threads == 1 || threads == cpu_smt_max_threads;
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
__store_smt_control(struct device *dev, struct device_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
int ctrlval, ret;
|
||||
|
||||
if (sysfs_streq(buf, "on"))
|
||||
ctrlval = CPU_SMT_ENABLED;
|
||||
else if (sysfs_streq(buf, "off"))
|
||||
ctrlval = CPU_SMT_DISABLED;
|
||||
else if (sysfs_streq(buf, "forceoff"))
|
||||
ctrlval = CPU_SMT_FORCE_DISABLED;
|
||||
else
|
||||
return -EINVAL;
|
||||
int ctrlval, ret, num_threads, orig_threads;
|
||||
bool force_off;
|
||||
|
||||
if (cpu_smt_control == CPU_SMT_FORCE_DISABLED)
|
||||
return -EPERM;
|
||||
@ -2859,21 +2896,39 @@ __store_smt_control(struct device *dev, struct device_attribute *attr,
|
||||
if (cpu_smt_control == CPU_SMT_NOT_SUPPORTED)
|
||||
return -ENODEV;
|
||||
|
||||
if (sysfs_streq(buf, "on")) {
|
||||
ctrlval = CPU_SMT_ENABLED;
|
||||
num_threads = cpu_smt_max_threads;
|
||||
} else if (sysfs_streq(buf, "off")) {
|
||||
ctrlval = CPU_SMT_DISABLED;
|
||||
num_threads = 1;
|
||||
} else if (sysfs_streq(buf, "forceoff")) {
|
||||
ctrlval = CPU_SMT_FORCE_DISABLED;
|
||||
num_threads = 1;
|
||||
} else if (kstrtoint(buf, 10, &num_threads) == 0) {
|
||||
if (num_threads == 1)
|
||||
ctrlval = CPU_SMT_DISABLED;
|
||||
else if (cpu_smt_num_threads_valid(num_threads))
|
||||
ctrlval = CPU_SMT_ENABLED;
|
||||
else
|
||||
return -EINVAL;
|
||||
} else {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ret = lock_device_hotplug_sysfs();
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (ctrlval != cpu_smt_control) {
|
||||
switch (ctrlval) {
|
||||
case CPU_SMT_ENABLED:
|
||||
ret = cpuhp_smt_enable();
|
||||
break;
|
||||
case CPU_SMT_DISABLED:
|
||||
case CPU_SMT_FORCE_DISABLED:
|
||||
ret = cpuhp_smt_disable(ctrlval);
|
||||
break;
|
||||
}
|
||||
}
|
||||
orig_threads = cpu_smt_num_threads;
|
||||
cpu_smt_num_threads = num_threads;
|
||||
|
||||
force_off = ctrlval != cpu_smt_control && ctrlval == CPU_SMT_FORCE_DISABLED;
|
||||
|
||||
if (num_threads > orig_threads)
|
||||
ret = cpuhp_smt_enable();
|
||||
else if (num_threads < orig_threads || force_off)
|
||||
ret = cpuhp_smt_disable(ctrlval);
|
||||
|
||||
unlock_device_hotplug();
|
||||
return ret ? ret : count;
|
||||
@ -2901,6 +2956,17 @@ static ssize_t control_show(struct device *dev,
|
||||
{
|
||||
const char *state = smt_states[cpu_smt_control];
|
||||
|
||||
#ifdef CONFIG_HOTPLUG_SMT
|
||||
/*
|
||||
* If SMT is enabled but not all threads are enabled then show the
|
||||
* number of threads. If all threads are enabled show "on". Otherwise
|
||||
* show the state name.
|
||||
*/
|
||||
if (cpu_smt_control == CPU_SMT_ENABLED &&
|
||||
cpu_smt_num_threads != cpu_smt_max_threads)
|
||||
return sysfs_emit(buf, "%d\n", cpu_smt_num_threads);
|
||||
#endif
|
||||
|
||||
return snprintf(buf, PAGE_SIZE - 2, "%s\n", state);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user