4848#include <trace/events/power.h>
4949#include <linux/sched.h>
5050#include <linux/sched/smt.h>
51+ #include <linux/mutex.h>
5152#include <linux/notifier.h>
5253#include <linux/cpu.h>
5354#include <linux/moduleparam.h>
55+ #include <linux/sysfs.h>
5456#include <asm/cpuid.h>
5557#include <asm/cpu_device_id.h>
5658#include <asm/intel-family.h>
@@ -92,9 +94,15 @@ struct idle_cpu {
9294 */
9395 unsigned long auto_demotion_disable_flags ;
9496 bool disable_promotion_to_c1e ;
97+ bool c1_demotion_supported ;
9598 bool use_acpi ;
9699};
97100
101+ static bool c1_demotion_supported ;
102+ static DEFINE_MUTEX (c1_demotion_mutex );
103+
104+ static struct device * sysfs_root __initdata ;
105+
98106static const struct idle_cpu * icpu __initdata ;
99107static struct cpuidle_state * cpuidle_state_table __initdata ;
100108
@@ -1549,18 +1557,21 @@ static const struct idle_cpu idle_cpu_gmt __initconst = {
15491557static const struct idle_cpu idle_cpu_spr __initconst = {
15501558 .state_table = spr_cstates ,
15511559 .disable_promotion_to_c1e = true,
1560+ .c1_demotion_supported = true,
15521561 .use_acpi = true,
15531562};
15541563
15551564static const struct idle_cpu idle_cpu_gnr __initconst = {
15561565 .state_table = gnr_cstates ,
15571566 .disable_promotion_to_c1e = true,
1567+ .c1_demotion_supported = true,
15581568 .use_acpi = true,
15591569};
15601570
15611571static const struct idle_cpu idle_cpu_gnrd __initconst = {
15621572 .state_table = gnrd_cstates ,
15631573 .disable_promotion_to_c1e = true,
1574+ .c1_demotion_supported = true,
15641575 .use_acpi = true,
15651576};
15661577
@@ -1599,12 +1610,14 @@ static const struct idle_cpu idle_cpu_snr __initconst = {
15991610static const struct idle_cpu idle_cpu_grr __initconst = {
16001611 .state_table = grr_cstates ,
16011612 .disable_promotion_to_c1e = true,
1613+ .c1_demotion_supported = true,
16021614 .use_acpi = true,
16031615};
16041616
16051617static const struct idle_cpu idle_cpu_srf __initconst = {
16061618 .state_table = srf_cstates ,
16071619 .disable_promotion_to_c1e = true,
1620+ .c1_demotion_supported = true,
16081621 .use_acpi = true,
16091622};
16101623
@@ -2324,6 +2337,88 @@ static void __init intel_idle_cpuidle_devices_uninit(void)
23242337 cpuidle_unregister_device (per_cpu_ptr (intel_idle_cpuidle_devices , i ));
23252338}
23262339
2340+ static void intel_c1_demotion_toggle (void * enable )
2341+ {
2342+ unsigned long long msr_val ;
2343+
2344+ rdmsrl (MSR_PKG_CST_CONFIG_CONTROL , msr_val );
2345+ /*
2346+ * Enable/disable C1 undemotion along with C1 demotion, as this is the
2347+ * most sensible configuration in general.
2348+ */
2349+ if (enable )
2350+ msr_val |= NHM_C1_AUTO_DEMOTE | SNB_C1_AUTO_UNDEMOTE ;
2351+ else
2352+ msr_val &= ~(NHM_C1_AUTO_DEMOTE | SNB_C1_AUTO_UNDEMOTE );
2353+ wrmsrl (MSR_PKG_CST_CONFIG_CONTROL , msr_val );
2354+ }
2355+
2356+ static ssize_t intel_c1_demotion_store (struct device * dev ,
2357+ struct device_attribute * attr ,
2358+ const char * buf , size_t count )
2359+ {
2360+ bool enable ;
2361+ int err ;
2362+
2363+ err = kstrtobool (buf , & enable );
2364+ if (err )
2365+ return err ;
2366+
2367+ mutex_lock (& c1_demotion_mutex );
2368+ /* Enable/disable C1 demotion on all CPUs */
2369+ on_each_cpu (intel_c1_demotion_toggle , (void * )enable , 1 );
2370+ mutex_unlock (& c1_demotion_mutex );
2371+
2372+ return count ;
2373+ }
2374+
2375+ static ssize_t intel_c1_demotion_show (struct device * dev ,
2376+ struct device_attribute * attr , char * buf )
2377+ {
2378+ unsigned long long msr_val ;
2379+
2380+ /*
2381+ * Read the MSR value for a CPU and assume it is the same for all CPUs. Any other
2382+ * configuration would be a BIOS bug.
2383+ */
2384+ rdmsrl (MSR_PKG_CST_CONFIG_CONTROL , msr_val );
2385+ return sysfs_emit (buf , "%d\n" , !!(msr_val & NHM_C1_AUTO_DEMOTE ));
2386+ }
2387+ static DEVICE_ATTR_RW (intel_c1_demotion );
2388+
2389+ static int __init intel_idle_sysfs_init (void )
2390+ {
2391+ int err ;
2392+
2393+ if (!c1_demotion_supported )
2394+ return 0 ;
2395+
2396+ sysfs_root = bus_get_dev_root (& cpu_subsys );
2397+ if (!sysfs_root )
2398+ return 0 ;
2399+
2400+ err = sysfs_add_file_to_group (& sysfs_root -> kobj ,
2401+ & dev_attr_intel_c1_demotion .attr ,
2402+ "cpuidle" );
2403+ if (err ) {
2404+ put_device (sysfs_root );
2405+ return err ;
2406+ }
2407+
2408+ return 0 ;
2409+ }
2410+
2411+ static void __init intel_idle_sysfs_uninit (void )
2412+ {
2413+ if (!sysfs_root )
2414+ return ;
2415+
2416+ sysfs_remove_file_from_group (& sysfs_root -> kobj ,
2417+ & dev_attr_intel_c1_demotion .attr ,
2418+ "cpuidle" );
2419+ put_device (sysfs_root );
2420+ }
2421+
23272422static int __init intel_idle_init (void )
23282423{
23292424 const struct x86_cpu_id * id ;
@@ -2374,6 +2469,8 @@ static int __init intel_idle_init(void)
23742469 auto_demotion_disable_flags = icpu -> auto_demotion_disable_flags ;
23752470 if (icpu -> disable_promotion_to_c1e )
23762471 c1e_promotion = C1E_PROMOTION_DISABLE ;
2472+ if (icpu -> c1_demotion_supported )
2473+ c1_demotion_supported = true;
23772474 if (icpu -> use_acpi || force_use_acpi )
23782475 intel_idle_acpi_cst_extract ();
23792476 } else if (!intel_idle_acpi_cst_extract ()) {
@@ -2387,6 +2484,10 @@ static int __init intel_idle_init(void)
23872484 if (!intel_idle_cpuidle_devices )
23882485 return - ENOMEM ;
23892486
2487+ retval = intel_idle_sysfs_init ();
2488+ if (retval )
2489+ pr_warn ("failed to initialized sysfs" );
2490+
23902491 intel_idle_cpuidle_driver_init (& intel_idle_driver );
23912492
23922493 retval = cpuidle_register_driver (& intel_idle_driver );
@@ -2411,6 +2512,7 @@ static int __init intel_idle_init(void)
24112512 intel_idle_cpuidle_devices_uninit ();
24122513 cpuidle_unregister_driver (& intel_idle_driver );
24132514init_driver_fail :
2515+ intel_idle_sysfs_uninit ();
24142516 free_percpu (intel_idle_cpuidle_devices );
24152517 return retval ;
24162518
0 commit comments