Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/dev/pci Implement softint-based interrupt handling in if...



details:   https://anonhg.NetBSD.org/src/rev/76aa93cc4d7c
branches:  trunk
changeset: 334979:76aa93cc4d7c
user:      ozaki-r <ozaki-r%NetBSD.org@localhost>
date:      Fri Dec 19 06:54:40 2014 +0000

description:
Implement softint-based interrupt handling in if_vioif

Softint-based interrupt handling is considered as a future direction
of the (network) device driver architecture in NetBSD. pq3etsec of
ppc is already implemented based on the architecture (unlike pq3etsec,
this change doesn't include softint-based if_start). In this
architecture, a hardware interrupt handler just schedules a softint
and the softint performs actual interrupt processing. It reduces
processing in hardware interrupt context and allows Layer 2 network
stack (e.g., bridge, vlan and even bpf) run in softint context,
which makes it easy to implement fine-grain locking in the layer.

This is an experimental implementation of the architecture in if_viof.

virtio introduces a new flag VIRTIO_F_PCI_INTR_SOFTINT. If a driver
of virtio sets it to sc_flags of virtio_softc, virtio calls
softint_schedule in virtio_intr instead of directly calling the
interrupt handler of the driver.

When VIOIF_SOFTINT_INTR is on, vioif doesn't use the existing softint
(vioif_rx_softint) that is called from vioif_rx_vq_done. Because
vioif_rx_softint already runs in softint context and another softint
isn't needed. This change actually improves performance in some cases.

The feature is disabled by default and enabled when SOFTINT_INTR is
set somewhere (normally in a kernel configuration).

diffstat:

 sys/dev/pci/if_vioif.c  |  36 +++++++++++++++++++++++++++++-------
 sys/dev/pci/virtio.c    |  34 ++++++++++++++++++++++++++++++----
 sys/dev/pci/virtiovar.h |   4 +++-
 3 files changed, 62 insertions(+), 12 deletions(-)

diffs (211 lines):

diff -r 09d137fa4a7e -r 76aa93cc4d7c sys/dev/pci/if_vioif.c
--- a/sys/dev/pci/if_vioif.c    Fri Dec 19 05:21:51 2014 +0000
+++ b/sys/dev/pci/if_vioif.c    Fri Dec 19 06:54:40 2014 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: if_vioif.c,v 1.11 2014/10/09 04:58:42 ozaki-r Exp $    */
+/*     $NetBSD: if_vioif.c,v 1.12 2014/12/19 06:54:40 ozaki-r Exp $    */
 
 /*
  * Copyright (c) 2010 Minoura Makoto.
@@ -26,7 +26,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: if_vioif.c,v 1.11 2014/10/09 04:58:42 ozaki-r Exp $");
+__KERNEL_RCSID(0, "$NetBSD: if_vioif.c,v 1.12 2014/12/19 06:54:40 ozaki-r Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -39,6 +39,7 @@
 #include <sys/mbuf.h>
 #include <sys/mutex.h>
 #include <sys/sockio.h>
+#include <sys/cpu.h>
 
 #include <dev/pci/pcidevs.h>
 #include <dev/pci/pcireg.h>
@@ -57,6 +58,10 @@
 #define VIOIF_MPSAFE   1
 #endif
 
+#ifdef SOFTINT_INTR
+#define VIOIF_SOFTINT_INTR     1
+#endif
+
 /*
  * if_vioifreg.h:
  */
@@ -220,6 +225,7 @@
 static int     vioif_add_rx_mbuf(struct vioif_softc *, int);
 static void    vioif_free_rx_mbuf(struct vioif_softc *, int);
 static void    vioif_populate_rx_mbufs(struct vioif_softc *);
+static void    vioif_populate_rx_mbufs_locked(struct vioif_softc *);
 static int     vioif_rx_deq(struct vioif_softc *);
 static int     vioif_rx_deq_locked(struct vioif_softc *);
 static int     vioif_rx_vq_done(struct virtqueue *);
@@ -498,6 +504,9 @@
 #ifdef VIOIF_MPSAFE
        vsc->sc_flags |= VIRTIO_F_PCI_INTR_MPSAFE;
 #endif
+#ifdef VIOIF_SOFTINT_INTR
+       vsc->sc_flags |= VIRTIO_F_PCI_INTR_SOFTINT;
+#endif
 
        features = virtio_negotiate_features(vsc,
                                             (VIRTIO_NET_F_MAC |
@@ -883,14 +892,22 @@
 static void
 vioif_populate_rx_mbufs(struct vioif_softc *sc)
 {
+       VIOIF_RX_LOCK(sc);
+       vioif_populate_rx_mbufs_locked(sc);
+       VIOIF_RX_UNLOCK(sc);
+}
+
+static void
+vioif_populate_rx_mbufs_locked(struct vioif_softc *sc)
+{
        struct virtio_softc *vsc = sc->sc_virtio;
        int i, r, ndone = 0;
        struct virtqueue *vq = &sc->sc_vq[0]; /* rx vq */
 
-       VIOIF_RX_LOCK(sc);
+       KASSERT(VIOIF_RX_LOCKED(sc));
 
        if (sc->sc_stopping)
-               goto out;
+               return;
 
        for (i = 0; i < vq->vq_num; i++) {
                int slot;
@@ -925,9 +942,6 @@
        }
        if (ndone > 0)
                virtio_enqueue_commit(vsc, vq, -1, true);
-
-out:
-       VIOIF_RX_UNLOCK(sc);
 }
 
 /* dequeue recieved packets */
@@ -996,6 +1010,10 @@
        struct vioif_softc *sc = device_private(vsc->sc_child);
        int r = 0;
 
+#ifdef VIOIF_SOFTINT_INTR
+       KASSERT(!cpu_intr_p());
+#endif
+
        VIOIF_RX_LOCK(sc);
 
        if (sc->sc_stopping)
@@ -1003,7 +1021,11 @@
 
        r = vioif_rx_deq_locked(sc);
        if (r)
+#ifdef VIOIF_SOFTINT_INTR
+               vioif_populate_rx_mbufs_locked(sc);
+#else
                softint_schedule(sc->sc_rx_softint);
+#endif
 
 out:
        VIOIF_RX_UNLOCK(sc);
diff -r 09d137fa4a7e -r 76aa93cc4d7c sys/dev/pci/virtio.c
--- a/sys/dev/pci/virtio.c      Fri Dec 19 05:21:51 2014 +0000
+++ b/sys/dev/pci/virtio.c      Fri Dec 19 06:54:40 2014 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: virtio.c,v 1.7 2014/10/06 13:31:54 mlelstv Exp $       */
+/*     $NetBSD: virtio.c,v 1.8 2014/12/19 06:54:40 ozaki-r Exp $       */
 
 /*
  * Copyright (c) 2010 Minoura Makoto.
@@ -26,7 +26,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: virtio.c,v 1.7 2014/10/06 13:31:54 mlelstv Exp $");
+__KERNEL_RCSID(0, "$NetBSD: virtio.c,v 1.8 2014/12/19 06:54:40 ozaki-r Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -49,6 +49,7 @@
 static void    virtio_attach(device_t, device_t, void *);
 static int     virtio_detach(device_t, int);
 static int     virtio_intr(void *arg);
+static void    virtio_soft_intr(void *arg);
 static void    virtio_init_vq(struct virtio_softc *,
                    struct virtqueue *, const bool);
 
@@ -188,6 +189,17 @@
        }
        aprint_normal_dev(self, "interrupting at %s\n", intrstr);
 
+       sc->sc_soft_ih = NULL;
+       if (sc->sc_flags & VIRTIO_F_PCI_INTR_SOFTINT) {
+               u_int flags = SOFTINT_NET;
+               if (sc->sc_flags & VIRTIO_F_PCI_INTR_MPSAFE)
+                       flags |= SOFTINT_MPSAFE;
+
+               sc->sc_soft_ih = softint_establish(flags, virtio_soft_intr, sc);
+               if (sc->sc_soft_ih == NULL)
+                       aprint_error(": failed to establish soft interrupt\n");
+       }
+
        virtio_set_status(sc, VIRTIO_CONFIG_DEVICE_STATUS_DRIVER_OK);
 
        return;
@@ -388,12 +400,26 @@
        if ((isr & VIRTIO_CONFIG_ISR_CONFIG_CHANGE) &&
            (sc->sc_config_change != NULL))
                r = (sc->sc_config_change)(sc);
-       if (sc->sc_intrhand != NULL)
-               r |= (sc->sc_intrhand)(sc);
+       if (sc->sc_intrhand != NULL) {
+               if (sc->sc_soft_ih != NULL)
+                       softint_schedule(sc->sc_soft_ih);
+               else
+                       r |= (sc->sc_intrhand)(sc);
+       }
 
        return r;
 }
 
+static void
+virtio_soft_intr(void *arg)
+{
+       struct virtio_softc *sc = arg;
+
+       KASSERT(sc->sc_intrhand != NULL);
+
+       (sc->sc_intrhand)(sc);
+}
+
 /*
  * dmamap sync operations for a virtqueue.
  */
diff -r 09d137fa4a7e -r 76aa93cc4d7c sys/dev/pci/virtiovar.h
--- a/sys/dev/pci/virtiovar.h   Fri Dec 19 05:21:51 2014 +0000
+++ b/sys/dev/pci/virtiovar.h   Fri Dec 19 06:54:40 2014 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: virtiovar.h,v 1.3 2014/07/22 01:55:54 ozaki-r Exp $    */
+/*     $NetBSD: virtiovar.h,v 1.4 2014/12/19 06:54:40 ozaki-r Exp $    */
 
 /*
  * Copyright (c) 2010 Minoura Makoto.
@@ -126,6 +126,7 @@
 
        int                     sc_ipl; /* set by child */
        void                    *sc_ih;
+       void                    *sc_soft_ih;
 
        int                     sc_flags; /* set by child */
 
@@ -149,6 +150,7 @@
 };
 
 #define VIRTIO_F_PCI_INTR_MPSAFE       (1 << 0)
+#define VIRTIO_F_PCI_INTR_SOFTINT      (1 << 1)
 
 /* public interface */
 uint32_t virtio_negotiate_features(struct virtio_softc*, uint32_t);



Home | Main Index | Thread Index | Old Index