diff options
author | Matthew Wilcox <matthew@wil.cx> | 2008-07-25 15:42:58 -0600 |
---|---|---|
committer | Jesse Barnes <jbarnes@virtuousgeek.org> | 2008-07-28 14:43:22 -0700 |
commit | ce6fce4295ba727b36fdc73040e444bd1aae64cd (patch) | |
tree | 7c8e4134b799d3d0ed56888bb8936e0071a05caf | |
parent | 29111f579f4f3f2a07385f931854ab0527ae7ea5 (diff) | |
download | op-kernel-dev-ce6fce4295ba727b36fdc73040e444bd1aae64cd.zip op-kernel-dev-ce6fce4295ba727b36fdc73040e444bd1aae64cd.tar.gz |
PCI MSI: Don't disable MSIs if the mask bit isn't supported
David Vrabel has a device which generates an interrupt storm on the INTx
pin if we disable MSI interrupts altogether. Masking interrupts is only
a performance optimisation, so we can ignore the request to mask the
interrupt.
Signed-off-by: Matthew Wilcox <willy@linux.intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
-rw-r--r-- | drivers/pci/msi.c | 15 |
1 files changed, 12 insertions, 3 deletions
diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c index 15af618..1835481 100644 --- a/drivers/pci/msi.c +++ b/drivers/pci/msi.c @@ -126,7 +126,16 @@ static void msix_flush_writes(unsigned int irq) } } -static void msi_set_mask_bits(unsigned int irq, u32 mask, u32 flag) +/* + * PCI 2.3 does not specify mask bits for each MSI interrupt. Attempting to + * mask all MSI interrupts by clearing the MSI enable bit does not work + * reliably as devices without an INTx disable bit will then generate a + * level IRQ which will never be cleared. + * + * Returns 1 if it succeeded in masking the interrupt and 0 if the device + * doesn't support MSI masking. + */ +static int msi_set_mask_bits(unsigned int irq, u32 mask, u32 flag) { struct msi_desc *entry; @@ -144,8 +153,7 @@ static void msi_set_mask_bits(unsigned int irq, u32 mask, u32 flag) mask_bits |= flag & mask; pci_write_config_dword(entry->dev, pos, mask_bits); } else { - __msi_set_enable(entry->dev, entry->msi_attrib.pos, - !flag); + return 0; } break; case PCI_CAP_ID_MSIX: @@ -161,6 +169,7 @@ static void msi_set_mask_bits(unsigned int irq, u32 mask, u32 flag) break; } entry->msi_attrib.masked = !!flag; + return 1; } void read_msi_msg(unsigned int irq, struct msi_msg *msg) |