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 */

Reply via email to