From b11e58856c0582a7c58b7cfee81f0248b1ae8ed1 Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Tue, 24 Feb 2009 22:58:57 +0900 Subject: [PATCH] --- yaml --- r: 133283 b: refs/heads/master c: bdaa6e8062d7f8085d8ed94ff88c99406ad53d79 h: refs/heads/master i: 133281: 7baf02ef792effc674a91f84a590bc64127ce20d 133279: be421facb9931dae3d427c660eb68fc13f2d7b5a v: v3 --- [refs] | 2 +- trunk/arch/sh/kernel/irq.c | 2 +- trunk/drivers/sh/intc.c | 47 +++++++++++++++++++++++++++++++++++ trunk/include/linux/sh_intc.h | 1 + 4 files changed, 50 insertions(+), 2 deletions(-) diff --git a/[refs] b/[refs] index f7644eddb2e2..b5f5c82b32a7 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 3e91faec47e9e12b965c952d698b0bb64847af06 +refs/heads/master: bdaa6e8062d7f8085d8ed94ff88c99406ad53d79 diff --git a/trunk/arch/sh/kernel/irq.c b/trunk/arch/sh/kernel/irq.c index 64b7690c664c..90d63aefd275 100644 --- a/trunk/arch/sh/kernel/irq.c +++ b/trunk/arch/sh/kernel/irq.c @@ -106,7 +106,7 @@ asmlinkage int do_IRQ(unsigned int irq, struct pt_regs *regs) } #endif - irq = irq_demux(evt2irq(irq)); + irq = irq_demux(intc_evt2irq(irq)); #ifdef CONFIG_IRQSTACKS curctx = (union irq_ctx *)current_thread_info(); diff --git a/trunk/drivers/sh/intc.c b/trunk/drivers/sh/intc.c index 58d24c5a76ce..d7b8959d9d92 100644 --- a/trunk/drivers/sh/intc.c +++ b/trunk/drivers/sh/intc.c @@ -568,6 +568,10 @@ static void __init intc_register_irq(struct intc_desc *desc, if (!data[0] && data[1]) primary = 1; + if (!data[0] && !data[1]) + pr_warning("intc: missing unique irq mask for 0x%04x\n", + irq2evt(irq)); + data[0] = data[0] ? data[0] : intc_mask_data(desc, d, enum_id, 1); data[1] = data[1] ? data[1] : intc_prio_data(desc, d, enum_id, 1); @@ -641,6 +645,17 @@ 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) +{ + unsigned int irq = evt2irq(vector); + + if (intc_evt2irq_table && intc_evt2irq_table[irq]) + irq = intc_evt2irq_table[irq]; + + return irq; +} void __init register_intc_controller(struct intc_desc *desc) { @@ -705,9 +720,41 @@ 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 = alloc_bootmem(NR_IRQS); + + 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; + if (!vect->enum_id) + continue; + intc_register_irq(desc, d, vect->enum_id, evt2irq(vect->vect)); } } diff --git a/trunk/include/linux/sh_intc.h b/trunk/include/linux/sh_intc.h index 68e212ff9dde..eb1423a0078d 100644 --- a/trunk/include/linux/sh_intc.h +++ b/trunk/include/linux/sh_intc.h @@ -85,6 +85,7 @@ 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);