From 5eae2c8aca10b5062301f8e723ddd44aba59680d Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Wed, 4 Mar 2009 14:43:47 -0800 Subject: [PATCH] --- yaml --- r: 132217 b: refs/heads/master c: d0cac39e4ec8097e4c7099d291b1fdcc0fe56b58 h: refs/heads/master i: 132215: 0a4b7057f20a86d70f1d24ebfd01be272aec9829 v: v3 --- [refs] | 2 +- trunk/arch/sparc/kernel/irq_64.c | 29 +++++++++++++++++++---------- 2 files changed, 20 insertions(+), 11 deletions(-) diff --git a/[refs] b/[refs] index b3f04c0b2137..467a4519631f 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: f4c13638185c91a269c63fcfb980d89180cf43a1 +refs/heads/master: d0cac39e4ec8097e4c7099d291b1fdcc0fe56b58 diff --git a/trunk/arch/sparc/kernel/irq_64.c b/trunk/arch/sparc/kernel/irq_64.c index e289376198eb..1c378d8e90c5 100644 --- a/trunk/arch/sparc/kernel/irq_64.c +++ b/trunk/arch/sparc/kernel/irq_64.c @@ -323,17 +323,25 @@ static void sun4u_set_affinity(unsigned int virt_irq, sun4u_irq_enable(virt_irq); } +/* Don't do anything. The desc->status check for IRQ_DISABLED in + * handler_irq() will skip the handler call and that will leave the + * interrupt in the sent state. The next ->enable() call will hit the + * ICLR register to reset the state machine. + * + * This scheme is necessary, instead of clearing the Valid bit in the + * IMAP register, to handle the case of IMAP registers being shared by + * multiple INOs (and thus ICLR registers). Since we use a different + * virtual IRQ for each shared IMAP instance, the generic code thinks + * there is only one user so it prematurely calls ->disable() on + * free_irq(). + * + * We have to provide an explicit ->disable() method instead of using + * NULL to get the default. The reason is that if the generic code + * sees that, it also hooks up a default ->shutdown method which + * invokes ->mask() which we do not want. See irq_chip_set_defaults(). + */ static void sun4u_irq_disable(unsigned int virt_irq) { - struct irq_handler_data *data = get_irq_chip_data(virt_irq); - - if (likely(data)) { - unsigned long imap = data->imap; - unsigned long tmp = upa_readq(imap); - - tmp &= ~IMAP_VALID; - upa_writeq(tmp, imap); - } } static void sun4u_irq_eoi(unsigned int virt_irq) @@ -746,7 +754,8 @@ void handler_irq(int irq, struct pt_regs *regs) desc = irq_desc + virt_irq; - desc->handle_irq(virt_irq, desc); + if (!(desc->status & IRQ_DISABLED)) + desc->handle_irq(virt_irq, desc); bucket_pa = next_pa; }