summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorDavid Gwynne <dlg@cvs.openbsd.org>2020-07-17 06:27:37 +0000
committerDavid Gwynne <dlg@cvs.openbsd.org>2020-07-17 06:27:37 +0000
commit26de37b7bbadd5cd56b3bfe420bcf61fe7fb51bd (patch)
tree3ac17628616a32247ffc274341a8e44960b8f261 /sys
parent78e44116d25652244cee02204356dd4bb808564a (diff)
enable multiq support for ix.
this is an updated version of a diff from christiano haesbaert by way of mpi@ to enable the use of multiple tx and rx rings with msi-x. now that patrick@ got interrupts on multiple cpus working on arm64, i can commit this. the main changes are to use an intrmap pointer as the flag for whether msix has been enabled or not, and to use the intrmap to establish vectors on multiple cpus. tested by hrvoje popovski
Diffstat (limited to 'sys')
-rw-r--r--sys/dev/pci/files.pci4
-rw-r--r--sys/dev/pci/if_ix.c123
-rw-r--r--sys/dev/pci/if_ix.h4
-rw-r--r--sys/dev/pci/ixgbe.h3
4 files changed, 72 insertions, 62 deletions
diff --git a/sys/dev/pci/files.pci b/sys/dev/pci/files.pci
index f8f3be2da18..f33e54621e7 100644
--- a/sys/dev/pci/files.pci
+++ b/sys/dev/pci/files.pci
@@ -1,4 +1,4 @@
-# $OpenBSD: files.pci,v 1.350 2020/07/14 04:10:18 jmatthew Exp $
+# $OpenBSD: files.pci,v 1.351 2020/07/17 06:27:36 dlg Exp $
# $NetBSD: files.pci,v 1.20 1996/09/24 17:47:15 christos Exp $
#
# Config file and device description for machine-independent PCI code.
@@ -343,7 +343,7 @@ file dev/pci/ixgb_ee.c ixgb
file dev/pci/ixgb_hw.c ixgb
# Intel 82598 10GbE
-device ix: ether, ifnet, ifmedia
+device ix: ether, ifnet, ifmedia, intrmap
attach ix at pci
file dev/pci/if_ix.c ix
file dev/pci/ixgbe.c ix
diff --git a/sys/dev/pci/if_ix.c b/sys/dev/pci/if_ix.c
index da4ea7236c4..5bca3667431 100644
--- a/sys/dev/pci/if_ix.c
+++ b/sys/dev/pci/if_ix.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: if_ix.c,v 1.167 2020/07/10 13:26:38 patrick Exp $ */
+/* $OpenBSD: if_ix.c,v 1.168 2020/07/17 06:27:36 dlg Exp $ */
/******************************************************************************
@@ -115,7 +115,7 @@ void ixgbe_identify_hardware(struct ix_softc *);
int ixgbe_allocate_pci_resources(struct ix_softc *);
int ixgbe_allocate_legacy(struct ix_softc *);
int ixgbe_allocate_msix(struct ix_softc *);
-int ixgbe_setup_msix(struct ix_softc *);
+void ixgbe_setup_msix(struct ix_softc *);
int ixgbe_allocate_queues(struct ix_softc *);
void ixgbe_free_pci_resources(struct ix_softc *);
void ixgbe_local_timer(void *);
@@ -199,7 +199,7 @@ struct cfattach ix_ca = {
};
int ixgbe_smart_speed = ixgbe_smart_speed_on;
-int ixgbe_enable_msix = 0;
+int ixgbe_enable_msix = 1;
/*********************************************************************
* Device identification routine
@@ -301,7 +301,7 @@ ixgbe_attach(struct device *parent, struct device *self, void *aux)
bcopy(sc->hw.mac.addr, sc->arpcom.ac_enaddr,
IXGBE_ETH_LENGTH_OF_ADDRESS);
- if (sc->msix > 1)
+ if (sc->sc_intrmap)
error = ixgbe_allocate_msix(sc);
else
error = ixgbe_allocate_legacy(sc);
@@ -604,7 +604,7 @@ ixgbe_rxrinfo(struct ix_softc *sc, struct if_rxrinfo *ifri)
for (i = 0; i < sc->num_queues; i++) {
rxr = &sc->rx_rings[i];
ifr[n].ifr_size = sc->rx_mbuf_sz;
- snprintf(ifr[n].ifr_name, sizeof(ifr[n].ifr_name), "/%d", i);
+ snprintf(ifr[n].ifr_name, sizeof(ifr[n].ifr_name), "%d", i);
ifr[n].ifr_info = rxr->rx_ring;
n++;
}
@@ -798,7 +798,7 @@ ixgbe_init(void *arg)
timeout_add_sec(&sc->timer, 1);
/* Set up MSI/X routing */
- if (sc->msix > 1) {
+ if (sc->sc_intrmap) {
ixgbe_configure_ivars(sc);
/* Set up auto-mask */
if (sc->hw.mac.type == ixgbe_mac_82598EB)
@@ -829,7 +829,7 @@ ixgbe_init(void *arg)
itr |= IXGBE_EITR_LLI_MOD | IXGBE_EITR_CNT_WDIS;
IXGBE_WRITE_REG(&sc->hw, IXGBE_EITR(0), itr);
- if (sc->msix > 1) {
+ if (sc->sc_intrmap) {
/* Set moderation on the Link interrupt */
IXGBE_WRITE_REG(&sc->hw, IXGBE_EITR(sc->linkvec),
IXGBE_LINK_ITR);
@@ -903,7 +903,7 @@ ixgbe_config_gpie(struct ix_softc *sc)
gpie |= 0xf << IXGBE_GPIE_LLI_DELAY_SHIFT;
}
- if (sc->msix > 1) {
+ if (sc->sc_intrmap) {
/* Enable Enhanced MSIX mode */
gpie |= IXGBE_GPIE_MSIX_MODE;
gpie |= IXGBE_GPIE_EIAME | IXGBE_GPIE_PBA_SUPPORT |
@@ -1617,6 +1617,7 @@ ixgbe_stop(void *arg)
ifq_barrier(ifq);
ifq_clr_oactive(ifq);
+ intr_barrier(sc->queues[i].tag);
timeout_del(&sc->rx_rings[i].rx_refill);
}
@@ -1717,80 +1718,86 @@ ixgbe_allocate_msix(struct ix_softc *sc)
{
struct ixgbe_osdep *os = &sc->osdep;
struct pci_attach_args *pa = &os->os_pa;
- int vec, error = 0;
- struct ix_queue *que = sc->queues;
- const char *intrstr = NULL;
- pci_chipset_tag_t pc = pa->pa_pc;
+ int i = 0, error = 0;
+ struct ix_queue *que;
pci_intr_handle_t ih;
- vec = 0;
- if (pci_intr_map_msix(pa, vec, &ih)) {
- printf(": couldn't map interrupt\n");
- return (ENXIO);
- }
+ for (i = 0, que = sc->queues; i < sc->num_queues; i++, que++) {
+ if (pci_intr_map_msix(pa, i, &ih)) {
+ printf("ixgbe_allocate_msix: "
+ "pci_intr_map_msix vec %d failed\n", i);
+ error = ENOMEM;
+ goto fail;
+ }
- que->msix = vec;
- snprintf(que->name, sizeof(que->name), "%s:%d", sc->dev.dv_xname, vec);
+ que->tag = pci_intr_establish_cpu(pa->pa_pc, ih,
+ IPL_NET | IPL_MPSAFE, intrmap_cpu(sc->sc_intrmap, i),
+ ixgbe_queue_intr, que, que->name);
+ if (que->tag == NULL) {
+ printf("ixgbe_allocate_msix: "
+ "pci_intr_establish vec %d failed\n", i);
+ error = ENOMEM;
+ goto fail;
+ }
- intrstr = pci_intr_string(pc, ih);
- que->tag = pci_intr_establish(pc, ih, IPL_NET | IPL_MPSAFE,
- ixgbe_queue_intr, que, que->name);
- if (que->tag == NULL) {
- printf(": couldn't establish interrupt");
- if (intrstr != NULL)
- printf(" at %s", intrstr);
- printf("\n");
- return (ENXIO);
+ que->msix = i;
}
/* Now the link status/control last MSI-X vector */
- vec++;
- if (pci_intr_map_msix(pa, vec, &ih)) {
- printf(": couldn't map link vector\n");
- error = ENXIO;
+ if (pci_intr_map_msix(pa, i, &ih)) {
+ printf("ixgbe_allocate_msix: "
+ "pci_intr_map_msix link vector failed\n");
+ error = ENOMEM;
goto fail;
}
- intrstr = pci_intr_string(pc, ih);
- sc->tag = pci_intr_establish(pc, ih, IPL_NET | IPL_MPSAFE,
+ sc->tag = pci_intr_establish(pa->pa_pc, ih, IPL_NET | IPL_MPSAFE,
ixgbe_link_intr, sc, sc->dev.dv_xname);
if (sc->tag == NULL) {
- printf(": couldn't establish interrupt");
- if (intrstr != NULL)
- printf(" at %s", intrstr);
- printf("\n");
- error = ENXIO;
+ printf("ixgbe_allocate_msix: "
+ "pci_intr_establish link vector failed\n");
+ error = ENOMEM;
goto fail;
}
-
- sc->linkvec = vec;
- printf(", %s, %d queue%s", intrstr, vec, (vec > 1) ? "s" : "");
+ sc->linkvec = i;
+ printf(", %s, %d queue%s", pci_intr_string(pa->pa_pc, ih),
+ i, (i > 1) ? "s" : "");
return (0);
fail:
- pci_intr_disestablish(pc, que->tag);
- que->tag = NULL;
+ for (que = sc->queues; i > 0; i--, que++) {
+ if (que->tag == NULL)
+ continue;
+ pci_intr_disestablish(pa->pa_pc, que->tag);
+ que->tag = NULL;
+ }
+
return (error);
}
-int
+void
ixgbe_setup_msix(struct ix_softc *sc)
{
struct ixgbe_osdep *os = &sc->osdep;
struct pci_attach_args *pa = &os->os_pa;
- pci_intr_handle_t dummy;
+ int nmsix;
+ unsigned int maxq;
if (!ixgbe_enable_msix)
- return (0);
+ return;
- /*
- * Try a dummy map, maybe this bus doesn't like MSI, this function
- * has no side effects.
- */
- if (pci_intr_map_msix(pa, 0, &dummy))
- return (0);
+ nmsix = pci_intr_msix_count(pa->pa_pc, pa->pa_tag);
+ if (nmsix <= 1)
+ return;
+
+ /* give one vector to events */
+ nmsix--;
- return (2); /* queue vector + link vector */
+ /* XXX the number of queues is limited to what we can keep stats on */
+ maxq = (sc->hw.mac.type == ixgbe_mac_82598EB) ? 8 : 16;
+
+ sc->sc_intrmap = intrmap_create(&sc->dev, nmsix, maxq, 0);
+ sc->num_queues = intrmap_count(sc->sc_intrmap);
}
int
@@ -1818,7 +1825,7 @@ ixgbe_allocate_pci_resources(struct ix_softc *sc)
sc->hw.back = os;
/* Now setup MSI or MSI/X, return us the number of supported vectors. */
- sc->msix = ixgbe_setup_msix(sc);
+ ixgbe_setup_msix(sc);
return (0);
}
@@ -2159,6 +2166,8 @@ ixgbe_allocate_queues(struct ix_softc *sc)
que->sc = sc;
que->txr = &sc->tx_rings[i];
que->rxr = &sc->rx_rings[i];
+ snprintf(que->name, sizeof(que->name), "%s:%d",
+ sc->dev.dv_xname, i);
}
return (0);
@@ -3295,7 +3304,7 @@ ixgbe_enable_intr(struct ix_softc *sc)
IXGBE_WRITE_REG(hw, IXGBE_EIMS, mask);
/* With MSI-X we use auto clear */
- if (sc->msix > 1) {
+ if (sc->sc_intrmap) {
mask = IXGBE_EIMS_ENABLE_MASK;
/* Don't autoclear Link */
mask &= ~IXGBE_EIMS_OTHER;
@@ -3309,7 +3318,7 @@ ixgbe_enable_intr(struct ix_softc *sc)
void
ixgbe_disable_intr(struct ix_softc *sc)
{
- if (sc->msix > 1)
+ if (sc->sc_intrmap)
IXGBE_WRITE_REG(&sc->hw, IXGBE_EIAC, 0);
if (sc->hw.mac.type == ixgbe_mac_82598EB) {
IXGBE_WRITE_REG(&sc->hw, IXGBE_EIMC, ~0);
diff --git a/sys/dev/pci/if_ix.h b/sys/dev/pci/if_ix.h
index 5c7ccf04a39..ba3aa817d38 100644
--- a/sys/dev/pci/if_ix.h
+++ b/sys/dev/pci/if_ix.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: if_ix.h,v 1.41 2020/06/07 23:52:05 dlg Exp $ */
+/* $OpenBSD: if_ix.h,v 1.42 2020/07/17 06:27:36 dlg Exp $ */
/******************************************************************************
@@ -234,7 +234,7 @@ struct ix_softc {
struct ifmedia media;
struct timeout timer;
- int msix;
+ struct intrmap *sc_intrmap;
int if_flags;
uint16_t num_vlans;
diff --git a/sys/dev/pci/ixgbe.h b/sys/dev/pci/ixgbe.h
index 5c3b7400d28..ed843fa8bab 100644
--- a/sys/dev/pci/ixgbe.h
+++ b/sys/dev/pci/ixgbe.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: ixgbe.h,v 1.29 2020/03/02 01:59:01 jmatthew Exp $ */
+/* $OpenBSD: ixgbe.h,v 1.30 2020/07/17 06:27:36 dlg Exp $ */
/******************************************************************************
@@ -53,6 +53,7 @@
#include <sys/timeout.h>
#include <sys/pool.h>
#include <sys/rwlock.h>
+#include <sys/intrmap.h>
#include <sys/atomic.h>
#include <net/if.h>