Wally reported, interrupts was being serviced more times than it was
actually happening. The original codes service multiple interrupts that
are detected at the same time.  However, the code assumes that
interrupts will not be enabled by the "call process_int" function.
Unfortunately Linux enables interrupts when tasklets are run, and the
tasklets are run before "call process_int" returns. For example, two
interrupts (a high priority interrupt that schedules a tasklet, and our
interrupt) are detected at the same time.  The high priority interrupt
is serviced first by "call process_int", but before returning the
tasklet is run with interrupts enabled.  As soon as interrupts are
enabled, our interrupt occurs.  It is serviced and returns to the
tasklet code.  When the tasklet completes the "call process_int"
returns, then the original loop processes our interrupt a second time
(because our interrupt bit is still set in register r12).

This patch checks pending interrupt requests again before serving.

Signed-off-by: Thomas Chou <[EMAIL PROTECTED]>
---
 linux-2.6.x/arch/nios2nommu/kernel/entry.S |    8 ++++----
 1 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/linux-2.6.x/arch/nios2nommu/kernel/entry.S 
b/linux-2.6.x/arch/nios2nommu/kernel/entry.S
index 93fbc74..7d84a3e 100644
--- a/linux-2.6.x/arch/nios2nommu/kernel/entry.S
+++ b/linux-2.6.x/arch/nios2nommu/kernel/entry.S
@@ -176,7 +176,7 @@ ENTRY(inthandler)
 
        addi    ea,ea,-4                /* re-issue the interrupted instruction 
*/
        stw     ea,PT_EA(sp)
-       rdctl   r9,ienable              /* Isolate possible interrupts */
+2:     rdctl   r9,ienable              /* Isolate possible interrupts */
        and     r12,r12,r9
        beq     r12,r0,ret_from_interrupt /* No one to service done */
        movi    r4,%lo(-1)              /* Start from bit position 0, highest 
priority */
@@ -191,9 +191,9 @@ ENTRY(inthandler)
        PUSH    r4                      /* Save state for return */
        PUSH    r12
        call    process_int
-       POP     r12
-       POP     r4
-       br      1b                      /* Check for other interrupts while 
here */
+       addi    sp,sp,8                 /* pop r12,r4 */
+       rdctl   r12,ipending            /* check again if irq still pending */
+       bne     r12,r0,2b
 
 ENTRY(ret_from_interrupt)
        ldw     r4,PT_STATUS_EXTENSION(sp)
-- 
1.5.3.3

_______________________________________________
uClinux-dev mailing list
[email protected]
http://mailman.uclinux.org/mailman/listinfo/uclinux-dev
This message was resent by [email protected]
To unsubscribe see:
http://mailman.uclinux.org/mailman/options/uclinux-dev

Reply via email to