Module Name: src
Committed By: yamaguchi
Date: Thu Mar 23 02:42:49 UTC 2023
Modified Files:
src/sys/dev/pci: if_vioif.c
Log Message:
vioif(4): added new data structure for network queues
and moved the same parameters in vioif_txqueue and
vioif_rxqueue into the new structure
To generate a diff of this commit:
cvs rdiff -u -r1.97 -r1.98 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.97 src/sys/dev/pci/if_vioif.c:1.98
--- src/sys/dev/pci/if_vioif.c:1.97 Thu Mar 23 02:33:34 2023
+++ src/sys/dev/pci/if_vioif.c Thu Mar 23 02:42:49 2023
@@ -1,4 +1,4 @@
-/* $NetBSD: if_vioif.c,v 1.97 2023/03/23 02:33:34 yamaguchi Exp $ */
+/* $NetBSD: if_vioif.c,v 1.98 2023/03/23 02:42:49 yamaguchi Exp $ */
/*
* Copyright (c) 2020 The NetBSD Foundation, Inc.
@@ -27,7 +27,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: if_vioif.c,v 1.97 2023/03/23 02:33:34 yamaguchi Exp $");
+__KERNEL_RCSID(0, "$NetBSD: if_vioif.c,v 1.98 2023/03/23 02:42:49 yamaguchi Exp $");
#ifdef _KERNEL_OPT
#include "opt_net_mpsafe.h"
@@ -205,12 +205,13 @@ struct virtio_net_ctrl_mq {
/*
* Locking notes:
- * + a field in vioif_txqueue is protected by txq_lock (a spin mutex), and
- * a field in vioif_rxqueue is protected by rxq_lock (a spin mutex).
+ * + a field in vioif_netueue is protected by netq_lock (a spin mutex)
* - more than one lock cannot be held at onece
+ * + a field in vioif_tx_context and vioif_rx_context is also protected
+ * by netq_lock.
* + 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
+ * - netq_lock cannot be held along with ctrlq_wait_lock
* + fields in vioif_softc except queues are protected by
* sc->sc_lock(an adaptive mutex)
* - the lock is held before acquisition of other locks
@@ -236,49 +237,44 @@ struct vioif_net_map {
bus_dmamap_t vnm_mbuf_map;
};
-struct vioif_txqueue {
- kmutex_t *txq_lock; /* lock for tx operations */
+#define VIOIF_NETQ_RX 0
+#define VIOIF_NETQ_TX 1
+#define VIOIF_NETQ_IDX 2
+#define VIOIF_NETQ_DIR(n) ((n) % VIOIF_NETQ_IDX)
+#define VIOIF_NETQ_PAIRIDX(n) ((n) / VIOIF_NETQ_IDX)
+#define VIOIF_NETQ_RXQID(n) ((n) * VIOIF_NETQ_IDX + VIOIF_NETQ_RX)
+#define VIOIF_NETQ_TXQID(n) ((n) * VIOIF_NETQ_IDX + VIOIF_NETQ_TX)
+
+struct vioif_netqueue {
+ kmutex_t netq_lock;
+ struct virtqueue *netq_vq;
+ bool netq_stopping;
+ bool netq_running_handle;
+ void *netq_maps_kva;
+ struct vioif_net_map *netq_maps;
+
+ void *netq_softint;
+ struct vioif_work netq_work;
+ bool netq_workqueue;
+
+ char netq_evgroup[32];
+ struct evcnt netq_mbuf_load_failed;
+ struct evcnt netq_enqueue_reserve_failed;
- struct virtqueue *txq_vq;
- bool txq_stopping;
- bool txq_link_active;
- pcq_t *txq_intrq;
-
- void *txq_maps_kva;
- struct vioif_net_map *txq_maps;
-
- void *txq_deferred_transmit;
- void *txq_handle_si;
- struct vioif_work txq_work;
- bool txq_workqueue;
- bool txq_running_handle;
-
- char txq_evgroup[16];
- struct evcnt txq_defrag_failed;
- struct evcnt txq_mbuf_load_failed;
- struct evcnt txq_enqueue_reserve_failed;
+ void *netq_ctx;
};
-struct vioif_rxqueue {
- kmutex_t *rxq_lock; /* lock for rx operations */
+struct vioif_tx_context {
+ bool txc_link_active;
+ pcq_t *txc_intrq;
+ void *txc_deferred_transmit;
- struct virtqueue *rxq_vq;
- bool rxq_stopping;
-
- void *rxq_maps_kva;
- struct vioif_net_map *rxq_maps;
-
- void *rxq_handle_si;
- struct vioif_work rxq_work;
- bool rxq_workqueue;
- bool rxq_running_handle;
-
- char rxq_evgroup[16];
- struct evcnt rxq_mbuf_enobufs;
- struct evcnt rxq_mbuf_load_failed;
- struct evcnt rxq_enqueue_reserve_failed;
+ struct evcnt txc_defrag_failed;
};
+struct vioif_rx_context {
+ struct evcnt rxc_mbuf_enobufs;
+};
struct vioif_ctrlqueue {
struct virtqueue *ctrlq_vq;
enum {
@@ -325,8 +321,7 @@ struct vioif_softc {
struct ethercom sc_ethercom;
int sc_link_state;
- struct vioif_txqueue *sc_txq;
- struct vioif_rxqueue *sc_rxq;
+ struct vioif_netqueue *sc_netqs;
bool sc_has_ctrl;
struct vioif_ctrlqueue sc_ctrlq;
@@ -365,34 +360,34 @@ static int vioif_finalize_teardown(devic
static int vioif_init(struct ifnet *);
static void vioif_stop(struct ifnet *, int);
static void vioif_start(struct ifnet *);
-static void vioif_start_locked(struct ifnet *, struct vioif_txqueue *);
+static void vioif_start_locked(struct ifnet *, struct vioif_netqueue *);
static int vioif_transmit(struct ifnet *, struct mbuf *);
-static void vioif_transmit_locked(struct ifnet *, struct vioif_txqueue *);
+static void vioif_transmit_locked(struct ifnet *, struct vioif_netqueue *);
static int vioif_ioctl(struct ifnet *, u_long, void *);
static void vioif_watchdog(struct ifnet *);
static int vioif_ifflags_cb(struct ethercom *);
+/* tx & rx */
+static void vioif_net_sched_handle(struct vioif_softc *,
+ struct vioif_netqueue *);
+
/* rx */
static void vioif_populate_rx_mbufs_locked(struct vioif_softc *,
- struct vioif_rxqueue *);
+ struct vioif_netqueue *);
static void vioif_rx_queue_clear(struct vioif_softc *, struct virtio_softc *,
- struct vioif_rxqueue *);
+ struct vioif_netqueue *);
static bool vioif_rx_deq_locked(struct vioif_softc *, struct virtio_softc *,
- struct vioif_rxqueue *, u_int, size_t *);
+ struct vioif_netqueue *, u_int, size_t *);
static int vioif_rx_intr(void *);
static void vioif_rx_handle(void *);
-static void vioif_rx_sched_handle(struct vioif_softc *,
- struct vioif_rxqueue *);
/* tx */
static int vioif_tx_intr(void *);
static void vioif_tx_handle(void *);
-static void vioif_tx_sched_handle(struct vioif_softc *,
- struct vioif_txqueue *);
static void vioif_tx_queue_clear(struct vioif_softc *, struct virtio_softc *,
- struct vioif_txqueue *);
+ struct vioif_netqueue *);
static bool vioif_tx_deq_locked(struct vioif_softc *, struct virtio_softc *,
- struct vioif_txqueue *, u_int);
+ struct vioif_netqueue *, u_int);
static void vioif_deferred_transmit(void *);
/* workqueue */
@@ -501,60 +496,199 @@ static void
vioif_alloc_queues(struct vioif_softc *sc)
{
int nvq_pairs = sc->sc_max_nvq_pairs;
- int nvqs = nvq_pairs * 2;
- int i;
+ size_t nvqs, netq_num;
KASSERT(nvq_pairs <= VIRTIO_NET_CTRL_MQ_VQ_PAIRS_MAX);
- sc->sc_rxq = kmem_zalloc(sizeof(sc->sc_rxq[0]) * nvq_pairs,
- KM_SLEEP);
- sc->sc_txq = kmem_zalloc(sizeof(sc->sc_txq[0]) * nvq_pairs,
- KM_SLEEP);
-
+ nvqs = netq_num = sc->sc_max_nvq_pairs * 2;
if (sc->sc_has_ctrl)
nvqs++;
sc->sc_vqs = kmem_zalloc(sizeof(sc->sc_vqs[0]) * nvqs, KM_SLEEP);
- nvqs = 0;
- for (i = 0; i < nvq_pairs; i++) {
- sc->sc_rxq[i].rxq_vq = &sc->sc_vqs[nvqs++];
- sc->sc_txq[i].txq_vq = &sc->sc_vqs[nvqs++];
- }
-
- if (sc->sc_has_ctrl)
- sc->sc_ctrlq.ctrlq_vq = &sc->sc_vqs[nvqs++];
+ sc->sc_netqs = kmem_zalloc(sizeof(sc->sc_vqs[0]) * netq_num,
+ KM_SLEEP);
}
static void
vioif_free_queues(struct vioif_softc *sc)
{
- int nvq_pairs = sc->sc_max_nvq_pairs;
- int nvqs = nvq_pairs * 2;
+ size_t nvqs, netq_num;
+ nvqs = netq_num = sc->sc_max_nvq_pairs * 2;
if (sc->sc_ctrlq.ctrlq_vq)
nvqs++;
- if (sc->sc_txq) {
- kmem_free(sc->sc_txq, sizeof(sc->sc_txq[0]) * nvq_pairs);
- sc->sc_txq = NULL;
+ kmem_free(sc->sc_netqs, sizeof(sc->sc_netqs[0]) * netq_num);
+ kmem_free(sc->sc_vqs, sizeof(sc->sc_vqs[0]) * nvqs);
+ sc->sc_netqs = NULL;
+ sc->sc_vqs = NULL;
+}
+
+static int
+vioif_netqueue_init(struct vioif_softc *sc, struct virtio_softc *vsc,
+ size_t qid, u_int softint_flags)
+{
+ static const struct {
+ const char *dirname;
+ int segsize;
+ int nsegs;
+ int (*intrhand)(void *);
+ void (*sihand)(void *);
+ } params[VIOIF_NETQ_IDX] = {
+ [VIOIF_NETQ_RX] = {
+ .dirname = "rx",
+ .segsize = MCLBYTES,
+ .nsegs = 2,
+ .intrhand = vioif_rx_intr,
+ .sihand = vioif_rx_handle,
+ },
+ [VIOIF_NETQ_TX] = {
+ .dirname = "tx",
+ .segsize = ETHER_MAX_LEN - ETHER_HDR_LEN,
+ .nsegs = 2,
+ .intrhand = vioif_tx_intr,
+ .sihand = vioif_tx_handle,
+ }
+ };
+
+ struct virtqueue *vq;
+ struct vioif_netqueue *netq;
+ struct vioif_tx_context *txc;
+ struct vioif_rx_context *rxc;
+ char qname[32];
+ int r, dir;
+
+ txc = NULL;
+ rxc = NULL;
+ netq = &sc->sc_netqs[qid];
+ vq = &sc->sc_vqs[qid];
+ dir = VIOIF_NETQ_DIR(qid);
+
+ netq->netq_vq = &sc->sc_vqs[qid];
+ netq->netq_stopping = false;
+ netq->netq_running_handle = false;
+
+ snprintf(qname, sizeof(qname), "%s%zu",
+ params[dir].dirname, VIOIF_NETQ_PAIRIDX(qid));
+ snprintf(netq->netq_evgroup, sizeof(netq->netq_evgroup),
+ "%s-%s", device_xname(sc->sc_dev), qname);
+
+ mutex_init(&netq->netq_lock, MUTEX_DEFAULT, IPL_NET);
+ r = virtio_alloc_vq(vsc, vq, qid,
+ params[dir].segsize + sc->sc_hdr_size,
+ params[dir].nsegs, qname);
+ if (r != 0)
+ goto err;
+ netq->netq_vq = vq;
+
+ netq->netq_vq->vq_intrhand = params[dir].intrhand;
+ netq->netq_vq->vq_intrhand_arg = netq;
+ netq->netq_softint = softint_establish(softint_flags,
+ params[dir].sihand, netq);
+ if (netq->netq_softint == NULL) {
+ aprint_error_dev(sc->sc_dev,
+ "couldn't establish %s softint\n",
+ params[dir].dirname);
+ goto err;
}
+ vioif_work_set(&netq->netq_work, params[dir].sihand, netq);
- if (sc->sc_rxq) {
- kmem_free(sc->sc_rxq, sizeof(sc->sc_rxq[0]) * nvq_pairs);
- sc->sc_rxq = NULL;
+ switch (dir) {
+ case VIOIF_NETQ_RX:
+ rxc = kmem_zalloc(sizeof(*rxc), KM_SLEEP);
+ netq->netq_ctx = rxc;
+ /* nothing to do */
+ break;
+ case VIOIF_NETQ_TX:
+ txc = kmem_zalloc(sizeof(*txc), KM_SLEEP);
+ netq->netq_ctx = (void *)txc;
+ txc->txc_deferred_transmit = softint_establish(softint_flags,
+ vioif_deferred_transmit, netq);
+ if (txc->txc_deferred_transmit == NULL) {
+ aprint_error_dev(sc->sc_dev,
+ "couldn't establish softint for "
+ "tx deferred transmit\n");
+ goto err;
+ }
+ txc->txc_link_active = VIOIF_IS_LINK_ACTIVE(sc);
+ txc->txc_intrq = pcq_create(vq->vq_num, KM_SLEEP);
+ break;
}
- if (sc->sc_vqs) {
- kmem_free(sc->sc_vqs, sizeof(sc->sc_vqs[0]) * nvqs);
- sc->sc_vqs = NULL;
+ return 0;
+
+err:
+ netq->netq_ctx = NULL;
+
+ if (rxc != NULL) {
+ kmem_free(rxc, sizeof(*rxc));
+ }
+
+ if (txc != NULL) {
+ if (txc->txc_deferred_transmit != NULL)
+ softint_disestablish(txc->txc_deferred_transmit);
+ if (txc->txc_intrq != NULL)
+ pcq_destroy(txc->txc_intrq);
+ kmem_free(txc, sizeof(txc));
+ }
+
+ vioif_work_set(&netq->netq_work, NULL, NULL);
+ if (netq->netq_softint != NULL) {
+ softint_disestablish(netq->netq_softint);
+ netq->netq_softint = NULL;
+ }
+ netq->netq_vq->vq_intrhand = NULL;
+ netq->netq_vq->vq_intrhand_arg = NULL;
+
+ virtio_free_vq(vsc, vq);
+ mutex_destroy(&netq->netq_lock);
+ netq->netq_vq = NULL;
+
+ return -1;
+}
+
+static void
+vioif_netqueue_teardown(struct vioif_softc *sc, struct virtio_softc *vsc,
+ size_t qid)
+{
+ struct vioif_netqueue *netq;
+ struct vioif_rx_context *rxc;
+ struct vioif_tx_context *txc;
+ int dir;
+
+ netq = &sc->sc_netqs[qid];
+
+ if (netq->netq_vq == NULL)
+ return;
+
+ netq = &sc->sc_netqs[qid];
+ dir = VIOIF_NETQ_DIR(qid);
+ switch (dir) {
+ case VIOIF_NETQ_RX:
+ rxc = netq->netq_ctx;
+ netq->netq_ctx = NULL;
+ kmem_free(rxc, sizeof(*rxc));
+ break;
+ case VIOIF_NETQ_TX:
+ txc = netq->netq_ctx;
+ netq->netq_ctx = NULL;
+ softint_disestablish(txc->txc_deferred_transmit);
+ pcq_destroy(txc->txc_intrq);
+ kmem_free(txc, sizeof(*txc));
+ break;
}
+
+ softint_disestablish(netq->netq_softint);
+ virtio_free_vq(vsc, netq->netq_vq);
+ mutex_destroy(&netq->netq_lock);
+ netq->netq_vq = NULL;
}
/* allocate memory */
/*
* dma memory is used for:
- * rxq_maps_kva: metadata array for received frames (READ)
- * txq_maps_kva: metadata array for frames to be sent (WRITE)
+ * netq_maps_kva: metadata array for received frames (READ) and
+ * sent frames (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
@@ -570,62 +704,69 @@ static int
vioif_alloc_mems(struct vioif_softc *sc)
{
struct virtio_softc *vsc = sc->sc_virtio;
- struct vioif_txqueue *txq;
- struct vioif_rxqueue *rxq;
- struct vioif_net_map *maps;
+ struct vioif_netqueue *netq;
struct vioif_ctrlqueue *ctrlq = &sc->sc_ctrlq;
- int allocsize, allocsize2, r, rsegs, i, qid;
+ struct vioif_net_map *maps;
+ unsigned int vq_num;
+ int r, rsegs;
+ bus_size_t dmamemsize;
+ size_t qid, i, netq_num, kmemsize;
void *vaddr;
intptr_t p;
- allocsize = 0;
- for (qid = 0; qid < sc->sc_max_nvq_pairs; qid++) {
- rxq = &sc->sc_rxq[qid];
- txq = &sc->sc_txq[qid];
+ netq_num = sc->sc_max_nvq_pairs * 2;
+
+ /* allocate DMA memory */
+ dmamemsize = 0;
- allocsize += sizeof(struct virtio_net_hdr) *
- (rxq->rxq_vq->vq_num + txq->txq_vq->vq_num);
+ for (qid = 0; qid < netq_num; qid++) {
+ maps = sc->sc_netqs[qid].netq_maps;
+ vq_num = sc->sc_netqs[qid].netq_vq->vq_num;
+ dmamemsize += sizeof(*maps[0].vnm_hdr) * vq_num;
}
+
if (sc->sc_has_ctrl) {
- allocsize += sizeof(struct virtio_net_ctrl_cmd);
- allocsize += sizeof(struct virtio_net_ctrl_status);
- allocsize += sizeof(struct virtio_net_ctrl_rx);
- allocsize += sizeof(struct virtio_net_ctrl_mac_tbl)
+ dmamemsize += sizeof(struct virtio_net_ctrl_cmd);
+ dmamemsize += sizeof(struct virtio_net_ctrl_status);
+ dmamemsize += sizeof(struct virtio_net_ctrl_rx);
+ dmamemsize += sizeof(struct virtio_net_ctrl_mac_tbl)
+ ETHER_ADDR_LEN;
- allocsize += sizeof(struct virtio_net_ctrl_mac_tbl)
+ dmamemsize += sizeof(struct virtio_net_ctrl_mac_tbl)
+ ETHER_ADDR_LEN * VIRTIO_NET_CTRL_MAC_MAXENTRIES;
- allocsize += sizeof(struct virtio_net_ctrl_mac_addr);
- allocsize += sizeof(struct virtio_net_ctrl_mq);
+ dmamemsize += sizeof(struct virtio_net_ctrl_mac_addr);
+ dmamemsize += sizeof(struct virtio_net_ctrl_mq);
}
- r = bus_dmamem_alloc(virtio_dmat(vsc), allocsize, 0, 0,
+
+ r = bus_dmamem_alloc(virtio_dmat(vsc), dmamemsize, 0, 0,
&sc->sc_hdr_segs[0], 1, &rsegs, BUS_DMA_NOWAIT);
if (r != 0) {
aprint_error_dev(sc->sc_dev,
- "DMA memory allocation failed, size %d, "
- "error code %d\n", allocsize, r);
+ "DMA memory allocation failed, size %zu, "
+ "error code %d\n", dmamemsize, r);
goto err_none;
}
- r = bus_dmamem_map(virtio_dmat(vsc),
- &sc->sc_hdr_segs[0], 1, allocsize, &vaddr, BUS_DMA_NOWAIT);
+ r = bus_dmamem_map(virtio_dmat(vsc),&sc->sc_hdr_segs[0], 1,
+ dmamemsize, &vaddr, BUS_DMA_NOWAIT);
if (r != 0) {
aprint_error_dev(sc->sc_dev,
"DMA memory map failed, error code %d\n", r);
goto err_dmamem_alloc;
}
- memset(vaddr, 0, allocsize);
+ /* assign DMA memory */
+ memset(vaddr, 0, dmamemsize);
sc->sc_dmamem = vaddr;
p = (intptr_t) vaddr;
- for (qid = 0; qid < sc->sc_max_nvq_pairs; qid++) {
- rxq = &sc->sc_rxq[qid];
- txq = &sc->sc_txq[qid];
-
- rxq->rxq_maps_kva = vioif_assign_mem(&p,
- sizeof(struct virtio_net_hdr) * rxq->rxq_vq->vq_num);
- txq->txq_maps_kva = vioif_assign_mem(&p,
- sizeof(struct virtio_net_hdr) * txq->txq_vq->vq_num);
+ for (qid = 0; qid < netq_num; qid++) {
+ netq = &sc->sc_netqs[qid];
+ maps = netq->netq_maps;
+ vq_num = netq->netq_vq->vq_num;
+
+ netq->netq_maps_kva = vioif_assign_mem(&p,
+ sizeof(*maps[0].vnm_hdr) * vq_num);
}
+
if (sc->sc_has_ctrl) {
ctrlq->ctrlq_cmd = vioif_assign_mem(&p,
sizeof(*ctrlq->ctrlq_cmd));
@@ -644,72 +785,76 @@ vioif_alloc_mems(struct vioif_softc *sc)
ctrlq->ctrlq_mq = vioif_assign_mem(&p, sizeof(*ctrlq->ctrlq_mq));
}
- allocsize2 = 0;
- for (qid = 0; qid < sc->sc_max_nvq_pairs; qid++) {
- int rxqsize, txqsize;
-
- rxq = &sc->sc_rxq[qid];
- txq = &sc->sc_txq[qid];
+ /* allocate kmem */
+ kmemsize = 0;
- rxqsize = rxq->rxq_vq->vq_num;
- txqsize = txq->txq_vq->vq_num;
+ for (qid = 0; qid < netq_num; qid++) {
+ netq = &sc->sc_netqs[qid];
+ vq_num = netq->netq_vq->vq_num;
- allocsize2 += sizeof(rxq->rxq_maps[0]) * rxqsize;
- allocsize2 += sizeof(txq->txq_maps[0]) * txqsize;
+ kmemsize += sizeof(netq->netq_maps[0]) * vq_num;
}
- vaddr = kmem_zalloc(allocsize2, KM_SLEEP);
+
+ vaddr = kmem_zalloc(kmemsize, KM_SLEEP);
sc->sc_kmem = vaddr;
+
+ /* assign allocated kmem */
p = (intptr_t) vaddr;
- for (qid = 0; qid < sc->sc_max_nvq_pairs; qid++) {
- int rxqsize, txqsize;
- rxq = &sc->sc_rxq[qid];
- txq = &sc->sc_txq[qid];
- rxqsize = rxq->rxq_vq->vq_num;
- txqsize = txq->txq_vq->vq_num;
-
- rxq->rxq_maps = vioif_assign_mem(&p,
- sizeof(rxq->rxq_maps[0]) * rxqsize);
- txq->txq_maps = vioif_assign_mem(&p,
- sizeof(txq->txq_maps[0]) * txqsize);
- }
+ for (qid = 0; qid < netq_num; qid++) {
+ netq = &sc->sc_netqs[qid];
+ vq_num = netq->netq_vq->vq_num;
+
+ netq->netq_maps = vioif_assign_mem(&p,
+ sizeof(netq->netq_maps[0]) * vq_num);
+ }
+
+ /* prepare dmamaps */
+ for (qid = 0; qid < netq_num; qid++) {
+ static const struct {
+ const char *msg_hdr;
+ const char *msg_payload;
+ int dma_flag;
+ bus_size_t dma_size;
+ int dma_nsegs;
+ } dmaparams[VIOIF_NETQ_IDX] = {
+ [VIOIF_NETQ_RX] = {
+ .msg_hdr = "rx header",
+ .msg_payload = "rx payload",
+ .dma_flag = BUS_DMA_READ,
+ .dma_size = MCLBYTES - ETHER_ALIGN,
+ .dma_nsegs = 1,
+ },
+ [VIOIF_NETQ_TX] = {
+ .msg_hdr = "tx header",
+ .msg_payload = "tx payload",
+ .dma_flag = BUS_DMA_WRITE,
+ .dma_size = ETHER_MAX_LEN,
+ .dma_nsegs = VIRTIO_NET_TX_MAXNSEGS,
+ }
+ };
- for (qid = 0; qid < sc->sc_max_nvq_pairs; qid++) {
struct virtio_net_hdr *hdrs;
- unsigned int vq_num;
+ int dir;
- rxq = &sc->sc_rxq[qid];
- vq_num = rxq->rxq_vq->vq_num;
- maps = rxq->rxq_maps;
- hdrs = (struct virtio_net_hdr *)rxq->rxq_maps_kva;
- for (i = 0; i < vq_num; i++) {
- maps[i].vnm_hdr = &hdrs[i];
- r = vioif_dmamap_create_load(sc, &maps[i].vnm_hdr_map,
- maps[i].vnm_hdr, sc->sc_hdr_size, 1, BUS_DMA_READ,
- "rx header");
- if (r != 0)
- goto err_reqs;
+ dir = VIOIF_NETQ_DIR(qid);
+ netq = &sc->sc_netqs[qid];
+ vq_num = netq->netq_vq->vq_num;
+ maps = netq->netq_maps;
+ hdrs = netq->netq_maps_kva;
- r = vioif_dmamap_create(sc, &maps[i].vnm_mbuf_map,
- MCLBYTES - ETHER_ALIGN, 1, "rx payload");
- if (r != 0)
- goto err_reqs;
- }
-
- txq = &sc->sc_txq[qid];
- vq_num = txq->txq_vq->vq_num;
- maps = txq->txq_maps;
- hdrs = (struct virtio_net_hdr *)txq->txq_maps_kva;
for (i = 0; i < vq_num; i++) {
maps[i].vnm_hdr = &hdrs[i];
+
r = vioif_dmamap_create_load(sc, &maps[i].vnm_hdr_map,
- maps[i].vnm_hdr, sc->sc_hdr_size, 1, BUS_DMA_WRITE,
- "tx header");
+ maps[i].vnm_hdr, sc->sc_hdr_size, 1,
+ dmaparams[dir].dma_flag, dmaparams[dir].msg_hdr);
if (r != 0)
goto err_reqs;
r = vioif_dmamap_create(sc, &maps[i].vnm_mbuf_map,
- ETHER_MAX_LEN, VIRTIO_NET_TX_MAXNSEGS, "tx payload");
+ dmaparams[dir].dma_size, dmaparams[dir].dma_nsegs,
+ dmaparams[dir].msg_payload);
if (r != 0)
goto err_reqs;
}
@@ -779,30 +924,20 @@ err_reqs:
vioif_dmamap_destroy(sc, &ctrlq->ctrlq_status_dmamap);
vioif_dmamap_destroy(sc, &ctrlq->ctrlq_cmd_dmamap);
vioif_dmamap_destroy(sc, &ctrlq->ctrlq_mac_addr_dmamap);
- for (qid = 0; qid < sc->sc_max_nvq_pairs; qid++) {
- unsigned int vq_num;
- rxq = &sc->sc_rxq[qid];
- txq = &sc->sc_txq[qid];
+ for (qid = 0; qid < netq_num; qid++) {
+ vq_num = sc->sc_netqs[qid].netq_vq->vq_num;
+ maps = sc->sc_netqs[qid].netq_maps;
- vq_num = txq->txq_vq->vq_num;
- maps = txq->txq_maps;
- for (i = 0; i < vq_num; i++) {
- vioif_dmamap_destroy(sc, &maps[i].vnm_mbuf_map);
- vioif_dmamap_destroy(sc, &maps[i].vnm_hdr_map);
- }
-
- vq_num = txq->txq_vq->vq_num;
- maps = txq->txq_maps;
for (i = 0; i < vq_num; i++) {
vioif_dmamap_destroy(sc, &maps[i].vnm_mbuf_map);
vioif_dmamap_destroy(sc, &maps[i].vnm_hdr_map);
}
}
if (sc->sc_kmem) {
- kmem_free(sc->sc_kmem, allocsize2);
+ kmem_free(sc->sc_kmem, kmemsize);
sc->sc_kmem = NULL;
}
- bus_dmamem_unmap(virtio_dmat(vsc), sc->sc_dmamem, allocsize);
+ bus_dmamem_unmap(virtio_dmat(vsc), sc->sc_dmamem, dmamemsize);
err_dmamem_alloc:
bus_dmamem_free(virtio_dmat(vsc), &sc->sc_hdr_segs[0], 1);
err_none:
@@ -814,14 +949,14 @@ vioif_attach(device_t parent, device_t s
{
struct vioif_softc *sc = device_private(self);
struct virtio_softc *vsc = device_private(parent);
+ struct vioif_netqueue *txq0;
struct vioif_ctrlqueue *ctrlq = &sc->sc_ctrlq;
- struct vioif_txqueue *txq;
- struct vioif_rxqueue *rxq;
uint64_t features, req_features;
struct ifnet *ifp = &sc->sc_ethercom.ec_if;
u_int softint_flags;
- int r, i, nvqs = 0, req_flags;
+ int r, i, req_flags;
char xnamebuf[MAXCOMLEN];
+ size_t netq_num;
if (virtio_child(vsc) != NULL) {
aprint_normal(": child already attached for %s; "
@@ -933,70 +1068,22 @@ vioif_attach(device_t parent, device_t s
#endif
/*
- * Allocating virtqueues
+ * Initialize network queues
*/
- for (i = 0; i < sc->sc_max_nvq_pairs; i++) {
- rxq = &sc->sc_rxq[i];
- txq = &sc->sc_txq[i];
- char qname[32];
-
- rxq->rxq_lock = mutex_obj_alloc(MUTEX_DEFAULT, IPL_NET);
-
- rxq->rxq_handle_si = softint_establish(softint_flags,
- vioif_rx_handle, rxq);
- if (rxq->rxq_handle_si == NULL) {
- aprint_error_dev(self, "cannot establish rx softint\n");
- goto err;
- }
-
- snprintf(qname, sizeof(qname), "rx%d", i);
- r = virtio_alloc_vq(vsc, rxq->rxq_vq, nvqs,
- MCLBYTES + sc->sc_hdr_size, 2, qname);
+ netq_num = sc->sc_max_nvq_pairs * 2;
+ for (i = 0; i < netq_num; i++) {
+ r = vioif_netqueue_init(sc, vsc, i, softint_flags);
if (r != 0)
goto err;
- nvqs++;
- rxq->rxq_vq->vq_intrhand = vioif_rx_intr;
- rxq->rxq_vq->vq_intrhand_arg = (void *)rxq;
- rxq->rxq_stopping = false;
- rxq->rxq_running_handle = false;
- vioif_work_set(&rxq->rxq_work, vioif_rx_handle, rxq);
-
- txq->txq_lock = mutex_obj_alloc(MUTEX_DEFAULT, IPL_NET);
-
- txq->txq_deferred_transmit = softint_establish(softint_flags,
- vioif_deferred_transmit, txq);
- if (txq->txq_deferred_transmit == NULL) {
- aprint_error_dev(self, "cannot establish tx softint\n");
- goto err;
- }
- txq->txq_handle_si = softint_establish(softint_flags,
- vioif_tx_handle, txq);
- if (txq->txq_handle_si == NULL) {
- aprint_error_dev(self, "cannot establish tx softint\n");
- goto err;
- }
-
- snprintf(qname, sizeof(qname), "tx%d", i);
- r = virtio_alloc_vq(vsc, txq->txq_vq, nvqs,
- sc->sc_hdr_size + (ETHER_MAX_LEN - ETHER_HDR_LEN),
- VIRTIO_NET_TX_MAXNSEGS + 1, qname);
- if (r != 0)
- goto err;
- nvqs++;
- txq->txq_vq->vq_intrhand = vioif_tx_intr;
- txq->txq_vq->vq_intrhand_arg = (void *)txq;
- txq->txq_link_active = VIOIF_IS_LINK_ACTIVE(sc);
- txq->txq_stopping = false;
- txq->txq_running_handle = false;
- txq->txq_intrq = pcq_create(txq->txq_vq->vq_num, KM_SLEEP);
- vioif_work_set(&txq->txq_work, vioif_tx_handle, txq);
}
if (sc->sc_has_ctrl) {
+ int ctrlq_idx = sc->sc_max_nvq_pairs * 2;
/*
* Allocating a virtqueue for control channel
*/
- r = virtio_alloc_vq(vsc, ctrlq->ctrlq_vq, nvqs,
+ sc->sc_ctrlq.ctrlq_vq = &sc->sc_vqs[ctrlq_idx];
+ r = virtio_alloc_vq(vsc, ctrlq->ctrlq_vq, ctrlq_idx,
NBPG, 1, "control");
if (r != 0) {
aprint_error_dev(self, "failed to allocate "
@@ -1007,7 +1094,6 @@ vioif_attach(device_t parent, device_t s
cv_destroy(&ctrlq->ctrlq_wait);
mutex_destroy(&ctrlq->ctrlq_wait_lock);
} else {
- nvqs++;
ctrlq->ctrlq_vq->vq_intrhand = vioif_ctrl_intr;
ctrlq->ctrlq_vq->vq_intrhand_arg = (void *) ctrlq;
}
@@ -1047,8 +1133,8 @@ vioif_attach(device_t parent, device_t s
ifp->if_stop = vioif_stop;
ifp->if_capabilities = 0;
ifp->if_watchdog = vioif_watchdog;
- txq = &sc->sc_txq[0];
- IFQ_SET_MAXLEN(&ifp->if_snd, MAX(txq->txq_vq->vq_num, IFQ_MAXLEN));
+ txq0 = &sc->sc_netqs[VIOIF_NETQ_TXQID(0)];
+ IFQ_SET_MAXLEN(&ifp->if_snd, MAX(txq0->netq_vq->vq_num, IFQ_MAXLEN));
IFQ_SET_READY(&ifp->if_snd);
sc->sc_ethercom.ec_capabilities |= ETHERCAP_VLAN_MTU;
@@ -1061,49 +1147,18 @@ vioif_attach(device_t parent, device_t s
return;
err:
- for (i = 0; i < sc->sc_max_nvq_pairs; i++) {
- rxq = &sc->sc_rxq[i];
- txq = &sc->sc_txq[i];
-
- if (rxq->rxq_lock) {
- mutex_obj_free(rxq->rxq_lock);
- rxq->rxq_lock = NULL;
- }
-
- if (rxq->rxq_handle_si) {
- softint_disestablish(rxq->rxq_handle_si);
- rxq->rxq_handle_si = NULL;
- }
-
- if (txq->txq_lock) {
- mutex_obj_free(txq->txq_lock);
- txq->txq_lock = NULL;
- }
-
- if (txq->txq_handle_si) {
- softint_disestablish(txq->txq_handle_si);
- txq->txq_handle_si = NULL;
- }
-
- if (txq->txq_deferred_transmit) {
- softint_disestablish(txq->txq_deferred_transmit);
- txq->txq_deferred_transmit = NULL;
- }
-
- if (txq->txq_intrq) {
- pcq_destroy(txq->txq_intrq);
- txq->txq_intrq = NULL;
- }
+ netq_num = sc->sc_max_nvq_pairs * 2;
+ for (i = 0; i < netq_num; i++) {
+ vioif_netqueue_teardown(sc, vsc, i);
}
if (sc->sc_has_ctrl) {
cv_destroy(&ctrlq->ctrlq_wait);
mutex_destroy(&ctrlq->ctrlq_wait_lock);
+ virtio_free_vq(vsc, ctrlq->ctrlq_vq);
+ ctrlq->ctrlq_vq = NULL;
}
- while (nvqs > 0)
- virtio_free_vq(vsc, &sc->sc_vqs[--nvqs]);
-
vioif_free_queues(sc);
mutex_destroy(&sc->sc_lock);
virtio_child_attach_failed(vsc);
@@ -1129,16 +1184,13 @@ static void
vioif_enable_interrupt_vqpairs(struct vioif_softc *sc)
{
struct virtio_softc *vsc = sc->sc_virtio;
- struct vioif_txqueue *txq;
- struct vioif_rxqueue *rxq;
- int i;
-
- for (i = 0; i < sc->sc_act_nvq_pairs; i++) {
- txq = &sc->sc_txq[i];
- rxq = &sc->sc_rxq[i];
+ struct vioif_netqueue *netq;
+ size_t i, netq_act_num;
- virtio_start_vq_intr(vsc, txq->txq_vq);
- virtio_start_vq_intr(vsc, rxq->rxq_vq);
+ netq_act_num = sc->sc_act_nvq_pairs * 2;
+ for (i = 0; i < netq_act_num; i++) {
+ netq = &sc->sc_netqs[i];
+ virtio_start_vq_intr(vsc, netq->netq_vq);
}
}
@@ -1146,16 +1198,13 @@ static void
vioif_disable_interrupt_vqpairs(struct vioif_softc *sc)
{
struct virtio_softc *vsc = sc->sc_virtio;
- struct vioif_txqueue *txq;
- struct vioif_rxqueue *rxq;
- int i;
-
- for (i = 0; i < sc->sc_act_nvq_pairs; i++) {
- rxq = &sc->sc_rxq[i];
- txq = &sc->sc_txq[i];
+ struct vioif_netqueue *netq;
+ size_t i, netq_act_num;
- virtio_stop_vq_intr(vsc, rxq->rxq_vq);
- virtio_stop_vq_intr(vsc, txq->txq_vq);
+ netq_act_num = sc->sc_act_nvq_pairs * 2;
+ for (i = 0; i < netq_act_num; i++) {
+ netq = &sc->sc_netqs[i];
+ virtio_stop_vq_intr(vsc, netq->netq_vq);
}
}
@@ -1167,7 +1216,7 @@ vioif_init(struct ifnet *ifp)
{
struct vioif_softc *sc = ifp->if_softc;
struct virtio_softc *vsc = sc->sc_virtio;
- struct vioif_rxqueue *rxq;
+ struct vioif_netqueue *netq;
struct vioif_ctrlqueue *ctrlq = &sc->sc_ctrlq;
int r, i;
@@ -1182,12 +1231,11 @@ vioif_init(struct ifnet *ifp)
virtio_negotiate_features(vsc, virtio_features(vsc));
for (i = 0; i < sc->sc_req_nvq_pairs; i++) {
- rxq = &sc->sc_rxq[i];
-
- mutex_enter(rxq->rxq_lock);
- vioif_populate_rx_mbufs_locked(sc, rxq);
- mutex_exit(rxq->rxq_lock);
+ netq = &sc->sc_netqs[VIOIF_NETQ_RXQID(i)];
+ mutex_enter(&netq->netq_lock);
+ vioif_populate_rx_mbufs_locked(sc, netq);
+ mutex_exit(&netq->netq_lock);
}
virtio_reinit_end(vsc);
@@ -1201,11 +1249,12 @@ vioif_init(struct ifnet *ifp)
else
sc->sc_act_nvq_pairs = 1;
+ SET(ifp->if_flags, IFF_RUNNING);
+ CLR(ifp->if_flags, IFF_OACTIVE);
+
vioif_enable_interrupt_vqpairs(sc);
vioif_update_link_status(sc);
- ifp->if_flags |= IFF_RUNNING;
- ifp->if_flags &= ~IFF_OACTIVE;
r = vioif_rx_filter(sc);
return r;
@@ -1216,23 +1265,19 @@ 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;
- struct vioif_rxqueue *rxq;
+ struct vioif_netqueue *netq;
struct vioif_ctrlqueue *ctrlq = &sc->sc_ctrlq;
- int i;
+ size_t i, netq_act_num;
+ netq_act_num = sc->sc_act_nvq_pairs * 2;
- for (i = 0; i < sc->sc_act_nvq_pairs; i++) {
- txq = &sc->sc_txq[i];
- rxq = &sc->sc_rxq[i];
+ CLR(ifp->if_flags, IFF_RUNNING);
+ for (i = 0; i < netq_act_num; i++) {
+ netq = &sc->sc_netqs[i];
- mutex_enter(rxq->rxq_lock);
- rxq->rxq_stopping = true;
- mutex_exit(rxq->rxq_lock);
-
- mutex_enter(txq->txq_lock);
- txq->txq_stopping = true;
- mutex_exit(txq->txq_lock);
+ mutex_enter(&netq->netq_lock);
+ netq->netq_stopping = true;
+ mutex_exit(&netq->netq_lock);
}
/* disable interrupts */
@@ -1250,59 +1295,55 @@ vioif_stop(struct ifnet *ifp, int disabl
vioif_intr_barrier();
- for (i = 0; i < sc->sc_act_nvq_pairs; i++) {
- txq = &sc->sc_txq[i];
- rxq = &sc->sc_rxq[i];
-
- vioif_work_wait(sc->sc_txrx_workqueue, &rxq->rxq_work);
- vioif_work_wait(sc->sc_txrx_workqueue, &txq->txq_work);
+ for (i = 0; i < netq_act_num; i++) {
+ netq = &sc->sc_netqs[i];
+ vioif_work_wait(sc->sc_txrx_workqueue, &netq->netq_work);
}
for (i = 0; i < sc->sc_act_nvq_pairs; i++) {
- vioif_rx_queue_clear(sc, vsc, &sc->sc_rxq[i]);
- vioif_tx_queue_clear(sc, vsc, &sc->sc_txq[i]);
- }
+ netq = &sc->sc_netqs[VIOIF_NETQ_RXQID(i)];
+ vioif_rx_queue_clear(sc, vsc, netq);
- ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE);
+ netq = &sc->sc_netqs[VIOIF_NETQ_TXQID(i)];
+ vioif_tx_queue_clear(sc, vsc, netq);
+ }
/* all packet processing is stopped */
- for (i = 0; i < sc->sc_act_nvq_pairs; i++) {
- txq = &sc->sc_txq[i];
- rxq = &sc->sc_rxq[i];
+ for (i = 0; i < netq_act_num; i++) {
+ netq = &sc->sc_netqs[i];
- mutex_enter(rxq->rxq_lock);
- rxq->rxq_stopping = false;
- KASSERT(!rxq->rxq_running_handle);
- mutex_exit(rxq->rxq_lock);
-
- mutex_enter(txq->txq_lock);
- txq->txq_stopping = false;
- KASSERT(!txq->txq_running_handle);
- mutex_exit(txq->txq_lock);
+ mutex_enter(&netq->netq_lock);
+ netq->netq_stopping = false;
+ mutex_exit(&netq->netq_lock);
}
}
static void
-vioif_send_common_locked(struct ifnet *ifp, struct vioif_txqueue *txq,
+vioif_send_common_locked(struct ifnet *ifp, struct vioif_netqueue *netq,
bool is_transmit)
{
struct vioif_softc *sc = ifp->if_softc;
struct virtio_softc *vsc = sc->sc_virtio;
- struct virtqueue *vq = txq->txq_vq;
+ struct virtqueue *vq = netq->netq_vq;
+ struct vioif_tx_context *txc;
struct vioif_net_map *map;
struct virtio_net_hdr *hdr;
struct mbuf *m;
int queued = 0;
- KASSERT(mutex_owned(txq->txq_lock));
+ KASSERT(mutex_owned(&netq->netq_lock));
- if ((ifp->if_flags & IFF_RUNNING) == 0)
+ if (netq->netq_stopping ||
+ !ISSET(ifp->if_flags, IFF_RUNNING))
return;
- if (!txq->txq_link_active || txq->txq_stopping)
+ txc = netq->netq_ctx;
+
+ if (!txc->txc_link_active)
return;
- if ((ifp->if_flags & IFF_OACTIVE) != 0 && !is_transmit)
+ if (!is_transmit &&
+ ISSET(ifp->if_flags, IFF_OACTIVE))
return;
for (;;) {
@@ -1314,7 +1355,7 @@ vioif_send_common_locked(struct ifnet *i
panic("enqueue_prep for tx buffers");
if (is_transmit)
- m = pcq_get(txq->txq_intrq);
+ m = pcq_get(txc->txc_intrq);
else
IFQ_DEQUEUE(&ifp->if_snd, m);
@@ -1323,7 +1364,7 @@ vioif_send_common_locked(struct ifnet *i
break;
}
- map = &txq->txq_maps[slot];
+ map = &netq->netq_maps[slot];
KASSERT(map->vnm_mbuf == NULL);
r = bus_dmamap_load_mbuf(virtio_dmat(vsc),
@@ -1334,7 +1375,7 @@ vioif_send_common_locked(struct ifnet *i
newm = m_defrag(m, M_NOWAIT);
if (newm == NULL) {
- txq->txq_defrag_failed.ev_count++;
+ txc->txc_defrag_failed.ev_count++;
goto skip;
}
@@ -1343,7 +1384,7 @@ vioif_send_common_locked(struct ifnet *i
map->vnm_mbuf_map, m,
BUS_DMA_WRITE | BUS_DMA_NOWAIT);
if (r != 0) {
- txq->txq_mbuf_load_failed.ev_count++;
+ netq->netq_mbuf_load_failed.ev_count++;
skip:
m_freem(m);
if_statinc(ifp, if_oerrors);
@@ -1356,7 +1397,7 @@ skip:
r = virtio_enqueue_reserve(vsc, vq, slot,
map->vnm_mbuf_map->dm_nsegs + 1);
if (r != 0) {
- txq->txq_enqueue_reserve_failed.ev_count++;
+ netq->netq_enqueue_reserve_failed.ev_count++;
bus_dmamap_unload(virtio_dmat(vsc),
map->vnm_mbuf_map);
/* slot already freed by virtio_enqueue_reserve */
@@ -1387,13 +1428,13 @@ skip:
}
static void
-vioif_start_locked(struct ifnet *ifp, struct vioif_txqueue *txq)
+vioif_start_locked(struct ifnet *ifp, struct vioif_netqueue *netq)
{
/*
* ifp->if_obytes and ifp->if_omcasts are added in if_transmit()@if.c.
*/
- vioif_send_common_locked(ifp, txq, false);
+ vioif_send_common_locked(ifp, netq, false);
}
@@ -1401,15 +1442,15 @@ static void
vioif_start(struct ifnet *ifp)
{
struct vioif_softc *sc = ifp->if_softc;
- struct vioif_txqueue *txq = &sc->sc_txq[0];
+ struct vioif_netqueue *txq0 = &sc->sc_netqs[VIOIF_NETQ_TXQID(0)];
#ifdef VIOIF_MPSAFE
KASSERT(if_is_mpsafe(ifp));
#endif
- mutex_enter(txq->txq_lock);
- vioif_start_locked(ifp, txq);
- mutex_exit(txq->txq_lock);
+ mutex_enter(&txq0->netq_lock);
+ vioif_start_locked(ifp, txq0);
+ mutex_exit(&txq0->netq_lock);
}
static inline int
@@ -1418,27 +1459,29 @@ vioif_select_txqueue(struct ifnet *ifp,
struct vioif_softc *sc = ifp->if_softc;
u_int cpuid = cpu_index(curcpu());
- return cpuid % sc->sc_act_nvq_pairs;
+ return VIOIF_NETQ_TXQID(cpuid % sc->sc_act_nvq_pairs);
}
static void
-vioif_transmit_locked(struct ifnet *ifp, struct vioif_txqueue *txq)
+vioif_transmit_locked(struct ifnet *ifp, struct vioif_netqueue *netq)
{
- vioif_send_common_locked(ifp, txq, true);
+ vioif_send_common_locked(ifp, netq, true);
}
static int
vioif_transmit(struct ifnet *ifp, struct mbuf *m)
{
struct vioif_softc *sc = ifp->if_softc;
- struct vioif_txqueue *txq;
+ struct vioif_netqueue *netq;
+ struct vioif_tx_context *txc;
int qid;
qid = vioif_select_txqueue(ifp, m);
- txq = &sc->sc_txq[qid];
+ netq = &sc->sc_netqs[qid];
+ txc = netq->netq_ctx;
- if (__predict_false(!pcq_put(txq->txq_intrq, m))) {
+ if (__predict_false(!pcq_put(txc->txc_intrq, m))) {
m_freem(m);
return ENOBUFS;
}
@@ -1449,9 +1492,9 @@ vioif_transmit(struct ifnet *ifp, struct
if_statinc_ref(nsr, if_omcasts);
IF_STAT_PUTREF(ifp);
- if (mutex_tryenter(txq->txq_lock)) {
- vioif_transmit_locked(ifp, txq);
- mutex_exit(txq->txq_lock);
+ if (mutex_tryenter(&netq->netq_lock)) {
+ vioif_transmit_locked(ifp, netq);
+ mutex_exit(&netq->netq_lock);
}
return 0;
@@ -1460,14 +1503,14 @@ vioif_transmit(struct ifnet *ifp, struct
static void
vioif_deferred_transmit(void *arg)
{
- struct vioif_txqueue *txq = arg;
- struct virtio_softc *vsc = txq->txq_vq->vq_owner;
+ struct vioif_netqueue *netq = arg;
+ struct virtio_softc *vsc = netq->netq_vq->vq_owner;
struct vioif_softc *sc = device_private(virtio_child(vsc));
struct ifnet *ifp = &sc->sc_ethercom.ec_if;
- mutex_enter(txq->txq_lock);
- vioif_send_common_locked(ifp, txq, true);
- mutex_exit(txq->txq_lock);
+ mutex_enter(&netq->netq_lock);
+ vioif_send_common_locked(ifp, netq, true);
+ mutex_exit(&netq->netq_lock);
}
static int
@@ -1495,37 +1538,54 @@ void
vioif_watchdog(struct ifnet *ifp)
{
struct vioif_softc *sc = ifp->if_softc;
- struct vioif_txqueue *txq;
+ struct vioif_netqueue *netq;
int i;
if (ifp->if_flags & IFF_RUNNING) {
for (i = 0; i < sc->sc_act_nvq_pairs; i++) {
- txq = &sc->sc_txq[i];
+ netq = &sc->sc_netqs[VIOIF_NETQ_TXQID(i)];
- mutex_enter(txq->txq_lock);
- if (!txq->txq_running_handle) {
- txq->txq_running_handle = true;
- vioif_tx_sched_handle(sc, txq);
+ mutex_enter(&netq->netq_lock);
+ if (!netq->netq_running_handle) {
+ netq->netq_running_handle = true;
+ vioif_net_sched_handle(sc, netq);
}
- mutex_exit(txq->txq_lock);
+ mutex_exit(&netq->netq_lock);
}
}
}
+static void
+vioif_net_sched_handle(struct vioif_softc *sc, struct vioif_netqueue *netq)
+{
+
+ KASSERT(mutex_owned(&netq->netq_lock));
+ KASSERT(!netq->netq_stopping);
+
+ if (netq->netq_workqueue) {
+ vioif_work_add(sc->sc_txrx_workqueue, &netq->netq_work);
+ } else {
+ softint_schedule(netq->netq_softint);
+ }
+}
+
/*
* Receive implementation
*/
/* add mbufs for all the empty receive slots */
static void
-vioif_populate_rx_mbufs_locked(struct vioif_softc *sc, struct vioif_rxqueue *rxq)
+vioif_populate_rx_mbufs_locked(struct vioif_softc *sc, struct vioif_netqueue *netq)
{
- struct virtqueue *vq = rxq->rxq_vq;
+ struct virtqueue *vq = netq->netq_vq;
struct virtio_softc *vsc = vq->vq_owner;
+ struct vioif_rx_context *rxc;
struct vioif_net_map *map;
struct mbuf *m;
int i, r, ndone = 0;
- KASSERT(mutex_owned(rxq->rxq_lock));
+ KASSERT(mutex_owned(&netq->netq_lock));
+
+ rxc = netq->netq_ctx;
for (i = 0; i < vq->vq_num; i++) {
int slot;
@@ -1535,20 +1595,20 @@ vioif_populate_rx_mbufs_locked(struct vi
if (__predict_false(r != 0))
panic("enqueue_prep for rx buffers");
- map = &rxq->rxq_maps[slot];
+ map = &netq->netq_maps[slot];
KASSERT(map->vnm_mbuf == NULL);
MGETHDR(m, M_DONTWAIT, MT_DATA);
if (m == NULL) {
virtio_enqueue_abort(vsc, vq, slot);
- rxq->rxq_mbuf_enobufs.ev_count++;
+ rxc->rxc_mbuf_enobufs.ev_count++;
break;
}
MCLGET(m, M_DONTWAIT);
if ((m->m_flags & M_EXT) == 0) {
virtio_enqueue_abort(vsc, vq, slot);
m_freem(m);
- rxq->rxq_mbuf_enobufs.ev_count++;
+ rxc->rxc_mbuf_enobufs.ev_count++;
break;
}
@@ -1561,14 +1621,14 @@ vioif_populate_rx_mbufs_locked(struct vi
if (r != 0) {
virtio_enqueue_abort(vsc, vq, slot);
m_freem(m);
- rxq->rxq_mbuf_load_failed.ev_count++;
+ netq->netq_mbuf_load_failed.ev_count++;
break;
}
r = virtio_enqueue_reserve(vsc, vq, slot,
map->vnm_mbuf_map->dm_nsegs + 1);
if (r != 0) {
- rxq->rxq_enqueue_reserve_failed.ev_count++;
+ netq->netq_enqueue_reserve_failed.ev_count++;
bus_dmamap_unload(virtio_dmat(vsc), map->vnm_mbuf_map);
m_freem(m);
/* slot already freed by virtio_enqueue_reserve */
@@ -1591,23 +1651,23 @@ vioif_populate_rx_mbufs_locked(struct vi
static void
vioif_rx_queue_clear(struct vioif_softc *sc, struct virtio_softc *vsc,
- struct vioif_rxqueue *rxq)
+ struct vioif_netqueue *netq)
{
struct vioif_net_map *map;
unsigned int i, vq_num;
bool more;
- mutex_enter(rxq->rxq_lock);
- vq_num = rxq->rxq_vq->vq_num;
+ mutex_enter(&netq->netq_lock);
+ vq_num = netq->netq_vq->vq_num;
for (;;) {
- more = vioif_rx_deq_locked(sc, vsc, rxq, vq_num, NULL);
+ more = vioif_rx_deq_locked(sc, vsc, netq, vq_num, NULL);
if (more == false)
break;
}
for (i = 0; i < vq_num; i++) {
- map = &rxq->rxq_maps[i];
+ map = &netq->netq_maps[i];
if (map->vnm_mbuf == NULL)
continue;
@@ -1616,15 +1676,15 @@ vioif_rx_queue_clear(struct vioif_softc
m_freem(map->vnm_mbuf);
map->vnm_mbuf = NULL;
}
- mutex_exit(rxq->rxq_lock);
+ mutex_exit(&netq->netq_lock);
}
/* dequeue received packets */
static bool
vioif_rx_deq_locked(struct vioif_softc *sc, struct virtio_softc *vsc,
- struct vioif_rxqueue *rxq, u_int limit, size_t *ndeqp)
+ struct vioif_netqueue *netq, u_int limit, size_t *ndeqp)
{
- struct virtqueue *vq = rxq->rxq_vq;
+ struct virtqueue *vq = netq->netq_vq;
struct ifnet *ifp = &sc->sc_ethercom.ec_if;
struct vioif_net_map *map;
struct mbuf *m;
@@ -1632,7 +1692,7 @@ vioif_rx_deq_locked(struct vioif_softc *
bool more;
size_t ndeq;
- KASSERT(mutex_owned(rxq->rxq_lock));
+ KASSERT(mutex_owned(&netq->netq_lock));
more = false;
ndeq = 0;
@@ -1649,7 +1709,7 @@ vioif_rx_deq_locked(struct vioif_softc *
if (virtio_dequeue(vsc, vq, &slot, &len) != 0)
break;
- map = &rxq->rxq_maps[slot];
+ map = &netq->netq_maps[slot];
KASSERT(map->vnm_mbuf != NULL);
bus_dmamap_sync(virtio_dmat(vsc), map->vnm_hdr_map,
@@ -1677,106 +1737,87 @@ done:
/* rx interrupt; call _dequeue above and schedule a softint */
static void
-vioif_rx_handle_locked(void *xrxq, u_int limit)
+vioif_rx_handle_locked(void *xnetq, u_int limit)
{
- struct vioif_rxqueue *rxq = xrxq;
- struct virtqueue *vq = rxq->rxq_vq;
+ struct vioif_netqueue *netq = xnetq;
+ struct virtqueue *vq = netq->netq_vq;
struct virtio_softc *vsc = vq->vq_owner;
struct vioif_softc *sc = device_private(virtio_child(vsc));
bool more;
int enqueued;
size_t ndeq;
- KASSERT(mutex_owned(rxq->rxq_lock));
- KASSERT(!rxq->rxq_stopping);
+ KASSERT(mutex_owned(&netq->netq_lock));
+ KASSERT(!netq->netq_stopping);
- more = vioif_rx_deq_locked(sc, vsc, rxq, limit, &ndeq);
+ more = vioif_rx_deq_locked(sc, vsc, netq, limit, &ndeq);
if (ndeq > 0)
- vioif_populate_rx_mbufs_locked(sc, rxq);
+ vioif_populate_rx_mbufs_locked(sc, netq);
if (more) {
- vioif_rx_sched_handle(sc, rxq);
+ vioif_net_sched_handle(sc, netq);
return;
}
- enqueued = virtio_start_vq_intr(vsc, rxq->rxq_vq);
+ enqueued = virtio_start_vq_intr(vsc, netq->netq_vq);
if (enqueued != 0) {
- virtio_stop_vq_intr(vsc, rxq->rxq_vq);
- vioif_rx_sched_handle(sc, rxq);
+ virtio_stop_vq_intr(vsc, netq->netq_vq);
+ vioif_net_sched_handle(sc, netq);
return;
}
- rxq->rxq_running_handle = false;
+ netq->netq_running_handle = false;
}
static int
vioif_rx_intr(void *arg)
{
- struct vioif_rxqueue *rxq = arg;
- struct virtqueue *vq = rxq->rxq_vq;
+ struct vioif_netqueue *netq = arg;
+ struct virtqueue *vq = netq->netq_vq;
struct virtio_softc *vsc = vq->vq_owner;
struct vioif_softc *sc = device_private(virtio_child(vsc));
u_int limit;
+ mutex_enter(&netq->netq_lock);
- mutex_enter(rxq->rxq_lock);
-
- /* rx handler is already running in softint/workqueue */
- if (rxq->rxq_running_handle)
+ /* handler is already running in softint/workqueue */
+ if (netq->netq_running_handle)
goto done;
- if (rxq->rxq_stopping)
- goto done;
-
- rxq->rxq_running_handle = true;
+ netq->netq_running_handle = true;
limit = sc->sc_rx_intr_process_limit;
virtio_stop_vq_intr(vsc, vq);
- vioif_rx_handle_locked(rxq, limit);
+ vioif_rx_handle_locked(netq, limit);
done:
- mutex_exit(rxq->rxq_lock);
+ mutex_exit(&netq->netq_lock);
return 1;
}
static void
-vioif_rx_handle(void *xrxq)
+vioif_rx_handle(void *xnetq)
{
- struct vioif_rxqueue *rxq = xrxq;
- struct virtqueue *vq = rxq->rxq_vq;
+ struct vioif_netqueue *netq = xnetq;
+ struct virtqueue *vq = netq->netq_vq;
struct virtio_softc *vsc = vq->vq_owner;
struct vioif_softc *sc = device_private(virtio_child(vsc));
u_int limit;
- mutex_enter(rxq->rxq_lock);
+ mutex_enter(&netq->netq_lock);
- KASSERT(rxq->rxq_running_handle);
+ KASSERT(netq->netq_running_handle);
- if (rxq->rxq_stopping) {
- rxq->rxq_running_handle = false;
+ if (netq->netq_stopping) {
+ netq->netq_running_handle = false;
goto done;
}
limit = sc->sc_rx_process_limit;
- vioif_rx_handle_locked(rxq, limit);
+ vioif_rx_handle_locked(netq, limit);
done:
- mutex_exit(rxq->rxq_lock);
-}
-
-static void
-vioif_rx_sched_handle(struct vioif_softc *sc, struct vioif_rxqueue *rxq)
-{
-
- KASSERT(mutex_owned(rxq->rxq_lock));
-
- if (rxq->rxq_stopping)
- return;
-
- if (rxq->rxq_workqueue)
- vioif_work_add(sc->sc_txrx_workqueue, &rxq->rxq_work);
- else
- softint_schedule(rxq->rxq_handle_si);
+ mutex_exit(&netq->netq_lock);
}
/*
@@ -1790,21 +1831,22 @@ vioif_rx_sched_handle(struct vioif_softc
*/
static void
-vioif_tx_handle_locked(struct vioif_txqueue *txq, u_int limit)
+vioif_tx_handle_locked(struct vioif_netqueue *netq, u_int limit)
{
- struct virtqueue *vq = txq->txq_vq;
+ struct virtqueue *vq = netq->netq_vq;
+ struct vioif_tx_context *txc = netq->netq_ctx;
struct virtio_softc *vsc = vq->vq_owner;
struct vioif_softc *sc = device_private(virtio_child(vsc));
struct ifnet *ifp = &sc->sc_ethercom.ec_if;
bool more;
int enqueued;
- KASSERT(mutex_owned(txq->txq_lock));
- KASSERT(!txq->txq_stopping);
+ KASSERT(mutex_owned(&netq->netq_lock));
+ KASSERT(!netq->netq_stopping);
- more = vioif_tx_deq_locked(sc, vsc, txq, limit);
+ more = vioif_tx_deq_locked(sc, vsc, netq, limit);
if (more) {
- vioif_tx_sched_handle(sc, txq);
+ vioif_net_sched_handle(sc, netq);
return;
}
@@ -1813,111 +1855,94 @@ vioif_tx_handle_locked(struct vioif_txqu
virtio_start_vq_intr(vsc, vq);
if (enqueued != 0) {
virtio_stop_vq_intr(vsc, vq);
- vioif_tx_sched_handle(sc, txq);
+ vioif_net_sched_handle(sc, netq);
return;
}
- txq->txq_running_handle = false;
+ netq->netq_running_handle = false;
/* for ALTQ */
- if (txq == &sc->sc_txq[0]) {
+ if (netq == &sc->sc_netqs[VIOIF_NETQ_TXQID(0)]) {
if_schedule_deferred_start(ifp);
ifp->if_flags &= ~IFF_OACTIVE;
}
- softint_schedule(txq->txq_deferred_transmit);
+ softint_schedule(txc->txc_deferred_transmit);
}
-
static int
vioif_tx_intr(void *arg)
{
- struct vioif_txqueue *txq = arg;
- struct virtqueue *vq = txq->txq_vq;
+ struct vioif_netqueue *netq = arg;
+ struct virtqueue *vq = netq->netq_vq;
struct virtio_softc *vsc = vq->vq_owner;
struct vioif_softc *sc = device_private(virtio_child(vsc));
u_int limit;
- limit = sc->sc_tx_intr_process_limit;
-
- mutex_enter(txq->txq_lock);
+ mutex_enter(&netq->netq_lock);
/* tx handler is already running in softint/workqueue */
- if (txq->txq_running_handle)
+ if (netq->netq_running_handle)
goto done;
- if (txq->txq_stopping)
+ if (netq->netq_stopping)
goto done;
- txq->txq_running_handle = true;
+ netq->netq_running_handle = true;
virtio_stop_vq_intr(vsc, vq);
- txq->txq_workqueue = sc->sc_txrx_workqueue_sysctl;
- vioif_tx_handle_locked(txq, limit);
+ netq->netq_workqueue = sc->sc_txrx_workqueue_sysctl;
+ limit = sc->sc_tx_intr_process_limit;
+ vioif_tx_handle_locked(netq, limit);
done:
- mutex_exit(txq->txq_lock);
+ mutex_exit(&netq->netq_lock);
return 1;
}
static void
-vioif_tx_handle(void *xtxq)
+vioif_tx_handle(void *xnetq)
{
- struct vioif_txqueue *txq = xtxq;
- struct virtqueue *vq = txq->txq_vq;
+ struct vioif_netqueue *netq = xnetq;
+ struct virtqueue *vq = netq->netq_vq;
struct virtio_softc *vsc = vq->vq_owner;
struct vioif_softc *sc = device_private(virtio_child(vsc));
u_int limit;
- mutex_enter(txq->txq_lock);
+ mutex_enter(&netq->netq_lock);
- KASSERT(txq->txq_running_handle);
+ KASSERT(netq->netq_running_handle);
- if (txq->txq_stopping) {
- txq->txq_running_handle = false;
+ if (netq->netq_stopping) {
+ netq->netq_running_handle = false;
goto done;
}
limit = sc->sc_tx_process_limit;
- vioif_tx_handle_locked(txq, limit);
+ vioif_tx_handle_locked(netq, limit);
done:
- mutex_exit(txq->txq_lock);
-}
-
-static void
-vioif_tx_sched_handle(struct vioif_softc *sc, struct vioif_txqueue *txq)
-{
-
- KASSERT(mutex_owned(txq->txq_lock));
-
- if (txq->txq_stopping)
- return;
-
- if (txq->txq_workqueue)
- vioif_work_add(sc->sc_txrx_workqueue, &txq->txq_work);
- else
- softint_schedule(txq->txq_handle_si);
+ mutex_exit(&netq->netq_lock);
}
static void
vioif_tx_queue_clear(struct vioif_softc *sc, struct virtio_softc *vsc,
- struct vioif_txqueue *txq)
+ struct vioif_netqueue *netq)
{
struct vioif_net_map *map;
unsigned int i, vq_num;
bool more;
- mutex_enter(txq->txq_lock);
+ mutex_enter(&netq->netq_lock);
- vq_num = txq->txq_vq->vq_num;
+ vq_num = netq->netq_vq->vq_num;
for (;;) {
- more = vioif_tx_deq_locked(sc, vsc, txq, vq_num);
+ more = vioif_tx_deq_locked(sc, vsc, netq, vq_num);
if (more == false)
break;
}
for (i = 0; i < vq_num; i++) {
- map = &txq->txq_maps[i];
+ map = &netq->netq_maps[i];
if (map->vnm_mbuf == NULL)
continue;
@@ -1925,21 +1950,21 @@ vioif_tx_queue_clear(struct vioif_softc
m_freem(map->vnm_mbuf);
map->vnm_mbuf = NULL;
}
- mutex_exit(txq->txq_lock);
+ mutex_exit(&netq->netq_lock);
}
static bool
vioif_tx_deq_locked(struct vioif_softc *sc, struct virtio_softc *vsc,
- struct vioif_txqueue *txq, u_int limit)
+ struct vioif_netqueue *netq, u_int limit)
{
- struct virtqueue *vq = txq->txq_vq;
+ struct virtqueue *vq = netq->netq_vq;
struct ifnet *ifp = &sc->sc_ethercom.ec_if;
struct vioif_net_map *map;
struct mbuf *m;
int slot, len;
bool more = false;
- KASSERT(mutex_owned(txq->txq_lock));
+ KASSERT(mutex_owned(&netq->netq_lock));
if (virtio_vq_is_enqueued(vsc, vq) == false)
return false;
@@ -1953,7 +1978,7 @@ vioif_tx_deq_locked(struct vioif_softc *
if (virtio_dequeue(vsc, vq, &slot, &len) != 0)
break;
- map = &txq->txq_maps[slot];
+ map = &netq->netq_maps[slot];
KASSERT(map->vnm_mbuf != NULL);
bus_dmamap_sync(virtio_dmat(vsc), map->vnm_hdr_map,
@@ -2444,7 +2469,8 @@ static void
vioif_update_link_status(struct vioif_softc *sc)
{
struct ifnet *ifp = &sc->sc_ethercom.ec_if;
- struct vioif_txqueue *txq;
+ struct vioif_netqueue *netq;
+ struct vioif_tx_context *txc;
bool active;
int link, i;
@@ -2459,11 +2485,12 @@ vioif_update_link_status(struct vioif_so
active = VIOIF_IS_LINK_ACTIVE(sc);
for (i = 0; i < sc->sc_act_nvq_pairs; i++) {
- txq = &sc->sc_txq[i];
+ netq = &sc->sc_netqs[VIOIF_NETQ_TXQID(i)];
- mutex_enter(txq->txq_lock);
- txq->txq_link_active = active;
- mutex_exit(txq->txq_lock);
+ mutex_enter(&netq->netq_lock);
+ txc = netq->netq_ctx;
+ txc->txc_link_active = active;
+ mutex_exit(&netq->netq_lock);
}
if_link_state_change(ifp, sc->sc_link_state);
@@ -2628,31 +2655,34 @@ out:
static void
vioif_setup_stats(struct vioif_softc *sc)
{
- struct vioif_rxqueue *rxq;
- struct vioif_txqueue *txq;
- int i;
-
- for (i = 0; i < sc->sc_max_nvq_pairs; i++) {
- rxq = &sc->sc_rxq[i];
- txq = &sc->sc_txq[i];
-
- snprintf(txq->txq_evgroup, sizeof(txq->txq_evgroup), "%s-TX%d",
- device_xname(sc->sc_dev), i);
- evcnt_attach_dynamic(&txq->txq_defrag_failed, EVCNT_TYPE_MISC,
- NULL, txq->txq_evgroup, "tx m_defrag() failed");
- evcnt_attach_dynamic(&txq->txq_mbuf_load_failed, EVCNT_TYPE_MISC,
- NULL, txq->txq_evgroup, "tx dmamap load failed");
- evcnt_attach_dynamic(&txq->txq_enqueue_reserve_failed, EVCNT_TYPE_MISC,
- NULL, txq->txq_evgroup, "virtio_enqueue_reserve failed");
-
- snprintf(rxq->rxq_evgroup, sizeof(rxq->rxq_evgroup), "%s-RX%d",
- device_xname(sc->sc_dev), i);
- evcnt_attach_dynamic(&rxq->rxq_mbuf_enobufs, EVCNT_TYPE_MISC,
- NULL, rxq->rxq_evgroup, "no receive buffer");
- evcnt_attach_dynamic(&rxq->rxq_mbuf_load_failed, EVCNT_TYPE_MISC,
- NULL, rxq->rxq_evgroup, "tx dmamap load failed");
- evcnt_attach_dynamic(&rxq->rxq_enqueue_reserve_failed, EVCNT_TYPE_MISC,
- NULL, rxq->rxq_evgroup, "virtio_enqueue_reserve failed");
+ struct vioif_netqueue *netq;
+ struct vioif_tx_context *txc;
+ struct vioif_rx_context *rxc;
+ size_t i, netq_num;
+
+ netq_num = sc->sc_max_nvq_pairs * 2;
+ for (i = 0; i < netq_num; i++) {
+ netq = &sc->sc_netqs[i];
+ evcnt_attach_dynamic(&netq->netq_mbuf_load_failed, EVCNT_TYPE_MISC,
+ NULL, netq->netq_evgroup, "failed to load mbuf to DMA");
+ evcnt_attach_dynamic(&netq->netq_enqueue_reserve_failed,
+ EVCNT_TYPE_MISC, NULL, netq->netq_evgroup,
+ "virtio_enqueue_reserve failed");
+
+ switch (VIOIF_NETQ_DIR(i)) {
+ case VIOIF_NETQ_RX:
+ rxc = netq->netq_ctx;
+ evcnt_attach_dynamic(&rxc->rxc_mbuf_enobufs,
+ EVCNT_TYPE_MISC, NULL, netq->netq_evgroup,
+ "no receive buffer");
+ break;
+ case VIOIF_NETQ_TX:
+ txc = netq->netq_ctx;
+ evcnt_attach_dynamic(&txc->txc_defrag_failed,
+ EVCNT_TYPE_MISC, NULL, netq->netq_evgroup,
+ "m_defrag() failed");
+ break;
+ }
}
evcnt_attach_dynamic(&sc->sc_ctrlq.ctrlq_cmd_load_failed, EVCNT_TYPE_MISC,