diff options
-rw-r--r-- | drivers/idle/intel_idle.c | 133 |
1 files changed, 111 insertions, 22 deletions
diff --git a/drivers/idle/intel_idle.c b/drivers/idle/intel_idle.c index cd4510a63375..ba947df5a8c7 100644 --- a/drivers/idle/intel_idle.c +++ b/drivers/idle/intel_idle.c | |||
@@ -65,7 +65,7 @@ | |||
65 | #include <asm/mwait.h> | 65 | #include <asm/mwait.h> |
66 | #include <asm/msr.h> | 66 | #include <asm/msr.h> |
67 | 67 | ||
68 | #define INTEL_IDLE_VERSION "0.4" | 68 | #define INTEL_IDLE_VERSION "0.4.1" |
69 | #define PREFIX "intel_idle: " | 69 | #define PREFIX "intel_idle: " |
70 | 70 | ||
71 | static struct cpuidle_driver intel_idle_driver = { | 71 | static struct cpuidle_driver intel_idle_driver = { |
@@ -716,6 +716,26 @@ static struct cpuidle_state avn_cstates[] = { | |||
716 | { | 716 | { |
717 | .enter = NULL } | 717 | .enter = NULL } |
718 | }; | 718 | }; |
719 | static struct cpuidle_state knl_cstates[] = { | ||
720 | { | ||
721 | .name = "C1-KNL", | ||
722 | .desc = "MWAIT 0x00", | ||
723 | .flags = MWAIT2flg(0x00), | ||
724 | .exit_latency = 1, | ||
725 | .target_residency = 2, | ||
726 | .enter = &intel_idle, | ||
727 | .enter_freeze = intel_idle_freeze }, | ||
728 | { | ||
729 | .name = "C6-KNL", | ||
730 | .desc = "MWAIT 0x10", | ||
731 | .flags = MWAIT2flg(0x10) | CPUIDLE_FLAG_TLB_FLUSHED, | ||
732 | .exit_latency = 120, | ||
733 | .target_residency = 500, | ||
734 | .enter = &intel_idle, | ||
735 | .enter_freeze = intel_idle_freeze }, | ||
736 | { | ||
737 | .enter = NULL } | ||
738 | }; | ||
719 | 739 | ||
720 | /** | 740 | /** |
721 | * intel_idle | 741 | * intel_idle |
@@ -890,6 +910,10 @@ static const struct idle_cpu idle_cpu_avn = { | |||
890 | .disable_promotion_to_c1e = true, | 910 | .disable_promotion_to_c1e = true, |
891 | }; | 911 | }; |
892 | 912 | ||
913 | static const struct idle_cpu idle_cpu_knl = { | ||
914 | .state_table = knl_cstates, | ||
915 | }; | ||
916 | |||
893 | #define ICPU(model, cpu) \ | 917 | #define ICPU(model, cpu) \ |
894 | { X86_VENDOR_INTEL, 6, model, X86_FEATURE_MWAIT, (unsigned long)&cpu } | 918 | { X86_VENDOR_INTEL, 6, model, X86_FEATURE_MWAIT, (unsigned long)&cpu } |
895 | 919 | ||
@@ -921,6 +945,7 @@ static const struct x86_cpu_id intel_idle_ids[] __initconst = { | |||
921 | ICPU(0x56, idle_cpu_bdw), | 945 | ICPU(0x56, idle_cpu_bdw), |
922 | ICPU(0x4e, idle_cpu_skl), | 946 | ICPU(0x4e, idle_cpu_skl), |
923 | ICPU(0x5e, idle_cpu_skl), | 947 | ICPU(0x5e, idle_cpu_skl), |
948 | ICPU(0x57, idle_cpu_knl), | ||
924 | {} | 949 | {} |
925 | }; | 950 | }; |
926 | MODULE_DEVICE_TABLE(x86cpu, intel_idle_ids); | 951 | MODULE_DEVICE_TABLE(x86cpu, intel_idle_ids); |
@@ -994,36 +1019,92 @@ static void intel_idle_cpuidle_devices_uninit(void) | |||
994 | } | 1019 | } |
995 | 1020 | ||
996 | /* | 1021 | /* |
997 | * intel_idle_state_table_update() | 1022 | * ivt_idle_state_table_update(void) |
998 | * | 1023 | * |
999 | * Update the default state_table for this CPU-id | 1024 | * Tune IVT multi-socket targets |
1000 | * | ||
1001 | * Currently used to access tuned IVT multi-socket targets | ||
1002 | * Assumption: num_sockets == (max_package_num + 1) | 1025 | * Assumption: num_sockets == (max_package_num + 1) |
1003 | */ | 1026 | */ |
1004 | void intel_idle_state_table_update(void) | 1027 | static void ivt_idle_state_table_update(void) |
1005 | { | 1028 | { |
1006 | /* IVT uses a different table for 1-2, 3-4, and > 4 sockets */ | 1029 | /* IVT uses a different table for 1-2, 3-4, and > 4 sockets */ |
1007 | if (boot_cpu_data.x86_model == 0x3e) { /* IVT */ | 1030 | int cpu, package_num, num_sockets = 1; |
1008 | int cpu, package_num, num_sockets = 1; | 1031 | |
1009 | 1032 | for_each_online_cpu(cpu) { | |
1010 | for_each_online_cpu(cpu) { | 1033 | package_num = topology_physical_package_id(cpu); |
1011 | package_num = topology_physical_package_id(cpu); | 1034 | if (package_num + 1 > num_sockets) { |
1012 | if (package_num + 1 > num_sockets) { | 1035 | num_sockets = package_num + 1; |
1013 | num_sockets = package_num + 1; | 1036 | |
1014 | 1037 | if (num_sockets > 4) { | |
1015 | if (num_sockets > 4) { | 1038 | cpuidle_state_table = ivt_cstates_8s; |
1016 | cpuidle_state_table = ivt_cstates_8s; | 1039 | return; |
1017 | return; | ||
1018 | } | ||
1019 | } | 1040 | } |
1020 | } | 1041 | } |
1042 | } | ||
1043 | |||
1044 | if (num_sockets > 2) | ||
1045 | cpuidle_state_table = ivt_cstates_4s; | ||
1021 | 1046 | ||
1022 | if (num_sockets > 2) | 1047 | /* else, 1 and 2 socket systems use default ivt_cstates */ |
1023 | cpuidle_state_table = ivt_cstates_4s; | 1048 | } |
1024 | /* else, 1 and 2 socket systems use default ivt_cstates */ | 1049 | /* |
1050 | * sklh_idle_state_table_update(void) | ||
1051 | * | ||
1052 | * On SKL-H (model 0x5e) disable C8 and C9 if: | ||
1053 | * C10 is enabled and SGX disabled | ||
1054 | */ | ||
1055 | static void sklh_idle_state_table_update(void) | ||
1056 | { | ||
1057 | unsigned long long msr; | ||
1058 | unsigned int eax, ebx, ecx, edx; | ||
1059 | |||
1060 | |||
1061 | /* if PC10 disabled via cmdline intel_idle.max_cstate=7 or shallower */ | ||
1062 | if (max_cstate <= 7) | ||
1063 | return; | ||
1064 | |||
1065 | /* if PC10 not present in CPUID.MWAIT.EDX */ | ||
1066 | if ((mwait_substates & (0xF << 28)) == 0) | ||
1067 | return; | ||
1068 | |||
1069 | rdmsrl(MSR_NHM_SNB_PKG_CST_CFG_CTL, msr); | ||
1070 | |||
1071 | /* PC10 is not enabled in PKG C-state limit */ | ||
1072 | if ((msr & 0xF) != 8) | ||
1073 | return; | ||
1074 | |||
1075 | ecx = 0; | ||
1076 | cpuid(7, &eax, &ebx, &ecx, &edx); | ||
1077 | |||
1078 | /* if SGX is present */ | ||
1079 | if (ebx & (1 << 2)) { | ||
1080 | |||
1081 | rdmsrl(MSR_IA32_FEATURE_CONTROL, msr); | ||
1082 | |||
1083 | /* if SGX is enabled */ | ||
1084 | if (msr & (1 << 18)) | ||
1085 | return; | ||
1086 | } | ||
1087 | |||
1088 | skl_cstates[5].disabled = 1; /* C8-SKL */ | ||
1089 | skl_cstates[6].disabled = 1; /* C9-SKL */ | ||
1090 | } | ||
1091 | /* | ||
1092 | * intel_idle_state_table_update() | ||
1093 | * | ||
1094 | * Update the default state_table for this CPU-id | ||
1095 | */ | ||
1096 | |||
1097 | static void intel_idle_state_table_update(void) | ||
1098 | { | ||
1099 | switch (boot_cpu_data.x86_model) { | ||
1100 | |||
1101 | case 0x3e: /* IVT */ | ||
1102 | ivt_idle_state_table_update(); | ||
1103 | break; | ||
1104 | case 0x5e: /* SKL-H */ | ||
1105 | sklh_idle_state_table_update(); | ||
1106 | break; | ||
1025 | } | 1107 | } |
1026 | return; | ||
1027 | } | 1108 | } |
1028 | 1109 | ||
1029 | /* | 1110 | /* |
@@ -1063,6 +1144,14 @@ static int __init intel_idle_cpuidle_driver_init(void) | |||
1063 | if (num_substates == 0) | 1144 | if (num_substates == 0) |
1064 | continue; | 1145 | continue; |
1065 | 1146 | ||
1147 | /* if state marked as disabled, skip it */ | ||
1148 | if (cpuidle_state_table[cstate].disabled != 0) { | ||
1149 | pr_debug(PREFIX "state %s is disabled", | ||
1150 | cpuidle_state_table[cstate].name); | ||
1151 | continue; | ||
1152 | } | ||
1153 | |||
1154 | |||
1066 | if (((mwait_cstate + 1) > 2) && | 1155 | if (((mwait_cstate + 1) > 2) && |
1067 | !boot_cpu_has(X86_FEATURE_NONSTOP_TSC)) | 1156 | !boot_cpu_has(X86_FEATURE_NONSTOP_TSC)) |
1068 | mark_tsc_unstable("TSC halts in idle" | 1157 | mark_tsc_unstable("TSC halts in idle" |