Index: dev/ic/tulip.c =================================================================== RCS file: /cvsroot/src/sys/dev/ic/tulip.c,v retrieving revision 1.214 diff -u -p -r1.214 tulip.c --- dev/ic/tulip.c 10 Dec 2025 21:33:00 -0000 1.214 +++ dev/ic/tulip.c 25 Jul 2026 14:43:45 -0000 @@ -52,6 +52,8 @@ __KERNEL_RCSID(0, "$NetBSD: tulip.c,v 1. #include +#define __IFMEDIA_PRIVATE /* XXX for 2114x NWay handling */ + #include #include #include @@ -5166,17 +5168,31 @@ tlp_2114x_isv_tmsw_init(struct tulip_sof static void tlp_2114x_nway_get(struct tulip_softc *sc, struct ifmediareq *ifmr) { + struct mii_data * const mii = &sc->sc_mii; + + IFMEDIA_LOCK_FOR_LEGACY(&mii->mii_media); + KASSERT(mii_locked(mii)); (void) tlp_2114x_nway_service(sc, MII_POLLSTAT); - ifmr->ifm_status = sc->sc_mii.mii_media_status; - ifmr->ifm_active = sc->sc_mii.mii_media_active; + ifmr->ifm_status = mii->mii_media_status; + ifmr->ifm_active = mii->mii_media_active; + + IFMEDIA_UNLOCK_FOR_LEGACY(&mii->mii_media); } static int tlp_2114x_nway_set(struct tulip_softc *sc) { + struct mii_data * const mii = &sc->sc_mii; + int rv; + + IFMEDIA_LOCK_FOR_LEGACY(&mii->mii_media); + KASSERT(mii_locked(mii)); + + rv = tlp_2114x_nway_service(sc, MII_MEDIACHG); - return tlp_2114x_nway_service(sc, MII_MEDIACHG); + IFMEDIA_UNLOCK_FOR_LEGACY(&mii->mii_media); + return rv; } static void @@ -5186,10 +5202,12 @@ tlp_2114x_nway_statchg(struct ifnet *ifp struct mii_data *mii = &sc->sc_mii; struct ifmedia_entry *ife; + KASSERT(mii_locked(mii)); + if (IFM_SUBTYPE(mii->mii_media_active) == IFM_NONE) return; - if ((ife = ifmedia_match(&mii->mii_media, mii->mii_media_active, + if ((ife = ifmedia_match_locked(&mii->mii_media, mii->mii_media_active, mii->mii_media.ifm_mask)) == NULL) { printf("tlp_2114x_nway_statchg: no match for media 0x%x/0x%x\n", mii->mii_media_active, ~mii->mii_media.ifm_mask); @@ -5204,29 +5222,39 @@ tlp_2114x_nway_tick(void *arg) { struct tulip_softc *sc = arg; struct mii_data *mii = &sc->sc_mii; - int s, ticks; + int ticks; + bool do_start = false; if (!device_is_active(sc->sc_dev)) return; - s = splnet(); + /* N.B. acquiring the media lock will take us to splnet(). */ + IFMEDIA_LOCK_FOR_LEGACY(&mii->mii_media); + KASSERT(mii_locked(mii)); + tlp_2114x_nway_service(sc, MII_TICK); if ((sc->sc_flags & TULIPF_LINK_UP) == 0 && (mii->mii_media_status & IFM_ACTIVE) != 0 && IFM_SUBTYPE(mii->mii_media_active) != IFM_NONE) { sc->sc_flags |= TULIPF_LINK_UP; - tlp_start(&sc->sc_ethercom.ec_if); + do_start = true; } else if ((sc->sc_flags & TULIPF_LINK_UP) != 0 && (mii->mii_media_status & IFM_ACTIVE) == 0) { sc->sc_flags &= ~TULIPF_LINK_UP; } - splx(s); if ((sc->sc_flags & TULIPF_LINK_UP) == 0) ticks = hz >> 3; else ticks = hz; + + IFMEDIA_UNLOCK_FOR_LEGACY(&mii->mii_media); + callout_reset(&sc->sc_tick_callout, ticks, tlp_2114x_nway_tick, sc); + + if (do_start) { + tlp_start(&sc->sc_ethercom.ec_if); + } } /* @@ -5240,6 +5268,8 @@ tlp_2114x_nway_service(struct tulip_soft struct mii_data *mii = &sc->sc_mii; struct ifmedia_entry *ife = mii->mii_media.ifm_cur; + KASSERT(mii_locked(mii)); + if ((mii->mii_ifp->if_flags & IFF_UP) == 0) return 0; @@ -5348,6 +5378,8 @@ tlp_2114x_nway_status(struct tulip_softc struct mii_data *mii = &sc->sc_mii; uint32_t siatxrx, siastat, anlpar; + KASSERT(mii_locked(mii)); + mii->mii_media_status = IFM_AVALID; mii->mii_media_active = IFM_ETHER; Index: net/if_media.c =================================================================== RCS file: /cvsroot/src/sys/net/if_media.c,v retrieving revision 1.54 diff -u -p -r1.54 if_media.c --- net/if_media.c 3 Sep 2022 02:47:59 -0000 1.54 +++ net/if_media.c 25 Jul 2026 14:43:45 -0000 @@ -92,8 +92,6 @@ __KERNEL_RCSID(0, "$NetBSD: if_media.c,v static void ifmedia_status(struct ifmedia *, struct ifnet *, struct ifmediareq *); -static struct ifmedia_entry * - ifmedia_match_locked(struct ifmedia *, u_int, u_int); /* * Compile-time options: @@ -541,7 +539,7 @@ ifmedia_ioctl(struct ifnet *ifp, struct /* * Find media entry matching a given ifm word. */ -static struct ifmedia_entry * +struct ifmedia_entry * ifmedia_match_locked(struct ifmedia *ifm, u_int target, u_int mask) { struct ifmedia_entry *match, *next; Index: net/if_media.h =================================================================== RCS file: /cvsroot/src/sys/net/if_media.h,v retrieving revision 1.72 diff -u -p -r1.72 if_media.h --- net/if_media.h 18 Apr 2024 10:32:03 -0000 1.72 +++ net/if_media.h 25 Jul 2026 14:43:45 -0000 @@ -999,6 +999,7 @@ int ifmedia_ioctl(struct ifnet *, struct /* Look up a media entry. */ struct ifmedia_entry *ifmedia_match(struct ifmedia *, u_int, u_int); +struct ifmedia_entry *ifmedia_match_locked(struct ifmedia *, u_int, u_int); /* Delete all media for a given media instance */ void ifmedia_delete_instance(struct ifmedia *, u_int);