aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLen Brown <len.brown@intel.com>2016-04-06 17:00:47 -0400
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>2016-04-08 20:17:43 -0400
commit5dcef694860100fd16885f052591b1268b764d21 (patch)
tree7c083237a14697091466b2506f039e8d45363daa
parentc998c07836f985b24361629dc98506ec7893e7a0 (diff)
intel_idle: add BXT support
Broxton has all the HSW C-states, except C3. BXT C-state timing is slightly different. Here we trust the IRTL MSRs as authority on maximum C-state latency, and override the driver's tables with the values found in the associated IRTL MSRs. Further we set the target_residency to 1x maximum latency, trusting the hardware demotion logic. Signed-off-by: Len Brown <len.brown@intel.com> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
-rw-r--r--arch/x86/include/asm/msr-index.h8
-rw-r--r--drivers/idle/intel_idle.c137
2 files changed, 145 insertions, 0 deletions
diff --git a/arch/x86/include/asm/msr-index.h b/arch/x86/include/asm/msr-index.h
index b05402ef3b84..73d66fa48638 100644
--- a/arch/x86/include/asm/msr-index.h
+++ b/arch/x86/include/asm/msr-index.h
@@ -162,6 +162,14 @@
162#define MSR_PKG_C9_RESIDENCY 0x00000631 162#define MSR_PKG_C9_RESIDENCY 0x00000631
163#define MSR_PKG_C10_RESIDENCY 0x00000632 163#define MSR_PKG_C10_RESIDENCY 0x00000632
164 164
165/* Interrupt Response Limit */
166#define MSR_PKGC3_IRTL 0x0000060a
167#define MSR_PKGC6_IRTL 0x0000060b
168#define MSR_PKGC7_IRTL 0x0000060c
169#define MSR_PKGC8_IRTL 0x00000633
170#define MSR_PKGC9_IRTL 0x00000634
171#define MSR_PKGC10_IRTL 0x00000635
172
165/* Run Time Average Power Limiting (RAPL) Interface */ 173/* Run Time Average Power Limiting (RAPL) Interface */
166 174
167#define MSR_RAPL_POWER_UNIT 0x00000606 175#define MSR_RAPL_POWER_UNIT 0x00000606
diff --git a/drivers/idle/intel_idle.c b/drivers/idle/intel_idle.c
index c6935de425fa..c96649292b55 100644
--- a/drivers/idle/intel_idle.c
+++ b/drivers/idle/intel_idle.c
@@ -766,6 +766,67 @@ static struct cpuidle_state knl_cstates[] = {
766 .enter = NULL } 766 .enter = NULL }
767}; 767};
768 768
769static struct cpuidle_state bxt_cstates[] = {
770 {
771 .name = "C1-BXT",
772 .desc = "MWAIT 0x00",
773 .flags = MWAIT2flg(0x00),
774 .exit_latency = 2,
775 .target_residency = 2,
776 .enter = &intel_idle,
777 .enter_freeze = intel_idle_freeze, },
778 {
779 .name = "C1E-BXT",
780 .desc = "MWAIT 0x01",
781 .flags = MWAIT2flg(0x01),
782 .exit_latency = 10,
783 .target_residency = 20,
784 .enter = &intel_idle,
785 .enter_freeze = intel_idle_freeze, },
786 {
787 .name = "C6-BXT",
788 .desc = "MWAIT 0x20",
789 .flags = MWAIT2flg(0x20) | CPUIDLE_FLAG_TLB_FLUSHED,
790 .exit_latency = 133,
791 .target_residency = 133,
792 .enter = &intel_idle,
793 .enter_freeze = intel_idle_freeze, },
794 {
795 .name = "C7s-BXT",
796 .desc = "MWAIT 0x31",
797 .flags = MWAIT2flg(0x31) | CPUIDLE_FLAG_TLB_FLUSHED,
798 .exit_latency = 155,
799 .target_residency = 155,
800 .enter = &intel_idle,
801 .enter_freeze = intel_idle_freeze, },
802 {
803 .name = "C8-BXT",
804 .desc = "MWAIT 0x40",
805 .flags = MWAIT2flg(0x40) | CPUIDLE_FLAG_TLB_FLUSHED,
806 .exit_latency = 1000,
807 .target_residency = 1000,
808 .enter = &intel_idle,
809 .enter_freeze = intel_idle_freeze, },
810 {
811 .name = "C9-BXT",
812 .desc = "MWAIT 0x50",
813 .flags = MWAIT2flg(0x50) | CPUIDLE_FLAG_TLB_FLUSHED,
814 .exit_latency = 2000,
815 .target_residency = 2000,
816 .enter = &intel_idle,
817 .enter_freeze = intel_idle_freeze, },
818 {
819 .name = "C10-BXT",
820 .desc = "MWAIT 0x60",
821 .flags = MWAIT2flg(0x60) | CPUIDLE_FLAG_TLB_FLUSHED,
822 .exit_latency = 10000,
823 .target_residency = 10000,
824 .enter = &intel_idle,
825 .enter_freeze = intel_idle_freeze, },
826 {
827 .enter = NULL }
828};
829
769/** 830/**
770 * intel_idle 831 * intel_idle
771 * @dev: cpuidle_device 832 * @dev: cpuidle_device
@@ -950,6 +1011,11 @@ static const struct idle_cpu idle_cpu_knl = {
950 .state_table = knl_cstates, 1011 .state_table = knl_cstates,
951}; 1012};
952 1013
1014static const struct idle_cpu idle_cpu_bxt = {
1015 .state_table = bxt_cstates,
1016 .disable_promotion_to_c1e = true,
1017};
1018
953#define ICPU(model, cpu) \ 1019#define ICPU(model, cpu) \
954 { X86_VENDOR_INTEL, 6, model, X86_FEATURE_MWAIT, (unsigned long)&cpu } 1020 { X86_VENDOR_INTEL, 6, model, X86_FEATURE_MWAIT, (unsigned long)&cpu }
955 1021
@@ -985,6 +1051,7 @@ static const struct x86_cpu_id intel_idle_ids[] __initconst = {
985 ICPU(0x9e, idle_cpu_skl), 1051 ICPU(0x9e, idle_cpu_skl),
986 ICPU(0x55, idle_cpu_skx), 1052 ICPU(0x55, idle_cpu_skx),
987 ICPU(0x57, idle_cpu_knl), 1053 ICPU(0x57, idle_cpu_knl),
1054 ICPU(0x5c, idle_cpu_bxt),
988 {} 1055 {}
989}; 1056};
990MODULE_DEVICE_TABLE(x86cpu, intel_idle_ids); 1057MODULE_DEVICE_TABLE(x86cpu, intel_idle_ids);
@@ -1075,6 +1142,73 @@ static void ivt_idle_state_table_update(void)
1075 1142
1076 /* else, 1 and 2 socket systems use default ivt_cstates */ 1143 /* else, 1 and 2 socket systems use default ivt_cstates */
1077} 1144}
1145
1146/*
1147 * Translate IRTL (Interrupt Response Time Limit) MSR to usec
1148 */
1149
1150static unsigned int irtl_ns_units[] = {
1151 1, 32, 1024, 32768, 1048576, 33554432, 0, 0 };
1152
1153static unsigned long long irtl_2_usec(unsigned long long irtl)
1154{
1155 unsigned long long ns;
1156
1157 ns = irtl_ns_units[(irtl >> 10) & 0x3];
1158
1159 return div64_u64((irtl & 0x3FF) * ns, 1000);
1160}
1161/*
1162 * bxt_idle_state_table_update(void)
1163 *
1164 * On BXT, we trust the IRTL to show the definitive maximum latency
1165 * We use the same value for target_residency.
1166 */
1167static void bxt_idle_state_table_update(void)
1168{
1169 unsigned long long msr;
1170
1171 rdmsrl(MSR_PKGC6_IRTL, msr);
1172 if (msr) {
1173 unsigned int usec = irtl_2_usec(msr);
1174
1175 bxt_cstates[2].exit_latency = usec;
1176 bxt_cstates[2].target_residency = usec;
1177 }
1178
1179 rdmsrl(MSR_PKGC7_IRTL, msr);
1180 if (msr) {
1181 unsigned int usec = irtl_2_usec(msr);
1182
1183 bxt_cstates[3].exit_latency = usec;
1184 bxt_cstates[3].target_residency = usec;
1185 }
1186
1187 rdmsrl(MSR_PKGC8_IRTL, msr);
1188 if (msr) {
1189 unsigned int usec = irtl_2_usec(msr);
1190
1191 bxt_cstates[4].exit_latency = usec;
1192 bxt_cstates[4].target_residency = usec;
1193 }
1194
1195 rdmsrl(MSR_PKGC9_IRTL, msr);
1196 if (msr) {
1197 unsigned int usec = irtl_2_usec(msr);
1198
1199 bxt_cstates[5].exit_latency = usec;
1200 bxt_cstates[5].target_residency = usec;
1201 }
1202
1203 rdmsrl(MSR_PKGC10_IRTL, msr);
1204 if (msr) {
1205 unsigned int usec = irtl_2_usec(msr);
1206
1207 bxt_cstates[6].exit_latency = usec;
1208 bxt_cstates[6].target_residency = usec;
1209 }
1210
1211}
1078/* 1212/*
1079 * sklh_idle_state_table_update(void) 1213 * sklh_idle_state_table_update(void)
1080 * 1214 *
@@ -1130,6 +1264,9 @@ static void intel_idle_state_table_update(void)
1130 case 0x3e: /* IVT */ 1264 case 0x3e: /* IVT */
1131 ivt_idle_state_table_update(); 1265 ivt_idle_state_table_update();
1132 break; 1266 break;
1267 case 0x5c: /* BXT */
1268 bxt_idle_state_table_update();
1269 break;
1133 case 0x5e: /* SKL-H */ 1270 case 0x5e: /* SKL-H */
1134 sklh_idle_state_table_update(); 1271 sklh_idle_state_table_update();
1135 break; 1272 break;