aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/idle/intel_idle.c133
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
71static struct cpuidle_driver intel_idle_driver = { 71static 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};
719static 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
913static 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};
926MODULE_DEVICE_TABLE(x86cpu, intel_idle_ids); 951MODULE_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 */
1004void intel_idle_state_table_update(void) 1027static 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 */
1055static 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
1097static 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"