diff --git a/drivers/cpuidle/cpuidle.c b/drivers/cpuidle/cpuidle.c index 96a3a9bf8b12..682691226434 100644 --- a/drivers/cpuidle/cpuidle.c +++ b/drivers/cpuidle/cpuidle.c @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include @@ -654,16 +655,36 @@ EXPORT_SYMBOL_GPL(cpuidle_register); #ifdef CONFIG_SMP +static void wake_up_idle_cpus(void *v) +{ + int cpu; + struct cpumask cpus; + + if (v) { + cpumask_andnot(&cpus, v, cpu_isolated_mask); + cpumask_and(&cpus, &cpus, cpu_online_mask); + } else + cpumask_andnot(&cpus, cpu_online_mask, cpu_isolated_mask); + + preempt_disable(); + for_each_cpu(cpu, &cpus) { + if (cpu == smp_processor_id()) + continue; + wake_up_if_idle(cpu); + } + preempt_enable(); +} + /* * This function gets called when a part of the kernel has a new latency - * requirement. This means we need to get all processors out of their C-state, - * and then recalculate a new suitable C-state. Just do a cross-cpu IPI; that - * wakes them all right up. + * requirement. This means we need to get only those processors out of their + * C-state for which qos requirement is changed, and then recalculate a new + * suitable C-state. Just do a cross-cpu IPI; that wakes them all right up. */ static int cpuidle_latency_notify(struct notifier_block *b, unsigned long l, void *v) { - wake_up_all_idle_cpus(); + wake_up_idle_cpus(v); return NOTIFY_OK; }