Module Name:    src
Committed By:   ozaki-r
Date:           Fri Dec 19 06:54:40 UTC 2014

Modified Files:
        src/sys/dev/pci: if_vioif.c virtio.c virtiovar.h

Log Message:
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).


To generate a diff of this commit:
cvs rdiff -u -r1.11 -r1.12 src/sys/dev/pci/if_vioif.c
cvs rdiff -u -r1.7 -r1.8 src/sys/dev/pci/virtio.c
cvs rdiff -u -r1.3 -r1.4 src/sys/dev/pci/virtiovar.h

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.11 src/sys/dev/pci/if_vioif.c:1.12
--- src/sys/dev/pci/if_vioif.c:1.11	Thu Oct  9 04:58:42 2014
+++ src/sys/dev/pci/if_vioif.c	Fri Dec 19 06:54:40 2014
@@ -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 @@ __KERNEL_RCSID(0, "$NetBSD: if_vioif.c,v
 #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 @@ __KERNEL_RCSID(0, "$NetBSD: if_vioif.c,v
 #define VIOIF_MPSAFE	1
 #endif
 
+#ifdef SOFTINT_INTR
+#define VIOIF_SOFTINT_INTR	1
+#endif
+
 /*
  * if_vioifreg.h:
  */
@@ -220,6 +225,7 @@ static void	vioif_watchdog(struct ifnet 
 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 @@ vioif_attach(device_t parent, device_t s
 #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 @@ vioif_free_rx_mbuf(struct vioif_softc *s
 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 @@ vioif_populate_rx_mbufs(struct vioif_sof
 	}
 	if (ndone > 0)
 		virtio_enqueue_commit(vsc, vq, -1, true);
-
-out:
-	VIOIF_RX_UNLOCK(sc);
 }
 
 /* dequeue recieved packets */
@@ -996,6 +1010,10 @@ vioif_rx_vq_done(struct virtqueue *vq)
 	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 @@ vioif_rx_vq_done(struct virtqueue *vq)
 
 	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);

Index: src/sys/dev/pci/virtio.c
diff -u src/sys/dev/pci/virtio.c:1.7 src/sys/dev/pci/virtio.c:1.8
--- src/sys/dev/pci/virtio.c:1.7	Mon Oct  6 13:31:54 2014
+++ src/sys/dev/pci/virtio.c	Fri Dec 19 06:54:40 2014
@@ -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 int	virtio_match(device_t, cfdata
 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 @@ virtio_attach(device_t parent, device_t 
 	}
 	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 @@ virtio_intr(void *arg)
 	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.
  */

Index: src/sys/dev/pci/virtiovar.h
diff -u src/sys/dev/pci/virtiovar.h:1.3 src/sys/dev/pci/virtiovar.h:1.4
--- src/sys/dev/pci/virtiovar.h:1.3	Tue Jul 22 01:55:54 2014
+++ src/sys/dev/pci/virtiovar.h	Fri Dec 19 06:54:40 2014
@@ -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 @@ struct virtio_softc {
 
 	int			sc_ipl; /* set by child */
 	void			*sc_ih;
+	void			*sc_soft_ih;
 
 	int			sc_flags; /* set by child */
 
@@ -149,6 +150,7 @@ struct virtio_softc {
 };
 
 #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);

Reply via email to