m68k/amiga: Optimize interrupts using chain handlers
Geert Uytterhoeven [Wed, 1 Jun 2011 09:49:18 +0000 (11:49 +0200)]
Signed-off-by: Geert Uytterhoeven <geert@linux-m68k.org>

arch/m68k/amiga/amiints.c

index c3da534..a8da471 100644 (file)
@@ -48,6 +48,99 @@ static struct irq_chip amiga_irq_chip = {
  * The builtin Amiga hardware interrupt handlers.
  */
 
+#ifdef CONFIG_GENERIC_HARDIRQS
+static void ami_int1(unsigned int irq, struct irq_desc *desc)
+{
+       unsigned short ints = amiga_custom.intreqr & amiga_custom.intenar;
+
+       /* if serial transmit buffer empty, interrupt */
+       if (ints & IF_TBE) {
+               amiga_custom.intreq = IF_TBE;
+               generic_handle_irq(IRQ_AMIGA_TBE);
+       }
+
+       /* if floppy disk transfer complete, interrupt */
+       if (ints & IF_DSKBLK) {
+               amiga_custom.intreq = IF_DSKBLK;
+               generic_handle_irq(IRQ_AMIGA_DSKBLK);
+       }
+
+       /* if software interrupt set, interrupt */
+       if (ints & IF_SOFT) {
+               amiga_custom.intreq = IF_SOFT;
+               generic_handle_irq(IRQ_AMIGA_SOFT);
+       }
+}
+
+static void ami_int3(unsigned int irq, struct irq_desc *desc)
+{
+       unsigned short ints = amiga_custom.intreqr & amiga_custom.intenar;
+
+       /* if a blitter interrupt */
+       if (ints & IF_BLIT) {
+               amiga_custom.intreq = IF_BLIT;
+               generic_handle_irq(IRQ_AMIGA_BLIT);
+       }
+
+       /* if a copper interrupt */
+       if (ints & IF_COPER) {
+               amiga_custom.intreq = IF_COPER;
+               generic_handle_irq(IRQ_AMIGA_COPPER);
+       }
+
+       /* if a vertical blank interrupt */
+       if (ints & IF_VERTB) {
+               amiga_custom.intreq = IF_VERTB;
+               generic_handle_irq(IRQ_AMIGA_VERTB);
+       }
+}
+
+static void ami_int4(unsigned int irq, struct irq_desc *desc)
+{
+       unsigned short ints = amiga_custom.intreqr & amiga_custom.intenar;
+
+       /* if audio 0 interrupt */
+       if (ints & IF_AUD0) {
+               amiga_custom.intreq = IF_AUD0;
+               generic_handle_irq(IRQ_AMIGA_AUD0);
+       }
+
+       /* if audio 1 interrupt */
+       if (ints & IF_AUD1) {
+               amiga_custom.intreq = IF_AUD1;
+               generic_handle_irq(IRQ_AMIGA_AUD1);
+       }
+
+       /* if audio 2 interrupt */
+       if (ints & IF_AUD2) {
+               amiga_custom.intreq = IF_AUD2;
+               generic_handle_irq(IRQ_AMIGA_AUD2);
+       }
+
+       /* if audio 3 interrupt */
+       if (ints & IF_AUD3) {
+               amiga_custom.intreq = IF_AUD3;
+               generic_handle_irq(IRQ_AMIGA_AUD3);
+       }
+}
+
+static void ami_int5(unsigned int irq, struct irq_desc *desc)
+{
+       unsigned short ints = amiga_custom.intreqr & amiga_custom.intenar;
+
+       /* if serial receive buffer full interrupt */
+       if (ints & IF_RBF) {
+               /* acknowledge of IF_RBF must be done by the serial interrupt */
+               generic_handle_irq(IRQ_AMIGA_RBF);
+       }
+
+       /* if a disk sync interrupt */
+       if (ints & IF_DSKSYN) {
+               amiga_custom.intreq = IF_DSKSYN;
+               generic_handle_irq(IRQ_AMIGA_DSKSYN);
+       }
+}
+#else /* !CONFIG_GENERIC_HARDIRQS */
 static irqreturn_t ami_int1(int irq, void *dev_id)
 {
        unsigned short ints = amiga_custom.intreqr & amiga_custom.intenar;
@@ -143,6 +236,7 @@ static irqreturn_t ami_int5(int irq, void *dev_id)
        }
        return IRQ_HANDLED;
 }
+#endif /* !CONFIG_GENERIC_HARDIRQS */
 
 
 /*
@@ -158,6 +252,15 @@ static irqreturn_t ami_int5(int irq, void *dev_id)
 
 void __init amiga_init_IRQ(void)
 {
+#ifdef CONFIG_GENERIC_HARDIRQS
+       m68k_setup_irq_controller(&amiga_irq_chip, handle_simple_irq, IRQ_USER,
+                                 AMI_STD_IRQS);
+
+       irq_set_chained_handler(IRQ_AUTO_1, ami_int1);
+       irq_set_chained_handler(IRQ_AUTO_3, ami_int3);
+       irq_set_chained_handler(IRQ_AUTO_4, ami_int4);
+       irq_set_chained_handler(IRQ_AUTO_5, ami_int5);
+#else /* !CONFIG_GENERIC_HARDIRQS */
        if (request_irq(IRQ_AUTO_1, ami_int1, 0, "int1", NULL))
                pr_err("Couldn't register int%d\n", 1);
        if (request_irq(IRQ_AUTO_3, ami_int3, 0, "int3", NULL))
@@ -169,6 +272,7 @@ void __init amiga_init_IRQ(void)
 
        m68k_setup_irq_controller(&amiga_irq_chip, handle_simple_irq, IRQ_USER,
                                  AMI_STD_IRQS);
+#endif /* !CONFIG_GENERIC_HARDIRQS */
 
        /* turn off PCMCIA interrupts */
        if (AMIGAHW_PRESENT(PCMCIA))