Module Name: src Committed By: thorpej Date: Wed Jun 30 20:00:18 UTC 2021
Modified Files: src/sys/dev/ic: ax88190.c dl10019.c dp8390.c dp8390var.h Log Message: Fix a couple of problems with MII-equipped NE2000 derivatives reported by Björn Johannesson on current-users@: - Re-factor dp8390_stop() into dp8390_halt() (that does the stuff to halt the hardware) and dp8390_stop() (which alls dp8390_halt() before calling mii_down() via sc->sc_stop_card()). This prevents us from calling mii_down() before all of the interface data structures have been set up, which these days can trip a KASSERT(). - Add a 1-second timer to call mii_tick(), and enable it in the sc->sc_init_card() callback, and cancel it in the sc->sc_stop_card() and sc->sc_media_fini() callbacks. This is actually a long-standing bug that previously didn't have much practical effect, but causes problems with dhcpcd's link live-ness detection logic. To generate a diff of this commit: cvs rdiff -u -r1.16 -r1.17 src/sys/dev/ic/ax88190.c cvs rdiff -u -r1.15 -r1.16 src/sys/dev/ic/dl10019.c cvs rdiff -u -r1.97 -r1.98 src/sys/dev/ic/dp8390.c cvs rdiff -u -r1.34 -r1.35 src/sys/dev/ic/dp8390var.h Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/dev/ic/ax88190.c diff -u src/sys/dev/ic/ax88190.c:1.16 src/sys/dev/ic/ax88190.c:1.17 --- src/sys/dev/ic/ax88190.c:1.16 Tue Feb 4 05:25:39 2020 +++ src/sys/dev/ic/ax88190.c Wed Jun 30 20:00:18 2021 @@ -1,4 +1,4 @@ -/* $NetBSD: ax88190.c,v 1.16 2020/02/04 05:25:39 thorpej Exp $ */ +/* $NetBSD: ax88190.c,v 1.17 2021/06/30 20:00:18 thorpej Exp $ */ /*- * Copyright (c) 2001 The NetBSD Foundation, Inc. @@ -30,7 +30,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: ax88190.c,v 1.16 2020/02/04 05:25:39 thorpej Exp $"); +__KERNEL_RCSID(0, "$NetBSD: ax88190.c,v 1.17 2021/06/30 20:00:18 thorpej Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -80,12 +80,27 @@ static const struct mii_bitbang_ops ax88 } }; +static void +ax88190_tick(void *arg) +{ + struct dp8390_softc *sc = arg; + int s; + + s = splnet(); + mii_tick(&sc->sc_mii); + splx(s); + + callout_schedule(&sc->sc_tick_ch, hz); +} + void ax88190_media_init(struct dp8390_softc *sc) { struct ifnet *ifp = &sc->sc_ec.ec_if; struct mii_data *mii = &sc->sc_mii; + callout_setfunc(&sc->sc_tick_ch, ax88190_tick, sc); + mii->mii_ifp = ifp; mii->mii_readreg = ax88190_mii_readreg; mii->mii_writereg = ax88190_mii_writereg; @@ -107,8 +122,9 @@ void ax88190_media_fini(struct dp8390_softc *sc) { + callout_stop(&sc->sc_tick_ch); mii_detach(&sc->sc_mii, MII_PHY_ANY, MII_OFFSET_ANY); - ifmedia_fini(&sc->sc_mii.mii_media); + /* dp8390_detach() will call ifmedia_fini(). */ } int @@ -135,12 +151,14 @@ ax88190_init_card(struct dp8390_softc *s { mii_mediachg(&sc->sc_mii); + callout_schedule(&sc->sc_tick_ch, hz); } void ax88190_stop_card(struct dp8390_softc *sc) { + callout_stop(&sc->sc_tick_ch); mii_down(&sc->sc_mii); } Index: src/sys/dev/ic/dl10019.c diff -u src/sys/dev/ic/dl10019.c:1.15 src/sys/dev/ic/dl10019.c:1.16 --- src/sys/dev/ic/dl10019.c:1.15 Tue Feb 4 05:25:39 2020 +++ src/sys/dev/ic/dl10019.c Wed Jun 30 20:00:18 2021 @@ -1,4 +1,4 @@ -/* $NetBSD: dl10019.c,v 1.15 2020/02/04 05:25:39 thorpej Exp $ */ +/* $NetBSD: dl10019.c,v 1.16 2021/06/30 20:00:18 thorpej Exp $ */ /*- * Copyright (c) 2001 The NetBSD Foundation, Inc. @@ -30,7 +30,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: dl10019.c,v 1.15 2020/02/04 05:25:39 thorpej Exp $"); +__KERNEL_RCSID(0, "$NetBSD: dl10019.c,v 1.16 2021/06/30 20:00:18 thorpej Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -113,12 +113,27 @@ dl10019_mii_reset(struct dp8390_softc *s bus_space_write_1(sc->sc_regt, sc->sc_regh, NEDL_DL0_GPIO, 0x00); } +static void +dl10019_tick(void *arg) +{ + struct dp8390_softc *sc = arg; + int s; + + s = splnet(); + mii_tick(&sc->sc_mii); + splx(s); + + callout_schedule(&sc->sc_tick_ch, hz); +} + void dl10019_media_init(struct dp8390_softc *sc) { struct ifnet *ifp = &sc->sc_ec.ec_if; struct mii_data *mii = &sc->sc_mii; + callout_setfunc(&sc->sc_tick_ch, dl10019_tick, sc); + mii->mii_ifp = ifp; mii->mii_readreg = dl10019_mii_readreg; mii->mii_writereg = dl10019_mii_writereg; @@ -142,8 +157,9 @@ void dl10019_media_fini(struct dp8390_softc *sc) { + callout_stop(&sc->sc_tick_ch); mii_detach(&sc->sc_mii, MII_PHY_ANY, MII_OFFSET_ANY); - ifmedia_fini(&sc->sc_mii.mii_media); + /* dp8390_detach() will call ifmedia_fini(). */ } int @@ -171,12 +187,14 @@ dl10019_init_card(struct dp8390_softc *s dl10019_mii_reset(sc); mii_mediachg(&sc->sc_mii); + callout_schedule(&sc->sc_tick_ch, hz); } void dl10019_stop_card(struct dp8390_softc *sc) { + callout_stop(&sc->sc_tick_ch); mii_down(&sc->sc_mii); } Index: src/sys/dev/ic/dp8390.c diff -u src/sys/dev/ic/dp8390.c:1.97 src/sys/dev/ic/dp8390.c:1.98 --- src/sys/dev/ic/dp8390.c:1.97 Tue Feb 4 05:25:39 2020 +++ src/sys/dev/ic/dp8390.c Wed Jun 30 20:00:18 2021 @@ -1,4 +1,4 @@ -/* $NetBSD: dp8390.c,v 1.97 2020/02/04 05:25:39 thorpej Exp $ */ +/* $NetBSD: dp8390.c,v 1.98 2021/06/30 20:00:18 thorpej Exp $ */ /* * Device driver for National Semiconductor DS8390/WD83C690 based ethernet @@ -14,7 +14,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: dp8390.c,v 1.97 2020/02/04 05:25:39 thorpej Exp $"); +__KERNEL_RCSID(0, "$NetBSD: dp8390.c,v 1.98 2021/06/30 20:00:18 thorpej Exp $"); #include "opt_inet.h" @@ -51,6 +51,8 @@ __KERNEL_RCSID(0, "$NetBSD: dp8390.c,v 1 int dp8390_debug = 0; #endif +static void dp8390_halt(struct dp8390_softc *); + static void dp8390_xmit(struct dp8390_softc *); static void dp8390_read_hdr(struct dp8390_softc *, int, struct dp8390_ring *); @@ -115,7 +117,9 @@ dp8390_config(struct dp8390_softc *sc) goto out; /* Set interface to stopped condition (reset). */ - dp8390_stop(sc); + dp8390_halt(sc); + + callout_init(&sc->sc_tick_ch, 0); /* Initialize ifnet structure. */ strcpy(ifp->if_xname, device_xname(sc->sc_dev)); @@ -201,8 +205,8 @@ dp8390_reset(struct dp8390_softc *sc) /* * Take interface offline. */ -void -dp8390_stop(struct dp8390_softc *sc) +static void +dp8390_halt(struct dp8390_softc *sc) { bus_space_tag_t regt = sc->sc_regt; bus_space_handle_t regh = sc->sc_regh; @@ -221,7 +225,12 @@ dp8390_stop(struct dp8390_softc *sc) */ while (((NIC_GET(regt, regh, ED_P0_ISR) & ED_ISR_RST) == 0) && --n) DELAY(1); +} +void +dp8390_stop(struct dp8390_softc *sc) +{ + dp8390_halt(sc); if (sc->stop_card != NULL) (*sc->stop_card)(sc); } Index: src/sys/dev/ic/dp8390var.h diff -u src/sys/dev/ic/dp8390var.h:1.34 src/sys/dev/ic/dp8390var.h:1.35 --- src/sys/dev/ic/dp8390var.h:1.34 Sun Jul 15 05:16:45 2018 +++ src/sys/dev/ic/dp8390var.h Wed Jun 30 20:00:18 2021 @@ -1,4 +1,4 @@ -/* $NetBSD: dp8390var.h,v 1.34 2018/07/15 05:16:45 maxv Exp $ */ +/* $NetBSD: dp8390var.h,v 1.35 2021/06/30 20:00:18 thorpej Exp $ */ /* * Device driver for National Semiconductor DS8390/WD83C690 based ethernet @@ -19,6 +19,7 @@ * We include MII glue here -- some DP8390 compatible chips have * MII interfaces on them (scary, isn't it...). */ +#include <sys/callout.h> #include <dev/mii/miivar.h> #define INTERFACE_NAME_LEN 32 @@ -34,6 +35,7 @@ struct dp8390_softc { struct ethercom sc_ec; /* ethernet common */ struct mii_data sc_mii; /* MII glue */ #define sc_media sc_mii.mii_media /* compatibilty definition */ + callout_t sc_tick_ch; /* MII tick callout */ bus_space_tag_t sc_regt; /* NIC register space tag */ bus_space_handle_t sc_regh; /* NIC register space handle */