summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorhselasky <hselasky@FreeBSD.org>2017-03-14 15:15:37 +0000
committerhselasky <hselasky@FreeBSD.org>2017-03-14 15:15:37 +0000
commitd24a26937c7a9afb5185c99f91d1c47009c2558f (patch)
tree97a1ca8dd4e99fbd565058f4919cceff8f05b329
parentc2d58806b9c8f951eb62c390161af34447d7edd3 (diff)
downloadFreeBSD-src-d24a26937c7a9afb5185c99f91d1c47009c2558f.zip
FreeBSD-src-d24a26937c7a9afb5185c99f91d1c47009c2558f.tar.gz
MFC r310806:
Add MSIX rewrite table quirk for use with VMs. This patch solves IRQ generation problems using the mlx5en(4) driver with xenserver v6.5.0 in SRIOV and PCI-passthrough modes. Until further the hw.pci.msix_rewrite_table quirk must be set manually in /boot/loader.conf . Reviewed by: jhb @ Sponsored by: Mellanox Technologies
-rw-r--r--sys/dev/pci/pci.c52
1 files changed, 45 insertions, 7 deletions
diff --git a/sys/dev/pci/pci.c b/sys/dev/pci/pci.c
index d36f4cc..9fa7ead 100644
--- a/sys/dev/pci/pci.c
+++ b/sys/dev/pci/pci.c
@@ -351,6 +351,11 @@ TUNABLE_INT("hw.pci.enable_msix", &pci_do_msix);
SYSCTL_INT(_hw_pci, OID_AUTO, enable_msix, CTLFLAG_RW, &pci_do_msix, 1,
"Enable support for MSI-X interrupts");
+static int pci_msix_rewrite_table = 0;
+SYSCTL_INT(_hw_pci, OID_AUTO, msix_rewrite_table, CTLFLAG_RWTUN,
+ &pci_msix_rewrite_table, 0,
+ "Rewrite entire MSI-X table when updating MSI-X entries");
+
static int pci_honor_msi_blacklist = 1;
TUNABLE_INT("hw.pci.honor_msi_blacklist", &pci_honor_msi_blacklist);
SYSCTL_INT(_hw_pci, OID_AUTO, honor_msi_blacklist, CTLFLAG_RD,
@@ -1375,11 +1380,10 @@ pci_find_extcap_method(device_t dev, device_t child, int capability,
/*
* Support for MSI-X message interrupts.
*/
-void
-pci_enable_msix_method(device_t dev, device_t child, u_int index,
- uint64_t address, uint32_t data)
+static void
+pci_write_msix_entry(device_t dev, u_int index, uint64_t address, uint32_t data)
{
- struct pci_devinfo *dinfo = device_get_ivars(child);
+ struct pci_devinfo *dinfo = device_get_ivars(dev);
struct pcicfg_msix *msix = &dinfo->cfg.msix;
uint32_t offset;
@@ -1388,6 +1392,31 @@ pci_enable_msix_method(device_t dev, device_t child, u_int index,
bus_write_4(msix->msix_table_res, offset, address & 0xffffffff);
bus_write_4(msix->msix_table_res, offset + 4, address >> 32);
bus_write_4(msix->msix_table_res, offset + 8, data);
+}
+
+void
+pci_enable_msix_method(device_t dev, device_t child, u_int index,
+ uint64_t address, uint32_t data)
+{
+
+ if (pci_msix_rewrite_table) {
+ struct pci_devinfo *dinfo = device_get_ivars(child);
+ struct pcicfg_msix *msix = &dinfo->cfg.msix;
+
+ /*
+ * Some VM hosts require MSIX to be disabled in the
+ * control register before updating the MSIX table
+ * entries are allowed. It is not enough to only
+ * disable MSIX while updating a single entry. MSIX
+ * must be disabled while updating all entries in the
+ * table.
+ */
+ pci_write_config(child,
+ msix->msix_location + PCIR_MSIX_CTRL,
+ msix->msix_ctrl & ~PCIM_MSIXCTRL_MSIX_ENABLE, 2);
+ pci_resume_msix(child);
+ } else
+ pci_write_msix_entry(child, index, address, data);
/* Enable MSI -> HT mapping. */
pci_ht_map_msi(child, address);
@@ -1463,7 +1492,8 @@ pci_resume_msix(device_t dev)
if (mte->mte_vector == 0 || mte->mte_handlers == 0)
continue;
mv = &msix->msix_vectors[mte->mte_vector - 1];
- pci_enable_msix(dev, i, mv->mv_address, mv->mv_data);
+ pci_write_msix_entry(dev, i, mv->mv_address,
+ mv->mv_data);
pci_unmask_msix(dev, i);
}
}
@@ -3980,12 +4010,20 @@ pci_setup_intr(device_t dev, device_t child, struct resource *irq, int flags,
mv->mv_address = addr;
mv->mv_data = data;
}
- if (mte->mte_handlers == 0) {
+
+ /*
+ * The MSIX table entry must be made valid by
+ * incrementing the mte_handlers before
+ * calling pci_enable_msix() and
+ * pci_resume_msix(). Else the MSIX rewrite
+ * table quirk will not work as expected.
+ */
+ mte->mte_handlers++;
+ if (mte->mte_handlers == 1) {
pci_enable_msix(child, rid - 1, mv->mv_address,
mv->mv_data);
pci_unmask_msix(child, rid - 1);
}
- mte->mte_handlers++;
}
/*
OpenPOWER on IntegriCloud