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