On 07/30/2013 03:54 PM, Daniel Lezcano wrote:
Commit 89878baa73f0f1c679355006bd8632e5d78f96c2 introduced the flag CPUIDLE_FLAG_TIMER_STOP where we specify a specific idle state stops the local timer.
Commit a06df062a189a8d5588babb8bf0bb78672497798 introduced the initialization of the timer broadcast framework depending of the flag presence.
If a system is booted with some cpus offline, by setting for example, maxcpus=1 in the kernel command line, and then they are set online, the timer broadcast won't be setup automatically.
Fix this by adding the cpu hotplug notifier and enable/disable the timer broadcast automatically. So no need to handle that at the arch specific driver level like eg. intel_idle does.
Signed-off-by: Daniel Lezcano daniel.lezcano@linaro.org
Len, Rafael,
any comment on these two patches ?
Thanks -- Daniel
drivers/cpuidle/driver.c | 48 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+)
diff --git a/drivers/cpuidle/driver.c b/drivers/cpuidle/driver.c index 3ac499d..e976994 100644 --- a/drivers/cpuidle/driver.c +++ b/drivers/cpuidle/driver.c @@ -10,6 +10,7 @@ #include <linux/mutex.h> #include <linux/module.h> +#include <linux/cpu.h> #include <linux/cpuidle.h> #include <linux/cpumask.h> #include <linux/clockchips.h> @@ -147,6 +148,48 @@ static void cpuidle_setup_broadcast_timer(void *arg) } /**
- cpuidle_hotplug_notify: notifier callback when a cpu is onlined/offlined
 
- @n: the notifier block
 
- @action: an unsigned long giving the event related to the notification
 
- @hcpu: a void pointer but used as the cpu number which the event is related
 
- The kernel can boot with some cpus offline, we have to init the timer
 
- broadcast for these cpus when they are onlined. Also we have to disable
 
- the timer broadcast when the cpu is down.
 
- Returns NOTIFY_OK
 - */
 +static int cpuidle_hotplug_notify(struct notifier_block *n,
unsigned long action, void *hcpu)+{
- int cpu = (unsigned long)hcpu;
 - struct cpuidle_driver *drv;
 - drv = __cpuidle_get_cpu_driver(cpu);
 - if (!drv || !drv->bctimer)
 goto out;- switch (action & 0xf) {
 - case CPU_ONLINE:
 smp_call_function_single(cpu, cpuidle_setup_broadcast_timer,(void *)CLOCK_EVT_NOTIFY_BROADCAST_ON,1);break;- case CPU_DEAD:
 smp_call_function_single(cpu, cpuidle_setup_broadcast_timer,(void *)CLOCK_EVT_NOTIFY_BROADCAST_OFF,1);break;- }
 +out:
- return NOTIFY_OK;
 +}
+static struct notifier_block cpuidle_hotplug_notifier = {
- .notifier_call = cpuidle_hotplug_notify,
 +};
+/**
- __cpuidle_driver_init - initialize the driver's internal data
 - @drv: a valid pointer to a struct cpuidle_driver
 @@ -262,6 +305,9 @@ int cpuidle_register_driver(struct cpuidle_driver *drv) ret = __cpuidle_register_driver(drv); spin_unlock(&cpuidle_driver_lock);
- if (!ret)
 ret = register_cpu_notifier(&cpuidle_hotplug_notifier);- return ret;
 } EXPORT_SYMBOL_GPL(cpuidle_register_driver); @@ -276,6 +322,8 @@ EXPORT_SYMBOL_GPL(cpuidle_register_driver); */ void cpuidle_unregister_driver(struct cpuidle_driver *drv) {
- unregister_cpu_notifier(&cpuidle_hotplug_notifier);
 - spin_lock(&cpuidle_driver_lock); __cpuidle_unregister_driver(drv); spin_unlock(&cpuidle_driver_lock);