diff options
Diffstat (limited to 'drivers/idle/intel_idle.c')
-rw-r--r-- | drivers/idle/intel_idle.c | 97 |
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 | ||
663 | static 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 | |||
663 | static struct cpuidle_state atom_cstates[] = { | 692 | static 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 | ||
939 | static const struct idle_cpu idle_cpu_skx = { | ||
940 | .state_table = skx_cstates, | ||
941 | .disable_promotion_to_c1e = true, | ||
942 | }; | ||
907 | 943 | ||
908 | static const struct idle_cpu idle_cpu_avn = { | 944 | static 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 | */ |
1007 | static void intel_idle_cpuidle_devices_uninit(void) | 1039 | static 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 | */ |
1114 | static int __init intel_idle_cpuidle_driver_init(void) | 1143 | static 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 | ||
1251 | static void __exit intel_idle_exit(void) | 1282 | static 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 | ||
1267 | module_init(intel_idle_init); | 1304 | module_init(intel_idle_init); |