sh: Simplify "multi-evt" interrupt handling.
authorPawel Moll <pawel.moll@st.com>
Mon, 24 Aug 2009 10:52:38 +0000 (19:52 +0900)
committerPaul Mundt <lethal@linux-sh.org>
Mon, 24 Aug 2009 10:52:38 +0000 (19:52 +0900)
This patch changes the way in which "multi-evt" interrups are handled.
The intc_evt2irq_table and related intc_evt2irq() have been removed and
the "redirecting" handler is installed for the coupled interrupts.

Thanks to that the do_IRQ() function don't have to use another level
of indirection for all the interrupts...

Signed-off-by: Pawel Moll <pawel.moll@st.com>
Signed-off-by: Stuart Menefy <stuart.menefy@st.com>
Signed-off-by: Paul Mundt <lethal@linux-sh.org>
arch/sh/kernel/irq.c
drivers/sh/intc.c
include/linux/sh_intc.h

index 278c68c..d105339 100644 (file)
@@ -114,7 +114,7 @@ asmlinkage int do_IRQ(unsigned int irq, struct pt_regs *regs)
 #endif
 
        irq_enter();
-       irq = irq_demux(intc_evt2irq(irq));
+       irq = irq_demux(evt2irq(irq));
 
 #ifdef CONFIG_IRQSTACKS
        curctx = (union irq_ctx *)current_thread_info();
index 4b1ca9d..a9174ec 100644 (file)
@@ -663,16 +663,9 @@ static unsigned int __init save_reg(struct intc_desc_int *d,
        return 0;
 }
 
-static unsigned char *intc_evt2irq_table;
-
-unsigned int intc_evt2irq(unsigned int vector)
+static void intc_redirect_irq(unsigned int irq, struct irq_desc *desc)
 {
-       unsigned int irq = evt2irq(vector);
-
-       if (intc_evt2irq_table && intc_evt2irq_table[irq])
-               irq = intc_evt2irq_table[irq];
-
-       return irq;
+       generic_handle_irq((unsigned int)get_irq_data(irq));
 }
 
 void __init register_intc_controller(struct intc_desc *desc)
@@ -745,34 +738,6 @@ void __init register_intc_controller(struct intc_desc *desc)
 
        BUG_ON(k > 256); /* _INTC_ADDR_E() and _INTC_ADDR_D() are 8 bits */
 
-       /* keep the first vector only if same enum is used multiple times */
-       for (i = 0; i < desc->nr_vectors; i++) {
-               struct intc_vect *vect = desc->vectors + i;
-               int first_irq = evt2irq(vect->vect);
-
-               if (!vect->enum_id)
-                       continue;
-
-               for (k = i + 1; k < desc->nr_vectors; k++) {
-                       struct intc_vect *vect2 = desc->vectors + k;
-
-                       if (vect->enum_id != vect2->enum_id)
-                               continue;
-
-                       vect2->enum_id = 0;
-
-                       if (!intc_evt2irq_table)
-                               intc_evt2irq_table = kzalloc(NR_IRQS, GFP_NOWAIT);
-
-                       if (!intc_evt2irq_table) {
-                               pr_warning("intc: cannot allocate evt2irq!\n");
-                               continue;
-                       }
-
-                       intc_evt2irq_table[evt2irq(vect2->vect)] = first_irq;
-               }
-       }
-
        /* register the vectors one by one */
        for (i = 0; i < desc->nr_vectors; i++) {
                struct intc_vect *vect = desc->vectors + i;
@@ -789,6 +754,21 @@ void __init register_intc_controller(struct intc_desc *desc)
                }
 
                intc_register_irq(desc, d, vect->enum_id, irq);
+
+               for (k = i + 1; k < desc->nr_vectors; k++) {
+                       struct intc_vect *vect2 = desc->vectors + k;
+                       unsigned int irq2 = evt2irq(vect2->vect);
+
+                       if (vect->enum_id != vect2->enum_id)
+                               continue;
+
+                       vect2->enum_id = 0;
+
+                       /* redirect this interrupts to the first one */
+                       set_irq_chip_and_handler_name(irq2, &d->chip,
+                                       intc_redirect_irq, "redirect");
+                       set_irq_data(irq2, (void *)irq);
+               }
        }
 }
 
index eb1423a..68e212f 100644 (file)
@@ -85,7 +85,6 @@ struct intc_desc symbol __initdata = {                                        \
 }
 #endif
 
-unsigned int intc_evt2irq(unsigned int vector);
 void __init register_intc_controller(struct intc_desc *desc);
 int intc_set_priority(unsigned int irq, unsigned int prio);