cleanup
[linux-2.4.21-pre4.git] / arch / ppc64 / kernel / idle.c
1 /*
2  * Idle daemon for PowerPC.  Idle daemon will handle any action
3  * that needs to be taken when the system becomes idle.
4  *
5  * Written by Cort Dougan (cort@cs.nmt.edu)
6  *
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.
11  */
12 #include <linux/config.h>
13 #include <linux/errno.h>
14 #include <linux/sched.h>
15 #include <linux/kernel.h>
16 #include <linux/mm.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>
23
24 #include <asm/pgtable.h>
25 #include <asm/uaccess.h>
26 #include <asm/system.h>
27 #include <asm/io.h>
28 #include <asm/processor.h>
29 #include <asm/mmu.h>
30 #include <asm/cache.h>
31
32 #include <asm/time.h>
33 #include <asm/iSeries/LparData.h>
34 #include <asm/iSeries/HvCall.h>
35 #include <asm/iSeries/ItLpQueue.h>
36
37 #ifdef CONFIG_PPC_ISERIES
38 static void yield_shared_processor(void)
39 {
40         struct paca_struct *lpaca = get_paca();
41         unsigned long tb;
42
43         HvCall_setEnabledInterrupts( HvCall_MaskIPI |
44                                      HvCall_MaskLpEvent |
45                                      HvCall_MaskLpProd |
46                                      HvCall_MaskTimeout );
47
48         if ( ! ItLpQueue_isLpIntPending( paca->lpQueuePtr ) ) {
49           tb = get_tb();
50           /* Compute future tb value when yield should expire */
51           HvCall_yieldProcessor( HvCall_YieldTimed, tb+tb_ticks_per_jiffy );
52           
53           /* The decrementer stops during the yield.  Force a fake decrementer
54            * here and let the timer_interrupt code sort out the actual time.
55            */
56           lpaca->xLpPaca.xIntDword.xFields.xDecrInt = 1;
57         }
58           
59         process_iSeries_events();
60 }
61 #endif /* CONFIG_PPC_ISERIES */
62
63 int idled(void)
64 {
65         struct paca_struct *lpaca;
66         long oldval;
67 #ifdef CONFIG_PPC_ISERIES
68         unsigned long CTRL;
69 #endif
70
71         /* endless loop with no priority at all */
72         current->nice = 20;
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;
77         CTRL = mfspr(CTRLF);
78         CTRL &= ~RUNLATCH;
79         mtspr(CTRLT, CTRL);
80 #endif
81         init_idle();    
82
83         lpaca = get_paca();
84
85         for (;;) {
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();
92                 }
93                 else 
94 #endif
95                 {
96                         /* Avoid an IPI by setting need_resched */
97                         oldval = xchg(&current->need_resched, -1);
98                         if (!oldval) {
99                                 while(current->need_resched == -1) {
100 #ifdef CONFIG_PPC_ISERIES
101                                         HMT_medium();
102                                         if ( ItLpQueue_isLpIntPending( lpaca->lpQueuePtr ) )
103                                                 process_iSeries_events();
104 #endif
105                                         HMT_low();
106                                 }
107                         }
108                 }
109                 HMT_medium();
110                 if (current->need_resched) {
111                         schedule();
112                         check_pgt_cache();
113                 }
114         }
115         return 0;
116 }
117
118 /*
119  * SMP entry into the idle task - calls the same thing as the
120  * non-smp versions. -- Cort
121  */
122 int cpu_idle(void)
123 {
124         idled();
125         return 0; 
126 }