Source-Changes-HG archive

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

[src/trunk]: src/sys/dev/mii mii(4): Make mii_down wait for concurrent mii_ph...



details:   https://anonhg.NetBSD.org/src/rev/c44f166c41a7
branches:  trunk
changeset: 369486:c44f166c41a7
user:      riastradh <riastradh%NetBSD.org@localhost>
date:      Sat Aug 20 11:12:46 2022 +0000

description:
mii(4): Make mii_down wait for concurrent mii_phy_auto to finish.

This is important for callers in if_stop routines to guarantee that
all concurrent access to the mii registers has ended.

Drivers must not call this from softint context.  Drivers with custom
watchdog timers (not if_watchdog) that do if_stop from callout must
defer to thread context instead, e.g. via workqueue(9) -- as they
should be doing anyway for heavyweight operations like if_stop.

diffstat:

 sys/dev/mii/mii_physubr.c |  46 +++++++++++++++-------------------------------
 1 files changed, 15 insertions(+), 31 deletions(-)

diffs (75 lines):

diff -r 1728c7d51e1d -r c44f166c41a7 sys/dev/mii/mii_physubr.c
--- a/sys/dev/mii/mii_physubr.c Sat Aug 20 11:09:41 2022 +0000
+++ b/sys/dev/mii/mii_physubr.c Sat Aug 20 11:12:46 2022 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: mii_physubr.c,v 1.99 2022/08/14 20:34:26 riastradh Exp $       */
+/*     $NetBSD: mii_physubr.c,v 1.100 2022/08/20 11:12:46 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.99 2022/08/14 20:34:26 riastradh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: mii_physubr.c,v 1.100 2022/08/20 11:12:46 riastradh Exp $");
 
 #include <sys/param.h>
 #include <sys/device.h>
@@ -435,23 +435,18 @@
 
        KASSERT(mii_locked(sc->mii_pdata));
 
-       if ((sc->mii_flags & (MIIF_DOINGAUTO|MIIF_AUTOTSLEEP)) ==
-           (MIIF_DOINGAUTO|MIIF_AUTOTSLEEP)) {
-               /*
-                * Try to stop it.
-                *
-                * - If we stopped it before it expired, callout_stop
-                *   returns 0, and it is our responsibility to clear
-                *   MIIF_DOINGAUTO.
-                *
-                * - Otherwise, we're too late -- the callout has
-                *   already begun, and we must leave MIIF_DOINGAUTO
-                *   set so mii_phy_detach will wait for it to
-                *   complete.
-                */
-               if (!callout_stop(&sc->mii_nway_ch))
-                       sc->mii_flags &= ~MIIF_DOINGAUTO;
+       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);
+               }
        }
+       KASSERT((sc->mii_flags & MIIF_DOINGAUTO) == 0);
 }
 
 void
@@ -691,19 +686,8 @@
 {
        struct mii_softc *sc = device_private(self);
 
-       mii_lock(sc->mii_pdata);
-       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);
+       /* No mii_lock because mii_flags should be stable by now.  */
+       KASSERT((sc->mii_flags & MIIF_DOINGAUTO) == 0);
 
        if (sc->mii_flags & MIIF_AUTOTSLEEP)
                cv_destroy(&sc->mii_nway_cv);



Home | Main Index | Thread Index | Old Index