diff --git a/drivers/cpuidle/cpuidle.c b/drivers/cpuidle/cpuidle.c index 3bf28f4ebe74..500f265e0d14 100644 --- a/drivers/cpuidle/cpuidle.c +++ b/drivers/cpuidle/cpuidle.c @@ -428,7 +428,7 @@ void cpuidle_uninstall_idle_handler(void) { if (enabled_devices) { initialized = 0; - wake_up_all_idle_cpus(); + wake_up_all_online_idle_cpus(); } /* diff --git a/include/linux/smp.h b/include/linux/smp.h index 04f44e0aa2e0..7ce15c3be7aa 100644 --- a/include/linux/smp.h +++ b/include/linux/smp.h @@ -127,6 +127,7 @@ int smp_call_function_any(const struct cpumask *mask, void kick_all_cpus_sync(void); void wake_up_all_idle_cpus(void); +void wake_up_all_online_idle_cpus(void); /* * Generic and arch helpers @@ -182,6 +183,7 @@ smp_call_function_any(const struct cpumask *mask, smp_call_func_t func, static inline void kick_all_cpus_sync(void) { } static inline void wake_up_all_idle_cpus(void) { } +static inline void wake_up_all_online_idle_cpus(void) { } #ifdef CONFIG_UP_LATE_INIT extern void __init up_late_init(void); diff --git a/kernel/smp.c b/kernel/smp.c index b5dd54708781..6677e077e4be 100644 --- a/kernel/smp.c +++ b/kernel/smp.c @@ -967,6 +967,27 @@ void wake_up_all_idle_cpus(void) } EXPORT_SYMBOL_GPL(wake_up_all_idle_cpus); +/** + * wake_up_all_online_idle_cpus - break all online cpus out of idle + * wake_up_all_online_idle_cpus try to break all online cpus which is in idle + * state even including idle polling cpus, for non-idle cpus, we will do nothing + * for them. + */ +void wake_up_all_online_idle_cpus(void) +{ + int cpu; + + preempt_disable(); + for_each_online_cpu(cpu) { + if (cpu == smp_processor_id()) + continue; + + wake_up_if_idle(cpu); + } + preempt_enable(); +} +EXPORT_SYMBOL_GPL(wake_up_all_online_idle_cpus); + /** * smp_call_on_cpu - Call a function on a specific cpu *