]> git.kernelconcepts.de Git - karo-tx-linux.git/commitdiff
intel_idle: export both C1 and C1E
authorLen Brown <len.brown@intel.com>
Sat, 2 Feb 2013 06:31:56 +0000 (01:31 -0500)
committerLen Brown <len.brown@intel.com>
Wed, 13 Feb 2013 23:22:08 +0000 (18:22 -0500)
Here we disable HW promotion of C1 to C1E
and export both C1 and C1E and distinct C-states.

This allows a cpuidle governor to choose a lower latency
C-state than C1E when necessary to satisfy performance
and QOS constraints -- and still save power versus polling.
This also corrects the erroneous latency previously reported
for C1E -- it is 10usec, not 1usec.

Note that if you use "intel_idle.max_cstate=N",
then you must increment N by 1 to get the same behavior
after this change.

Signed-off-by: Len Brown <len.brown@intel.com>
drivers/idle/intel_idle.c

index 927cfb4d66f40961f9ab1c86048e5159a992d47b..5d66750138647d619d9521922a3d2c5421db73e4 100644 (file)
@@ -90,6 +90,7 @@ struct idle_cpu {
         * Indicate which enable bits to clear here.
         */
        unsigned long auto_demotion_disable_flags;
+       bool disable_promotion_to_c1e;
 };
 
 static const struct idle_cpu *icpu;
@@ -131,6 +132,13 @@ static struct cpuidle_state nehalem_cstates[CPUIDLE_STATE_MAX] = {
                .exit_latency = 3,
                .target_residency = 6,
                .enter = &intel_idle },
+       {
+               .name = "C1E-NHM",
+               .desc = "MWAIT 0x01",
+               .flags = MWAIT2flg(0x01) | CPUIDLE_FLAG_TIME_VALID,
+               .exit_latency = 10,
+               .target_residency = 20,
+               .enter = &intel_idle },
        {
                .name = "C3-NHM",
                .desc = "MWAIT 0x10",
@@ -154,8 +162,15 @@ static struct cpuidle_state snb_cstates[CPUIDLE_STATE_MAX] = {
                .name = "C1-SNB",
                .desc = "MWAIT 0x00",
                .flags = MWAIT2flg(0x00) | CPUIDLE_FLAG_TIME_VALID,
-               .exit_latency = 1,
-               .target_residency = 1,
+               .exit_latency = 2,
+               .target_residency = 2,
+               .enter = &intel_idle },
+       {
+               .name = "C1E-SNB",
+               .desc = "MWAIT 0x01",
+               .flags = MWAIT2flg(0x01) | CPUIDLE_FLAG_TIME_VALID,
+               .exit_latency = 10,
+               .target_residency = 20,
                .enter = &intel_idle },
        {
                .name = "C3-SNB",
@@ -190,6 +205,13 @@ static struct cpuidle_state ivb_cstates[CPUIDLE_STATE_MAX] = {
                .exit_latency = 1,
                .target_residency = 1,
                .enter = &intel_idle },
+       {
+               .name = "C1E-IVB",
+               .desc = "MWAIT 0x01",
+               .flags = MWAIT2flg(0x01) | CPUIDLE_FLAG_TIME_VALID,
+               .exit_latency = 10,
+               .target_residency = 20,
+               .enter = &intel_idle },
        {
                .name = "C3-IVB",
                .desc = "MWAIT 0x10",
@@ -223,6 +245,13 @@ static struct cpuidle_state hsw_cstates[CPUIDLE_STATE_MAX] = {
                .exit_latency = 2,
                .target_residency = 2,
                .enter = &intel_idle },
+       {
+               .name = "C1E-HSW",
+               .desc = "MWAIT 0x01",
+               .flags = MWAIT2flg(0x01) | CPUIDLE_FLAG_TIME_VALID,
+               .exit_latency = 10,
+               .target_residency = 20,
+               .enter = &intel_idle },
        {
                .name = "C3-HSW",
                .desc = "MWAIT 0x10",
@@ -250,11 +279,11 @@ static struct cpuidle_state hsw_cstates[CPUIDLE_STATE_MAX] = {
 
 static struct cpuidle_state atom_cstates[CPUIDLE_STATE_MAX] = {
        {
-               .name = "C1-ATM",
+               .name = "C1E-ATM",
                .desc = "MWAIT 0x00",
                .flags = MWAIT2flg(0x00) | CPUIDLE_FLAG_TIME_VALID,
-               .exit_latency = 1,
-               .target_residency = 4,
+               .exit_latency = 10,
+               .target_residency = 20,
                .enter = &intel_idle },
        {
                .name = "C2-ATM",
@@ -377,10 +406,19 @@ static void auto_demotion_disable(void *dummy)
        msr_bits &= ~(icpu->auto_demotion_disable_flags);
        wrmsrl(MSR_NHM_SNB_PKG_CST_CFG_CTL, msr_bits);
 }
+static void c1e_promotion_disable(void *dummy)
+{
+       unsigned long long msr_bits;
+
+       rdmsrl(MSR_IA32_POWER_CTL, msr_bits);
+       msr_bits &= ~0x2;
+       wrmsrl(MSR_IA32_POWER_CTL, msr_bits);
+}
 
 static const struct idle_cpu idle_cpu_nehalem = {
        .state_table = nehalem_cstates,
        .auto_demotion_disable_flags = NHM_C1_AUTO_DEMOTE | NHM_C3_AUTO_DEMOTE,
+       .disable_promotion_to_c1e = true,
 };
 
 static const struct idle_cpu idle_cpu_atom = {
@@ -394,14 +432,17 @@ static const struct idle_cpu idle_cpu_lincroft = {
 
 static const struct idle_cpu idle_cpu_snb = {
        .state_table = snb_cstates,
+       .disable_promotion_to_c1e = true,
 };
 
 static const struct idle_cpu idle_cpu_ivb = {
        .state_table = ivb_cstates,
+       .disable_promotion_to_c1e = true,
 };
 
 static const struct idle_cpu idle_cpu_hsw = {
        .state_table = hsw_cstates,
+       .disable_promotion_to_c1e = true,
 };
 
 #define ICPU(model, cpu) \
@@ -544,6 +585,9 @@ static int intel_idle_cpuidle_driver_init(void)
        if (icpu->auto_demotion_disable_flags)
                on_each_cpu(auto_demotion_disable, NULL, 1);
 
+       if (icpu->disable_promotion_to_c1e)     /* each-cpu is redundant */
+               on_each_cpu(c1e_promotion_disable, NULL, 1);
+
        return 0;
 }