diff options
author | David Gwynne <dlg@cvs.openbsd.org> | 2020-06-17 06:36:18 +0000 |
---|---|---|
committer | David Gwynne <dlg@cvs.openbsd.org> | 2020-06-17 06:36:18 +0000 |
commit | b659102db9c942b8e9da50e7ce040b072858abf4 (patch) | |
tree | d54017897e515ea2a392737a55445d79f7b69031 | |
parent | e995f9ef8644770967a6bac59067c7a579db9b4d (diff) |
enable multiple queues (and interrupts on multiple cpus) on vmx(4).
im doing this with vmx(4) because it only exists on two archs (well,
one and a half archs really) so any impact is localised. most other
drivers i'm working on are enabled on 3 or 4 archs, and we're still
working on the interrupt code on those archs.
in the meantime vmx(4) can be used as a reference driver on how to
implement multiq. it shows the use of rss, toeplitz, intrmap, and
interrupts on multiple cpus. it's also a relatively simple device,
which makes it easier to understand the above features.
note that vmx(4) seems to advertise 25 msi-x vectors. it appears
that the intention is that 16 of these vectors are supposed to be
used for rx, 8 for tx, and 1 for events (eg, link up and down).
we're keeping things simple for now and using a maximum of 8 vectors
for both tx and rx, and one for events.
this is mostly based on work that jmatthew@ did, but it's simplified
now cos intrmap makes things easier.
-rw-r--r-- | sys/dev/pci/files.pci | 4 | ||||
-rw-r--r-- | sys/dev/pci/if_vmx.c | 82 |
2 files changed, 53 insertions, 33 deletions
diff --git a/sys/dev/pci/files.pci b/sys/dev/pci/files.pci index 266f42b091f..6ca9c269c4a 100644 --- a/sys/dev/pci/files.pci +++ b/sys/dev/pci/files.pci @@ -1,4 +1,4 @@ -# $OpenBSD: files.pci,v 1.346 2020/06/16 05:31:15 dlg Exp $ +# $OpenBSD: files.pci,v 1.347 2020/06/17 06:36:17 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. @@ -718,7 +718,7 @@ attach vic at pci file dev/pci/if_vic.c vic # VMware VMXNET3 virtual interface -device vmx: ether, ifnet, ifmedia, stoeplitz +device vmx: ether, ifnet, ifmedia, stoeplitz, intrmap attach vmx at pci file dev/pci/if_vmx.c vmx diff --git a/sys/dev/pci/if_vmx.c b/sys/dev/pci/if_vmx.c index 3c308131406..b1f2844015d 100644 --- a/sys/dev/pci/if_vmx.c +++ b/sys/dev/pci/if_vmx.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if_vmx.c,v 1.57 2020/06/16 05:31:15 dlg Exp $ */ +/* $OpenBSD: if_vmx.c,v 1.58 2020/06/17 06:36:17 dlg Exp $ */ /* * Copyright (c) 2013 Tsubai Masanari @@ -25,6 +25,7 @@ #include <sys/sockio.h> #include <sys/systm.h> #include <sys/atomic.h> +#include <sys/intrmap.h> #include <net/bpf.h> #include <net/if.h> @@ -43,7 +44,7 @@ #include <dev/pci/pcivar.h> #include <dev/pci/pcidevs.h> -#define VMX_MAX_QUEUES 1 +#define VMX_MAX_QUEUES MIN(VMXNET3_MAX_TX_QUEUES, VMXNET3_MAX_RX_QUEUES) #define NTXDESC 512 /* tx ring size */ #define NTXSEGS 8 /* tx descriptors per packet */ @@ -92,24 +93,27 @@ struct vmxnet3_comp_ring { }; struct vmxnet3_txqueue { + struct vmxnet3_softc *sc; /* sigh */ struct vmxnet3_txring cmd_ring; struct vmxnet3_comp_ring comp_ring; struct vmxnet3_txq_shared *ts; struct ifqueue *ifq; -}; +} __aligned(64); struct vmxnet3_rxqueue { + struct vmxnet3_softc *sc; /* sigh */ struct vmxnet3_rxring cmd_ring[2]; struct vmxnet3_comp_ring comp_ring; struct vmxnet3_rxq_shared *rs; struct ifiqueue *ifiq; -}; +} __aligned(64); struct vmxnet3_queue { struct vmxnet3_txqueue tx; struct vmxnet3_rxqueue rx; struct vmxnet3_softc *sc; - char intrname[8]; + char intrname[16]; + void *ih; int intr; }; @@ -124,11 +128,11 @@ struct vmxnet3_softc { bus_space_handle_t sc_ioh1; bus_dma_tag_t sc_dmat; void *sc_ih; - void *sc_qih[VMX_MAX_QUEUES]; - int sc_nintr; + int sc_nqueues; + struct vmxnet3_queue *sc_q; + struct intrmap *sc_intrmap; - struct vmxnet3_queue sc_q[VMX_MAX_QUEUES]; struct vmxnet3_driver_shared *sc_ds; u_int8_t *sc_mcast; struct vmxnet3_upt1_rss_conf *sc_rss; @@ -227,6 +231,7 @@ vmxnet3_attach(struct device *parent, struct device *self, void *aux) u_int memtype, ver, macl, mach, intrcfg; u_char enaddr[ETHER_ADDR_LEN]; int (*isr)(void *); + int msix = 0; int i; memtype = pci_mapreg_type(pa->pa_pc, pa->pa_tag, 0x10); @@ -261,15 +266,23 @@ vmxnet3_attach(struct device *parent, struct device *self, void *aux) WRITE_CMD(sc, VMXNET3_CMD_GET_INTRCFG); intrcfg = READ_BAR1(sc, VMXNET3_BAR1_CMD); isr = vmxnet3_intr; - sc->sc_nintr = 0; sc->sc_nqueues = 1; switch (intrcfg & VMXNET3_INTRCFG_TYPE_MASK) { case VMXNET3_INTRCFG_TYPE_AUTO: case VMXNET3_INTRCFG_TYPE_MSIX: - if (pci_intr_map_msix(pa, 0, &ih) == 0) { - isr = vmxnet3_intr_event; - sc->sc_nintr = sc->sc_nqueues + 1; + msix = pci_intr_msix_count(pa->pa_pc, pa->pa_tag); + if (msix > 0) { + if (pci_intr_map_msix(pa, 0, &ih) == 0) { + msix--; /* are there spares for tx/rx qs? */ + if (msix == 0) + break; + + isr = vmxnet3_intr_event; + sc->sc_intrmap = intrmap_create(&sc->sc_dev, + msix, VMX_MAX_QUEUES, 0); + sc->sc_nqueues = intrmap_count(sc->sc_intrmap); + } break; } @@ -293,7 +306,10 @@ vmxnet3_attach(struct device *parent, struct device *self, void *aux) if (intrstr) printf(": %s", intrstr); - if (sc->sc_nintr > 1) { + sc->sc_q = mallocarray(sc->sc_nqueues, sizeof(*sc->sc_q), + M_DEVBUF, M_WAITOK|M_ZERO); + + if (sc->sc_intrmap != NULL) { for (i = 0; i < sc->sc_nqueues; i++) { struct vmxnet3_queue *q; int vec; @@ -306,9 +322,11 @@ vmxnet3_attach(struct device *parent, struct device *self, void *aux) } snprintf(q->intrname, sizeof(q->intrname), "%s:%d", self->dv_xname, i); - sc->sc_qih[i] = pci_intr_establish(pa->pa_pc, ih, - IPL_NET | IPL_MPSAFE, vmxnet3_intr_queue, q, - q->intrname); + /* this should be pci_intr_establish_cpu */ + q->ih = pci_intr_establish(pa->pa_pc, ih, + IPL_NET | IPL_MPSAFE, + /* intrmap_cpu(sc->sc_intrmap, i), */ + vmxnet3_intr_queue, q, q->intrname); q->intr = vec; q->sc = sc; @@ -399,10 +417,7 @@ vmxnet3_dma_init(struct vmxnet3_softc *sc) sc->sc_q[queue].rx.rs = rs++; for (queue = 0; queue < sc->sc_nqueues; queue++) { - if (sc->sc_nintr > 0) - intr = queue + 1; - else - intr = 0; + intr = sc->sc_q[queue].intr; if (vmxnet3_alloc_txring(sc, queue, intr)) return -1; @@ -453,10 +468,10 @@ vmxnet3_dma_init(struct vmxnet3_softc *sc) ds->nrxqueue = sc->sc_nqueues; ds->mcast_table = mcast_pa; ds->automask = 1; - ds->nintr = sc->sc_nintr; + ds->nintr = 1 + (sc->sc_intrmap != NULL ? sc->sc_nqueues : 0); ds->evintr = 0; ds->ictrl = VMXNET3_ICTRL_DISABLE_ALL; - for (i = 0; i < sc->sc_nintr; i++) + for (i = 0; i < ds->nintr; i++) ds->modlevel[i] = UPT1_IMOD_ADAPTIVE; if (sc->sc_nqueues > 1) { @@ -766,8 +781,11 @@ vmxnet3_enable_all_intrs(struct vmxnet3_softc *sc) int i; sc->sc_ds->ictrl &= ~VMXNET3_ICTRL_DISABLE_ALL; - for (i = 0; i < sc->sc_nintr; i++) - vmxnet3_enable_intr(sc, i); + vmxnet3_enable_intr(sc, 0); + if (sc->sc_intrmap) { + for (i = 0; i < sc->sc_nqueues; i++) + vmxnet3_enable_intr(sc, sc->sc_q[i].intr); + } } void @@ -776,8 +794,11 @@ vmxnet3_disable_all_intrs(struct vmxnet3_softc *sc) int i; sc->sc_ds->ictrl |= VMXNET3_ICTRL_DISABLE_ALL; - for (i = 0; i < sc->sc_nintr; i++) - vmxnet3_disable_intr(sc, i); + vmxnet3_disable_intr(sc, 0); + if (sc->sc_intrmap) { + for (i = 0; i < sc->sc_nqueues; i++) + vmxnet3_disable_intr(sc, sc->sc_q[i].intr); + } } int @@ -1116,12 +1137,11 @@ vmxnet3_stop(struct ifnet *ifp) WRITE_CMD(sc, VMXNET3_CMD_DISABLE); - if (sc->sc_nintr == 1) - intr_barrier(sc->sc_ih); - else { + if (sc->sc_intrmap != NULL) { for (queue = 0; queue < sc->sc_nqueues; queue++) - intr_barrier(sc->sc_qih[queue]); - } + intr_barrier(sc->sc_q[queue].ih); + } else + intr_barrier(sc->sc_ih); for (queue = 0; queue < sc->sc_nqueues; queue++) vmxnet3_txstop(sc, &sc->sc_q[queue].tx); |