|
@@ -96,6 +96,7 @@ static const struct idle_cpu *icpu;
|
|
static struct cpuidle_device __percpu *intel_idle_cpuidle_devices;
|
|
static struct cpuidle_device __percpu *intel_idle_cpuidle_devices;
|
|
static int intel_idle(struct cpuidle_device *dev,
|
|
static int intel_idle(struct cpuidle_device *dev,
|
|
struct cpuidle_driver *drv, int index);
|
|
struct cpuidle_driver *drv, int index);
|
|
|
|
+static int intel_idle_cpu_init(int cpu);
|
|
|
|
|
|
static struct cpuidle_state *cpuidle_state_table;
|
|
static struct cpuidle_state *cpuidle_state_table;
|
|
|
|
|
|
@@ -302,22 +303,35 @@ static void __setup_broadcast_timer(void *arg)
|
|
clockevents_notify(reason, &cpu);
|
|
clockevents_notify(reason, &cpu);
|
|
}
|
|
}
|
|
|
|
|
|
-static int setup_broadcast_cpuhp_notify(struct notifier_block *n,
|
|
|
|
- unsigned long action, void *hcpu)
|
|
|
|
|
|
+static int cpu_hotplug_notify(struct notifier_block *n,
|
|
|
|
+ unsigned long action, void *hcpu)
|
|
{
|
|
{
|
|
int hotcpu = (unsigned long)hcpu;
|
|
int hotcpu = (unsigned long)hcpu;
|
|
|
|
+ struct cpuidle_device *dev;
|
|
|
|
|
|
switch (action & 0xf) {
|
|
switch (action & 0xf) {
|
|
case CPU_ONLINE:
|
|
case CPU_ONLINE:
|
|
- smp_call_function_single(hotcpu, __setup_broadcast_timer,
|
|
|
|
- (void *)true, 1);
|
|
|
|
|
|
+
|
|
|
|
+ if (lapic_timer_reliable_states != LAPIC_TIMER_ALWAYS_RELIABLE)
|
|
|
|
+ smp_call_function_single(hotcpu, __setup_broadcast_timer,
|
|
|
|
+ (void *)true, 1);
|
|
|
|
+
|
|
|
|
+ /*
|
|
|
|
+ * Some systems can hotplug a cpu at runtime after
|
|
|
|
+ * the kernel has booted, we have to initialize the
|
|
|
|
+ * driver in this case
|
|
|
|
+ */
|
|
|
|
+ dev = per_cpu_ptr(intel_idle_cpuidle_devices, hotcpu);
|
|
|
|
+ if (!dev->registered)
|
|
|
|
+ intel_idle_cpu_init(hotcpu);
|
|
|
|
+
|
|
break;
|
|
break;
|
|
}
|
|
}
|
|
return NOTIFY_OK;
|
|
return NOTIFY_OK;
|
|
}
|
|
}
|
|
|
|
|
|
-static struct notifier_block setup_broadcast_notifier = {
|
|
|
|
- .notifier_call = setup_broadcast_cpuhp_notify,
|
|
|
|
|
|
+static struct notifier_block cpu_hotplug_notifier = {
|
|
|
|
+ .notifier_call = cpu_hotplug_notify,
|
|
};
|
|
};
|
|
|
|
|
|
static void auto_demotion_disable(void *dummy)
|
|
static void auto_demotion_disable(void *dummy)
|
|
@@ -405,10 +419,10 @@ static int intel_idle_probe(void)
|
|
|
|
|
|
if (boot_cpu_has(X86_FEATURE_ARAT)) /* Always Reliable APIC Timer */
|
|
if (boot_cpu_has(X86_FEATURE_ARAT)) /* Always Reliable APIC Timer */
|
|
lapic_timer_reliable_states = LAPIC_TIMER_ALWAYS_RELIABLE;
|
|
lapic_timer_reliable_states = LAPIC_TIMER_ALWAYS_RELIABLE;
|
|
- else {
|
|
|
|
|
|
+ else
|
|
on_each_cpu(__setup_broadcast_timer, (void *)true, 1);
|
|
on_each_cpu(__setup_broadcast_timer, (void *)true, 1);
|
|
- register_cpu_notifier(&setup_broadcast_notifier);
|
|
|
|
- }
|
|
|
|
|
|
+
|
|
|
|
+ register_cpu_notifier(&cpu_hotplug_notifier);
|
|
|
|
|
|
pr_debug(PREFIX "v" INTEL_IDLE_VERSION
|
|
pr_debug(PREFIX "v" INTEL_IDLE_VERSION
|
|
" model 0x%X\n", boot_cpu_data.x86_model);
|
|
" model 0x%X\n", boot_cpu_data.x86_model);
|
|
@@ -494,7 +508,7 @@ static int intel_idle_cpuidle_driver_init(void)
|
|
* allocate, initialize, register cpuidle_devices
|
|
* allocate, initialize, register cpuidle_devices
|
|
* @cpu: cpu/core to initialize
|
|
* @cpu: cpu/core to initialize
|
|
*/
|
|
*/
|
|
-int intel_idle_cpu_init(int cpu)
|
|
|
|
|
|
+static int intel_idle_cpu_init(int cpu)
|
|
{
|
|
{
|
|
int cstate;
|
|
int cstate;
|
|
struct cpuidle_device *dev;
|
|
struct cpuidle_device *dev;
|
|
@@ -539,7 +553,6 @@ int intel_idle_cpu_init(int cpu)
|
|
|
|
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
-EXPORT_SYMBOL_GPL(intel_idle_cpu_init);
|
|
|
|
|
|
|
|
static int __init intel_idle_init(void)
|
|
static int __init intel_idle_init(void)
|
|
{
|
|
{
|
|
@@ -581,10 +594,10 @@ static void __exit intel_idle_exit(void)
|
|
intel_idle_cpuidle_devices_uninit();
|
|
intel_idle_cpuidle_devices_uninit();
|
|
cpuidle_unregister_driver(&intel_idle_driver);
|
|
cpuidle_unregister_driver(&intel_idle_driver);
|
|
|
|
|
|
- if (lapic_timer_reliable_states != LAPIC_TIMER_ALWAYS_RELIABLE) {
|
|
|
|
|
|
+
|
|
|
|
+ if (lapic_timer_reliable_states != LAPIC_TIMER_ALWAYS_RELIABLE)
|
|
on_each_cpu(__setup_broadcast_timer, (void *)false, 1);
|
|
on_each_cpu(__setup_broadcast_timer, (void *)false, 1);
|
|
- unregister_cpu_notifier(&setup_broadcast_notifier);
|
|
|
|
- }
|
|
|
|
|
|
+ unregister_cpu_notifier(&cpu_hotplug_notifier);
|
|
|
|
|
|
return;
|
|
return;
|
|
}
|
|
}
|