From: Jun S. <ju...@us...> - 2001-11-08 01:46:46
|
Update of /cvsroot/linux-mips/linux/arch/mips/korva In directory usw-pr-cvs1:/tmp/cvs-serv20691/arch/mips/korva Modified Files: int_handler.S irq_korva.c Log Message: Fix tx stall problem in ether driver. Update irq dispatching code. Index: int_handler.S =================================================================== RCS file: /cvsroot/linux-mips/linux/arch/mips/korva/int_handler.S,v retrieving revision 1.1 retrieving revision 1.2 diff -u -d -r1.1 -r1.2 --- int_handler.S 2001/08/23 19:13:56 1.1 +++ int_handler.S 2001/11/08 01:46:43 1.2 @@ -33,6 +33,8 @@ * 10 - UART * 11 - External interrupt * 12 - Wakeup + * + * Dispatching korva irqs is moved to a C routine in irq_korva.c file. */ #include <linux/config.h> @@ -130,36 +132,11 @@ j ret_from_irq ll_cpu_ip6: - /* it is korva 2nd level interrupts */ - /* reading ISR will clear it */ - la t0, KORVA_BASE_VIRT + KORVA_S_ISR - lw s0, 0(t0) - - /* and with the mask - just to be safe */ - la t0, KORVA_BASE_VIRT + KORVA_S_IMR - lw t0, 0(t0) - and s0, s0, t0 - - /* do we need to deliver all the pending ones? */ - li a0, 8 - li a1, 13 - li t0, 1 - -loop: - and t1, t0, s0 - bnez t1, foundone - - sll t0, t0, 1 - addiu a0, a0, 1 - - /* check if we reach the end */ - beq a0, a1, error - j loop + move a0, sp + jal korva_irq_dispatch -foundone: - move a1, sp - jal do_IRQ - j ret_from_irq + beqz v0, error + j ret_from_irq error: j spurious_interrupt Index: irq_korva.c =================================================================== RCS file: /cvsroot/linux-mips/linux/arch/mips/korva/irq_korva.c,v retrieving revision 1.5 retrieving revision 1.6 diff -u -d -r1.5 -r1.6 --- irq_korva.c 2001/10/30 21:43:37 1.5 +++ irq_korva.c 2001/11/08 01:46:43 1.6 @@ -19,10 +19,11 @@ #include <linux/irq.h> #include <linux/types.h> #include <linux/kernel.h> +#include <linux/linkage.h> + #include <asm/korva.h> #include <asm/mipsregs.h> -/* [jsun] sooner or later we should move this debug stuff to MIPS common */ #include <asm/debug.h> #define NUM_KORVA_IRQS 5 @@ -96,3 +97,45 @@ korva_irq_base = irq_base; } + +/* + * STRATEGY: + * + * We read the irq status word and status are cleared. We need + * to deliver all the pending irqs if there are multiple of them. + * + * The tricky part is that while we are calling do_IRQ for one interrupt, + * another interrupt may happen. In that case, the second irq_dispatch() + * simply add bits to the pending flag. The first irq_dispatch() won't + * exit this function until all pending flags are cleared. + */ +extern unsigned int do_IRQ(int irq, struct pt_regs *regs); +asmlinkage int +korva_irq_dispatch(struct pt_regs *regs) +{ + static u32 irq_pending=0; + u32 status; + + status = korva_in32(KORVA_S_ISR) & korva_in32(KORVA_S_IMR); + + if (irq_pending) { + /* this is a nested interrupt, just add new status */ + irq_pending |= status; + + } else { + + irq_pending |= status; + for (; irq_pending; ) { + int index=1; + int irq=korva_irq_base; + int i=0; + for(; i< NUM_KORVA_IRQS; i++, index <<=1, irq++) { + if (index & irq_pending) + do_IRQ(irq, regs); + irq_pending &= ~index; + } + } + } + + return status; +} |