sparc64: Fix lost interrupts on sun4u.
authorDavid S. Miller <davem@davemloft.net>
Wed, 4 Mar 2009 22:43:47 +0000 (14:43 -0800)
committerDavid S. Miller <davem@davemloft.net>
Wed, 4 Mar 2009 22:43:47 +0000 (14:43 -0800)
commitd0cac39e4ec8097e4c7099d291b1fdcc0fe56b58
tree329143d8b8600e72aafe48f7d136004e34f0a2a7
parentf4c13638185c91a269c63fcfb980d89180cf43a1
sparc64: Fix lost interrupts on sun4u.

Based upon a report by Meelis Roos.

Sparc64 SBUS and PCI controllers use a combination of IMAP and ICLR
registers to manage device interrupts.

The IMAP register contains the "valid" enable bit as well as CPU
targetting information.  Whereas the ICLR register is written with
zero at the end of handling an interrupt to reset the state machine
for that interrupt to IDLE so it can be sent again.

For PCI slot and SBUS slot devices we can have multiple interrupts
sharing the same IMAP register.  There are individual ICLR registers
but only one IMAP register for managing those.

We represent each shared case with individual virtual IRQs so the
generic IRQ layer thinks there is only one user of the IRQ instance.

In such shared IMAP cases this is wrong, so if there are multiple
active users then a free_irq() call will prematurely turn off the
interrupt by clearing the Valid bit in the IMAP register even though
there are other active users.

Fix this by simply doing nothing in sun4u_disable_irq() and checking
IRQF_DISABLED during IRQ dispatch.

This situation doesn't exist in the hypervisor sun4v cases, so I left
those alone.

Tested-by: Meelis Roos <mroos@linux.ee>
Signed-off-by: David S. Miller <davem@davemloft.net>
arch/sparc/kernel/irq_64.c