diff options
Diffstat (limited to 'drivers/cpuidle/driver.c')
-rw-r--r-- | drivers/cpuidle/driver.c | 31 |
1 files changed, 29 insertions, 2 deletions
diff --git a/drivers/cpuidle/driver.c b/drivers/cpuidle/driver.c index 422c7b69ba7c..8dfaaae94444 100644 --- a/drivers/cpuidle/driver.c +++ b/drivers/cpuidle/driver.c | |||
@@ -11,6 +11,8 @@ | |||
11 | #include <linux/mutex.h> | 11 | #include <linux/mutex.h> |
12 | #include <linux/module.h> | 12 | #include <linux/module.h> |
13 | #include <linux/cpuidle.h> | 13 | #include <linux/cpuidle.h> |
14 | #include <linux/cpumask.h> | ||
15 | #include <linux/clockchips.h> | ||
14 | 16 | ||
15 | #include "cpuidle.h" | 17 | #include "cpuidle.h" |
16 | 18 | ||
@@ -19,9 +21,28 @@ DEFINE_SPINLOCK(cpuidle_driver_lock); | |||
19 | static void __cpuidle_set_cpu_driver(struct cpuidle_driver *drv, int cpu); | 21 | static void __cpuidle_set_cpu_driver(struct cpuidle_driver *drv, int cpu); |
20 | static struct cpuidle_driver * __cpuidle_get_cpu_driver(int cpu); | 22 | static struct cpuidle_driver * __cpuidle_get_cpu_driver(int cpu); |
21 | 23 | ||
22 | static void __cpuidle_driver_init(struct cpuidle_driver *drv) | 24 | static void cpuidle_setup_broadcast_timer(void *arg) |
23 | { | 25 | { |
26 | int cpu = smp_processor_id(); | ||
27 | clockevents_notify((long)(arg), &cpu); | ||
28 | } | ||
29 | |||
30 | static void __cpuidle_driver_init(struct cpuidle_driver *drv, int cpu) | ||
31 | { | ||
32 | int i; | ||
33 | |||
24 | drv->refcnt = 0; | 34 | drv->refcnt = 0; |
35 | |||
36 | for (i = drv->state_count - 1; i >= 0 ; i--) { | ||
37 | |||
38 | if (!(drv->states[i].flags & CPUIDLE_FLAG_TIMER_STOP)) | ||
39 | continue; | ||
40 | |||
41 | drv->bctimer = 1; | ||
42 | on_each_cpu_mask(get_cpu_mask(cpu), cpuidle_setup_broadcast_timer, | ||
43 | (void *)CLOCK_EVT_NOTIFY_BROADCAST_ON, 1); | ||
44 | break; | ||
45 | } | ||
25 | } | 46 | } |
26 | 47 | ||
27 | static int __cpuidle_register_driver(struct cpuidle_driver *drv, int cpu) | 48 | static int __cpuidle_register_driver(struct cpuidle_driver *drv, int cpu) |
@@ -35,7 +56,7 @@ static int __cpuidle_register_driver(struct cpuidle_driver *drv, int cpu) | |||
35 | if (__cpuidle_get_cpu_driver(cpu)) | 56 | if (__cpuidle_get_cpu_driver(cpu)) |
36 | return -EBUSY; | 57 | return -EBUSY; |
37 | 58 | ||
38 | __cpuidle_driver_init(drv); | 59 | __cpuidle_driver_init(drv, cpu); |
39 | 60 | ||
40 | __cpuidle_set_cpu_driver(drv, cpu); | 61 | __cpuidle_set_cpu_driver(drv, cpu); |
41 | 62 | ||
@@ -49,6 +70,12 @@ static void __cpuidle_unregister_driver(struct cpuidle_driver *drv, int cpu) | |||
49 | 70 | ||
50 | if (!WARN_ON(drv->refcnt > 0)) | 71 | if (!WARN_ON(drv->refcnt > 0)) |
51 | __cpuidle_set_cpu_driver(NULL, cpu); | 72 | __cpuidle_set_cpu_driver(NULL, cpu); |
73 | |||
74 | if (drv->bctimer) { | ||
75 | drv->bctimer = 0; | ||
76 | on_each_cpu_mask(get_cpu_mask(cpu), cpuidle_setup_broadcast_timer, | ||
77 | (void *)CLOCK_EVT_NOTIFY_BROADCAST_OFF, 1); | ||
78 | } | ||
52 | } | 79 | } |
53 | 80 | ||
54 | #ifdef CONFIG_CPU_IDLE_MULTIPLE_DRIVERS | 81 | #ifdef CONFIG_CPU_IDLE_MULTIPLE_DRIVERS |