diff options
author | Thomas Gleixner <tglx@linutronix.de> | 2013-03-21 17:49:47 -0400 |
---|---|---|
committer | Thomas Gleixner <tglx@linutronix.de> | 2013-04-08 11:39:25 -0400 |
commit | 91d591c387af34db00c39da2d1d25e69a91cf591 (patch) | |
tree | 529435553ebebb83b4ed688f1e56954b72ece420 /arch | |
parent | 4e0fcc567239ef4b3f80bba778c30b0a4b624eff (diff) |
ia64: Use generic idle loop
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Rusty Russell <rusty@rustcorp.com.au>
Cc: Paul McKenney <paulmck@linux.vnet.ibm.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Reviewed-by: Cc: Srivatsa S. Bhat <srivatsa.bhat@linux.vnet.ibm.com>
Cc: Magnus Damm <magnus.damm@gmail.com>
Cc: Tony Luck <tony.luck@intel.com>
Link: http://lkml.kernel.org/r/20130321215234.406851909@linutronix.de
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Diffstat (limited to 'arch')
-rw-r--r-- | arch/ia64/Kconfig | 1 | ||||
-rw-r--r-- | arch/ia64/kernel/perfmon.c | 14 | ||||
-rw-r--r-- | arch/ia64/kernel/process.c | 78 | ||||
-rw-r--r-- | arch/ia64/kernel/smpboot.c | 2 |
4 files changed, 23 insertions, 72 deletions
diff --git a/arch/ia64/Kconfig b/arch/ia64/Kconfig index 9a02f71c6b1f..e0b39c3cb789 100644 --- a/arch/ia64/Kconfig +++ b/arch/ia64/Kconfig | |||
@@ -35,6 +35,7 @@ config IA64 | |||
35 | select ARCH_HAVE_NMI_SAFE_CMPXCHG | 35 | select ARCH_HAVE_NMI_SAFE_CMPXCHG |
36 | select GENERIC_IOMAP | 36 | select GENERIC_IOMAP |
37 | select GENERIC_SMP_IDLE_THREAD | 37 | select GENERIC_SMP_IDLE_THREAD |
38 | select GENERIC_IDLE_LOOP | ||
38 | select ARCH_INIT_TASK | 39 | select ARCH_INIT_TASK |
39 | select ARCH_TASK_STRUCT_ALLOCATOR | 40 | select ARCH_TASK_STRUCT_ALLOCATOR |
40 | select ARCH_THREAD_INFO_ALLOCATOR | 41 | select ARCH_THREAD_INFO_ALLOCATOR |
diff --git a/arch/ia64/kernel/perfmon.c b/arch/ia64/kernel/perfmon.c index 2eda28414abb..9ea25fce06d5 100644 --- a/arch/ia64/kernel/perfmon.c +++ b/arch/ia64/kernel/perfmon.c | |||
@@ -42,6 +42,7 @@ | |||
42 | #include <linux/completion.h> | 42 | #include <linux/completion.h> |
43 | #include <linux/tracehook.h> | 43 | #include <linux/tracehook.h> |
44 | #include <linux/slab.h> | 44 | #include <linux/slab.h> |
45 | #include <linux/cpu.h> | ||
45 | 46 | ||
46 | #include <asm/errno.h> | 47 | #include <asm/errno.h> |
47 | #include <asm/intrinsics.h> | 48 | #include <asm/intrinsics.h> |
@@ -1322,8 +1323,6 @@ out: | |||
1322 | } | 1323 | } |
1323 | EXPORT_SYMBOL(pfm_unregister_buffer_fmt); | 1324 | EXPORT_SYMBOL(pfm_unregister_buffer_fmt); |
1324 | 1325 | ||
1325 | extern void update_pal_halt_status(int); | ||
1326 | |||
1327 | static int | 1326 | static int |
1328 | pfm_reserve_session(struct task_struct *task, int is_syswide, unsigned int cpu) | 1327 | pfm_reserve_session(struct task_struct *task, int is_syswide, unsigned int cpu) |
1329 | { | 1328 | { |
@@ -1371,9 +1370,9 @@ pfm_reserve_session(struct task_struct *task, int is_syswide, unsigned int cpu) | |||
1371 | cpu)); | 1370 | cpu)); |
1372 | 1371 | ||
1373 | /* | 1372 | /* |
1374 | * disable default_idle() to go to PAL_HALT | 1373 | * Force idle() into poll mode |
1375 | */ | 1374 | */ |
1376 | update_pal_halt_status(0); | 1375 | cpu_idle_poll_ctrl(true); |
1377 | 1376 | ||
1378 | UNLOCK_PFS(flags); | 1377 | UNLOCK_PFS(flags); |
1379 | 1378 | ||
@@ -1430,11 +1429,8 @@ pfm_unreserve_session(pfm_context_t *ctx, int is_syswide, unsigned int cpu) | |||
1430 | is_syswide, | 1429 | is_syswide, |
1431 | cpu)); | 1430 | cpu)); |
1432 | 1431 | ||
1433 | /* | 1432 | /* Undo forced polling. Last session reenables pal_halt */ |
1434 | * if possible, enable default_idle() to go into PAL_HALT | 1433 | cpu_idle_poll_ctrl(false); |
1435 | */ | ||
1436 | if (pfm_sessions.pfs_task_sessions == 0 && pfm_sessions.pfs_sys_sessions == 0) | ||
1437 | update_pal_halt_status(1); | ||
1438 | 1434 | ||
1439 | UNLOCK_PFS(flags); | 1435 | UNLOCK_PFS(flags); |
1440 | 1436 | ||
diff --git a/arch/ia64/kernel/process.c b/arch/ia64/kernel/process.c index 6f7dc8b7b35c..a26fc640e4ce 100644 --- a/arch/ia64/kernel/process.c +++ b/arch/ia64/kernel/process.c | |||
@@ -209,41 +209,13 @@ do_notify_resume_user(sigset_t *unused, struct sigscratch *scr, long in_syscall) | |||
209 | local_irq_disable(); /* force interrupt disable */ | 209 | local_irq_disable(); /* force interrupt disable */ |
210 | } | 210 | } |
211 | 211 | ||
212 | static int pal_halt = 1; | ||
213 | static int can_do_pal_halt = 1; | ||
214 | |||
215 | static int __init nohalt_setup(char * str) | 212 | static int __init nohalt_setup(char * str) |
216 | { | 213 | { |
217 | pal_halt = can_do_pal_halt = 0; | 214 | cpu_idle_poll_ctrl(true); |
218 | return 1; | 215 | return 1; |
219 | } | 216 | } |
220 | __setup("nohalt", nohalt_setup); | 217 | __setup("nohalt", nohalt_setup); |
221 | 218 | ||
222 | void | ||
223 | update_pal_halt_status(int status) | ||
224 | { | ||
225 | can_do_pal_halt = pal_halt && status; | ||
226 | } | ||
227 | |||
228 | /* | ||
229 | * We use this if we don't have any better idle routine.. | ||
230 | */ | ||
231 | void | ||
232 | default_idle (void) | ||
233 | { | ||
234 | local_irq_enable(); | ||
235 | while (!need_resched()) { | ||
236 | if (can_do_pal_halt) { | ||
237 | local_irq_disable(); | ||
238 | if (!need_resched()) { | ||
239 | safe_halt(); | ||
240 | } | ||
241 | local_irq_enable(); | ||
242 | } else | ||
243 | cpu_relax(); | ||
244 | } | ||
245 | } | ||
246 | |||
247 | #ifdef CONFIG_HOTPLUG_CPU | 219 | #ifdef CONFIG_HOTPLUG_CPU |
248 | /* We don't actually take CPU down, just spin without interrupts. */ | 220 | /* We don't actually take CPU down, just spin without interrupts. */ |
249 | static inline void play_dead(void) | 221 | static inline void play_dead(void) |
@@ -270,47 +242,29 @@ static inline void play_dead(void) | |||
270 | } | 242 | } |
271 | #endif /* CONFIG_HOTPLUG_CPU */ | 243 | #endif /* CONFIG_HOTPLUG_CPU */ |
272 | 244 | ||
273 | void __attribute__((noreturn)) | 245 | void arch_cpu_idle_dead(void) |
274 | cpu_idle (void) | 246 | { |
247 | play_dead(); | ||
248 | } | ||
249 | |||
250 | void arch_cpu_idle(void) | ||
275 | { | 251 | { |
276 | void (*mark_idle)(int) = ia64_mark_idle; | 252 | void (*mark_idle)(int) = ia64_mark_idle; |
277 | int cpu = smp_processor_id(); | ||
278 | |||
279 | /* endless idle loop with no priority at all */ | ||
280 | while (1) { | ||
281 | rcu_idle_enter(); | ||
282 | if (can_do_pal_halt) { | ||
283 | current_thread_info()->status &= ~TS_POLLING; | ||
284 | /* | ||
285 | * TS_POLLING-cleared state must be visible before we | ||
286 | * test NEED_RESCHED: | ||
287 | */ | ||
288 | smp_mb(); | ||
289 | } else { | ||
290 | current_thread_info()->status |= TS_POLLING; | ||
291 | } | ||
292 | 253 | ||
293 | if (!need_resched()) { | ||
294 | #ifdef CONFIG_SMP | 254 | #ifdef CONFIG_SMP |
295 | min_xtp(); | 255 | min_xtp(); |
296 | #endif | 256 | #endif |
297 | rmb(); | 257 | rmb(); |
298 | if (mark_idle) | 258 | if (mark_idle) |
299 | (*mark_idle)(1); | 259 | (*mark_idle)(1); |
260 | |||
261 | safe_halt(); | ||
300 | 262 | ||
301 | default_idle(); | 263 | if (mark_idle) |
302 | if (mark_idle) | 264 | (*mark_idle)(0); |
303 | (*mark_idle)(0); | ||
304 | #ifdef CONFIG_SMP | 265 | #ifdef CONFIG_SMP |
305 | normal_xtp(); | 266 | normal_xtp(); |
306 | #endif | 267 | #endif |
307 | } | ||
308 | rcu_idle_exit(); | ||
309 | schedule_preempt_disabled(); | ||
310 | check_pgt_cache(); | ||
311 | if (cpu_is_offline(cpu)) | ||
312 | play_dead(); | ||
313 | } | ||
314 | } | 268 | } |
315 | 269 | ||
316 | void | 270 | void |
diff --git a/arch/ia64/kernel/smpboot.c b/arch/ia64/kernel/smpboot.c index 500f1e4d9f9d..8d87168d218d 100644 --- a/arch/ia64/kernel/smpboot.c +++ b/arch/ia64/kernel/smpboot.c | |||
@@ -455,7 +455,7 @@ start_secondary (void *unused) | |||
455 | preempt_disable(); | 455 | preempt_disable(); |
456 | smp_callin(); | 456 | smp_callin(); |
457 | 457 | ||
458 | cpu_idle(); | 458 | cpu_startup_entry(CPUHP_ONLINE); |
459 | return 0; | 459 | return 0; |
460 | } | 460 | } |
461 | 461 | ||