diff options
-rw-r--r-- | drivers/cpuidle/cpuidle.c | 49 | ||||
-rw-r--r-- | include/linux/cpuidle.h | 2 | ||||
-rw-r--r-- | kernel/sched/idle.c | 56 |
3 files changed, 56 insertions, 51 deletions
diff --git a/drivers/cpuidle/cpuidle.c b/drivers/cpuidle/cpuidle.c index 1506d69b3f0f..166a7322a2b6 100644 --- a/drivers/cpuidle/cpuidle.c +++ b/drivers/cpuidle/cpuidle.c | |||
@@ -173,55 +173,6 @@ void cpuidle_reflect(struct cpuidle_device *dev, int index) | |||
173 | } | 173 | } |
174 | 174 | ||
175 | /** | 175 | /** |
176 | * cpuidle_idle_call - the main idle loop | ||
177 | * | ||
178 | * NOTE: no locks or semaphores should be used here | ||
179 | * return non-zero on failure | ||
180 | */ | ||
181 | int cpuidle_idle_call(void) | ||
182 | { | ||
183 | struct cpuidle_device *dev = __this_cpu_read(cpuidle_devices); | ||
184 | struct cpuidle_driver *drv = cpuidle_get_cpu_driver(dev); | ||
185 | int next_state, entered_state, ret; | ||
186 | bool broadcast; | ||
187 | |||
188 | ret = cpuidle_enabled(drv, dev); | ||
189 | if (ret < 0) | ||
190 | return ret; | ||
191 | |||
192 | /* ask the governor for the next state */ | ||
193 | next_state = cpuidle_select(drv, dev); | ||
194 | |||
195 | if (need_resched()) { | ||
196 | dev->last_residency = 0; | ||
197 | /* give the governor an opportunity to reflect on the outcome */ | ||
198 | cpuidle_reflect(dev, next_state); | ||
199 | local_irq_enable(); | ||
200 | return 0; | ||
201 | } | ||
202 | |||
203 | broadcast = !!(drv->states[next_state].flags & CPUIDLE_FLAG_TIMER_STOP); | ||
204 | |||
205 | if (broadcast && | ||
206 | clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_ENTER, &dev->cpu)) | ||
207 | return -EBUSY; | ||
208 | |||
209 | trace_cpu_idle_rcuidle(next_state, dev->cpu); | ||
210 | |||
211 | entered_state = cpuidle_enter(drv, dev, next_state); | ||
212 | |||
213 | trace_cpu_idle_rcuidle(PWR_EVENT_EXIT, dev->cpu); | ||
214 | |||
215 | if (broadcast) | ||
216 | clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_EXIT, &dev->cpu); | ||
217 | |||
218 | /* give the governor an opportunity to reflect on the outcome */ | ||
219 | cpuidle_reflect(dev, entered_state); | ||
220 | |||
221 | return 0; | ||
222 | } | ||
223 | |||
224 | /** | ||
225 | * cpuidle_install_idle_handler - installs the cpuidle idle loop handler | 176 | * cpuidle_install_idle_handler - installs the cpuidle idle loop handler |
226 | */ | 177 | */ |
227 | void cpuidle_install_idle_handler(void) | 178 | void cpuidle_install_idle_handler(void) |
diff --git a/include/linux/cpuidle.h b/include/linux/cpuidle.h index accc2dd72049..8d97962d6d64 100644 --- a/include/linux/cpuidle.h +++ b/include/linux/cpuidle.h | |||
@@ -128,7 +128,6 @@ extern int cpuidle_enter(struct cpuidle_driver *drv, | |||
128 | struct cpuidle_device *dev, int index); | 128 | struct cpuidle_device *dev, int index); |
129 | extern void cpuidle_reflect(struct cpuidle_device *dev, int index); | 129 | extern void cpuidle_reflect(struct cpuidle_device *dev, int index); |
130 | 130 | ||
131 | extern int cpuidle_idle_call(void); | ||
132 | extern int cpuidle_register_driver(struct cpuidle_driver *drv); | 131 | extern int cpuidle_register_driver(struct cpuidle_driver *drv); |
133 | extern struct cpuidle_driver *cpuidle_get_driver(void); | 132 | extern struct cpuidle_driver *cpuidle_get_driver(void); |
134 | extern struct cpuidle_driver *cpuidle_driver_ref(void); | 133 | extern struct cpuidle_driver *cpuidle_driver_ref(void); |
@@ -160,7 +159,6 @@ static inline int cpuidle_enter(struct cpuidle_driver *drv, | |||
160 | struct cpuidle_device *dev, int index) | 159 | struct cpuidle_device *dev, int index) |
161 | {return -ENODEV; } | 160 | {return -ENODEV; } |
162 | static inline void cpuidle_reflect(struct cpuidle_device *dev, int index) { } | 161 | static inline void cpuidle_reflect(struct cpuidle_device *dev, int index) { } |
163 | static inline int cpuidle_idle_call(void) { return -ENODEV; } | ||
164 | static inline int cpuidle_register_driver(struct cpuidle_driver *drv) | 162 | static inline int cpuidle_register_driver(struct cpuidle_driver *drv) |
165 | {return -ENODEV; } | 163 | {return -ENODEV; } |
166 | static inline struct cpuidle_driver *cpuidle_get_driver(void) {return NULL; } | 164 | static inline struct cpuidle_driver *cpuidle_get_driver(void) {return NULL; } |
diff --git a/kernel/sched/idle.c b/kernel/sched/idle.c index b7976a127178..d5aaf5eb4531 100644 --- a/kernel/sched/idle.c +++ b/kernel/sched/idle.c | |||
@@ -63,6 +63,62 @@ void __weak arch_cpu_idle(void) | |||
63 | local_irq_enable(); | 63 | local_irq_enable(); |
64 | } | 64 | } |
65 | 65 | ||
66 | #ifdef CONFIG_CPU_IDLE | ||
67 | /** | ||
68 | * cpuidle_idle_call - the main idle function | ||
69 | * | ||
70 | * NOTE: no locks or semaphores should be used here | ||
71 | * return non-zero on failure | ||
72 | */ | ||
73 | static int cpuidle_idle_call(void) | ||
74 | { | ||
75 | struct cpuidle_device *dev = __this_cpu_read(cpuidle_devices); | ||
76 | struct cpuidle_driver *drv = cpuidle_get_cpu_driver(dev); | ||
77 | int next_state, entered_state, ret; | ||
78 | bool broadcast; | ||
79 | |||
80 | ret = cpuidle_enabled(drv, dev); | ||
81 | if (ret < 0) | ||
82 | return ret; | ||
83 | |||
84 | /* ask the governor for the next state */ | ||
85 | next_state = cpuidle_select(drv, dev); | ||
86 | |||
87 | if (need_resched()) { | ||
88 | dev->last_residency = 0; | ||
89 | /* give the governor an opportunity to reflect on the outcome */ | ||
90 | cpuidle_reflect(dev, next_state); | ||
91 | local_irq_enable(); | ||
92 | return 0; | ||
93 | } | ||
94 | |||
95 | broadcast = !!(drv->states[next_state].flags & CPUIDLE_FLAG_TIMER_STOP); | ||
96 | |||
97 | if (broadcast && | ||
98 | clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_ENTER, &dev->cpu)) | ||
99 | return -EBUSY; | ||
100 | |||
101 | trace_cpu_idle_rcuidle(next_state, dev->cpu); | ||
102 | |||
103 | entered_state = cpuidle_enter(drv, dev, next_state); | ||
104 | |||
105 | trace_cpu_idle_rcuidle(PWR_EVENT_EXIT, dev->cpu); | ||
106 | |||
107 | if (broadcast) | ||
108 | clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_EXIT, &dev->cpu); | ||
109 | |||
110 | /* give the governor an opportunity to reflect on the outcome */ | ||
111 | cpuidle_reflect(dev, entered_state); | ||
112 | |||
113 | return 0; | ||
114 | } | ||
115 | #else | ||
116 | static inline int cpuidle_idle_call(void) | ||
117 | { | ||
118 | return -ENODEV; | ||
119 | } | ||
120 | #endif | ||
121 | |||
66 | /* | 122 | /* |
67 | * Generic idle loop implementation | 123 | * Generic idle loop implementation |
68 | */ | 124 | */ |