Module Name:    src
Committed By:   riastradh
Date:           Sun Aug 14 20:34:26 UTC 2022

Modified Files:
        src/sys/dev/mii: mii.c mii_physubr.c miivar.h

Log Message:
mii(4): Wait for MIIF_DOINGAUTO to clear with MIIF_AUTOTSLEEP too.

Otherwise mii_phy_detach may return while mii_phy_auto_timeout_locked
is still in progress in another thread.

Reuse the storage for mii_nway_ch, which is unused if MIIF_AUTOTSLEEP
is set, for a new condvar in a union.  This doesn't change the kernel
ABI because sizeof(struct kcondvar) <= sizeof(struct callout) and
both have the same alignment, for an array of void *.


To generate a diff of this commit:
cvs rdiff -u -r1.57 -r1.58 src/sys/dev/mii/mii.c
cvs rdiff -u -r1.98 -r1.99 src/sys/dev/mii/mii_physubr.c
cvs rdiff -u -r1.74 -r1.75 src/sys/dev/mii/miivar.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/mii/mii.c
diff -u src/sys/dev/mii/mii.c:1.57 src/sys/dev/mii/mii.c:1.58
--- src/sys/dev/mii/mii.c:1.57	Sat Aug  7 16:19:13 2021
+++ src/sys/dev/mii/mii.c	Sun Aug 14 20:34:26 2022
@@ -1,4 +1,4 @@
-/*	$NetBSD: mii.c,v 1.57 2021/08/07 16:19:13 thorpej Exp $	*/
+/*	$NetBSD: mii.c,v 1.58 2022/08/14 20:34:26 riastradh Exp $	*/
 
 /*-
  * Copyright (c) 1998, 2000, 2020 The NetBSD Foundation, Inc.
@@ -36,7 +36,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: mii.c,v 1.57 2021/08/07 16:19:13 thorpej Exp $");
+__KERNEL_RCSID(0, "$NetBSD: mii.c,v 1.58 2022/08/14 20:34:26 riastradh Exp $");
 
 #define	__IFMEDIA_PRIVATE
 
@@ -179,7 +179,10 @@ mii_attach(device_t parent, struct mii_d
 					.locators = locs)));
 		if (child) {
 			/* Link it up in the parent's MII data. */
-			callout_init(&child->mii_nway_ch, 0);
+			if (child->mii_flags & MIIF_AUTOTSLEEP)
+				cv_init(&child->mii_nway_cv, "miiauto");
+			else
+				callout_init(&child->mii_nway_ch, 0);
 			mii_lock(mii);
 			LIST_INSERT_HEAD(&mii->mii_phys, child, mii_list);
 			child->mii_offset = offset;

Index: src/sys/dev/mii/mii_physubr.c
diff -u src/sys/dev/mii/mii_physubr.c:1.98 src/sys/dev/mii/mii_physubr.c:1.99
--- src/sys/dev/mii/mii_physubr.c:1.98	Sun Aug 14 20:33:57 2022
+++ src/sys/dev/mii/mii_physubr.c	Sun Aug 14 20:34:26 2022
@@ -1,4 +1,4 @@
-/*	$NetBSD: mii_physubr.c,v 1.98 2022/08/14 20:33:57 riastradh Exp $	*/
+/*	$NetBSD: mii_physubr.c,v 1.99 2022/08/14 20:34:26 riastradh Exp $	*/
 
 /*-
  * Copyright (c) 1998, 1999, 2000, 2001 The NetBSD Foundation, Inc.
@@ -35,7 +35,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: mii_physubr.c,v 1.98 2022/08/14 20:33:57 riastradh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: mii_physubr.c,v 1.99 2022/08/14 20:34:26 riastradh Exp $");
 
 #include <sys/param.h>
 #include <sys/device.h>
@@ -282,6 +282,8 @@ mii_phy_auto(struct mii_softc *sc)
 		sc->mii_flags |= MIIF_DOINGAUTO;
 		kpause("miiaut", false, hz >> 1, mii->mii_media.ifm_lock);
 		mii_phy_auto_timeout_locked(sc);
+		KASSERT((sc->mii_flags & MIIF_DOINGAUTO) == 0);
+		cv_broadcast(&sc->mii_nway_cv);
 	} else if ((sc->mii_flags & MIIF_DOINGAUTO) == 0) {
 		sc->mii_flags |= MIIF_DOINGAUTO;
 		callout_reset(&sc->mii_nway_ch, hz >> 1,
@@ -309,6 +311,7 @@ mii_phy_auto_timeout_locked(struct mii_s
 {
 
 	KASSERT(mii_locked(sc->mii_pdata));
+	KASSERT(sc->mii_flags & MIIF_DOINGAUTO);
 
 	if (!device_is_active(sc->mii_dev))
 		return;
@@ -432,7 +435,8 @@ mii_phy_down(struct mii_softc *sc)
 
 	KASSERT(mii_locked(sc->mii_pdata));
 
-	if (sc->mii_flags & MIIF_DOINGAUTO) {
+	if ((sc->mii_flags & (MIIF_DOINGAUTO|MIIF_AUTOTSLEEP)) ==
+	    (MIIF_DOINGAUTO|MIIF_AUTOTSLEEP)) {
 		/*
 		 * Try to stop it.
 		 *
@@ -688,13 +692,23 @@ mii_phy_detach(device_t self, int flags)
 	struct mii_softc *sc = device_private(self);
 
 	mii_lock(sc->mii_pdata);
-	if (sc->mii_flags & MIIF_DOINGAUTO) {
-		callout_halt(&sc->mii_nway_ch,
-		    sc->mii_pdata->mii_media.ifm_lock);
+	if (sc->mii_flags & MIIF_AUTOTSLEEP) {
+		while (sc->mii_flags & MIIF_DOINGAUTO) {
+			cv_wait(&sc->mii_nway_cv,
+			    sc->mii_pdata->mii_media.ifm_lock);
+		}
+	} else {
+		if (sc->mii_flags & MIIF_DOINGAUTO) {
+			callout_halt(&sc->mii_nway_ch,
+			    sc->mii_pdata->mii_media.ifm_lock);
+		}
 	}
 	mii_unlock(sc->mii_pdata);
 
-	callout_destroy(&sc->mii_nway_ch);
+	if (sc->mii_flags & MIIF_AUTOTSLEEP)
+		cv_destroy(&sc->mii_nway_cv);
+	else
+		callout_destroy(&sc->mii_nway_ch);
 
 	mii_phy_delete_media(sc);
 

Index: src/sys/dev/mii/miivar.h
diff -u src/sys/dev/mii/miivar.h:1.74 src/sys/dev/mii/miivar.h:1.75
--- src/sys/dev/mii/miivar.h:1.74	Tue Jun 29 21:03:36 2021
+++ src/sys/dev/mii/miivar.h	Sun Aug 14 20:34:26 2022
@@ -1,4 +1,4 @@
-/*	$NetBSD: miivar.h,v 1.74 2021/06/29 21:03:36 pgoyette Exp $	*/
+/*	$NetBSD: miivar.h,v 1.75 2022/08/14 20:34:26 riastradh Exp $	*/
 
 /*-
  * Copyright (c) 1998, 1999, 2000, 2001, 2020 The NetBSD Foundation, Inc.
@@ -150,7 +150,10 @@ struct mii_softc {
 	int mii_ticks;			/* m: MII_TICK counter */
 	int mii_anegticks;		/* m: ticks before retrying aneg */
 
-	struct callout mii_nway_ch;	/* m: NWAY callout */
+	union {
+		struct callout mii_nway_ch;	/* m: NWAY callout */
+		kcondvar_t mii_nway_cv;
+	};
 
 	u_int mii_media_active;		/* m: last active media */
 	int mii_media_status;		/* m: last active status */

Reply via email to