2 * Idle daemon for PowerPC. Idle daemon will handle any action
3 * that needs to be taken when the system becomes idle.
5 * Written by Cort Dougan (cort@cs.nmt.edu)
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version
10 * 2 of the License, or (at your option) any later version.
12 #include <linux/config.h>
13 #include <linux/errno.h>
14 #include <linux/sched.h>
15 #include <linux/kernel.h>
17 #include <linux/smp.h>
18 #include <linux/smp_lock.h>
19 #include <linux/stddef.h>
20 #include <linux/unistd.h>
21 #include <linux/ptrace.h>
22 #include <linux/slab.h>
24 #include <asm/pgtable.h>
25 #include <asm/uaccess.h>
26 #include <asm/system.h>
28 #include <asm/processor.h>
30 #include <asm/cache.h>
33 #include <asm/iSeries/LparData.h>
34 #include <asm/iSeries/HvCall.h>
35 #include <asm/iSeries/ItLpQueue.h>
37 #ifdef CONFIG_PPC_ISERIES
38 static void yield_shared_processor(void)
40 struct paca_struct *lpaca = get_paca();
43 HvCall_setEnabledInterrupts( HvCall_MaskIPI |
48 if ( ! ItLpQueue_isLpIntPending( paca->lpQueuePtr ) ) {
50 /* Compute future tb value when yield should expire */
51 HvCall_yieldProcessor( HvCall_YieldTimed, tb+tb_ticks_per_jiffy );
53 /* The decrementer stops during the yield. Force a fake decrementer
54 * here and let the timer_interrupt code sort out the actual time.
56 lpaca->xLpPaca.xIntDword.xFields.xDecrInt = 1;
59 process_iSeries_events();
61 #endif /* CONFIG_PPC_ISERIES */
65 struct paca_struct *lpaca;
67 #ifdef CONFIG_PPC_ISERIES
71 /* endless loop with no priority at all */
73 current->counter = -100;
74 #ifdef CONFIG_PPC_ISERIES
75 /* ensure iSeries run light will be out when idle */
76 current->thread.flags &= ~PPC_FLAG_RUN_LIGHT;
86 #ifdef CONFIG_PPC_ISERIES
87 if ( lpaca->xLpPaca.xSharedProc ) {
88 if ( ItLpQueue_isLpIntPending( lpaca->lpQueuePtr ) )
89 process_iSeries_events();
90 if ( !current->need_resched )
91 yield_shared_processor();
96 /* Avoid an IPI by setting need_resched */
97 oldval = xchg(¤t->need_resched, -1);
99 while(current->need_resched == -1) {
100 #ifdef CONFIG_PPC_ISERIES
102 if ( ItLpQueue_isLpIntPending( lpaca->lpQueuePtr ) )
103 process_iSeries_events();
110 if (current->need_resched) {
119 * SMP entry into the idle task - calls the same thing as the
120 * non-smp versions. -- Cort