svn commit: r289344 - head/sys/dev/ntb/ntb_hw
Conrad E. Meyer
cem at FreeBSD.org
Wed Oct 14 23:47:24 UTC 2015
Author: cem
Date: Wed Oct 14 23:47:23 2015
New Revision: 289344
URL: https://svnweb.freebsd.org/changeset/base/289344
Log:
NTB: Remap MSI-X messages over available slots
Remap MSI-X messages over available slots rather than falling back to
legacy INTx when fewer MSI-X slots are available than were requested.
N.B. the Linux driver does *not* do this.
To aid in testing, a tunable 'hw.ntb.force_remap_mode' has been added.
It defaults to off (0). When the tunable is enabled and sufficient
slots were available, the driver restricts the number of slots by one
and remaps the MSI-X messages over the remaining slots.
In case this is actually not okay (as I don't yet have access to this
hardware to test), a tunable 'hw.ntb.prefer_intx_to_remap' has been
added. It defaults to off (0). When the tunable is enabled and fewer
slots are available than requested, fall back to legacy INTx mode rather
than attempting to remap MSI-X messages.
Suggested by: jhb
Reviewed by: jhb (earlier version)
Sponsored by: EMC / Isilon Storage Division
Modified:
head/sys/dev/ntb/ntb_hw/ntb_hw.c
Modified: head/sys/dev/ntb/ntb_hw/ntb_hw.c
==============================================================================
--- head/sys/dev/ntb/ntb_hw/ntb_hw.c Wed Oct 14 23:47:08 2015 (r289343)
+++ head/sys/dev/ntb/ntb_hw/ntb_hw.c Wed Oct 14 23:47:23 2015 (r289344)
@@ -200,6 +200,7 @@ static int map_mmr_bar(struct ntb_softc
static int map_memory_window_bar(struct ntb_softc *ntb,
struct ntb_pci_bar_info *bar);
static void ntb_unmap_pci_bar(struct ntb_softc *ntb);
+static int ntb_remap_msix(device_t, uint32_t desired, uint32_t avail);
static int ntb_setup_interrupts(struct ntb_softc *ntb);
static int ntb_setup_legacy_interrupt(struct ntb_softc *ntb);
static int ntb_setup_xeon_msix(struct ntb_softc *ntb, uint32_t num_vectors);
@@ -551,10 +552,55 @@ ntb_setup_soc_msix(struct ntb_softc *ntb
return (0);
}
+/*
+ * The Linux NTB driver drops from MSI-X to legacy INTx if a unique vector
+ * cannot be allocated for each MSI-X message. JHB seems to think remapping
+ * should be okay. This tunable should enable us to test that hypothesis
+ * when someone gets their hands on some Xeon hardware.
+ */
+static int ntb_force_remap_mode;
+SYSCTL_INT(_hw_ntb, OID_AUTO, force_remap_mode, CTLFLAG_RDTUN,
+ &ntb_force_remap_mode, 0, "If enabled, force MSI-X messages to be remapped"
+ " to a smaller number of ithreads, even if the desired number are "
+ "available");
+
+/*
+ * In case it is NOT ok, give consumers an abort button.
+ */
+static int ntb_prefer_intx;
+SYSCTL_INT(_hw_ntb, OID_AUTO, prefer_intx_to_remap, CTLFLAG_RDTUN,
+ &ntb_prefer_intx, 0, "If enabled, prefer to use legacy INTx mode rather "
+ "than remapping MSI-X messages over available slots (match Linux driver "
+ "behavior)");
+
+/*
+ * Remap the desired number of MSI-X messages to available ithreads in a simple
+ * round-robin fashion.
+ */
+static int
+ntb_remap_msix(device_t dev, uint32_t desired, uint32_t avail)
+{
+ u_int *vectors;
+ uint32_t i;
+ int rc;
+
+ if (ntb_prefer_intx != 0)
+ return (ENXIO);
+
+ vectors = malloc(desired * sizeof(*vectors), M_NTB, M_ZERO | M_WAITOK);
+
+ for (i = 0; i < desired; i++)
+ vectors[i] = (i % avail) + 1;
+
+ rc = pci_remap_msix(dev, desired, vectors);
+ free(vectors, M_NTB);
+ return (rc);
+}
+
static int
ntb_setup_interrupts(struct ntb_softc *ntb)
{
- uint32_t num_vectors;
+ uint32_t desired_vectors, num_vectors;
int rc;
ntb->allocated_interrupts = 0;
@@ -568,10 +614,27 @@ ntb_setup_interrupts(struct ntb_softc *n
ntb_reg_write(2, ntb->reg_ofs.ldb_mask,
(uint16_t) ~(1 << XEON_LINK_DB));
- num_vectors = MIN(pci_msix_count(ntb->device),
+ num_vectors = desired_vectors = MIN(pci_msix_count(ntb->device),
ntb->limits.max_db_bits);
- if (num_vectors >= 1)
- pci_alloc_msix(ntb->device, &num_vectors);
+ if (desired_vectors >= 1) {
+ rc = pci_alloc_msix(ntb->device, &num_vectors);
+
+ if (ntb_force_remap_mode != 0 && rc == 0 &&
+ num_vectors == desired_vectors)
+ num_vectors--;
+
+ if (rc == 0 && num_vectors < desired_vectors) {
+ rc = ntb_remap_msix(ntb->device, desired_vectors,
+ num_vectors);
+ if (rc == 0)
+ num_vectors = desired_vectors;
+ else
+ pci_release_msi(ntb->device);
+ }
+ if (rc != 0)
+ num_vectors = 1;
+ } else
+ num_vectors = 1;
ntb_create_callbacks(ntb, num_vectors);
More information about the svn-src-head
mailing list