Source-Changes-HG archive

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

[src/trunk]: src/sys/arch/x86/pci fix vmx(4) cannot link up at boot time. re...



details:   https://anonhg.NetBSD.org/src/rev/0e2dcde9874d
branches:  trunk
changeset: 1008495:0e2dcde9874d
user:      knakahara <knakahara%NetBSD.org@localhost>
date:      Tue Mar 24 09:27:46 2020 +0000

description:
fix vmx(4) cannot link up at boot time.  reviewed by msaitoh@n.o, thanks.

vmx(4) could call if_link_state_change(ifp, LINK_STATE_UP) from vmxnet3_init()
before ifp->if_link_cansched was set, because dp->dom_if_up() (in6_if_up() for
INET6) could call ifp->if_init().  And then, workqueue_enqueue() was not called
at that time.
As the result, the last LQ_ITEM was stuck LINK_STATE_UP, so
if_link_state_change_work_schedule() was never called until
if_link_state_change(ifp, LINK_STATE_DOWN) was called.

To fix this issue, vmx(4) avoid calling if_link_state_change() before
ifp->if_link_cansched is set.

diffstat:

 sys/arch/x86/pci/if_vmx.c |  66 ++++++++++++++++++++++++++++++++--------------
 1 files changed, 46 insertions(+), 20 deletions(-)

diffs (156 lines):

diff -r 7cf305a7a265 -r 0e2dcde9874d sys/arch/x86/pci/if_vmx.c
--- a/sys/arch/x86/pci/if_vmx.c Tue Mar 24 08:48:31 2020 +0000
+++ b/sys/arch/x86/pci/if_vmx.c Tue Mar 24 09:27:46 2020 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: if_vmx.c,v 1.58 2020/03/15 23:04:50 thorpej Exp $      */
+/*     $NetBSD: if_vmx.c,v 1.59 2020/03/24 09:27:46 knakahara Exp $    */
 /*     $OpenBSD: if_vmx.c,v 1.16 2014/01/22 06:04:17 brad Exp $        */
 
 /*
@@ -19,7 +19,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: if_vmx.c,v 1.58 2020/03/15 23:04:50 thorpej Exp $");
+__KERNEL_RCSID(0, "$NetBSD: if_vmx.c,v 1.59 2020/03/24 09:27:46 knakahara Exp $");
 
 #include <sys/param.h>
 #include <sys/cpu.h>
@@ -445,9 +445,10 @@
 static int vmxnet3_watchdog(struct vmxnet3_txqueue *);
 static void vmxnet3_refresh_host_stats(struct vmxnet3_softc *);
 static void vmxnet3_tick(void *);
-static void vmxnet3_link_status(struct vmxnet3_softc *);
-static void vmxnet3_media_status(struct ifnet *, struct ifmediareq *);
-static int vmxnet3_media_change(struct ifnet *);
+static void vmxnet3_if_link_status(struct vmxnet3_softc *);
+static bool vmxnet3_cmd_link_status(struct ifnet *);
+static void vmxnet3_ifmedia_status(struct ifnet *, struct ifmediareq *);
+static int vmxnet3_ifmedia_change(struct ifnet *);
 static void vmxnet3_set_lladdr(struct vmxnet3_softc *);
 static void vmxnet3_get_lladdr(struct vmxnet3_softc *);
 
@@ -1857,8 +1858,8 @@
 
        /* Initialize ifmedia structures. */
        sc->vmx_ethercom.ec_ifmedia = &sc->vmx_media;
-       ifmedia_init_with_lock(&sc->vmx_media, IFM_IMASK, vmxnet3_media_change,
-           vmxnet3_media_status, sc->vmx_mtx);
+       ifmedia_init_with_lock(&sc->vmx_media, IFM_IMASK, vmxnet3_ifmedia_change,
+           vmxnet3_ifmedia_status, sc->vmx_mtx);
        ifmedia_add(&sc->vmx_media, IFM_ETHER | IFM_AUTO, 0, NULL);
        ifmedia_add(&sc->vmx_media, IFM_ETHER | IFM_10G_T | IFM_FDX, 0, NULL);
        ifmedia_add(&sc->vmx_media, IFM_ETHER | IFM_10G_T, 0, NULL);
@@ -1870,7 +1871,7 @@
        if_deferred_start_init(ifp, NULL);
        ether_ifattach(ifp, sc->vmx_lladdr);
        ether_set_ifflags_cb(&sc->vmx_ethercom, vmxnet3_ifflags_cb);
-       vmxnet3_link_status(sc);
+       vmxnet3_cmd_link_status(ifp);
 
        /* should set before setting interrupts */
        sc->vmx_rx_intr_process_limit = VMXNET3_RX_INTR_PROCESS_LIMIT;
@@ -2069,7 +2070,7 @@
 
        if (event & VMXNET3_EVENT_LINK) {
                sc->vmx_event_link.ev_count++;
-               vmxnet3_link_status(sc);
+               vmxnet3_if_link_status(sc);
                if (sc->vmx_link_active != 0)
                        if_schedule_deferred_start(&sc->vmx_ethercom.ec_if);
        }
@@ -2909,7 +2910,7 @@
        }
 
        ifp->if_flags |= IFF_RUNNING;
-       vmxnet3_link_status(sc);
+       vmxnet3_cmd_link_status(ifp);
 
        vmxnet3_enable_all_intrs(sc);
        callout_reset(&sc->vmx_tick, hz, vmxnet3_tick, sc);
@@ -3425,6 +3426,8 @@
        vmxnet3_set_rxfilter(sc);
        VMXNET3_CORE_UNLOCK(sc);
 
+       vmxnet3_if_link_status(sc);
+
        return 0;
 }
 
@@ -3481,17 +3484,20 @@
        VMXNET3_CORE_UNLOCK(sc);
 }
 
+/*
+ * update link state of ifnet and softc
+ */
 static void
-vmxnet3_link_status(struct vmxnet3_softc *sc)
+vmxnet3_if_link_status(struct vmxnet3_softc *sc)
 {
        struct ifnet *ifp = &sc->vmx_ethercom.ec_if;
-       u_int x, link, speed;
+       u_int x, link;
+
+       vmxnet3_cmd_link_status(ifp);
 
        x = vmxnet3_read_cmd(sc, VMXNET3_CMD_GET_LINK);
-       speed = x >> 16;
        if (x & 1) {
                sc->vmx_link_active = 1;
-               ifp->if_baudrate = IF_Mbps(speed);
                link = LINK_STATE_UP;
        } else {
                sc->vmx_link_active = 0;
@@ -3501,17 +3507,37 @@
        if_link_state_change(ifp, link);
 }
 
-static void
-vmxnet3_media_status(struct ifnet *ifp, struct ifmediareq *ifmr)
+/*
+ * check vmx(4) state by VMXNET3_CMD and update ifp->if_baudrate
+ *   returns
+ *       - true:  link up
+ *       - flase: link down
+ */
+static bool
+vmxnet3_cmd_link_status(struct ifnet *ifp)
 {
        struct vmxnet3_softc *sc = ifp->if_softc;
-
-       vmxnet3_link_status(sc);
+       u_int x, speed;
+
+       x = vmxnet3_read_cmd(sc, VMXNET3_CMD_GET_LINK);
+       if ((x & 1) == 0)
+               return false;
+
+       speed = x >> 16;
+       ifp->if_baudrate = IF_Mbps(speed);
+       return true;
+}
+
+static void
+vmxnet3_ifmedia_status(struct ifnet *ifp, struct ifmediareq *ifmr)
+{
+       bool up;
 
        ifmr->ifm_status = IFM_AVALID;
        ifmr->ifm_active = IFM_ETHER;
 
-       if (ifp->if_link_state != LINK_STATE_UP)
+       up = vmxnet3_cmd_link_status(ifp);
+       if (!up)
                return;
 
        ifmr->ifm_status |= IFM_ACTIVE;
@@ -3521,7 +3547,7 @@
 }
 
 static int
-vmxnet3_media_change(struct ifnet *ifp)
+vmxnet3_ifmedia_change(struct ifnet *ifp)
 {
        return 0;
 }



Home | Main Index | Thread Index | Old Index