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): Wait for MIIF_DOINGAUTO to clear with MI...



details:   https://anonhg.NetBSD.org/src/rev/5e2c977bb069
branches:  trunk
changeset: 368967:5e2c977bb069
user:      riastradh <riastradh%NetBSD.org@localhost>
date:      Sun Aug 14 20:34:26 2022 +0000

description:
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 *.

diffstat:

 sys/dev/mii/mii.c         |   9 ++++++---
 sys/dev/mii/mii_physubr.c |  28 +++++++++++++++++++++-------
 sys/dev/mii/miivar.h      |   7 +++++--
 3 files changed, 32 insertions(+), 12 deletions(-)

diffs (124 lines):

diff -r ef404de8dbae -r 5e2c977bb069 sys/dev/mii/mii.c
--- a/sys/dev/mii/mii.c Sun Aug 14 20:33:57 2022 +0000
+++ b/sys/dev/mii/mii.c Sun Aug 14 20:34:26 2022 +0000
@@ -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 @@
                                        .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;
diff -r ef404de8dbae -r 5e2c977bb069 sys/dev/mii/mii_physubr.c
--- a/sys/dev/mii/mii_physubr.c Sun Aug 14 20:33:57 2022 +0000
+++ b/sys/dev/mii/mii_physubr.c Sun Aug 14 20:34:26 2022 +0000
@@ -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 @@
                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 @@
 {
 
        KASSERT(mii_locked(sc->mii_pdata));
+       KASSERT(sc->mii_flags & MIIF_DOINGAUTO);
 
        if (!device_is_active(sc->mii_dev))
                return;
@@ -432,7 +435,8 @@
 
        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 @@
        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);
 
diff -r ef404de8dbae -r 5e2c977bb069 sys/dev/mii/miivar.h
--- a/sys/dev/mii/miivar.h      Sun Aug 14 20:33:57 2022 +0000
+++ b/sys/dev/mii/miivar.h      Sun Aug 14 20:34:26 2022 +0000
@@ -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 @@
        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 */



Home | Main Index | Thread Index | Old Index