aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/sh/kernel/irq.c25
1 files changed, 18 insertions, 7 deletions
diff --git a/arch/sh/kernel/irq.c b/arch/sh/kernel/irq.c
index edf4d2d21336..46a19e07abd3 100644
--- a/arch/sh/kernel/irq.c
+++ b/arch/sh/kernel/irq.c
@@ -78,8 +78,8 @@ union irq_ctx {
78 u32 stack[THREAD_SIZE/sizeof(u32)]; 78 u32 stack[THREAD_SIZE/sizeof(u32)];
79}; 79};
80 80
81static union irq_ctx *hardirq_ctx[NR_CPUS]; 81static union irq_ctx *hardirq_ctx[NR_CPUS] __read_mostly;
82static union irq_ctx *softirq_ctx[NR_CPUS]; 82static union irq_ctx *softirq_ctx[NR_CPUS] __read_mostly;
83#endif 83#endif
84 84
85asmlinkage int do_IRQ(unsigned long r4, unsigned long r5, 85asmlinkage int do_IRQ(unsigned long r4, unsigned long r5,
@@ -136,17 +136,24 @@ asmlinkage int do_IRQ(unsigned long r4, unsigned long r5,
136 irqctx->tinfo.task = curctx->tinfo.task; 136 irqctx->tinfo.task = curctx->tinfo.task;
137 irqctx->tinfo.previous_sp = current_stack_pointer; 137 irqctx->tinfo.previous_sp = current_stack_pointer;
138 138
139 /*
140 * Copy the softirq bits in preempt_count so that the
141 * softirq checks work in the hardirq context.
142 */
143 irqctx->tinfo.preempt_count =
144 (irqctx->tinfo.preempt_count & ~SOFTIRQ_MASK) |
145 (curctx->tinfo.preempt_count & SOFTIRQ_MASK);
146
139 __asm__ __volatile__ ( 147 __asm__ __volatile__ (
140 "mov %0, r4 \n" 148 "mov %0, r4 \n"
141 "mov r15, r9 \n" 149 "mov r15, r8 \n"
142 "jsr @%1 \n" 150 "jsr @%1 \n"
143 /* swith to the irq stack */ 151 /* swith to the irq stack */
144 " mov %2, r15 \n" 152 " mov %2, r15 \n"
145 /* restore the stack (ring zero) */ 153 /* restore the stack (ring zero) */
146 "mov r9, r15 \n" 154 "mov r8, r15 \n"
147 : /* no outputs */ 155 : /* no outputs */
148 : "r" (irq), "r" (generic_handle_irq), "r" (isp) 156 : "r" (irq), "r" (generic_handle_irq), "r" (isp)
149 /* XXX: A somewhat excessive clobber list? -PFM */
150 : "memory", "r0", "r1", "r2", "r3", "r4", 157 : "memory", "r0", "r1", "r2", "r3", "r4",
151 "r5", "r6", "r7", "r8", "t", "pr" 158 "r5", "r6", "r7", "r8", "t", "pr"
152 ); 159 );
@@ -194,7 +201,7 @@ void irq_ctx_init(int cpu)
194 irqctx->tinfo.task = NULL; 201 irqctx->tinfo.task = NULL;
195 irqctx->tinfo.exec_domain = NULL; 202 irqctx->tinfo.exec_domain = NULL;
196 irqctx->tinfo.cpu = cpu; 203 irqctx->tinfo.cpu = cpu;
197 irqctx->tinfo.preempt_count = SOFTIRQ_OFFSET; 204 irqctx->tinfo.preempt_count = 0;
198 irqctx->tinfo.addr_limit = MAKE_MM_SEG(0); 205 irqctx->tinfo.addr_limit = MAKE_MM_SEG(0);
199 206
200 softirq_ctx[cpu] = irqctx; 207 softirq_ctx[cpu] = irqctx;
@@ -240,10 +247,14 @@ asmlinkage void do_softirq(void)
240 "mov r9, r15 \n" 247 "mov r9, r15 \n"
241 : /* no outputs */ 248 : /* no outputs */
242 : "r" (__do_softirq), "r" (isp) 249 : "r" (__do_softirq), "r" (isp)
243 /* XXX: A somewhat excessive clobber list? -PFM */
244 : "memory", "r0", "r1", "r2", "r3", "r4", 250 : "memory", "r0", "r1", "r2", "r3", "r4",
245 "r5", "r6", "r7", "r8", "r9", "r15", "t", "pr" 251 "r5", "r6", "r7", "r8", "r9", "r15", "t", "pr"
246 ); 252 );
253
254 /*
255 * Shouldnt happen, we returned above if in_interrupt():
256 */
257 WARN_ON_ONCE(softirq_count());
247 } 258 }
248 259
249 local_irq_restore(flags); 260 local_irq_restore(flags);