commit 0693a2bc5ead3a8c441c42060ca6d9fc72528317 Author: Ryota Ozaki Date: Fri Dec 5 18:59:53 2014 +0900 softinted interrupts for vioif diff --git a/sys/dev/pci/if_vioif.c b/sys/dev/pci/if_vioif.c index 3058f6c..eac9219 100644 --- a/sys/dev/pci/if_vioif.c +++ b/sys/dev/pci/if_vioif.c @@ -39,6 +39,7 @@ __KERNEL_RCSID(0, "$NetBSD: if_vioif.c,v 1.11 2014/10/09 04:58:42 ozaki-r Exp $" #include #include #include +#include #include #include @@ -57,6 +58,10 @@ __KERNEL_RCSID(0, "$NetBSD: if_vioif.c,v 1.11 2014/10/09 04:58:42 ozaki-r Exp $" #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 self, void *aux) #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 *sc, int i) 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_softc *sc) } 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); diff --git a/sys/dev/pci/virtio.c b/sys/dev/pci/virtio.c index 450f52d..4ed30ac 100644 --- a/sys/dev/pci/virtio.c +++ b/sys/dev/pci/virtio.c @@ -49,6 +49,7 @@ static int virtio_match(device_t, cfdata_t, void *); 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 self, void *aux) } 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. */ diff --git a/sys/dev/pci/virtiovar.h b/sys/dev/pci/virtiovar.h index fee87c6..c65cab6 100644 --- a/sys/dev/pci/virtiovar.h +++ b/sys/dev/pci/virtiovar.h @@ -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);