Module Name: src
Committed By: yamaguchi
Date: Mon Jan 14 14:35:52 UTC 2019
Modified Files:
src/sys/dev/pci: if_vioif.c
Log Message:
Divide some elements of vioif_softc into txq, rxq, and ctrlq
To generate a diff of this commit:
cvs rdiff -u -r1.42 -r1.43 src/sys/dev/pci/if_vioif.c
Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.
Modified files:
Index: src/sys/dev/pci/if_vioif.c
diff -u src/sys/dev/pci/if_vioif.c:1.42 src/sys/dev/pci/if_vioif.c:1.43
--- src/sys/dev/pci/if_vioif.c:1.42 Mon Jan 14 14:32:13 2019
+++ src/sys/dev/pci/if_vioif.c Mon Jan 14 14:35:52 2019
@@ -1,4 +1,4 @@
-/* $NetBSD: if_vioif.c,v 1.42 2019/01/14 14:32:13 yamaguchi Exp $ */
+/* $NetBSD: if_vioif.c,v 1.43 2019/01/14 14:35:52 yamaguchi Exp $ */
/*
* Copyright (c) 2010 Minoura Makoto.
@@ -26,7 +26,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: if_vioif.c,v 1.42 2019/01/14 14:32:13 yamaguchi Exp $");
+__KERNEL_RCSID(0, "$NetBSD: if_vioif.c,v 1.43 2019/01/14 14:35:52 yamaguchi Exp $");
#ifdef _KERNEL_OPT
#include "opt_net_mpsafe.h"
@@ -175,6 +175,67 @@ struct virtio_net_ctrl_vlan {
/*
* if_vioifvar.h:
*/
+
+/*
+ * Locking notes:
+ * + a field in vioif_txqueue is protected by txq_lock (a spin mutex), and
+ * a filds in vioif_rxqueue is protected by rxq_lock (a spin mutex).
+ * - more than one lock cannot be held at onece
+ * + ctrlq_inuse is protected by ctrlq_wait_lock.
+ * - other fields in vioif_ctrlqueue are protected by ctrlq_inuse
+ * - txq_lock or rxq_lock cannot be held along with ctrlq_wait_lock
+ */
+
+struct vioif_txqueue {
+ kmutex_t *txq_lock; /* lock for tx operations */
+
+ struct virtqueue *txq_vq;
+ bool txq_stopping;
+ bool txq_link_active;
+
+ struct virtio_net_hdr *txq_hdrs;
+ bus_dmamap_t *txq_hdr_dmamaps;
+
+ struct mbuf **txq_mbufs;
+ bus_dmamap_t *txq_dmamaps;
+};
+
+struct vioif_rxqueue {
+ kmutex_t *rxq_lock; /* lock for rx operations */
+
+ struct virtqueue *rxq_vq;
+ bool rxq_stopping;
+
+ struct virtio_net_hdr *rxq_hdrs;
+ bus_dmamap_t *rxq_hdr_dmamaps;
+
+ struct mbuf **rxq_mbufs;
+ bus_dmamap_t *rxq_dmamaps;
+
+ void *rxq_softint;
+};
+
+struct vioif_ctrlqueue {
+ struct virtqueue *ctrlq_vq;
+ enum {
+ FREE, INUSE, DONE
+ } ctrlq_inuse;
+ kcondvar_t ctrlq_wait;
+ kmutex_t ctrlq_wait_lock;
+
+ struct virtio_net_ctrl_cmd *ctrlq_cmd;
+ struct virtio_net_ctrl_status *ctrlq_status;
+ struct virtio_net_ctrl_rx *ctrlq_rx;
+ struct virtio_net_ctrl_mac_tbl *ctrlq_mac_tbl_uc;
+ struct virtio_net_ctrl_mac_tbl *ctrlq_mac_tbl_mc;
+
+ bus_dmamap_t ctrlq_cmd_dmamap;
+ bus_dmamap_t ctrlq_status_dmamap;
+ bus_dmamap_t ctrlq_rx_dmamap;
+ bus_dmamap_t ctrlq_tbl_uc_dmamap;
+ bus_dmamap_t ctrlq_tbl_mc_dmamap;
+};
+
struct vioif_softc {
device_t sc_dev;
@@ -189,55 +250,28 @@ struct vioif_softc {
short sc_deferred_init_done;
bool sc_link_active;
- /* bus_dmamem */
- bus_dma_segment_t sc_hdr_segs[1];
- struct virtio_net_hdr *sc_hdrs;
-#define sc_rx_hdrs sc_hdrs
- struct virtio_net_hdr *sc_tx_hdrs;
- struct virtio_net_ctrl_cmd *sc_ctrl_cmd;
- struct virtio_net_ctrl_status *sc_ctrl_status;
- struct virtio_net_ctrl_rx *sc_ctrl_rx;
- struct virtio_net_ctrl_mac_tbl *sc_ctrl_mac_tbl_uc;
- struct virtio_net_ctrl_mac_tbl *sc_ctrl_mac_tbl_mc;
-
- /* kmem */
- bus_dmamap_t *sc_arrays;
-#define sc_rxhdr_dmamaps sc_arrays
- bus_dmamap_t *sc_txhdr_dmamaps;
- bus_dmamap_t *sc_rx_dmamaps;
- bus_dmamap_t *sc_tx_dmamaps;
- struct mbuf **sc_rx_mbufs;
- struct mbuf **sc_tx_mbufs;
-
- bus_dmamap_t sc_ctrl_cmd_dmamap;
- bus_dmamap_t sc_ctrl_status_dmamap;
- bus_dmamap_t sc_ctrl_rx_dmamap;
- bus_dmamap_t sc_ctrl_tbl_uc_dmamap;
- bus_dmamap_t sc_ctrl_tbl_mc_dmamap;
+ struct vioif_txqueue sc_txq;
+ struct vioif_rxqueue sc_rxq;
- void *sc_rx_softint;
- void *sc_ctl_softint;
+ bool sc_has_ctrl;
+ struct vioif_ctrlqueue sc_ctrlq;
- enum {
- FREE, INUSE, DONE
- } sc_ctrl_inuse;
- kcondvar_t sc_ctrl_wait;
- kmutex_t sc_ctrl_wait_lock;
- kmutex_t sc_tx_lock;
- kmutex_t sc_rx_lock;
- bool sc_stopping;
+ bus_dma_segment_t sc_hdr_segs[1];
+ void *sc_dmamem;
+ void *sc_kmem;
- bool sc_has_ctrl;
+ void *sc_ctl_softint;
};
#define VIRTIO_NET_TX_MAXNSEGS (16) /* XXX */
#define VIRTIO_NET_CTRL_MAC_MAXENTRIES (64) /* XXX */
-#define VIOIF_TX_LOCK(_sc) mutex_enter(&(_sc)->sc_tx_lock)
-#define VIOIF_TX_UNLOCK(_sc) mutex_exit(&(_sc)->sc_tx_lock)
-#define VIOIF_TX_LOCKED(_sc) mutex_owned(&(_sc)->sc_tx_lock)
-#define VIOIF_RX_LOCK(_sc) mutex_enter(&(_sc)->sc_rx_lock)
-#define VIOIF_RX_UNLOCK(_sc) mutex_exit(&(_sc)->sc_rx_lock)
-#define VIOIF_RX_LOCKED(_sc) mutex_owned(&(_sc)->sc_rx_lock)
+#define VIOIF_TXQ_LOCK(_q) mutex_enter((_q)->txq_lock)
+#define VIOIF_TXQ_UNLOCK(_q) mutex_exit((_q)->txq_lock)
+#define VIOIF_TXQ_LOCKED(_q) mutex_owned((_q)->txq_lock)
+
+#define VIOIF_RXQ_LOCK(_q) mutex_enter((_q)->rxq_lock)
+#define VIOIF_RXQ_UNLOCK(_q) mutex_exit((_q)->rxq_lock)
+#define VIOIF_RXQ_LOCKED(_q) mutex_owned((_q)->rxq_lock)
/* cfattach interface functions */
static int vioif_match(device_t, cfdata_t, void *);
@@ -296,39 +330,42 @@ vioif_match(device_t parent, cfdata_t ma
/* allocate memory */
/*
* dma memory is used for:
- * sc_rx_hdrs[slot]: metadata array for received frames (READ)
- * sc_tx_hdrs[slot]: metadata array for frames to be sent (WRITE)
- * sc_ctrl_cmd: command to be sent via ctrl vq (WRITE)
- * sc_ctrl_status: return value for a command via ctrl vq (READ)
- * sc_ctrl_rx: parameter for a VIRTIO_NET_CTRL_RX class command
+ * rxq_hdrs[slot]: metadata array for received frames (READ)
+ * txq_hdrs[slot]: metadata array for frames to be sent (WRITE)
+ * ctrlq_cmd: command to be sent via ctrl vq (WRITE)
+ * ctrlq_status: return value for a command via ctrl vq (READ)
+ * ctrlq_rx: parameter for a VIRTIO_NET_CTRL_RX class command
* (WRITE)
- * sc_ctrl_mac_tbl_uc: unicast MAC address filter for a VIRTIO_NET_CTRL_MAC
+ * ctrlq_mac_tbl_uc: unicast MAC address filter for a VIRTIO_NET_CTRL_MAC
* class command (WRITE)
- * sc_ctrl_mac_tbl_mc: multicast MAC address filter for a VIRTIO_NET_CTRL_MAC
+ * ctrlq_mac_tbl_mc: multicast MAC address filter for a VIRTIO_NET_CTRL_MAC
* class command (WRITE)
- * sc_ctrl_* structures are allocated only one each; they are protected by
- * sc_ctrl_inuse variable and sc_ctrl_wait condvar.
+ * ctrlq_* structures are allocated only one each; they are protected by
+ * ctrlq_inuse variable and ctrlq_wait condvar.
*/
/*
* dynamically allocated memory is used for:
- * sc_rxhdr_dmamaps[slot]: bus_dmamap_t array for sc_rx_hdrs[slot]
- * sc_txhdr_dmamaps[slot]: bus_dmamap_t array for sc_tx_hdrs[slot]
- * sc_rx_dmamaps[slot]: bus_dmamap_t array for received payload
- * sc_tx_dmamaps[slot]: bus_dmamap_t array for sent payload
- * sc_rx_mbufs[slot]: mbuf pointer array for received frames
- * sc_tx_mbufs[slot]: mbuf pointer array for sent frames
+ * rxq_hdr_dmamaps[slot]: bus_dmamap_t array for sc_rx_hdrs[slot]
+ * txq_hdr_dmamaps[slot]: bus_dmamap_t array for sc_tx_hdrs[slot]
+ * rxq_dmamaps[slot]: bus_dmamap_t array for received payload
+ * txq_dmamaps[slot]: bus_dmamap_t array for sent payload
+ * rxq_mbufs[slot]: mbuf pointer array for received frames
+ * txq_mbufs[slot]: mbuf pointer array for sent frames
*/
static int
vioif_alloc_mems(struct vioif_softc *sc)
{
struct virtio_softc *vsc = sc->sc_virtio;
+ struct vioif_txqueue *txq = &sc->sc_txq;
+ struct vioif_rxqueue *rxq = &sc->sc_rxq;
+ struct vioif_ctrlqueue *ctrlq = &sc->sc_ctrlq;
int allocsize, allocsize2, r, rsegs, i;
void *vaddr;
intptr_t p;
int rxqsize, txqsize;
- rxqsize = sc->sc_vq[VQ_RX].vq_num;
- txqsize = sc->sc_vq[VQ_TX].vq_num;
+ rxqsize = rxq->rxq_vq->vq_num;
+ txqsize = txq->txq_vq->vq_num;
allocsize = sizeof(struct virtio_net_hdr) * rxqsize;
allocsize += sizeof(struct virtio_net_hdr) * txqsize;
@@ -361,17 +398,18 @@ vioif_alloc_mems(struct vioif_softc *sc)
#define P(p, p0, p0size) do { p0 = (void *) p; \
p += p0size; } while (0)
memset(vaddr, 0, allocsize);
+ sc->sc_dmamem = vaddr;
p = (intptr_t) vaddr;
- P(p, sc->sc_rx_hdrs, sizeof(sc->sc_rx_hdrs[0]) * rxqsize);
- P(p, sc->sc_tx_hdrs, sizeof(sc->sc_tx_hdrs[0]) * txqsize);
+ P(p, rxq->rxq_hdrs, sizeof(rxq->rxq_hdrs[0]) * rxqsize);
+ P(p, txq->txq_hdrs, sizeof(txq->txq_hdrs[0]) * txqsize);
if (sc->sc_has_ctrl) {
- P(p, sc->sc_ctrl_cmd, sizeof(*sc->sc_ctrl_cmd));
- P(p, sc->sc_ctrl_status, sizeof(*sc->sc_ctrl_status));
- P(p, sc->sc_ctrl_rx, sizeof(*sc->sc_ctrl_rx));
- P(p, sc->sc_ctrl_mac_tbl_uc, sizeof(*sc->sc_ctrl_mac_tbl_uc) + 0);
- P(p, sc->sc_ctrl_mac_tbl_mc,
- (sizeof(*sc->sc_ctrl_mac_tbl_mc)
+ P(p, ctrlq->ctrlq_cmd, sizeof(*ctrlq->ctrlq_cmd));
+ P(p, ctrlq->ctrlq_status, sizeof(*ctrlq->ctrlq_status));
+ P(p, ctrlq->ctrlq_rx, sizeof(*ctrlq->ctrlq_rx));
+ P(p, ctrlq->ctrlq_mac_tbl_uc, sizeof(*ctrlq->ctrlq_mac_tbl_uc) + 0);
+ P(p, ctrlq->ctrlq_mac_tbl_mc,
+ (sizeof(*ctrlq->ctrlq_mac_tbl_mc)
+ ETHER_ADDR_LEN * VIRTIO_NET_CTRL_MAC_MAXENTRIES));
}
@@ -379,14 +417,15 @@ vioif_alloc_mems(struct vioif_softc *sc)
allocsize2 += sizeof(bus_dmamap_t) * (rxqsize + txqsize);
allocsize2 += sizeof(struct mbuf*) * (rxqsize + txqsize);
vaddr = kmem_zalloc(allocsize2, KM_SLEEP);
+ sc->sc_kmem = vaddr;
p = (intptr_t) vaddr;
- P(p, sc->sc_rxhdr_dmamaps, sizeof(sc->sc_rxhdr_dmamaps[0]) * rxqsize);
- P(p, sc->sc_txhdr_dmamaps, sizeof(sc->sc_txhdr_dmamaps[0]) * txqsize);
- P(p, sc->sc_rx_dmamaps, sizeof(sc->sc_rx_dmamaps[0]) * rxqsize);
- P(p, sc->sc_tx_dmamaps, sizeof(sc->sc_tx_dmamaps[0]) * txqsize);
- P(p, sc->sc_rx_mbufs, sizeof(sc->sc_rx_mbufs[0]) * rxqsize);
- P(p, sc->sc_tx_mbufs, sizeof(sc->sc_tx_mbufs[0]) * txqsize);
+ P(p, rxq->rxq_hdr_dmamaps, sizeof(rxq->rxq_hdr_dmamaps[0]) * rxqsize);
+ P(p, txq->txq_hdr_dmamaps, sizeof(txq->txq_hdr_dmamaps[0]) * txqsize);
+ P(p, rxq->rxq_dmamaps, sizeof(rxq->rxq_dmamaps[0]) * rxqsize);
+ P(p, txq->txq_dmamaps, sizeof(txq->txq_dmamaps[0]) * txqsize);
+ P(p, rxq->rxq_mbufs, sizeof(rxq->rxq_mbufs[0]) * rxqsize);
+ P(p, txq->txq_mbufs, sizeof(txq->txq_mbufs[0]) * txqsize);
#undef P
#define C(map, size, nsegs, usage) \
@@ -415,36 +454,40 @@ vioif_alloc_mems(struct vioif_softc *sc)
} \
} while (0)
for (i = 0; i < rxqsize; i++) {
- C_L(sc->sc_rxhdr_dmamaps[i], &sc->sc_rx_hdrs[i], sizeof(sc->sc_rx_hdrs[0]), 1,
+ C_L(rxq->rxq_hdr_dmamaps[i], &rxq->rxq_hdrs[i], sizeof(rxq->rxq_hdrs[0]), 1,
BUS_DMA_READ, "rx header");
- C(sc->sc_rx_dmamaps[i], MCLBYTES, 1, "rx payload");
+ C(rxq->rxq_dmamaps[i], MCLBYTES, 1, "rx payload");
}
for (i = 0; i < txqsize; i++) {
- C_L(sc->sc_txhdr_dmamaps[i], &sc->sc_tx_hdrs[i], sizeof(sc->sc_tx_hdrs[0]), 1,
+ C_L(txq->txq_hdr_dmamaps[i], &txq->txq_hdrs[i], sizeof(txq->txq_hdrs[0]), 1,
BUS_DMA_READ, "tx header");
- C(sc->sc_tx_dmamaps[i], ETHER_MAX_LEN, VIRTIO_NET_TX_MAXNSEGS, "tx payload");
+ C(txq->txq_dmamaps[i], ETHER_MAX_LEN, VIRTIO_NET_TX_MAXNSEGS, "tx payload");
}
if (sc->sc_has_ctrl) {
/* control vq class & command */
- C_L(sc->sc_ctrl_cmd_dmamap, sc->sc_ctrl_cmd, sizeof(*sc->sc_ctrl_cmd), 1,
+ C_L(ctrlq->ctrlq_cmd_dmamap,
+ ctrlq->ctrlq_cmd, sizeof(*ctrlq->ctrlq_cmd), 1,
BUS_DMA_WRITE, "control command");
- C_L(sc->sc_ctrl_status_dmamap, sc->sc_ctrl_status, sizeof(*sc->sc_ctrl_status), 1,
+ C_L(ctrlq->ctrlq_status_dmamap,
+ ctrlq->ctrlq_status, sizeof(*ctrlq->ctrlq_status), 1,
BUS_DMA_READ, "control status");
/* control vq rx mode command parameter */
- C_L(sc->sc_ctrl_rx_dmamap, sc->sc_ctrl_rx, sizeof(*sc->sc_ctrl_rx), 1,
+ C_L(ctrlq->ctrlq_rx_dmamap,
+ ctrlq->ctrlq_rx, sizeof(*ctrlq->ctrlq_rx), 1,
BUS_DMA_WRITE, "rx mode control command");
/* control vq MAC filter table for unicast */
/* do not load now since its length is variable */
- C(sc->sc_ctrl_tbl_uc_dmamap, sizeof(*sc->sc_ctrl_mac_tbl_uc) + 0, 1,
+ C(ctrlq->ctrlq_tbl_uc_dmamap,
+ sizeof(*ctrlq->ctrlq_mac_tbl_uc) + 0, 1,
"unicast MAC address filter command");
/* control vq MAC filter table for multicast */
- C(sc->sc_ctrl_tbl_mc_dmamap,
- sizeof(*sc->sc_ctrl_mac_tbl_mc)
+ C(ctrlq->ctrlq_tbl_mc_dmamap,
+ sizeof(*ctrlq->ctrlq_mac_tbl_mc)
+ ETHER_ADDR_LEN * VIRTIO_NET_CTRL_MAC_MAXENTRIES, 1,
"multicast MAC address filter command");
}
@@ -461,25 +504,25 @@ err_reqs:
map = NULL; \
} \
} while (0)
- D(sc->sc_ctrl_tbl_mc_dmamap);
- D(sc->sc_ctrl_tbl_uc_dmamap);
- D(sc->sc_ctrl_rx_dmamap);
- D(sc->sc_ctrl_status_dmamap);
- D(sc->sc_ctrl_cmd_dmamap);
+ D(ctrlq->ctrlq_tbl_mc_dmamap);
+ D(ctrlq->ctrlq_tbl_uc_dmamap);
+ D(ctrlq->ctrlq_rx_dmamap);
+ D(ctrlq->ctrlq_status_dmamap);
+ D(ctrlq->ctrlq_cmd_dmamap);
for (i = 0; i < txqsize; i++) {
- D(sc->sc_tx_dmamaps[i]);
- D(sc->sc_txhdr_dmamaps[i]);
+ D(txq->txq_dmamaps[i]);
+ D(txq->txq_hdr_dmamaps[i]);
}
for (i = 0; i < rxqsize; i++) {
- D(sc->sc_rx_dmamaps[i]);
- D(sc->sc_rxhdr_dmamaps[i]);
+ D(rxq->rxq_dmamaps[i]);
+ D(rxq->rxq_hdr_dmamaps[i]);
}
#undef D
- if (sc->sc_arrays) {
- kmem_free(sc->sc_arrays, allocsize2);
- sc->sc_arrays = 0;
+ if (sc->sc_kmem) {
+ kmem_free(sc->sc_kmem, allocsize2);
+ sc->sc_kmem = NULL;
}
- bus_dmamem_unmap(virtio_dmat(vsc), sc->sc_hdrs, allocsize);
+ bus_dmamem_unmap(virtio_dmat(vsc), sc->sc_dmamem, allocsize);
err_dmamem_alloc:
bus_dmamem_free(virtio_dmat(vsc), &sc->sc_hdr_segs[0], 1);
err_none:
@@ -491,9 +534,12 @@ vioif_attach(device_t parent, device_t s
{
struct vioif_softc *sc = device_private(self);
struct virtio_softc *vsc = device_private(parent);
+ struct vioif_txqueue *txq = &sc->sc_txq;
+ struct vioif_rxqueue *rxq = &sc->sc_rxq;
+ struct vioif_ctrlqueue *ctrlq = &sc->sc_ctrlq;
uint32_t features;
struct ifnet *ifp = &sc->sc_ethercom.ec_if;
- u_int flags;
+ u_int softint_flags;
int r, nvqs=0, req_flags;
if (virtio_child(vsc) != NULL) {
@@ -567,40 +613,56 @@ vioif_attach(device_t parent, device_t s
aprint_normal_dev(self, "Ethernet address %s\n", ether_sprintf(sc->sc_mac));
- mutex_init(&sc->sc_tx_lock, MUTEX_DEFAULT, IPL_NET);
- mutex_init(&sc->sc_rx_lock, MUTEX_DEFAULT, IPL_NET);
- sc->sc_stopping = false;
+#ifdef VIOIF_MPSAFE
+ softint_flags = SOFTINT_NET | SOFTINT_MPSAFE;
+#else
+ softint_flags = SOFTINT_NET;
+#endif
/*
* Allocating a virtqueue for Rx
*/
- r = virtio_alloc_vq(vsc, &sc->sc_vq[VQ_RX], VQ_RX,
+ rxq->rxq_vq = &sc->sc_vq[VQ_RX];
+ rxq->rxq_lock = mutex_obj_alloc(MUTEX_DEFAULT, IPL_NET);
+
+ rxq->rxq_softint = softint_establish(softint_flags, vioif_rx_softint, sc);
+ if (rxq->rxq_softint == NULL) {
+ aprint_error_dev(self, "cannot establish rx softint\n");
+ goto err;
+ }
+ r = virtio_alloc_vq(vsc, rxq->rxq_vq, VQ_RX,
MCLBYTES+sizeof(struct virtio_net_hdr), 2, "rx");
if (r != 0)
goto err;
nvqs = 1;
- sc->sc_vq[VQ_RX].vq_done = vioif_rx_vq_done;
+ rxq->rxq_vq->vq_done = vioif_rx_vq_done;
+ rxq->rxq_stopping = true;
/*
* Allocating a virtqueue for Tx
*/
- r = virtio_alloc_vq(vsc, &sc->sc_vq[VQ_TX], VQ_TX,
+ txq->txq_vq = &sc->sc_vq[VQ_TX];
+ txq->txq_lock = mutex_obj_alloc(MUTEX_DEFAULT, IPL_NET);
+ r = virtio_alloc_vq(vsc, txq->txq_vq, VQ_TX,
(sizeof(struct virtio_net_hdr) + (ETHER_MAX_LEN - ETHER_HDR_LEN)),
VIRTIO_NET_TX_MAXNSEGS + 1, "tx");
if (r != 0)
goto err;
nvqs = 2;
- sc->sc_vq[VQ_TX].vq_done = vioif_tx_vq_done;
+ txq->txq_vq->vq_done = vioif_tx_vq_done;
+ txq->txq_link_active = sc->sc_link_active;
+ txq->txq_stopping = false;
- virtio_start_vq_intr(vsc, &sc->sc_vq[VQ_RX]);
- virtio_stop_vq_intr(vsc, &sc->sc_vq[VQ_TX]); /* not urgent; do it later */
+ virtio_start_vq_intr(vsc, rxq->rxq_vq);
+ virtio_stop_vq_intr(vsc, txq->txq_vq); /* not urgent; do it later */
+ ctrlq->ctrlq_vq = &sc->sc_vq[VQ_CTRL];
if ((features & VIRTIO_NET_F_CTRL_VQ) &&
(features & VIRTIO_NET_F_CTRL_RX)) {
/*
* Allocating a virtqueue for control channel
*/
- r = virtio_alloc_vq(vsc, &sc->sc_vq[VQ_CTRL], VQ_CTRL,
+ r = virtio_alloc_vq(vsc, ctrlq->ctrlq_vq, VQ_CTRL,
NBPG, 1, "control");
if (r != 0) {
aprint_error_dev(self, "failed to allocate "
@@ -608,28 +670,18 @@ vioif_attach(device_t parent, device_t s
goto skip;
}
- sc->sc_vq[VQ_CTRL].vq_done = vioif_ctrl_vq_done;
- cv_init(&sc->sc_ctrl_wait, "ctrl_vq");
- mutex_init(&sc->sc_ctrl_wait_lock, MUTEX_DEFAULT, IPL_NET);
- sc->sc_ctrl_inuse = FREE;
- virtio_start_vq_intr(vsc, &sc->sc_vq[VQ_CTRL]);
+ ctrlq->ctrlq_vq->vq_done = vioif_ctrl_vq_done;
+ cv_init(&ctrlq->ctrlq_wait, "ctrl_vq");
+ mutex_init(&ctrlq->ctrlq_wait_lock, MUTEX_DEFAULT, IPL_NET);
+ ctrlq->ctrlq_inuse = FREE;
+ virtio_start_vq_intr(vsc, ctrlq->ctrlq_vq);
sc->sc_has_ctrl = true;
nvqs = 3;
}
skip:
-#ifdef VIOIF_MPSAFE
- flags = SOFTINT_NET | SOFTINT_MPSAFE;
-#else
- flags = SOFTINT_NET;
-#endif
- sc->sc_rx_softint = softint_establish(flags, vioif_rx_softint, sc);
- if (sc->sc_rx_softint == NULL) {
- aprint_error_dev(self, "cannot establish rx softint\n");
- goto err;
- }
- sc->sc_ctl_softint = softint_establish(flags, vioif_ctl_softint, sc);
+ sc->sc_ctl_softint = softint_establish(softint_flags, vioif_ctl_softint, sc);
if (sc->sc_ctl_softint == NULL) {
aprint_error_dev(self, "cannot establish ctl softint\n");
goto err;
@@ -650,7 +702,7 @@ skip:
ifp->if_stop = vioif_stop;
ifp->if_capabilities = 0;
ifp->if_watchdog = vioif_watchdog;
- IFQ_SET_MAXLEN(&ifp->if_snd, MAX(sc->sc_vq[VQ_TX].vq_num, IFQ_MAXLEN));
+ IFQ_SET_MAXLEN(&ifp->if_snd, MAX(txq->txq_vq->vq_num, IFQ_MAXLEN));
IFQ_SET_READY(&ifp->if_snd);
sc->sc_ethercom.ec_capabilities |= ETHERCAP_VLAN_MTU;
@@ -662,12 +714,24 @@ skip:
return;
err:
- mutex_destroy(&sc->sc_tx_lock);
- mutex_destroy(&sc->sc_rx_lock);
+ if (rxq->rxq_lock) {
+ mutex_obj_free(rxq->rxq_lock);
+ rxq->rxq_lock = NULL;
+ }
+
+ if (rxq->rxq_softint) {
+ softint_disestablish(rxq->rxq_softint);
+ rxq->rxq_softint = NULL;
+ }
+
+ if (txq->txq_lock) {
+ mutex_obj_free(txq->txq_lock);
+ txq->txq_lock = NULL;
+ }
if (sc->sc_has_ctrl) {
- cv_destroy(&sc->sc_ctrl_wait);
- mutex_destroy(&sc->sc_ctrl_wait_lock);
+ cv_destroy(&ctrlq->ctrlq_wait);
+ mutex_destroy(&ctrlq->ctrlq_wait_lock);
}
while (nvqs > 0)
@@ -702,15 +766,18 @@ vioif_init(struct ifnet *ifp)
{
struct vioif_softc *sc = ifp->if_softc;
struct virtio_softc *vsc = sc->sc_virtio;
+ struct vioif_txqueue *txq = &sc->sc_txq;
+ struct vioif_rxqueue *rxq = &sc->sc_rxq;
+ struct vioif_ctrlqueue *ctrlq = &sc->sc_ctrlq;
vioif_stop(ifp, 0);
virtio_reinit_start(vsc);
virtio_negotiate_features(vsc, virtio_features(vsc));
- virtio_start_vq_intr(vsc, &sc->sc_vq[VQ_RX]);
- virtio_stop_vq_intr(vsc, &sc->sc_vq[VQ_TX]);
+ virtio_start_vq_intr(vsc, rxq->rxq_vq);
+ virtio_stop_vq_intr(vsc, txq->txq_vq);
if (sc->sc_has_ctrl)
- virtio_start_vq_intr(vsc, &sc->sc_vq[VQ_CTRL]);
+ virtio_start_vq_intr(vsc, ctrlq->ctrlq_vq);
virtio_reinit_end(vsc);
if (!sc->sc_deferred_init_done) {
@@ -720,7 +787,8 @@ vioif_init(struct ifnet *ifp)
}
/* Have to set false before vioif_populate_rx_mbufs */
- sc->sc_stopping = false;
+ rxq->rxq_stopping = false;
+ txq->txq_stopping = false;
vioif_populate_rx_mbufs(sc);
@@ -737,19 +805,24 @@ vioif_stop(struct ifnet *ifp, int disabl
{
struct vioif_softc *sc = ifp->if_softc;
struct virtio_softc *vsc = sc->sc_virtio;
+ struct vioif_txqueue *txq = &sc->sc_txq;
+ struct vioif_rxqueue *rxq = &sc->sc_rxq;
+ struct vioif_ctrlqueue *ctrlq = &sc->sc_ctrlq;
/* Take the locks to ensure that ongoing TX/RX finish */
- VIOIF_TX_LOCK(sc);
- VIOIF_RX_LOCK(sc);
- sc->sc_stopping = true;
- VIOIF_RX_UNLOCK(sc);
- VIOIF_TX_UNLOCK(sc);
+ VIOIF_TXQ_LOCK(txq);
+ txq->txq_stopping = true;
+ VIOIF_TXQ_UNLOCK(txq);
+
+ VIOIF_RXQ_LOCK(rxq);
+ rxq->rxq_stopping = true;
+ VIOIF_RXQ_UNLOCK(rxq);
/* disable interrupts */
- virtio_stop_vq_intr(vsc, &sc->sc_vq[VQ_RX]);
- virtio_stop_vq_intr(vsc, &sc->sc_vq[VQ_TX]);
+ virtio_stop_vq_intr(vsc, rxq->rxq_vq);
+ virtio_stop_vq_intr(vsc, txq->txq_vq);
if (sc->sc_has_ctrl)
- virtio_stop_vq_intr(vsc, &sc->sc_vq[VQ_CTRL]);
+ virtio_stop_vq_intr(vsc, ctrlq->ctrlq_vq);
/* only way to stop I/O and DMA is resetting... */
virtio_reset(vsc);
@@ -757,6 +830,7 @@ vioif_stop(struct ifnet *ifp, int disabl
vioif_tx_drain(sc);
ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE);
sc->sc_link_active = false;
+ txq->txq_link_active = false;
if (disable)
vioif_rx_drain(sc);
@@ -767,17 +841,18 @@ vioif_start(struct ifnet *ifp)
{
struct vioif_softc *sc = ifp->if_softc;
struct virtio_softc *vsc = sc->sc_virtio;
- struct virtqueue *vq = &sc->sc_vq[VQ_TX];
+ struct vioif_txqueue *txq = &sc->sc_txq;
+ struct virtqueue *vq = txq->txq_vq;
struct mbuf *m;
int queued = 0;
- VIOIF_TX_LOCK(sc);
+ VIOIF_TXQ_LOCK(txq);
if ((ifp->if_flags & (IFF_RUNNING|IFF_OACTIVE)) != IFF_RUNNING ||
- !sc->sc_link_active)
+ !txq->txq_link_active)
goto out;
- if (sc->sc_stopping)
+ if (txq->txq_stopping)
goto out;
for (;;) {
@@ -797,7 +872,7 @@ vioif_start(struct ifnet *ifp)
panic("enqueue_prep for a tx buffer");
r = bus_dmamap_load_mbuf(virtio_dmat(vsc),
- sc->sc_tx_dmamaps[slot],
+ txq->txq_dmamaps[slot],
m, BUS_DMA_WRITE|BUS_DMA_NOWAIT);
if (r != 0) {
/* maybe just too fragmented */
@@ -812,7 +887,7 @@ vioif_start(struct ifnet *ifp)
m = newm;
r = bus_dmamap_load_mbuf(virtio_dmat(vsc),
- sc->sc_tx_dmamaps[slot],
+ txq->txq_dmamaps[slot],
m, BUS_DMA_WRITE|BUS_DMA_NOWAIT);
if (r != 0) {
aprint_error_dev(sc->sc_dev,
@@ -827,29 +902,29 @@ skip:
/* This should actually never fail */
r = virtio_enqueue_reserve(vsc, vq, slot,
- sc->sc_tx_dmamaps[slot]->dm_nsegs + 1);
+ txq->txq_dmamaps[slot]->dm_nsegs + 1);
if (r != 0) {
aprint_error_dev(sc->sc_dev,
"virtio_enqueue_reserve failed, error code %d\n",
r);
bus_dmamap_unload(virtio_dmat(vsc),
- sc->sc_tx_dmamaps[slot]);
+ txq->txq_dmamaps[slot]);
/* slot already freed by virtio_enqueue_reserve */
m_freem(m);
continue;
}
- sc->sc_tx_mbufs[slot] = m;
+ txq->txq_mbufs[slot] = m;
- memset(&sc->sc_tx_hdrs[slot], 0, sizeof(struct virtio_net_hdr));
- bus_dmamap_sync(virtio_dmat(vsc), sc->sc_tx_dmamaps[slot],
- 0, sc->sc_tx_dmamaps[slot]->dm_mapsize,
+ memset(&txq->txq_hdrs[slot], 0, sizeof(struct virtio_net_hdr));
+ bus_dmamap_sync(virtio_dmat(vsc), txq->txq_dmamaps[slot],
+ 0, txq->txq_dmamaps[slot]->dm_mapsize,
BUS_DMASYNC_PREWRITE);
- bus_dmamap_sync(virtio_dmat(vsc), sc->sc_txhdr_dmamaps[slot],
- 0, sc->sc_txhdr_dmamaps[slot]->dm_mapsize,
+ bus_dmamap_sync(virtio_dmat(vsc), txq->txq_hdr_dmamaps[slot],
+ 0, txq->txq_hdr_dmamaps[slot]->dm_mapsize,
BUS_DMASYNC_PREWRITE);
- virtio_enqueue(vsc, vq, slot, sc->sc_txhdr_dmamaps[slot], true);
- virtio_enqueue(vsc, vq, slot, sc->sc_tx_dmamaps[slot], true);
+ virtio_enqueue(vsc, vq, slot, txq->txq_hdr_dmamaps[slot], true);
+ virtio_enqueue(vsc, vq, slot, txq->txq_dmamaps[slot], true);
virtio_enqueue_commit(vsc, vq, slot, false);
queued++;
@@ -862,7 +937,7 @@ skip:
}
out:
- VIOIF_TX_UNLOCK(sc);
+ VIOIF_TXQ_UNLOCK(txq);
}
static int
@@ -890,9 +965,10 @@ void
vioif_watchdog(struct ifnet *ifp)
{
struct vioif_softc *sc = ifp->if_softc;
+ struct vioif_txqueue *txq = &sc->sc_txq;
if (ifp->if_flags & IFF_RUNNING)
- vioif_tx_vq_done(&sc->sc_vq[VQ_TX]);
+ vioif_tx_vq_done(txq->txq_vq);
}
@@ -903,6 +979,7 @@ vioif_watchdog(struct ifnet *ifp)
static int
vioif_add_rx_mbuf(struct vioif_softc *sc, int i)
{
+ struct vioif_rxqueue *rxq = &sc->sc_rxq;
struct mbuf *m;
int r;
@@ -914,14 +991,14 @@ vioif_add_rx_mbuf(struct vioif_softc *sc
m_freem(m);
return ENOBUFS;
}
- sc->sc_rx_mbufs[i] = m;
+ rxq->rxq_mbufs[i] = m;
m->m_len = m->m_pkthdr.len = m->m_ext.ext_size;
r = bus_dmamap_load_mbuf(virtio_dmat(sc->sc_virtio),
- sc->sc_rx_dmamaps[i],
+ rxq->rxq_dmamaps[i],
m, BUS_DMA_READ|BUS_DMA_NOWAIT);
if (r) {
m_freem(m);
- sc->sc_rx_mbufs[i] = 0;
+ rxq->rxq_mbufs[i] = 0;
return r;
}
@@ -932,30 +1009,35 @@ vioif_add_rx_mbuf(struct vioif_softc *sc
static void
vioif_free_rx_mbuf(struct vioif_softc *sc, int i)
{
- bus_dmamap_unload(virtio_dmat(sc->sc_virtio), sc->sc_rx_dmamaps[i]);
- m_freem(sc->sc_rx_mbufs[i]);
- sc->sc_rx_mbufs[i] = NULL;
+ struct vioif_rxqueue *rxq = &sc->sc_rxq;
+
+ bus_dmamap_unload(virtio_dmat(sc->sc_virtio), rxq->rxq_dmamaps[i]);
+ m_freem(rxq->rxq_mbufs[i]);
+ rxq->rxq_mbufs[i] = NULL;
}
/* add mbufs for all the empty receive slots */
static void
vioif_populate_rx_mbufs(struct vioif_softc *sc)
{
- VIOIF_RX_LOCK(sc);
+ struct vioif_rxqueue *rxq = &sc->sc_rxq;
+
+ VIOIF_RXQ_LOCK(rxq);
vioif_populate_rx_mbufs_locked(sc);
- VIOIF_RX_UNLOCK(sc);
+ VIOIF_RXQ_UNLOCK(rxq);
}
static void
vioif_populate_rx_mbufs_locked(struct vioif_softc *sc)
{
struct virtio_softc *vsc = sc->sc_virtio;
+ struct vioif_rxqueue *rxq = &sc->sc_rxq;
int i, r, ndone = 0;
- struct virtqueue *vq = &sc->sc_vq[VQ_RX];
+ struct virtqueue *vq = rxq->rxq_vq;
- KASSERT(VIOIF_RX_LOCKED(sc));
+ KASSERT(VIOIF_RXQ_LOCKED(rxq));
- if (sc->sc_stopping)
+ if (rxq->rxq_stopping)
return;
for (i = 0; i < vq->vq_num; i++) {
@@ -965,7 +1047,7 @@ vioif_populate_rx_mbufs_locked(struct vi
break;
if (r != 0)
panic("enqueue_prep for rx buffers");
- if (sc->sc_rx_mbufs[slot] == NULL) {
+ if (rxq->rxq_mbufs[slot] == NULL) {
r = vioif_add_rx_mbuf(sc, slot);
if (r != 0) {
printf("%s: rx mbuf allocation failed, "
@@ -975,17 +1057,17 @@ vioif_populate_rx_mbufs_locked(struct vi
}
}
r = virtio_enqueue_reserve(vsc, vq, slot,
- sc->sc_rx_dmamaps[slot]->dm_nsegs + 1);
+ rxq->rxq_dmamaps[slot]->dm_nsegs + 1);
if (r != 0) {
vioif_free_rx_mbuf(sc, slot);
break;
}
- bus_dmamap_sync(virtio_dmat(vsc), sc->sc_rxhdr_dmamaps[slot],
+ bus_dmamap_sync(virtio_dmat(vsc), rxq->rxq_hdr_dmamaps[slot],
0, sizeof(struct virtio_net_hdr), BUS_DMASYNC_PREREAD);
- bus_dmamap_sync(virtio_dmat(vsc), sc->sc_rx_dmamaps[slot],
+ bus_dmamap_sync(virtio_dmat(vsc), rxq->rxq_dmamaps[slot],
0, MCLBYTES, BUS_DMASYNC_PREREAD);
- virtio_enqueue(vsc, vq, slot, sc->sc_rxhdr_dmamaps[slot], false);
- virtio_enqueue(vsc, vq, slot, sc->sc_rx_dmamaps[slot], false);
+ virtio_enqueue(vsc, vq, slot, rxq->rxq_hdr_dmamaps[slot], false);
+ virtio_enqueue(vsc, vq, slot, rxq->rxq_dmamaps[slot], false);
virtio_enqueue_commit(vsc, vq, slot, false);
ndone++;
}
@@ -997,13 +1079,14 @@ vioif_populate_rx_mbufs_locked(struct vi
static int
vioif_rx_deq(struct vioif_softc *sc)
{
+ struct vioif_rxqueue *rxq = &sc->sc_rxq;
int r;
- KASSERT(sc->sc_stopping);
+ KASSERT(rxq->rxq_stopping);
- VIOIF_RX_LOCK(sc);
+ VIOIF_RXQ_LOCK(rxq);
r = vioif_rx_deq_locked(sc);
- VIOIF_RX_UNLOCK(sc);
+ VIOIF_RXQ_UNLOCK(rxq);
return r;
}
@@ -1013,36 +1096,37 @@ static int
vioif_rx_deq_locked(struct vioif_softc *sc)
{
struct virtio_softc *vsc = sc->sc_virtio;
- struct virtqueue *vq = &sc->sc_vq[VQ_RX];
+ struct vioif_rxqueue *rxq = &sc->sc_rxq;
+ struct virtqueue *vq = rxq->rxq_vq;
struct ifnet *ifp = &sc->sc_ethercom.ec_if;
struct mbuf *m;
int r = 0;
int slot, len;
- KASSERT(VIOIF_RX_LOCKED(sc));
+ KASSERT(VIOIF_RXQ_LOCKED(rxq));
while (virtio_dequeue(vsc, vq, &slot, &len) == 0) {
len -= sizeof(struct virtio_net_hdr);
r = 1;
- bus_dmamap_sync(virtio_dmat(vsc), sc->sc_rxhdr_dmamaps[slot],
+ bus_dmamap_sync(virtio_dmat(vsc), rxq->rxq_hdr_dmamaps[slot],
0, sizeof(struct virtio_net_hdr),
BUS_DMASYNC_POSTREAD);
- bus_dmamap_sync(virtio_dmat(vsc), sc->sc_rx_dmamaps[slot],
+ bus_dmamap_sync(virtio_dmat(vsc), rxq->rxq_dmamaps[slot],
0, MCLBYTES,
BUS_DMASYNC_POSTREAD);
- m = sc->sc_rx_mbufs[slot];
+ m = rxq->rxq_mbufs[slot];
KASSERT(m != NULL);
- bus_dmamap_unload(virtio_dmat(vsc), sc->sc_rx_dmamaps[slot]);
- sc->sc_rx_mbufs[slot] = 0;
+ bus_dmamap_unload(virtio_dmat(vsc), rxq->rxq_dmamaps[slot]);
+ rxq->rxq_mbufs[slot] = 0;
virtio_dequeue_commit(vsc, vq, slot);
m_set_rcvif(m, ifp);
m->m_len = m->m_pkthdr.len = len;
- VIOIF_RX_UNLOCK(sc);
+ VIOIF_RXQ_UNLOCK(rxq);
if_percpuq_enqueue(ifp->if_percpuq, m);
- VIOIF_RX_LOCK(sc);
+ VIOIF_RXQ_LOCK(rxq);
- if (sc->sc_stopping)
+ if (rxq->rxq_stopping)
break;
}
@@ -1055,15 +1139,16 @@ vioif_rx_vq_done(struct virtqueue *vq)
{
struct virtio_softc *vsc = vq->vq_owner;
struct vioif_softc *sc = device_private(virtio_child(vsc));
+ struct vioif_rxqueue *rxq = &sc->sc_rxq;
int r = 0;
#ifdef VIOIF_SOFTINT_INTR
KASSERT(!cpu_intr_p());
#endif
- VIOIF_RX_LOCK(sc);
+ VIOIF_RXQ_LOCK(rxq);
- if (sc->sc_stopping)
+ if (rxq->rxq_stopping)
goto out;
r = vioif_rx_deq_locked(sc);
@@ -1071,11 +1156,11 @@ vioif_rx_vq_done(struct virtqueue *vq)
#ifdef VIOIF_SOFTINT_INTR
vioif_populate_rx_mbufs_locked(sc);
#else
- softint_schedule(sc->sc_rx_softint);
+ softint_schedule(rxq->rxq_softint);
#endif
out:
- VIOIF_RX_UNLOCK(sc);
+ VIOIF_RXQ_UNLOCK(rxq);
return r;
}
@@ -1092,11 +1177,12 @@ vioif_rx_softint(void *arg)
static void
vioif_rx_drain(struct vioif_softc *sc)
{
- struct virtqueue *vq = &sc->sc_vq[VQ_RX];
+ struct vioif_rxqueue *rxq = &sc->sc_rxq;
+ struct virtqueue *vq = rxq->rxq_vq;
int i;
for (i = 0; i < vq->vq_num; i++) {
- if (sc->sc_rx_mbufs[i] == NULL)
+ if (rxq->rxq_mbufs[i] == NULL)
continue;
vioif_free_rx_mbuf(sc, i);
}
@@ -1118,17 +1204,18 @@ vioif_tx_vq_done(struct virtqueue *vq)
struct virtio_softc *vsc = vq->vq_owner;
struct vioif_softc *sc = device_private(virtio_child(vsc));
struct ifnet *ifp = &sc->sc_ethercom.ec_if;
+ struct vioif_txqueue *txq = &sc->sc_txq;
int r = 0;
- VIOIF_TX_LOCK(sc);
+ VIOIF_TXQ_LOCK(txq);
- if (sc->sc_stopping)
+ if (txq->txq_stopping)
goto out;
r = vioif_tx_vq_done_locked(vq);
out:
- VIOIF_TX_UNLOCK(sc);
+ VIOIF_TXQ_UNLOCK(txq);
if (r)
if_schedule_deferred_start(ifp);
return r;
@@ -1139,24 +1226,25 @@ vioif_tx_vq_done_locked(struct virtqueue
{
struct virtio_softc *vsc = vq->vq_owner;
struct vioif_softc *sc = device_private(virtio_child(vsc));
+ struct vioif_txqueue *txq = &sc->sc_txq;
struct ifnet *ifp = &sc->sc_ethercom.ec_if;
struct mbuf *m;
int r = 0;
int slot, len;
- KASSERT(VIOIF_TX_LOCKED(sc));
+ KASSERT(VIOIF_TXQ_LOCKED(txq));
while (virtio_dequeue(vsc, vq, &slot, &len) == 0) {
r++;
- bus_dmamap_sync(virtio_dmat(vsc), sc->sc_txhdr_dmamaps[slot],
+ bus_dmamap_sync(virtio_dmat(vsc), txq->txq_hdr_dmamaps[slot],
0, sizeof(struct virtio_net_hdr),
BUS_DMASYNC_POSTWRITE);
- bus_dmamap_sync(virtio_dmat(vsc), sc->sc_tx_dmamaps[slot],
- 0, sc->sc_tx_dmamaps[slot]->dm_mapsize,
+ bus_dmamap_sync(virtio_dmat(vsc), txq->txq_dmamaps[slot],
+ 0, txq->txq_dmamaps[slot]->dm_mapsize,
BUS_DMASYNC_POSTWRITE);
- m = sc->sc_tx_mbufs[slot];
- bus_dmamap_unload(virtio_dmat(vsc), sc->sc_tx_dmamaps[slot]);
- sc->sc_tx_mbufs[slot] = 0;
+ m = txq->txq_mbufs[slot];
+ bus_dmamap_unload(virtio_dmat(vsc), txq->txq_dmamaps[slot]);
+ txq->txq_mbufs[slot] = 0;
virtio_dequeue_commit(vsc, vq, slot);
ifp->if_opackets++;
m_freem(m);
@@ -1172,17 +1260,18 @@ static void
vioif_tx_drain(struct vioif_softc *sc)
{
struct virtio_softc *vsc = sc->sc_virtio;
- struct virtqueue *vq = &sc->sc_vq[VQ_TX];
+ struct vioif_txqueue *txq = &sc->sc_txq;
+ struct virtqueue *vq = txq->txq_vq;
int i;
- KASSERT(sc->sc_stopping);
+ KASSERT(txq->txq_stopping);
for (i = 0; i < vq->vq_num; i++) {
- if (sc->sc_tx_mbufs[i] == NULL)
+ if (txq->txq_mbufs[i] == NULL)
continue;
- bus_dmamap_unload(virtio_dmat(vsc), sc->sc_tx_dmamaps[i]);
- m_freem(sc->sc_tx_mbufs[i]);
- sc->sc_tx_mbufs[i] = NULL;
+ bus_dmamap_unload(virtio_dmat(vsc), txq->txq_dmamaps[i]);
+ m_freem(txq->txq_mbufs[i]);
+ txq->txq_mbufs[i] = NULL;
}
}
@@ -1194,29 +1283,30 @@ static int
vioif_ctrl_rx(struct vioif_softc *sc, int cmd, bool onoff)
{
struct virtio_softc *vsc = sc->sc_virtio;
- struct virtqueue *vq = &sc->sc_vq[VQ_CTRL];
+ struct vioif_ctrlqueue *ctrlq = &sc->sc_ctrlq;
+ struct virtqueue *vq = ctrlq->ctrlq_vq;
int r, slot;
if (!sc->sc_has_ctrl)
return ENOTSUP;
- mutex_enter(&sc->sc_ctrl_wait_lock);
- while (sc->sc_ctrl_inuse != FREE)
- cv_wait(&sc->sc_ctrl_wait, &sc->sc_ctrl_wait_lock);
- sc->sc_ctrl_inuse = INUSE;
- mutex_exit(&sc->sc_ctrl_wait_lock);
-
- sc->sc_ctrl_cmd->class = VIRTIO_NET_CTRL_RX;
- sc->sc_ctrl_cmd->command = cmd;
- sc->sc_ctrl_rx->onoff = onoff;
+ mutex_enter(&ctrlq->ctrlq_wait_lock);
+ while (ctrlq->ctrlq_inuse != FREE)
+ cv_wait(&ctrlq->ctrlq_wait, &ctrlq->ctrlq_wait_lock);
+ ctrlq->ctrlq_inuse = INUSE;
+ mutex_exit(&ctrlq->ctrlq_wait_lock);
+
+ ctrlq->ctrlq_cmd->class = VIRTIO_NET_CTRL_RX;
+ ctrlq->ctrlq_cmd->command = cmd;
+ ctrlq->ctrlq_rx->onoff = onoff;
- bus_dmamap_sync(virtio_dmat(vsc), sc->sc_ctrl_cmd_dmamap,
+ bus_dmamap_sync(virtio_dmat(vsc), ctrlq->ctrlq_cmd_dmamap,
0, sizeof(struct virtio_net_ctrl_cmd),
BUS_DMASYNC_PREWRITE);
- bus_dmamap_sync(virtio_dmat(vsc), sc->sc_ctrl_rx_dmamap,
+ bus_dmamap_sync(virtio_dmat(vsc), ctrlq->ctrlq_rx_dmamap,
0, sizeof(struct virtio_net_ctrl_rx),
BUS_DMASYNC_PREWRITE);
- bus_dmamap_sync(virtio_dmat(vsc), sc->sc_ctrl_status_dmamap,
+ bus_dmamap_sync(virtio_dmat(vsc), ctrlq->ctrlq_status_dmamap,
0, sizeof(struct virtio_net_ctrl_status),
BUS_DMASYNC_PREREAD);
@@ -1226,29 +1316,29 @@ vioif_ctrl_rx(struct vioif_softc *sc, in
r = virtio_enqueue_reserve(vsc, vq, slot, 3);
if (r != 0)
panic("%s: control vq busy!?", device_xname(sc->sc_dev));
- virtio_enqueue(vsc, vq, slot, sc->sc_ctrl_cmd_dmamap, true);
- virtio_enqueue(vsc, vq, slot, sc->sc_ctrl_rx_dmamap, true);
- virtio_enqueue(vsc, vq, slot, sc->sc_ctrl_status_dmamap, false);
+ virtio_enqueue(vsc, vq, slot, ctrlq->ctrlq_cmd_dmamap, true);
+ virtio_enqueue(vsc, vq, slot, ctrlq->ctrlq_rx_dmamap, true);
+ virtio_enqueue(vsc, vq, slot, ctrlq->ctrlq_status_dmamap, false);
virtio_enqueue_commit(vsc, vq, slot, true);
/* wait for done */
- mutex_enter(&sc->sc_ctrl_wait_lock);
- while (sc->sc_ctrl_inuse != DONE)
- cv_wait(&sc->sc_ctrl_wait, &sc->sc_ctrl_wait_lock);
- mutex_exit(&sc->sc_ctrl_wait_lock);
+ mutex_enter(&ctrlq->ctrlq_wait_lock);
+ while (ctrlq->ctrlq_inuse != DONE)
+ cv_wait(&ctrlq->ctrlq_wait, &ctrlq->ctrlq_wait_lock);
+ mutex_exit(&ctrlq->ctrlq_wait_lock);
/* already dequeueued */
- bus_dmamap_sync(virtio_dmat(vsc), sc->sc_ctrl_cmd_dmamap, 0,
+ bus_dmamap_sync(virtio_dmat(vsc), ctrlq->ctrlq_cmd_dmamap, 0,
sizeof(struct virtio_net_ctrl_cmd),
BUS_DMASYNC_POSTWRITE);
- bus_dmamap_sync(virtio_dmat(vsc), sc->sc_ctrl_rx_dmamap, 0,
+ bus_dmamap_sync(virtio_dmat(vsc), ctrlq->ctrlq_rx_dmamap, 0,
sizeof(struct virtio_net_ctrl_rx),
BUS_DMASYNC_POSTWRITE);
- bus_dmamap_sync(virtio_dmat(vsc), sc->sc_ctrl_status_dmamap, 0,
+ bus_dmamap_sync(virtio_dmat(vsc), ctrlq->ctrlq_status_dmamap, 0,
sizeof(struct virtio_net_ctrl_status),
BUS_DMASYNC_POSTREAD);
- if (sc->sc_ctrl_status->ack == VIRTIO_NET_OK)
+ if (ctrlq->ctrlq_status->ack == VIRTIO_NET_OK)
r = 0;
else {
printf("%s: failed setting rx mode\n",
@@ -1256,10 +1346,10 @@ vioif_ctrl_rx(struct vioif_softc *sc, in
r = EIO;
}
- mutex_enter(&sc->sc_ctrl_wait_lock);
- sc->sc_ctrl_inuse = FREE;
- cv_signal(&sc->sc_ctrl_wait);
- mutex_exit(&sc->sc_ctrl_wait_lock);
+ mutex_enter(&ctrlq->ctrlq_wait_lock);
+ ctrlq->ctrlq_inuse = FREE;
+ cv_signal(&ctrlq->ctrlq_wait);
+ mutex_exit(&ctrlq->ctrlq_wait_lock);
return r;
}
@@ -1288,57 +1378,58 @@ vioif_set_allmulti(struct vioif_softc *s
static int
vioif_set_rx_filter(struct vioif_softc *sc)
{
- /* filter already set in sc_ctrl_mac_tbl */
+ /* filter already set in ctrlq->ctrlq_mac_tbl */
struct virtio_softc *vsc = sc->sc_virtio;
- struct virtqueue *vq = &sc->sc_vq[VQ_CTRL];
+ struct vioif_ctrlqueue *ctrlq = &sc->sc_ctrlq;
+ struct virtqueue *vq = ctrlq->ctrlq_vq;
int r, slot;
if (!sc->sc_has_ctrl)
return ENOTSUP;
- mutex_enter(&sc->sc_ctrl_wait_lock);
- while (sc->sc_ctrl_inuse != FREE)
- cv_wait(&sc->sc_ctrl_wait, &sc->sc_ctrl_wait_lock);
- sc->sc_ctrl_inuse = INUSE;
- mutex_exit(&sc->sc_ctrl_wait_lock);
+ mutex_enter(&ctrlq->ctrlq_wait_lock);
+ while (ctrlq->ctrlq_inuse != FREE)
+ cv_wait(&ctrlq->ctrlq_wait, &ctrlq->ctrlq_wait_lock);
+ ctrlq->ctrlq_inuse = INUSE;
+ mutex_exit(&ctrlq->ctrlq_wait_lock);
- sc->sc_ctrl_cmd->class = VIRTIO_NET_CTRL_MAC;
- sc->sc_ctrl_cmd->command = VIRTIO_NET_CTRL_MAC_TABLE_SET;
+ ctrlq->ctrlq_cmd->class = VIRTIO_NET_CTRL_MAC;
+ ctrlq->ctrlq_cmd->command = VIRTIO_NET_CTRL_MAC_TABLE_SET;
- r = bus_dmamap_load(virtio_dmat(vsc), sc->sc_ctrl_tbl_uc_dmamap,
- sc->sc_ctrl_mac_tbl_uc,
+ r = bus_dmamap_load(virtio_dmat(vsc), ctrlq->ctrlq_tbl_uc_dmamap,
+ ctrlq->ctrlq_mac_tbl_uc,
(sizeof(struct virtio_net_ctrl_mac_tbl)
- + ETHER_ADDR_LEN * sc->sc_ctrl_mac_tbl_uc->nentries),
+ + ETHER_ADDR_LEN * ctrlq->ctrlq_mac_tbl_uc->nentries),
NULL, BUS_DMA_WRITE|BUS_DMA_NOWAIT);
if (r) {
printf("%s: control command dmamap load failed, "
"error code %d\n", device_xname(sc->sc_dev), r);
goto out;
}
- r = bus_dmamap_load(virtio_dmat(vsc), sc->sc_ctrl_tbl_mc_dmamap,
- sc->sc_ctrl_mac_tbl_mc,
+ r = bus_dmamap_load(virtio_dmat(vsc), ctrlq->ctrlq_tbl_mc_dmamap,
+ ctrlq->ctrlq_mac_tbl_mc,
(sizeof(struct virtio_net_ctrl_mac_tbl)
- + ETHER_ADDR_LEN * sc->sc_ctrl_mac_tbl_mc->nentries),
+ + ETHER_ADDR_LEN * ctrlq->ctrlq_mac_tbl_mc->nentries),
NULL, BUS_DMA_WRITE|BUS_DMA_NOWAIT);
if (r) {
printf("%s: control command dmamap load failed, "
"error code %d\n", device_xname(sc->sc_dev), r);
- bus_dmamap_unload(virtio_dmat(vsc), sc->sc_ctrl_tbl_uc_dmamap);
+ bus_dmamap_unload(virtio_dmat(vsc), ctrlq->ctrlq_tbl_uc_dmamap);
goto out;
}
- bus_dmamap_sync(virtio_dmat(vsc), sc->sc_ctrl_cmd_dmamap,
+ bus_dmamap_sync(virtio_dmat(vsc), ctrlq->ctrlq_cmd_dmamap,
0, sizeof(struct virtio_net_ctrl_cmd),
BUS_DMASYNC_PREWRITE);
- bus_dmamap_sync(virtio_dmat(vsc), sc->sc_ctrl_tbl_uc_dmamap, 0,
+ bus_dmamap_sync(virtio_dmat(vsc), ctrlq->ctrlq_tbl_uc_dmamap, 0,
(sizeof(struct virtio_net_ctrl_mac_tbl)
- + ETHER_ADDR_LEN * sc->sc_ctrl_mac_tbl_uc->nentries),
+ + ETHER_ADDR_LEN * ctrlq->ctrlq_mac_tbl_uc->nentries),
BUS_DMASYNC_PREWRITE);
- bus_dmamap_sync(virtio_dmat(vsc), sc->sc_ctrl_tbl_mc_dmamap, 0,
+ bus_dmamap_sync(virtio_dmat(vsc), ctrlq->ctrlq_tbl_mc_dmamap, 0,
(sizeof(struct virtio_net_ctrl_mac_tbl)
- + ETHER_ADDR_LEN * sc->sc_ctrl_mac_tbl_mc->nentries),
+ + ETHER_ADDR_LEN * ctrlq->ctrlq_mac_tbl_mc->nentries),
BUS_DMASYNC_PREWRITE);
- bus_dmamap_sync(virtio_dmat(vsc), sc->sc_ctrl_status_dmamap,
+ bus_dmamap_sync(virtio_dmat(vsc), ctrlq->ctrlq_status_dmamap,
0, sizeof(struct virtio_net_ctrl_status),
BUS_DMASYNC_PREREAD);
@@ -1348,37 +1439,37 @@ vioif_set_rx_filter(struct vioif_softc *
r = virtio_enqueue_reserve(vsc, vq, slot, 4);
if (r != 0)
panic("%s: control vq busy!?", device_xname(sc->sc_dev));
- virtio_enqueue(vsc, vq, slot, sc->sc_ctrl_cmd_dmamap, true);
- virtio_enqueue(vsc, vq, slot, sc->sc_ctrl_tbl_uc_dmamap, true);
- virtio_enqueue(vsc, vq, slot, sc->sc_ctrl_tbl_mc_dmamap, true);
- virtio_enqueue(vsc, vq, slot, sc->sc_ctrl_status_dmamap, false);
+ virtio_enqueue(vsc, vq, slot, ctrlq->ctrlq_cmd_dmamap, true);
+ virtio_enqueue(vsc, vq, slot, ctrlq->ctrlq_tbl_uc_dmamap, true);
+ virtio_enqueue(vsc, vq, slot, ctrlq->ctrlq_tbl_mc_dmamap, true);
+ virtio_enqueue(vsc, vq, slot, ctrlq->ctrlq_status_dmamap, false);
virtio_enqueue_commit(vsc, vq, slot, true);
/* wait for done */
- mutex_enter(&sc->sc_ctrl_wait_lock);
- while (sc->sc_ctrl_inuse != DONE)
- cv_wait(&sc->sc_ctrl_wait, &sc->sc_ctrl_wait_lock);
- mutex_exit(&sc->sc_ctrl_wait_lock);
+ mutex_enter(&ctrlq->ctrlq_wait_lock);
+ while (ctrlq->ctrlq_inuse != DONE)
+ cv_wait(&ctrlq->ctrlq_wait, &ctrlq->ctrlq_wait_lock);
+ mutex_exit(&ctrlq->ctrlq_wait_lock);
/* already dequeueued */
- bus_dmamap_sync(virtio_dmat(vsc), sc->sc_ctrl_cmd_dmamap, 0,
+ bus_dmamap_sync(virtio_dmat(vsc), ctrlq->ctrlq_cmd_dmamap, 0,
sizeof(struct virtio_net_ctrl_cmd),
BUS_DMASYNC_POSTWRITE);
- bus_dmamap_sync(virtio_dmat(vsc), sc->sc_ctrl_tbl_uc_dmamap, 0,
+ bus_dmamap_sync(virtio_dmat(vsc), ctrlq->ctrlq_tbl_uc_dmamap, 0,
(sizeof(struct virtio_net_ctrl_mac_tbl)
- + ETHER_ADDR_LEN * sc->sc_ctrl_mac_tbl_uc->nentries),
+ + ETHER_ADDR_LEN * ctrlq->ctrlq_mac_tbl_uc->nentries),
BUS_DMASYNC_POSTWRITE);
- bus_dmamap_sync(virtio_dmat(vsc), sc->sc_ctrl_tbl_mc_dmamap, 0,
+ bus_dmamap_sync(virtio_dmat(vsc), ctrlq->ctrlq_tbl_mc_dmamap, 0,
(sizeof(struct virtio_net_ctrl_mac_tbl)
- + ETHER_ADDR_LEN * sc->sc_ctrl_mac_tbl_mc->nentries),
+ + ETHER_ADDR_LEN * ctrlq->ctrlq_mac_tbl_mc->nentries),
BUS_DMASYNC_POSTWRITE);
- bus_dmamap_sync(virtio_dmat(vsc), sc->sc_ctrl_status_dmamap, 0,
+ bus_dmamap_sync(virtio_dmat(vsc), ctrlq->ctrlq_status_dmamap, 0,
sizeof(struct virtio_net_ctrl_status),
BUS_DMASYNC_POSTREAD);
- bus_dmamap_unload(virtio_dmat(vsc), sc->sc_ctrl_tbl_uc_dmamap);
- bus_dmamap_unload(virtio_dmat(vsc), sc->sc_ctrl_tbl_mc_dmamap);
+ bus_dmamap_unload(virtio_dmat(vsc), ctrlq->ctrlq_tbl_uc_dmamap);
+ bus_dmamap_unload(virtio_dmat(vsc), ctrlq->ctrlq_tbl_mc_dmamap);
- if (sc->sc_ctrl_status->ack == VIRTIO_NET_OK)
+ if (ctrlq->ctrlq_status->ack == VIRTIO_NET_OK)
r = 0;
else {
printf("%s: failed setting rx filter\n",
@@ -1387,10 +1478,10 @@ vioif_set_rx_filter(struct vioif_softc *
}
out:
- mutex_enter(&sc->sc_ctrl_wait_lock);
- sc->sc_ctrl_inuse = FREE;
- cv_signal(&sc->sc_ctrl_wait);
- mutex_exit(&sc->sc_ctrl_wait_lock);
+ mutex_enter(&ctrlq->ctrlq_wait_lock);
+ ctrlq->ctrlq_inuse = FREE;
+ cv_signal(&ctrlq->ctrlq_wait);
+ mutex_exit(&ctrlq->ctrlq_wait_lock);
return r;
}
@@ -1401,6 +1492,7 @@ vioif_ctrl_vq_done(struct virtqueue *vq)
{
struct virtio_softc *vsc = vq->vq_owner;
struct vioif_softc *sc = device_private(virtio_child(vsc));
+ struct vioif_ctrlqueue *ctrlq = &sc->sc_ctrlq;
int r, slot;
r = virtio_dequeue(vsc, vq, &slot, NULL);
@@ -1408,10 +1500,10 @@ vioif_ctrl_vq_done(struct virtqueue *vq)
return 0;
virtio_dequeue_commit(vsc, vq, slot);
- mutex_enter(&sc->sc_ctrl_wait_lock);
- sc->sc_ctrl_inuse = DONE;
- cv_signal(&sc->sc_ctrl_wait);
- mutex_exit(&sc->sc_ctrl_wait_lock);
+ mutex_enter(&ctrlq->ctrlq_wait_lock);
+ ctrlq->ctrlq_inuse = DONE;
+ cv_signal(&ctrlq->ctrlq_wait);
+ mutex_exit(&ctrlq->ctrlq_wait_lock);
return 1;
}
@@ -1431,6 +1523,7 @@ vioif_rx_filter(struct vioif_softc *sc)
struct ifnet *ifp = &sc->sc_ethercom.ec_if;
struct ether_multi *enm;
struct ether_multistep step;
+ struct vioif_ctrlqueue *ctrlq = &sc->sc_ctrlq;
int nentries;
int promisc = 0, allmulti = 0, rxfilter = 0;
int r;
@@ -1458,7 +1551,7 @@ vioif_rx_filter(struct vioif_softc *sc)
allmulti = 1;
goto set_unlock;
}
- memcpy(sc->sc_ctrl_mac_tbl_mc->macs[nentries],
+ memcpy(ctrlq->ctrlq_mac_tbl_mc->macs[nentries],
enm->enm_addrlo, ETHER_ADDR_LEN);
ETHER_NEXT_MULTI(step, enm);
}
@@ -1469,8 +1562,8 @@ set_unlock:
set:
if (rxfilter) {
- sc->sc_ctrl_mac_tbl_uc->nentries = 0;
- sc->sc_ctrl_mac_tbl_mc->nentries = nentries;
+ ctrlq->ctrlq_mac_tbl_uc->nentries = 0;
+ ctrlq->ctrlq_mac_tbl_mc->nentries = nentries;
r = vioif_set_rx_filter(sc);
if (r != 0) {
rxfilter = 0;
@@ -1478,8 +1571,8 @@ set:
}
} else {
/* remove rx filter */
- sc->sc_ctrl_mac_tbl_uc->nentries = 0;
- sc->sc_ctrl_mac_tbl_mc->nentries = 0;
+ ctrlq->ctrlq_mac_tbl_uc->nentries = 0;
+ ctrlq->ctrlq_mac_tbl_mc->nentries = 0;
r = vioif_set_rx_filter(sc);
/* what to do on failure? */
}
@@ -1522,13 +1615,13 @@ static void
vioif_update_link_status(struct vioif_softc *sc)
{
struct ifnet *ifp = &sc->sc_ethercom.ec_if;
+ struct vioif_txqueue *txq = &sc->sc_txq;
bool active, changed;
int link;
active = vioif_is_link_up(sc);
changed = false;
- VIOIF_TX_LOCK(sc);
if (active) {
if (!sc->sc_link_active)
changed = true;
@@ -1542,10 +1635,14 @@ vioif_update_link_status(struct vioif_so
link = LINK_STATE_DOWN;
sc->sc_link_active = false;
}
- VIOIF_TX_UNLOCK(sc);
- if (changed)
+ if (changed) {
+ VIOIF_TXQ_LOCK(txq);
+ txq->txq_link_active = sc->sc_link_active;
+ VIOIF_TXQ_UNLOCK(txq);
+
if_link_state_change(ifp, link);
+ }
}
static int