@@ -764,6 +764,106 @@ static struct cpuidle_state icx_cstates[] __initdata = {
764764 .enter = NULL }
765765};
766766
767+ /*
768+ * On AlderLake C1 has to be disabled if C1E is enabled, and vice versa.
769+ * C1E is enabled only if "C1E promotion" bit is set in MSR_IA32_POWER_CTL.
770+ * But in this case there is effectively no C1, because C1 requests are
771+ * promoted to C1E. If the "C1E promotion" bit is cleared, then both C1
772+ * and C1E requests end up with C1, so there is effectively no C1E.
773+ *
774+ * By default we enable C1E and disable C1 by marking it with
775+ * 'CPUIDLE_FLAG_UNUSABLE'.
776+ */
777+ static struct cpuidle_state adl_cstates [] __initdata = {
778+ {
779+ .name = "C1" ,
780+ .desc = "MWAIT 0x00" ,
781+ .flags = MWAIT2flg (0x00 ) | CPUIDLE_FLAG_UNUSABLE ,
782+ .exit_latency = 1 ,
783+ .target_residency = 1 ,
784+ .enter = & intel_idle ,
785+ .enter_s2idle = intel_idle_s2idle , },
786+ {
787+ .name = "C1E" ,
788+ .desc = "MWAIT 0x01" ,
789+ .flags = MWAIT2flg (0x01 ) | CPUIDLE_FLAG_ALWAYS_ENABLE ,
790+ .exit_latency = 2 ,
791+ .target_residency = 4 ,
792+ .enter = & intel_idle ,
793+ .enter_s2idle = intel_idle_s2idle , },
794+ {
795+ .name = "C6" ,
796+ .desc = "MWAIT 0x20" ,
797+ .flags = MWAIT2flg (0x20 ) | CPUIDLE_FLAG_TLB_FLUSHED ,
798+ .exit_latency = 220 ,
799+ .target_residency = 600 ,
800+ .enter = & intel_idle ,
801+ .enter_s2idle = intel_idle_s2idle , },
802+ {
803+ .name = "C8" ,
804+ .desc = "MWAIT 0x40" ,
805+ .flags = MWAIT2flg (0x40 ) | CPUIDLE_FLAG_TLB_FLUSHED ,
806+ .exit_latency = 280 ,
807+ .target_residency = 800 ,
808+ .enter = & intel_idle ,
809+ .enter_s2idle = intel_idle_s2idle , },
810+ {
811+ .name = "C10" ,
812+ .desc = "MWAIT 0x60" ,
813+ .flags = MWAIT2flg (0x60 ) | CPUIDLE_FLAG_TLB_FLUSHED ,
814+ .exit_latency = 680 ,
815+ .target_residency = 2000 ,
816+ .enter = & intel_idle ,
817+ .enter_s2idle = intel_idle_s2idle , },
818+ {
819+ .enter = NULL }
820+ };
821+
822+ static struct cpuidle_state adl_l_cstates [] __initdata = {
823+ {
824+ .name = "C1" ,
825+ .desc = "MWAIT 0x00" ,
826+ .flags = MWAIT2flg (0x00 ) | CPUIDLE_FLAG_UNUSABLE ,
827+ .exit_latency = 1 ,
828+ .target_residency = 1 ,
829+ .enter = & intel_idle ,
830+ .enter_s2idle = intel_idle_s2idle , },
831+ {
832+ .name = "C1E" ,
833+ .desc = "MWAIT 0x01" ,
834+ .flags = MWAIT2flg (0x01 ) | CPUIDLE_FLAG_ALWAYS_ENABLE ,
835+ .exit_latency = 2 ,
836+ .target_residency = 4 ,
837+ .enter = & intel_idle ,
838+ .enter_s2idle = intel_idle_s2idle , },
839+ {
840+ .name = "C6" ,
841+ .desc = "MWAIT 0x20" ,
842+ .flags = MWAIT2flg (0x20 ) | CPUIDLE_FLAG_TLB_FLUSHED ,
843+ .exit_latency = 170 ,
844+ .target_residency = 500 ,
845+ .enter = & intel_idle ,
846+ .enter_s2idle = intel_idle_s2idle , },
847+ {
848+ .name = "C8" ,
849+ .desc = "MWAIT 0x40" ,
850+ .flags = MWAIT2flg (0x40 ) | CPUIDLE_FLAG_TLB_FLUSHED ,
851+ .exit_latency = 200 ,
852+ .target_residency = 600 ,
853+ .enter = & intel_idle ,
854+ .enter_s2idle = intel_idle_s2idle , },
855+ {
856+ .name = "C10" ,
857+ .desc = "MWAIT 0x60" ,
858+ .flags = MWAIT2flg (0x60 ) | CPUIDLE_FLAG_TLB_FLUSHED ,
859+ .exit_latency = 230 ,
860+ .target_residency = 700 ,
861+ .enter = & intel_idle ,
862+ .enter_s2idle = intel_idle_s2idle , },
863+ {
864+ .enter = NULL }
865+ };
866+
767867/*
768868 * On Sapphire Rapids Xeon C1 has to be disabled if C1E is enabled, and vice
769869 * versa. On SPR C1E is enabled only if "C1E promotion" bit is set in
@@ -1147,6 +1247,14 @@ static const struct idle_cpu idle_cpu_icx __initconst = {
11471247 .use_acpi = true,
11481248};
11491249
1250+ static const struct idle_cpu idle_cpu_adl __initconst = {
1251+ .state_table = adl_cstates ,
1252+ };
1253+
1254+ static const struct idle_cpu idle_cpu_adl_l __initconst = {
1255+ .state_table = adl_l_cstates ,
1256+ };
1257+
11501258static const struct idle_cpu idle_cpu_spr __initconst = {
11511259 .state_table = spr_cstates ,
11521260 .disable_promotion_to_c1e = true,
@@ -1215,6 +1323,8 @@ static const struct x86_cpu_id intel_idle_ids[] __initconst = {
12151323 X86_MATCH_INTEL_FAM6_MODEL (SKYLAKE_X , & idle_cpu_skx ),
12161324 X86_MATCH_INTEL_FAM6_MODEL (ICELAKE_X , & idle_cpu_icx ),
12171325 X86_MATCH_INTEL_FAM6_MODEL (ICELAKE_D , & idle_cpu_icx ),
1326+ X86_MATCH_INTEL_FAM6_MODEL (ALDERLAKE , & idle_cpu_adl ),
1327+ X86_MATCH_INTEL_FAM6_MODEL (ALDERLAKE_L , & idle_cpu_adl_l ),
12181328 X86_MATCH_INTEL_FAM6_MODEL (SAPPHIRERAPIDS_X , & idle_cpu_spr ),
12191329 X86_MATCH_INTEL_FAM6_MODEL (XEON_PHI_KNL , & idle_cpu_knl ),
12201330 X86_MATCH_INTEL_FAM6_MODEL (XEON_PHI_KNM , & idle_cpu_knl ),
@@ -1573,6 +1683,25 @@ static void __init skx_idle_state_table_update(void)
15731683 }
15741684}
15751685
1686+ /**
1687+ * adl_idle_state_table_update - Adjust AlderLake idle states table.
1688+ */
1689+ static void __init adl_idle_state_table_update (void )
1690+ {
1691+ /* Check if user prefers C1 over C1E. */
1692+ if (preferred_states_mask & BIT (1 ) && !(preferred_states_mask & BIT (2 ))) {
1693+ cpuidle_state_table [0 ].flags &= ~CPUIDLE_FLAG_UNUSABLE ;
1694+ cpuidle_state_table [1 ].flags |= CPUIDLE_FLAG_UNUSABLE ;
1695+
1696+ /* Disable C1E by clearing the "C1E promotion" bit. */
1697+ c1e_promotion = C1E_PROMOTION_DISABLE ;
1698+ return ;
1699+ }
1700+
1701+ /* Make sure C1E is enabled by default */
1702+ c1e_promotion = C1E_PROMOTION_ENABLE ;
1703+ }
1704+
15761705/**
15771706 * spr_idle_state_table_update - Adjust Sapphire Rapids idle states table.
15781707 */
@@ -1642,6 +1771,10 @@ static void __init intel_idle_init_cstates_icpu(struct cpuidle_driver *drv)
16421771 case INTEL_FAM6_SAPPHIRERAPIDS_X :
16431772 spr_idle_state_table_update ();
16441773 break ;
1774+ case INTEL_FAM6_ALDERLAKE :
1775+ case INTEL_FAM6_ALDERLAKE_L :
1776+ adl_idle_state_table_update ();
1777+ break ;
16451778 }
16461779
16471780 for (cstate = 0 ; cstate < CPUIDLE_STATE_MAX ; ++ cstate ) {
0 commit comments