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