summaryrefslogtreecommitdiffstats
path: root/freebsd/sys/dev/pci/pci.c
diff options
context:
space:
mode:
Diffstat (limited to 'freebsd/sys/dev/pci/pci.c')
-rw-r--r--freebsd/sys/dev/pci/pci.c33
1 files changed, 31 insertions, 2 deletions
diff --git a/freebsd/sys/dev/pci/pci.c b/freebsd/sys/dev/pci/pci.c
index 7dcaa0d5..426d06a2 100644
--- a/freebsd/sys/dev/pci/pci.c
+++ b/freebsd/sys/dev/pci/pci.c
@@ -211,6 +211,7 @@ struct pci_quirk {
#define PCI_QUIRK_ENABLE_MSI_VM 3 /* Older chipset in VM where MSI works */
#define PCI_QUIRK_UNMAP_REG 4 /* Ignore PCI map register */
#define PCI_QUIRK_DISABLE_MSIX 5 /* MSI-X doesn't work */
+#define PCI_QUIRK_MSI_INTX_BUG 6 /* PCIM_CMD_INTxDIS disables MSI */
int arg1;
int arg2;
};
@@ -270,6 +271,26 @@ static const struct pci_quirk pci_quirks[] = {
*/
{ 0x43851002, PCI_QUIRK_UNMAP_REG, 0x14, 0 },
+ /*
+ * Atheros AR8161/AR8162/E2200 Ethernet controllers have a bug that
+ * MSI interrupt does not assert if PCIM_CMD_INTxDIS bit of the
+ * command register is set.
+ */
+ { 0x10911969, PCI_QUIRK_MSI_INTX_BUG, 0, 0 },
+ { 0xE0911969, PCI_QUIRK_MSI_INTX_BUG, 0, 0 },
+ { 0x10901969, PCI_QUIRK_MSI_INTX_BUG, 0, 0 },
+
+ /*
+ * Broadcom BCM5714(S)/BCM5715(S)/BCM5780(S) Ethernet MACs don't
+ * issue MSI interrupts with PCIM_CMD_INTxDIS set either.
+ */
+ { 0x166814e4, PCI_QUIRK_MSI_INTX_BUG, 0, 0 }, /* BCM5714 */
+ { 0x166914e4, PCI_QUIRK_MSI_INTX_BUG, 0, 0 }, /* BCM5714S */
+ { 0x166a14e4, PCI_QUIRK_MSI_INTX_BUG, 0, 0 }, /* BCM5780 */
+ { 0x166b14e4, PCI_QUIRK_MSI_INTX_BUG, 0, 0 }, /* BCM5780S */
+ { 0x167814e4, PCI_QUIRK_MSI_INTX_BUG, 0, 0 }, /* BCM5715 */
+ { 0x167914e4, PCI_QUIRK_MSI_INTX_BUG, 0, 0 }, /* BCM5715S */
+
{ 0 }
};
@@ -3567,8 +3588,16 @@ pci_setup_intr(device_t dev, device_t child, struct resource *irq, int flags,
mte->mte_handlers++;
}
- /* Make sure that INTx is disabled if we are using MSI/MSIX */
- pci_set_command_bit(dev, child, PCIM_CMD_INTxDIS);
+ /*
+ * Make sure that INTx is disabled if we are using MSI/MSI-X,
+ * unless the device is affected by PCI_QUIRK_MSI_INTX_BUG,
+ * in which case we "enable" INTx so MSI/MSI-X actually works.
+ */
+ if (!pci_has_quirk(pci_get_devid(child),
+ PCI_QUIRK_MSI_INTX_BUG))
+ pci_set_command_bit(dev, child, PCIM_CMD_INTxDIS);
+ else
+ pci_clear_command_bit(dev, child, PCIM_CMD_INTxDIS);
bad:
if (error) {
(void)bus_generic_teardown_intr(dev, child, irq,