aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSebastian Andrzej Siewior <bigeasy@linutronix.de>2016-11-29 04:51:43 -0500
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>2016-12-01 17:01:36 -0500
commitfb1013a01673acf7e94e38cda169828ac76b345a (patch)
tree025b27e54e2a2e8eafbbd20e497de9309ca94365
parent29d7bbada98e0969dd2ea159104aa55052a1c439 (diff)
intel_idle: Convert to hotplug state machine
Install the callbacks via the state machine and let the core invoke the callbacks on the already online CPUs. The two smp_call_function_single() invocations in intel_idle_cpu_init() have been removed because intel_idle_cpu_init() is now invoked via the hotplug callback which runs on the target CPU. The IRQ-off calling convention for auto_demotion_disable() and c1e_promotion_disable() has not been preserved because only those two modify the MSR during CPU intialization. Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de> Acked-by: Jacob Pan <jacob.jun.pan@linux.intel.com> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
-rw-r--r--drivers/idle/intel_idle.c103
1 files changed, 39 insertions, 64 deletions
diff --git a/drivers/idle/intel_idle.c b/drivers/idle/intel_idle.c
index 3828babfb77b..7d8ea3d5fda6 100644
--- a/drivers/idle/intel_idle.c
+++ b/drivers/idle/intel_idle.c
@@ -98,8 +98,6 @@ static int intel_idle(struct cpuidle_device *dev,
98 struct cpuidle_driver *drv, int index); 98 struct cpuidle_driver *drv, int index);
99static void intel_idle_freeze(struct cpuidle_device *dev, 99static void intel_idle_freeze(struct cpuidle_device *dev,
100 struct cpuidle_driver *drv, int index); 100 struct cpuidle_driver *drv, int index);
101static int intel_idle_cpu_init(int cpu);
102
103static struct cpuidle_state *cpuidle_state_table; 101static struct cpuidle_state *cpuidle_state_table;
104 102
105/* 103/*
@@ -951,50 +949,15 @@ static void intel_idle_freeze(struct cpuidle_device *dev,
951 mwait_idle_with_hints(eax, ecx); 949 mwait_idle_with_hints(eax, ecx);
952} 950}
953 951
954static void __setup_broadcast_timer(void *arg) 952static void __setup_broadcast_timer(bool on)
955{ 953{
956 unsigned long on = (unsigned long)arg;
957
958 if (on) 954 if (on)
959 tick_broadcast_enable(); 955 tick_broadcast_enable();
960 else 956 else
961 tick_broadcast_disable(); 957 tick_broadcast_disable();
962} 958}
963 959
964static int cpu_hotplug_notify(struct notifier_block *n, 960static void auto_demotion_disable(void)
965 unsigned long action, void *hcpu)
966{
967 int hotcpu = (unsigned long)hcpu;
968 struct cpuidle_device *dev;
969
970 switch (action & ~CPU_TASKS_FROZEN) {
971 case CPU_ONLINE:
972
973 if (lapic_timer_reliable_states != LAPIC_TIMER_ALWAYS_RELIABLE)
974 __setup_broadcast_timer((void *)true);
975
976 /*
977 * Some systems can hotplug a cpu at runtime after
978 * the kernel has booted, we have to initialize the
979 * driver in this case
980 */
981 dev = per_cpu_ptr(intel_idle_cpuidle_devices, hotcpu);
982 if (dev->registered)
983 break;
984
985 if (intel_idle_cpu_init(hotcpu))
986 return NOTIFY_BAD;
987
988 break;
989 }
990 return NOTIFY_OK;
991}
992
993static struct notifier_block cpu_hotplug_notifier = {
994 .notifier_call = cpu_hotplug_notify,
995};
996
997static void auto_demotion_disable(void *dummy)
998{ 961{
999 unsigned long long msr_bits; 962 unsigned long long msr_bits;
1000 963
@@ -1002,7 +965,7 @@ static void auto_demotion_disable(void *dummy)
1002 msr_bits &= ~(icpu->auto_demotion_disable_flags); 965 msr_bits &= ~(icpu->auto_demotion_disable_flags);
1003 wrmsrl(MSR_NHM_SNB_PKG_CST_CFG_CTL, msr_bits); 966 wrmsrl(MSR_NHM_SNB_PKG_CST_CFG_CTL, msr_bits);
1004} 967}
1005static void c1e_promotion_disable(void *dummy) 968static void c1e_promotion_disable(void)
1006{ 969{
1007 unsigned long long msr_bits; 970 unsigned long long msr_bits;
1008 971
@@ -1422,12 +1385,11 @@ static void __init intel_idle_cpuidle_driver_init(void)
1422 * allocate, initialize, register cpuidle_devices 1385 * allocate, initialize, register cpuidle_devices
1423 * @cpu: cpu/core to initialize 1386 * @cpu: cpu/core to initialize
1424 */ 1387 */
1425static int intel_idle_cpu_init(int cpu) 1388static int intel_idle_cpu_init(unsigned int cpu)
1426{ 1389{
1427 struct cpuidle_device *dev; 1390 struct cpuidle_device *dev;
1428 1391
1429 dev = per_cpu_ptr(intel_idle_cpuidle_devices, cpu); 1392 dev = per_cpu_ptr(intel_idle_cpuidle_devices, cpu);
1430
1431 dev->cpu = cpu; 1393 dev->cpu = cpu;
1432 1394
1433 if (cpuidle_register_device(dev)) { 1395 if (cpuidle_register_device(dev)) {
@@ -1436,17 +1398,36 @@ static int intel_idle_cpu_init(int cpu)
1436 } 1398 }
1437 1399
1438 if (icpu->auto_demotion_disable_flags) 1400 if (icpu->auto_demotion_disable_flags)
1439 smp_call_function_single(cpu, auto_demotion_disable, NULL, 1); 1401 auto_demotion_disable();
1440 1402
1441 if (icpu->disable_promotion_to_c1e) 1403 if (icpu->disable_promotion_to_c1e)
1442 smp_call_function_single(cpu, c1e_promotion_disable, NULL, 1); 1404 c1e_promotion_disable();
1405
1406 return 0;
1407}
1408
1409static int intel_idle_cpu_online(unsigned int cpu)
1410{
1411 struct cpuidle_device *dev;
1412
1413 if (lapic_timer_reliable_states != LAPIC_TIMER_ALWAYS_RELIABLE)
1414 __setup_broadcast_timer(true);
1415
1416 /*
1417 * Some systems can hotplug a cpu at runtime after
1418 * the kernel has booted, we have to initialize the
1419 * driver in this case
1420 */
1421 dev = per_cpu_ptr(intel_idle_cpuidle_devices, cpu);
1422 if (!dev->registered)
1423 return intel_idle_cpu_init(cpu);
1443 1424
1444 return 0; 1425 return 0;
1445} 1426}
1446 1427
1447static int __init intel_idle_init(void) 1428static int __init intel_idle_init(void)
1448{ 1429{
1449 int retval, i; 1430 int retval;
1450 1431
1451 /* Do not load intel_idle at all for now if idle= is passed */ 1432 /* Do not load intel_idle at all for now if idle= is passed */
1452 if (boot_option_idle_override != IDLE_NO_OVERRIDE) 1433 if (boot_option_idle_override != IDLE_NO_OVERRIDE)
@@ -1466,35 +1447,29 @@ static int __init intel_idle_init(void)
1466 struct cpuidle_driver *drv = cpuidle_get_driver(); 1447 struct cpuidle_driver *drv = cpuidle_get_driver();
1467 printk(KERN_DEBUG PREFIX "intel_idle yielding to %s", 1448 printk(KERN_DEBUG PREFIX "intel_idle yielding to %s",
1468 drv ? drv->name : "none"); 1449 drv ? drv->name : "none");
1469 free_percpu(intel_idle_cpuidle_devices); 1450 goto init_driver_fail;
1470 return retval;
1471 } 1451 }
1472 1452
1473 cpu_notifier_register_begin();
1474
1475 for_each_online_cpu(i) {
1476 retval = intel_idle_cpu_init(i);
1477 if (retval) {
1478 intel_idle_cpuidle_devices_uninit();
1479 cpu_notifier_register_done();
1480 cpuidle_unregister_driver(&intel_idle_driver);
1481 free_percpu(intel_idle_cpuidle_devices);
1482 return retval;
1483 }
1484 }
1485 __register_cpu_notifier(&cpu_hotplug_notifier);
1486
1487 if (boot_cpu_has(X86_FEATURE_ARAT)) /* Always Reliable APIC Timer */ 1453 if (boot_cpu_has(X86_FEATURE_ARAT)) /* Always Reliable APIC Timer */
1488 lapic_timer_reliable_states = LAPIC_TIMER_ALWAYS_RELIABLE; 1454 lapic_timer_reliable_states = LAPIC_TIMER_ALWAYS_RELIABLE;
1489 else
1490 on_each_cpu(__setup_broadcast_timer, (void *)true, 1);
1491 1455
1492 cpu_notifier_register_done(); 1456 retval = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "idle/intel:online",
1457 intel_idle_cpu_online, NULL);
1458 if (retval < 0)
1459 goto hp_setup_fail;
1493 1460
1494 pr_debug(PREFIX "lapic_timer_reliable_states 0x%x\n", 1461 pr_debug(PREFIX "lapic_timer_reliable_states 0x%x\n",
1495 lapic_timer_reliable_states); 1462 lapic_timer_reliable_states);
1496 1463
1497 return 0; 1464 return 0;
1465
1466hp_setup_fail:
1467 intel_idle_cpuidle_devices_uninit();
1468 cpuidle_unregister_driver(&intel_idle_driver);
1469init_driver_fail:
1470 free_percpu(intel_idle_cpuidle_devices);
1471 return retval;
1472
1498} 1473}
1499device_initcall(intel_idle_init); 1474device_initcall(intel_idle_init);
1500 1475