summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Gwynne <dlg@cvs.openbsd.org>2020-06-17 06:36:18 +0000
committerDavid Gwynne <dlg@cvs.openbsd.org>2020-06-17 06:36:18 +0000
commitb659102db9c942b8e9da50e7ce040b072858abf4 (patch)
treed54017897e515ea2a392737a55445d79f7b69031
parente995f9ef8644770967a6bac59067c7a579db9b4d (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.pci4
-rw-r--r--sys/dev/pci/if_vmx.c82
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);