aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/idle/intel_idle.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/idle/intel_idle.c')
-rw-r--r--drivers/idle/intel_idle.c97
1 files changed, 67 insertions, 30 deletions
diff --git a/drivers/idle/intel_idle.c b/drivers/idle/intel_idle.c
index ba947df5a8c7..c6935de425fa 100644
--- a/drivers/idle/intel_idle.c
+++ b/drivers/idle/intel_idle.c
@@ -660,6 +660,35 @@ static struct cpuidle_state skl_cstates[] = {
660 .enter = NULL } 660 .enter = NULL }
661}; 661};
662 662
663static struct cpuidle_state skx_cstates[] = {
664 {
665 .name = "C1-SKX",
666 .desc = "MWAIT 0x00",
667 .flags = MWAIT2flg(0x00),
668 .exit_latency = 2,
669 .target_residency = 2,
670 .enter = &intel_idle,
671 .enter_freeze = intel_idle_freeze, },
672 {
673 .name = "C1E-SKX",
674 .desc = "MWAIT 0x01",
675 .flags = MWAIT2flg(0x01),
676 .exit_latency = 10,
677 .target_residency = 20,
678 .enter = &intel_idle,
679 .enter_freeze = intel_idle_freeze, },
680 {
681 .name = "C6-SKX",
682 .desc = "MWAIT 0x20",
683 .flags = MWAIT2flg(0x20) | CPUIDLE_FLAG_TLB_FLUSHED,
684 .exit_latency = 133,
685 .target_residency = 600,
686 .enter = &intel_idle,
687 .enter_freeze = intel_idle_freeze, },
688 {
689 .enter = NULL }
690};
691
663static struct cpuidle_state atom_cstates[] = { 692static struct cpuidle_state atom_cstates[] = {
664 { 693 {
665 .name = "C1E-ATM", 694 .name = "C1E-ATM",
@@ -818,8 +847,11 @@ static int cpu_hotplug_notify(struct notifier_block *n,
818 * driver in this case 847 * driver in this case
819 */ 848 */
820 dev = per_cpu_ptr(intel_idle_cpuidle_devices, hotcpu); 849 dev = per_cpu_ptr(intel_idle_cpuidle_devices, hotcpu);
821 if (!dev->registered) 850 if (dev->registered)
822 intel_idle_cpu_init(hotcpu); 851 break;
852
853 if (intel_idle_cpu_init(hotcpu))
854 return NOTIFY_BAD;
823 855
824 break; 856 break;
825 } 857 }
@@ -904,6 +936,10 @@ static const struct idle_cpu idle_cpu_skl = {
904 .disable_promotion_to_c1e = true, 936 .disable_promotion_to_c1e = true,
905}; 937};
906 938
939static const struct idle_cpu idle_cpu_skx = {
940 .state_table = skx_cstates,
941 .disable_promotion_to_c1e = true,
942};
907 943
908static const struct idle_cpu idle_cpu_avn = { 944static const struct idle_cpu idle_cpu_avn = {
909 .state_table = avn_cstates, 945 .state_table = avn_cstates,
@@ -945,6 +981,9 @@ static const struct x86_cpu_id intel_idle_ids[] __initconst = {
945 ICPU(0x56, idle_cpu_bdw), 981 ICPU(0x56, idle_cpu_bdw),
946 ICPU(0x4e, idle_cpu_skl), 982 ICPU(0x4e, idle_cpu_skl),
947 ICPU(0x5e, idle_cpu_skl), 983 ICPU(0x5e, idle_cpu_skl),
984 ICPU(0x8e, idle_cpu_skl),
985 ICPU(0x9e, idle_cpu_skl),
986 ICPU(0x55, idle_cpu_skx),
948 ICPU(0x57, idle_cpu_knl), 987 ICPU(0x57, idle_cpu_knl),
949 {} 988 {}
950}; 989};
@@ -987,22 +1026,15 @@ static int __init intel_idle_probe(void)
987 icpu = (const struct idle_cpu *)id->driver_data; 1026 icpu = (const struct idle_cpu *)id->driver_data;
988 cpuidle_state_table = icpu->state_table; 1027 cpuidle_state_table = icpu->state_table;
989 1028
990 if (boot_cpu_has(X86_FEATURE_ARAT)) /* Always Reliable APIC Timer */
991 lapic_timer_reliable_states = LAPIC_TIMER_ALWAYS_RELIABLE;
992 else
993 on_each_cpu(__setup_broadcast_timer, (void *)true, 1);
994
995 pr_debug(PREFIX "v" INTEL_IDLE_VERSION 1029 pr_debug(PREFIX "v" INTEL_IDLE_VERSION
996 " model 0x%X\n", boot_cpu_data.x86_model); 1030 " model 0x%X\n", boot_cpu_data.x86_model);
997 1031
998 pr_debug(PREFIX "lapic_timer_reliable_states 0x%x\n",
999 lapic_timer_reliable_states);
1000 return 0; 1032 return 0;
1001} 1033}
1002 1034
1003/* 1035/*
1004 * intel_idle_cpuidle_devices_uninit() 1036 * intel_idle_cpuidle_devices_uninit()
1005 * unregister, free cpuidle_devices 1037 * Unregisters the cpuidle devices.
1006 */ 1038 */
1007static void intel_idle_cpuidle_devices_uninit(void) 1039static void intel_idle_cpuidle_devices_uninit(void)
1008{ 1040{
@@ -1013,9 +1045,6 @@ static void intel_idle_cpuidle_devices_uninit(void)
1013 dev = per_cpu_ptr(intel_idle_cpuidle_devices, i); 1045 dev = per_cpu_ptr(intel_idle_cpuidle_devices, i);
1014 cpuidle_unregister_device(dev); 1046 cpuidle_unregister_device(dev);
1015 } 1047 }
1016
1017 free_percpu(intel_idle_cpuidle_devices);
1018 return;
1019} 1048}
1020 1049
1021/* 1050/*
@@ -1111,7 +1140,7 @@ static void intel_idle_state_table_update(void)
1111 * intel_idle_cpuidle_driver_init() 1140 * intel_idle_cpuidle_driver_init()
1112 * allocate, initialize cpuidle_states 1141 * allocate, initialize cpuidle_states
1113 */ 1142 */
1114static int __init intel_idle_cpuidle_driver_init(void) 1143static void __init intel_idle_cpuidle_driver_init(void)
1115{ 1144{
1116 int cstate; 1145 int cstate;
1117 struct cpuidle_driver *drv = &intel_idle_driver; 1146 struct cpuidle_driver *drv = &intel_idle_driver;
@@ -1163,18 +1192,10 @@ static int __init intel_idle_cpuidle_driver_init(void)
1163 drv->state_count += 1; 1192 drv->state_count += 1;
1164 } 1193 }
1165 1194
1166 if (icpu->auto_demotion_disable_flags)
1167 on_each_cpu(auto_demotion_disable, NULL, 1);
1168
1169 if (icpu->byt_auto_demotion_disable_flag) { 1195 if (icpu->byt_auto_demotion_disable_flag) {
1170 wrmsrl(MSR_CC6_DEMOTION_POLICY_CONFIG, 0); 1196 wrmsrl(MSR_CC6_DEMOTION_POLICY_CONFIG, 0);
1171 wrmsrl(MSR_MC6_DEMOTION_POLICY_CONFIG, 0); 1197 wrmsrl(MSR_MC6_DEMOTION_POLICY_CONFIG, 0);
1172 } 1198 }
1173
1174 if (icpu->disable_promotion_to_c1e) /* each-cpu is redundant */
1175 on_each_cpu(c1e_promotion_disable, NULL, 1);
1176
1177 return 0;
1178} 1199}
1179 1200
1180 1201
@@ -1193,7 +1214,6 @@ static int intel_idle_cpu_init(int cpu)
1193 1214
1194 if (cpuidle_register_device(dev)) { 1215 if (cpuidle_register_device(dev)) {
1195 pr_debug(PREFIX "cpuidle_register_device %d failed!\n", cpu); 1216 pr_debug(PREFIX "cpuidle_register_device %d failed!\n", cpu);
1196 intel_idle_cpuidle_devices_uninit();
1197 return -EIO; 1217 return -EIO;
1198 } 1218 }
1199 1219
@@ -1218,40 +1238,51 @@ static int __init intel_idle_init(void)
1218 if (retval) 1238 if (retval)
1219 return retval; 1239 return retval;
1220 1240
1241 intel_idle_cpuidle_devices = alloc_percpu(struct cpuidle_device);
1242 if (intel_idle_cpuidle_devices == NULL)
1243 return -ENOMEM;
1244
1221 intel_idle_cpuidle_driver_init(); 1245 intel_idle_cpuidle_driver_init();
1222 retval = cpuidle_register_driver(&intel_idle_driver); 1246 retval = cpuidle_register_driver(&intel_idle_driver);
1223 if (retval) { 1247 if (retval) {
1224 struct cpuidle_driver *drv = cpuidle_get_driver(); 1248 struct cpuidle_driver *drv = cpuidle_get_driver();
1225 printk(KERN_DEBUG PREFIX "intel_idle yielding to %s", 1249 printk(KERN_DEBUG PREFIX "intel_idle yielding to %s",
1226 drv ? drv->name : "none"); 1250 drv ? drv->name : "none");
1251 free_percpu(intel_idle_cpuidle_devices);
1227 return retval; 1252 return retval;
1228 } 1253 }
1229 1254
1230 intel_idle_cpuidle_devices = alloc_percpu(struct cpuidle_device);
1231 if (intel_idle_cpuidle_devices == NULL)
1232 return -ENOMEM;
1233
1234 cpu_notifier_register_begin(); 1255 cpu_notifier_register_begin();
1235 1256
1236 for_each_online_cpu(i) { 1257 for_each_online_cpu(i) {
1237 retval = intel_idle_cpu_init(i); 1258 retval = intel_idle_cpu_init(i);
1238 if (retval) { 1259 if (retval) {
1260 intel_idle_cpuidle_devices_uninit();
1239 cpu_notifier_register_done(); 1261 cpu_notifier_register_done();
1240 cpuidle_unregister_driver(&intel_idle_driver); 1262 cpuidle_unregister_driver(&intel_idle_driver);
1263 free_percpu(intel_idle_cpuidle_devices);
1241 return retval; 1264 return retval;
1242 } 1265 }
1243 } 1266 }
1244 __register_cpu_notifier(&cpu_hotplug_notifier); 1267 __register_cpu_notifier(&cpu_hotplug_notifier);
1245 1268
1269 if (boot_cpu_has(X86_FEATURE_ARAT)) /* Always Reliable APIC Timer */
1270 lapic_timer_reliable_states = LAPIC_TIMER_ALWAYS_RELIABLE;
1271 else
1272 on_each_cpu(__setup_broadcast_timer, (void *)true, 1);
1273
1246 cpu_notifier_register_done(); 1274 cpu_notifier_register_done();
1247 1275
1276 pr_debug(PREFIX "lapic_timer_reliable_states 0x%x\n",
1277 lapic_timer_reliable_states);
1278
1248 return 0; 1279 return 0;
1249} 1280}
1250 1281
1251static void __exit intel_idle_exit(void) 1282static void __exit intel_idle_exit(void)
1252{ 1283{
1253 intel_idle_cpuidle_devices_uninit(); 1284 struct cpuidle_device *dev;
1254 cpuidle_unregister_driver(&intel_idle_driver); 1285 int i;
1255 1286
1256 cpu_notifier_register_begin(); 1287 cpu_notifier_register_begin();
1257 1288
@@ -1259,9 +1290,15 @@ static void __exit intel_idle_exit(void)
1259 on_each_cpu(__setup_broadcast_timer, (void *)false, 1); 1290 on_each_cpu(__setup_broadcast_timer, (void *)false, 1);
1260 __unregister_cpu_notifier(&cpu_hotplug_notifier); 1291 __unregister_cpu_notifier(&cpu_hotplug_notifier);
1261 1292
1293 for_each_possible_cpu(i) {
1294 dev = per_cpu_ptr(intel_idle_cpuidle_devices, i);
1295 cpuidle_unregister_device(dev);
1296 }
1297
1262 cpu_notifier_register_done(); 1298 cpu_notifier_register_done();
1263 1299
1264 return; 1300 cpuidle_unregister_driver(&intel_idle_driver);
1301 free_percpu(intel_idle_cpuidle_devices);
1265} 1302}
1266 1303
1267module_init(intel_idle_init); 1304module_init(intel_idle_init);