Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/dev/pci Introduce packet handling in softint or kthread ...
details: https://anonhg.NetBSD.org/src/rev/535cdbd13735
branches: trunk
changeset: 933348:535cdbd13735
user: yamaguchi <yamaguchi%NetBSD.org@localhost>
date: Mon May 25 08:16:23 2020 +0000
description:
Introduce packet handling in softint or kthread for vioif(4)
diffstat:
sys/dev/pci/if_vioif.c | 543 +++++++++++++++++++++++++++++++++++++++++++-----
1 files changed, 481 insertions(+), 62 deletions(-)
diffs (truncated from 812 to 300 lines):
diff -r 1c2788e33853 -r 535cdbd13735 sys/dev/pci/if_vioif.c
--- a/sys/dev/pci/if_vioif.c Mon May 25 07:52:16 2020 +0000
+++ b/sys/dev/pci/if_vioif.c Mon May 25 08:16:23 2020 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: if_vioif.c,v 1.54 2020/05/25 07:52:16 yamaguchi Exp $ */
+/* $NetBSD: if_vioif.c,v 1.55 2020/05/25 08:16:23 yamaguchi Exp $ */
/*
* Copyright (c) 2010 Minoura Makoto.
@@ -26,7 +26,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: if_vioif.c,v 1.54 2020/05/25 07:52:16 yamaguchi Exp $");
+__KERNEL_RCSID(0, "$NetBSD: if_vioif.c,v 1.55 2020/05/25 08:16:23 yamaguchi Exp $");
#ifdef _KERNEL_OPT
#include "opt_net_mpsafe.h"
@@ -35,6 +35,7 @@
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
+#include <sys/atomic.h>
#include <sys/bus.h>
#include <sys/condvar.h>
#include <sys/device.h>
@@ -46,6 +47,7 @@
#include <sys/cpu.h>
#include <sys/module.h>
#include <sys/pcq.h>
+#include <sys/workqueue.h>
#include <dev/pci/virtioreg.h>
#include <dev/pci/virtiovar.h>
@@ -205,6 +207,13 @@
* - txq_lock or rxq_lock cannot be held along with ctrlq_wait_lock
*/
+struct vioif_work {
+ struct work cookie;
+ void (*func)(void *);
+ void *arg;
+ unsigned int added;
+};
+
struct vioif_txqueue {
kmutex_t *txq_lock; /* lock for tx operations */
@@ -220,6 +229,10 @@
bus_dmamap_t *txq_dmamaps;
void *txq_deferred_transmit;
+ void *txq_handle_si;
+ struct vioif_work txq_work;
+ bool txq_workqueue;
+ bool txq_active;
};
struct vioif_rxqueue {
@@ -235,6 +248,10 @@
bus_dmamap_t *rxq_dmamaps;
void *rxq_softint;
+ void *rxq_handle_si;
+ struct vioif_work rxq_work;
+ bool rxq_workqueue;
+ bool rxq_active;
};
struct vioif_ctrlqueue {
@@ -263,6 +280,7 @@
struct vioif_softc {
device_t sc_dev;
+ struct sysctllog *sc_sysctllog;
struct virtio_softc *sc_virtio;
struct virtqueue *sc_vqs;
@@ -287,14 +305,29 @@
void *sc_kmem;
void *sc_ctl_softint;
+
+ struct workqueue *sc_txrx_workqueue;
+ bool sc_txrx_workqueue_sysctl;
+ u_int sc_tx_intr_process_limit;
+ u_int sc_tx_process_limit;
+ u_int sc_rx_intr_process_limit;
+ u_int sc_rx_process_limit;
};
#define VIRTIO_NET_TX_MAXNSEGS (16) /* XXX */
#define VIRTIO_NET_CTRL_MAC_MAXENTRIES (64) /* XXX */
+#define VIOIF_TX_INTR_PROCESS_LIMIT 256
+#define VIOIF_TX_PROCESS_LIMIT 256
+#define VIOIF_RX_INTR_PROCESS_LIMIT 0U
+#define VIOIF_RX_PROCESS_LIMIT 256
+
+#define VIOIF_WORKQUEUE_PRI PRI_SOFTNET
+
/* cfattach interface functions */
static int vioif_match(device_t, cfdata_t, void *);
static void vioif_attach(device_t, device_t, void *);
static void vioif_deferred_init(device_t);
+static int vioif_finalize_teardown(device_t);
/* ifnet interface functions */
static int vioif_init(struct ifnet *);
@@ -311,18 +344,36 @@
static void vioif_free_rx_mbuf(struct vioif_rxqueue *, int);
static void vioif_populate_rx_mbufs(struct vioif_rxqueue *);
static void vioif_populate_rx_mbufs_locked(struct vioif_rxqueue *);
-static int vioif_rx_deq(struct vioif_rxqueue *);
-static int vioif_rx_deq_locked(struct vioif_rxqueue *);
+static void vioif_rx_queue_clear(struct vioif_rxqueue *);
+static bool vioif_rx_deq_locked(struct vioif_softc *, struct virtio_softc *,
+ struct vioif_rxqueue *, u_int);
static int vioif_rx_intr(void *);
+static void vioif_rx_handle(void *);
+static void vioif_rx_sched_handle(struct vioif_softc *,
+ struct vioif_rxqueue *);
static void vioif_rx_softint(void *);
static void vioif_rx_drain(struct vioif_rxqueue *);
/* tx */
static int vioif_tx_intr(void *);
-static int vioif_tx_deq_locked(struct virtqueue *);
+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_txqueue *);
+static bool vioif_tx_deq_locked(struct vioif_softc *, struct virtio_softc *,
+ struct vioif_txqueue *, u_int);
static void vioif_tx_drain(struct vioif_txqueue *);
static void vioif_deferred_transmit(void *);
+/* workqueue */
+static struct workqueue*
+ vioif_workq_create(const char *, pri_t, int, int);
+static void vioif_workq_destroy(struct workqueue *);
+static void vioif_workq_work(struct work *, void *);
+static void vioif_work_set(struct vioif_work *, void(*)(void *), void *);
+static void vioif_work_add(struct workqueue *, struct vioif_work *);
+static void vioif_work_wait(struct workqueue *, struct vioif_work *);
+
/* other control */
static bool vioif_is_link_up(struct vioif_softc *);
static void vioif_update_link_status(struct vioif_softc *);
@@ -337,6 +388,7 @@
static int vioif_ctrl_mq_vq_pairs_set(struct vioif_softc *, int);
static void vioif_enable_interrupt_vqpairs(struct vioif_softc *);
static void vioif_disable_interrupt_vqpairs(struct vioif_softc *);
+static int vioif_setup_sysctl(struct vioif_softc *);
CFATTACH_DECL_NEW(vioif, sizeof(struct vioif_softc),
vioif_match, vioif_attach, NULL, NULL);
@@ -672,6 +724,7 @@
struct ifnet *ifp = &sc->sc_ethercom.ec_if;
u_int softint_flags;
int r, i, nvqs=0, req_flags;
+ char xnamebuf[MAXCOMLEN];
if (virtio_child(vsc) != NULL) {
aprint_normal(": child already attached for %s; "
@@ -686,6 +739,17 @@
sc->sc_max_nvq_pairs = 1;
sc->sc_req_nvq_pairs = 1;
sc->sc_act_nvq_pairs = 1;
+ sc->sc_txrx_workqueue_sysctl = true;
+ sc->sc_tx_intr_process_limit = VIOIF_TX_INTR_PROCESS_LIMIT;
+ sc->sc_tx_process_limit = VIOIF_TX_PROCESS_LIMIT;
+ sc->sc_rx_intr_process_limit = VIOIF_RX_INTR_PROCESS_LIMIT;
+ sc->sc_rx_process_limit = VIOIF_RX_PROCESS_LIMIT;
+
+ snprintf(xnamebuf, sizeof(xnamebuf), "%s_txrx", device_xname(self));
+ sc->sc_txrx_workqueue = vioif_workq_create(xnamebuf, VIOIF_WORKQUEUE_PRI,
+ IPL_NET, WQ_PERCPU | WQ_MPSAFE);
+ if (sc->sc_txrx_workqueue == NULL)
+ goto err;
req_flags = 0;
@@ -774,6 +838,13 @@
aprint_error_dev(self, "cannot establish rx softint\n");
goto err;
}
+ 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+sizeof(struct virtio_net_hdr), nvqs, qname);
@@ -783,14 +854,23 @@
rxq->rxq_vq->vq_intrhand = vioif_rx_intr;
rxq->rxq_vq->vq_intrhand_arg = (void *)rxq;
rxq->rxq_stopping = true;
+ 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,
sizeof(struct virtio_net_hdr)
@@ -804,6 +884,7 @@
txq->txq_link_active = sc->sc_link_active;
txq->txq_stopping = 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) {
@@ -840,6 +921,11 @@
if (virtio_child_attach_finish(vsc) != 0)
goto err;
+ if (vioif_setup_sysctl(sc) != 0) {
+ aprint_error_dev(self, "unable to create sysctl node\n");
+ /* continue */
+ }
+
strlcpy(ifp->if_xname, device_xname(self), IFNAMSIZ);
ifp->if_softc = sc;
ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
@@ -881,11 +967,21 @@
rxq->rxq_softint = 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;
@@ -906,11 +1002,25 @@
virtio_free_vq(vsc, &sc->sc_vqs[--nvqs]);
vioif_free_queues(sc);
-
virtio_child_attach_failed(vsc);
+ config_finalize_register(self, vioif_finalize_teardown);
+
return;
}
+static int
+vioif_finalize_teardown(device_t self)
+{
+ struct vioif_softc *sc = device_private(self);
+
+ if (sc->sc_txrx_workqueue != NULL) {
+ vioif_workq_destroy(sc->sc_txrx_workqueue);
+ sc->sc_txrx_workqueue = NULL;
+ }
+
+ return 0;
+}
+
/* we need interrupts to make promiscuous mode off */
static void
vioif_deferred_init(device_t self)
@@ -1049,8 +1159,26 @@
/* only way to stop I/O and DMA is resetting... */
virtio_reset(vsc);
- for (i = 0; i < sc->sc_act_nvq_pairs; i++)
- vioif_rx_deq(&sc->sc_rxq[i]);
+
+ /* rendezvous for finish of handlers */
+ for (i = 0; i < sc->sc_act_nvq_pairs; i++) {
+ txq = &sc->sc_txq[i];
+ rxq = &sc->sc_rxq[i];
Home |
Main Index |
Thread Index |
Old Index