diff options
author | Pawel Moll <pawel.moll@st.com> | 2009-08-24 06:52:38 -0400 |
---|---|---|
committer | Paul Mundt <lethal@linux-sh.org> | 2009-08-24 06:52:38 -0400 |
commit | 05ecd5a1f76c183cca381705b3adb7d77c9a0439 (patch) | |
tree | b10313518bb21df0290ec4d8d7088835b7fec457 | |
parent | 788e6af37a4ace8721eda72e4abe66fe0f6b49fd (diff) |
sh: Simplify "multi-evt" interrupt handling.
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>
-rw-r--r-- | arch/sh/kernel/irq.c | 2 | ||||
-rw-r--r-- | drivers/sh/intc.c | 54 | ||||
-rw-r--r-- | include/linux/sh_intc.h | 1 |
3 files changed, 18 insertions, 39 deletions
diff --git a/arch/sh/kernel/irq.c b/arch/sh/kernel/irq.c index 278c68c60488..d1053392e287 100644 --- a/arch/sh/kernel/irq.c +++ b/arch/sh/kernel/irq.c | |||
@@ -114,7 +114,7 @@ asmlinkage int do_IRQ(unsigned int irq, struct pt_regs *regs) | |||
114 | #endif | 114 | #endif |
115 | 115 | ||
116 | irq_enter(); | 116 | irq_enter(); |
117 | irq = irq_demux(intc_evt2irq(irq)); | 117 | irq = irq_demux(evt2irq(irq)); |
118 | 118 | ||
119 | #ifdef CONFIG_IRQSTACKS | 119 | #ifdef CONFIG_IRQSTACKS |
120 | curctx = (union irq_ctx *)current_thread_info(); | 120 | curctx = (union irq_ctx *)current_thread_info(); |
diff --git a/drivers/sh/intc.c b/drivers/sh/intc.c index 4b1ca9d28353..a9174ec72853 100644 --- a/drivers/sh/intc.c +++ b/drivers/sh/intc.c | |||
@@ -663,16 +663,9 @@ static unsigned int __init save_reg(struct intc_desc_int *d, | |||
663 | return 0; | 663 | return 0; |
664 | } | 664 | } |
665 | 665 | ||
666 | static unsigned char *intc_evt2irq_table; | 666 | static void intc_redirect_irq(unsigned int irq, struct irq_desc *desc) |
667 | |||
668 | unsigned int intc_evt2irq(unsigned int vector) | ||
669 | { | 667 | { |
670 | unsigned int irq = evt2irq(vector); | 668 | generic_handle_irq((unsigned int)get_irq_data(irq)); |
671 | |||
672 | if (intc_evt2irq_table && intc_evt2irq_table[irq]) | ||
673 | irq = intc_evt2irq_table[irq]; | ||
674 | |||
675 | return irq; | ||
676 | } | 669 | } |
677 | 670 | ||
678 | void __init register_intc_controller(struct intc_desc *desc) | 671 | void __init register_intc_controller(struct intc_desc *desc) |
@@ -745,34 +738,6 @@ void __init register_intc_controller(struct intc_desc *desc) | |||
745 | 738 | ||
746 | BUG_ON(k > 256); /* _INTC_ADDR_E() and _INTC_ADDR_D() are 8 bits */ | 739 | BUG_ON(k > 256); /* _INTC_ADDR_E() and _INTC_ADDR_D() are 8 bits */ |
747 | 740 | ||
748 | /* keep the first vector only if same enum is used multiple times */ | ||
749 | for (i = 0; i < desc->nr_vectors; i++) { | ||
750 | struct intc_vect *vect = desc->vectors + i; | ||
751 | int first_irq = evt2irq(vect->vect); | ||
752 | |||
753 | if (!vect->enum_id) | ||
754 | continue; | ||
755 | |||
756 | for (k = i + 1; k < desc->nr_vectors; k++) { | ||
757 | struct intc_vect *vect2 = desc->vectors + k; | ||
758 | |||
759 | if (vect->enum_id != vect2->enum_id) | ||
760 | continue; | ||
761 | |||
762 | vect2->enum_id = 0; | ||
763 | |||
764 | if (!intc_evt2irq_table) | ||
765 | intc_evt2irq_table = kzalloc(NR_IRQS, GFP_NOWAIT); | ||
766 | |||
767 | if (!intc_evt2irq_table) { | ||
768 | pr_warning("intc: cannot allocate evt2irq!\n"); | ||
769 | continue; | ||
770 | } | ||
771 | |||
772 | intc_evt2irq_table[evt2irq(vect2->vect)] = first_irq; | ||
773 | } | ||
774 | } | ||
775 | |||
776 | /* register the vectors one by one */ | 741 | /* register the vectors one by one */ |
777 | for (i = 0; i < desc->nr_vectors; i++) { | 742 | for (i = 0; i < desc->nr_vectors; i++) { |
778 | struct intc_vect *vect = desc->vectors + i; | 743 | struct intc_vect *vect = desc->vectors + i; |
@@ -789,6 +754,21 @@ void __init register_intc_controller(struct intc_desc *desc) | |||
789 | } | 754 | } |
790 | 755 | ||
791 | intc_register_irq(desc, d, vect->enum_id, irq); | 756 | intc_register_irq(desc, d, vect->enum_id, irq); |
757 | |||
758 | for (k = i + 1; k < desc->nr_vectors; k++) { | ||
759 | struct intc_vect *vect2 = desc->vectors + k; | ||
760 | unsigned int irq2 = evt2irq(vect2->vect); | ||
761 | |||
762 | if (vect->enum_id != vect2->enum_id) | ||
763 | continue; | ||
764 | |||
765 | vect2->enum_id = 0; | ||
766 | |||
767 | /* redirect this interrupts to the first one */ | ||
768 | set_irq_chip_and_handler_name(irq2, &d->chip, | ||
769 | intc_redirect_irq, "redirect"); | ||
770 | set_irq_data(irq2, (void *)irq); | ||
771 | } | ||
792 | } | 772 | } |
793 | } | 773 | } |
794 | 774 | ||
diff --git a/include/linux/sh_intc.h b/include/linux/sh_intc.h index eb1423a0078d..68e212ff9dde 100644 --- a/include/linux/sh_intc.h +++ b/include/linux/sh_intc.h | |||
@@ -85,7 +85,6 @@ struct intc_desc symbol __initdata = { \ | |||
85 | } | 85 | } |
86 | #endif | 86 | #endif |
87 | 87 | ||
88 | unsigned int intc_evt2irq(unsigned int vector); | ||
89 | void __init register_intc_controller(struct intc_desc *desc); | 88 | void __init register_intc_controller(struct intc_desc *desc); |
90 | int intc_set_priority(unsigned int irq, unsigned int prio); | 89 | int intc_set_priority(unsigned int irq, unsigned int prio); |
91 | 90 | ||