Source-Changes-HG archive

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

[src/trunk]: src/sys/dev/pci Handle config change interrupts to inhibit sendi...



details:   https://anonhg.NetBSD.org/src/rev/8adce2ce1ca1
branches:  trunk
changeset: 822613:8adce2ce1ca1
user:      ozaki-r <ozaki-r%NetBSD.org@localhost>
date:      Tue Mar 28 04:10:33 2017 +0000

description:
Handle config change interrupts to inhibit sending packets while link down

PR kern/52103 by s-yamaguchi@IIJ

diffstat:

 sys/dev/pci/if_vioif.c |  102 ++++++++++++++++++++++++++++++++++++++++++++++--
 sys/dev/pci/virtio.c   |   11 ++--
 2 files changed, 103 insertions(+), 10 deletions(-)

diffs (225 lines):

diff -r 729b1a596597 -r 8adce2ce1ca1 sys/dev/pci/if_vioif.c
--- a/sys/dev/pci/if_vioif.c    Tue Mar 28 04:09:52 2017 +0000
+++ b/sys/dev/pci/if_vioif.c    Tue Mar 28 04:10:33 2017 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: if_vioif.c,v 1.33 2017/03/28 04:09:52 ozaki-r Exp $    */
+/*     $NetBSD: if_vioif.c,v 1.34 2017/03/28 04:10:33 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.33 2017/03/28 04:09:52 ozaki-r Exp $");
+__KERNEL_RCSID(0, "$NetBSD: if_vioif.c,v 1.34 2017/03/28 04:10:33 ozaki-r Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_net_mpsafe.h"
@@ -190,6 +190,7 @@
        uint8_t                 sc_mac[ETHER_ADDR_LEN];
        struct ethercom         sc_ethercom;
        short                   sc_deferred_init_done;
+       bool                    sc_link_active;
 
        /* bus_dmamem */
        bus_dma_segment_t       sc_hdr_segs[1];
@@ -218,6 +219,7 @@
        bus_dmamap_t            sc_ctrl_tbl_mc_dmamap;
 
        void                    *sc_rx_softint;
+       void                    *sc_ctl_softint;
 
        enum {
                FREE, INUSE, DONE
@@ -269,12 +271,16 @@
 static void    vioif_tx_drain(struct vioif_softc *);
 
 /* other control */
+static bool    vioif_is_link_up(struct vioif_softc *);
+static void    vioif_update_link_status(struct vioif_softc *);
 static int     vioif_ctrl_rx(struct vioif_softc *, int, bool);
 static int     vioif_set_promisc(struct vioif_softc *, bool);
 static int     vioif_set_allmulti(struct vioif_softc *, bool);
 static int     vioif_set_rx_filter(struct vioif_softc *);
 static int     vioif_rx_filter(struct vioif_softc *);
 static int     vioif_ctrl_vq_done(struct virtqueue *);
+static int     vioif_config_change(struct virtio_softc *);
+static void    vioif_ctl_softint(void *);
 
 CFATTACH_DECL_NEW(vioif, sizeof(struct vioif_softc),
                  vioif_match, vioif_attach, NULL, NULL);
@@ -524,6 +530,7 @@
 
        sc->sc_dev = self;
        sc->sc_virtio = vsc;
+       sc->sc_link_active = false;
 
        req_flags = 0;
 
@@ -536,7 +543,7 @@
        req_flags |= VIRTIO_F_PCI_INTR_MSIX;
 
        virtio_child_attach_start(vsc, self, IPL_NET, sc->sc_vq,
-           NULL, virtio_vq_intr, req_flags,
+           vioif_config_change, virtio_vq_intr, req_flags,
            (VIRTIO_NET_F_MAC | VIRTIO_NET_F_STATUS | VIRTIO_NET_F_CTRL_VQ |
             VIRTIO_NET_F_CTRL_RX | VIRTIO_F_NOTIFY_ON_EMPTY),
            VIRTIO_NET_FLAG_BITS);
@@ -648,7 +655,13 @@
 #endif
        sc->sc_rx_softint = softint_establish(flags, vioif_rx_softint, sc);
        if (sc->sc_rx_softint == NULL) {
-               aprint_error_dev(self, "cannot establish softint\n");
+               aprint_error_dev(self, "cannot establish rx softint\n");
+               goto err;
+       }
+
+       sc->sc_ctl_softint = softint_establish(flags, vioif_ctl_softint, sc);
+       if (sc->sc_ctl_softint == NULL) {
+               aprint_error_dev(self, "cannot establish ctl softint\n");
                goto err;
        }
 
@@ -741,6 +754,7 @@
 
        vioif_populate_rx_mbufs(sc);
 
+       vioif_update_link_status(sc);
        ifp->if_flags |= IFF_RUNNING;
        ifp->if_flags &= ~IFF_OACTIVE;
        vioif_rx_filter(sc);
@@ -772,6 +786,7 @@
        vioif_rx_deq(sc);
        vioif_tx_drain(sc);
        ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE);
+       sc->sc_link_active = false;
 
        if (disable)
                vioif_rx_drain(sc);
@@ -788,7 +803,8 @@
 
        VIOIF_TX_LOCK(sc);
 
-       if ((ifp->if_flags & (IFF_RUNNING|IFF_OACTIVE)) != IFF_RUNNING)
+       if ((ifp->if_flags & (IFF_RUNNING|IFF_OACTIVE)) != IFF_RUNNING ||
+           !sc->sc_link_active)
                goto out;
 
        if (sc->sc_stopping)
@@ -1503,6 +1519,82 @@
        return r;
 }
 
+static bool
+vioif_is_link_up(struct vioif_softc *sc)
+{
+       struct virtio_softc *vsc = sc->sc_virtio;
+       uint16_t status;
+
+       if (virtio_features(vsc) & VIRTIO_NET_F_STATUS)
+               status = virtio_read_device_config_2(vsc,
+                   VIRTIO_NET_CONFIG_STATUS);
+       else
+               status = VIRTIO_NET_S_LINK_UP;
+
+       return ((status & VIRTIO_NET_S_LINK_UP) != 0);
+}
+
+/* change link status */
+static void
+vioif_update_link_status(struct vioif_softc *sc)
+{
+       struct ifnet *ifp = &sc->sc_ethercom.ec_if;
+       bool active, changed;
+       int link;
+
+       active = vioif_is_link_up(sc);
+       changed = false;
+
+       VIOIF_TX_LOCK(sc);
+       if (active) {
+               if (!sc->sc_link_active)
+                       changed = true;
+
+               link = LINK_STATE_UP;
+               sc->sc_link_active = true;
+       } else {
+               if (sc->sc_link_active)
+                       changed = true;
+
+               link = LINK_STATE_DOWN;
+               sc->sc_link_active = false;
+       }
+       VIOIF_TX_UNLOCK(sc);
+
+       if (changed)
+               if_link_state_change(ifp, link);
+}
+
+static int
+vioif_config_change(struct virtio_softc *vsc)
+{
+       struct vioif_softc *sc = device_private(virtio_child(vsc));
+
+#ifdef VIOIF_SOFTINT_INTR
+       struct ifnet *ifp = &sc->sc_ethercom.ec_if;
+#endif
+
+#ifdef VIOIF_SOFTINT_INTR
+       KASSERT(!cpu_intr_p());
+       vioif_update_link_status(sc);
+       vioif_start(ifp);
+#else
+       softint_schedule(sc->sc_ctl_softint);
+#endif
+
+       return 0;
+}
+
+static void
+vioif_ctl_softint(void *arg)
+{
+       struct vioif_softc *sc = arg;
+       struct ifnet *ifp = &sc->sc_ethercom.ec_if;
+
+       vioif_update_link_status(sc);
+       vioif_start(ifp);
+}
+
 MODULE(MODULE_CLASS_DRIVER, if_vioif, "virtio");
  
 #ifdef _MODULE
diff -r 729b1a596597 -r 8adce2ce1ca1 sys/dev/pci/virtio.c
--- a/sys/dev/pci/virtio.c      Tue Mar 28 04:09:52 2017 +0000
+++ b/sys/dev/pci/virtio.c      Tue Mar 28 04:10:33 2017 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: virtio.c,v 1.26 2017/03/26 16:53:36 jdolecek Exp $     */
+/*     $NetBSD: virtio.c,v 1.27 2017/03/28 04:10:33 ozaki-r Exp $      */
 
 /*
  * Copyright (c) 2010 Minoura Makoto.
@@ -26,7 +26,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: virtio.c,v 1.26 2017/03/26 16:53:36 jdolecek Exp $");
+__KERNEL_RCSID(0, "$NetBSD: virtio.c,v 1.27 2017/03/28 04:10:33 ozaki-r Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -720,10 +720,11 @@
 virtio_msix_config_intr(void *arg)
 {
        struct virtio_softc *sc = arg;
+       int r = 0;
 
-       /* TODO: handle events */
-       aprint_debug_dev(sc->sc_dev, "%s\n", __func__);
-       return 1;
+       if (sc->sc_config_change != NULL)
+               r = (sc->sc_config_change)(sc);
+       return r;
 }
 
 static void



Home | Main Index | Thread Index | Old Index