aboutsummaryrefslogtreecommitdiffstats
path: root/arch/sparc/kernel/irq_64.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/sparc/kernel/irq_64.c')
-rw-r--r--arch/sparc/kernel/irq_64.c29
1 files changed, 19 insertions, 10 deletions
diff --git a/arch/sparc/kernel/irq_64.c b/arch/sparc/kernel/irq_64.c
index e289376198eb..1c378d8e90c5 100644
--- a/arch/sparc/kernel/irq_64.c
+++ b/arch/sparc/kernel/irq_64.c
@@ -323,17 +323,25 @@ static void sun4u_set_affinity(unsigned int virt_irq,
323 sun4u_irq_enable(virt_irq); 323 sun4u_irq_enable(virt_irq);
324} 324}
325 325
326/* Don't do anything. The desc->status check for IRQ_DISABLED in
327 * handler_irq() will skip the handler call and that will leave the
328 * interrupt in the sent state. The next ->enable() call will hit the
329 * ICLR register to reset the state machine.
330 *
331 * This scheme is necessary, instead of clearing the Valid bit in the
332 * IMAP register, to handle the case of IMAP registers being shared by
333 * multiple INOs (and thus ICLR registers). Since we use a different
334 * virtual IRQ for each shared IMAP instance, the generic code thinks
335 * there is only one user so it prematurely calls ->disable() on
336 * free_irq().
337 *
338 * We have to provide an explicit ->disable() method instead of using
339 * NULL to get the default. The reason is that if the generic code
340 * sees that, it also hooks up a default ->shutdown method which
341 * invokes ->mask() which we do not want. See irq_chip_set_defaults().
342 */
326static void sun4u_irq_disable(unsigned int virt_irq) 343static void sun4u_irq_disable(unsigned int virt_irq)
327{ 344{
328 struct irq_handler_data *data = get_irq_chip_data(virt_irq);
329
330 if (likely(data)) {
331 unsigned long imap = data->imap;
332 unsigned long tmp = upa_readq(imap);
333
334 tmp &= ~IMAP_VALID;
335 upa_writeq(tmp, imap);
336 }
337} 345}
338 346
339static void sun4u_irq_eoi(unsigned int virt_irq) 347static void sun4u_irq_eoi(unsigned int virt_irq)
@@ -746,7 +754,8 @@ void handler_irq(int irq, struct pt_regs *regs)
746 754
747 desc = irq_desc + virt_irq; 755 desc = irq_desc + virt_irq;
748 756
749 desc->handle_irq(virt_irq, desc); 757 if (!(desc->status & IRQ_DISABLED))
758 desc->handle_irq(virt_irq, desc);
750 759
751 bucket_pa = next_pa; 760 bucket_pa = next_pa;
752 } 761 }