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