diff options
author | hselasky <hselasky@FreeBSD.org> | 2017-03-14 15:15:37 +0000 |
---|---|---|
committer | hselasky <hselasky@FreeBSD.org> | 2017-03-14 15:15:37 +0000 |
commit | d24a26937c7a9afb5185c99f91d1c47009c2558f (patch) | |
tree | 97a1ca8dd4e99fbd565058f4919cceff8f05b329 | |
parent | c2d58806b9c8f951eb62c390161af34447d7edd3 (diff) | |
download | FreeBSD-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.c | 52 |
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++; } /* |