Module Name: src Committed By: skrll Date: Fri Oct 4 10:42:12 UTC 2024
Modified Files: src/sys/dev/ic: dwc_eqos.c dwc_eqos_var.h Log Message: Fix a problem noted by Taylor... touching if_flags is forbidden in this context (no IFNET_LOCK guaranteed) sc_promisc should be cached when if_flags changes, not when SIOCADDMULTI/SIOCDELMULTI runs by caching if_flags in sc_if_flags via a ifflags_cb. To generate a diff of this commit: cvs rdiff -u -r1.39 -r1.40 src/sys/dev/ic/dwc_eqos.c cvs rdiff -u -r1.10 -r1.11 src/sys/dev/ic/dwc_eqos_var.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/dwc_eqos.c diff -u src/sys/dev/ic/dwc_eqos.c:1.39 src/sys/dev/ic/dwc_eqos.c:1.40 --- src/sys/dev/ic/dwc_eqos.c:1.39 Sat Sep 14 07:30:41 2024 +++ src/sys/dev/ic/dwc_eqos.c Fri Oct 4 10:42:12 2024 @@ -1,4 +1,4 @@ -/* $NetBSD: dwc_eqos.c,v 1.39 2024/09/14 07:30:41 skrll Exp $ */ +/* $NetBSD: dwc_eqos.c,v 1.40 2024/10/04 10:42:12 skrll Exp $ */ /*- * Copyright (c) 2022 Jared McNeill <jmcne...@invisible.ca> @@ -36,7 +36,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: dwc_eqos.c,v 1.39 2024/09/14 07:30:41 skrll Exp $"); +__KERNEL_RCSID(0, "$NetBSD: dwc_eqos.c,v 1.40 2024/10/04 10:42:12 skrll Exp $"); #include <sys/param.h> #include <sys/bus.h> @@ -458,7 +458,7 @@ eqos_tick(void *softc) EQOS_LOCK(sc); mii_tick(mii); - if (sc->sc_running) + if ((sc->sc_if_flags & IFF_RUNNING) != 0) callout_schedule(&sc->sc_stat_ch, hz); EQOS_UNLOCK(sc); } @@ -496,7 +496,7 @@ eqos_setup_rxfilter(struct eqos_softc *s hash[0] = hash[1] = ~0U; ETHER_LOCK(ec); - if (sc->sc_promisc) { + if ((sc->sc_if_flags & IFF_PROMISC) != 0) { ec->ec_flags |= ETHER_F_ALLMULTI; pfil |= GMAC_MAC_PACKET_FILTER_PR | GMAC_MAC_PACKET_FILTER_PCF_ALL; @@ -614,7 +614,7 @@ eqos_init_locked(struct eqos_softc *sc) eqos_init_rings(sc, 0); /* Setup RX filter */ - sc->sc_promisc = ifp->if_flags & IFF_PROMISC; + sc->sc_if_flags = ifp->if_flags; eqos_setup_rxfilter(sc); WR4(sc, GMAC_MAC_1US_TIC_COUNTER, (sc->sc_csr_clock / 1000000) - 1); @@ -699,8 +699,8 @@ eqos_init_locked(struct eqos_softc *sc) EQOS_ASSERT_TXLOCKED(sc); sc->sc_txrunning = true; - sc->sc_running = true; ifp->if_flags |= IFF_RUNNING; + sc->sc_if_flags |= IFF_RUNNING; mii_mediachg(mii); callout_schedule(&sc->sc_stat_ch, hz); @@ -736,7 +736,6 @@ eqos_stop_locked(struct eqos_softc *sc, sc->sc_txrunning = false; EQOS_TXUNLOCK(sc); - sc->sc_running = false; callout_halt(&sc->sc_stat_ch, &sc->sc_lock); mii_down(&sc->sc_mii); @@ -783,6 +782,7 @@ eqos_stop_locked(struct eqos_softc *sc, /* Disable interrupts */ eqos_disable_intr(sc); + sc->sc_if_flags &= ~IFF_RUNNING; ifp->if_flags &= ~IFF_RUNNING; } @@ -1234,8 +1234,7 @@ eqos_ioctl(struct ifnet *ifp, u_long cmd error = (*ifp->if_init)(ifp); else if (cmd == SIOCADDMULTI || cmd == SIOCDELMULTI) { EQOS_LOCK(sc); - sc->sc_promisc = ifp->if_flags & IFF_PROMISC; - if (sc->sc_running) + if ((sc->sc_if_flags & IFF_RUNNING) != 0) eqos_setup_rxfilter(sc); EQOS_UNLOCK(sc); } @@ -1246,6 +1245,31 @@ eqos_ioctl(struct ifnet *ifp, u_long cmd return error; } +static int +eqos_ifflags_cb(struct ethercom *ec) +{ + struct ifnet * const ifp = &ec->ec_if; + struct eqos_softc * const sc = ifp->if_softc; + int ret = 0; + + KASSERT(IFNET_LOCKED(ifp)); + EQOS_LOCK(sc); + + u_short change = ifp->if_flags ^ sc->sc_if_flags; + sc->sc_if_flags = ifp->if_flags; + + if ((change & ~(IFF_CANTCHANGE | IFF_DEBUG)) != 0) { + ret = ENETRESET; + } else if ((change & (IFF_PROMISC | IFF_ALLMULTI)) != 0) { + if ((sc->sc_if_flags & IFF_RUNNING) != 0) + eqos_setup_rxfilter(sc); + } + EQOS_UNLOCK(sc); + + return ret; +} + + static void eqos_get_eaddr(struct eqos_softc *sc, uint8_t *eaddr) { @@ -1629,6 +1653,7 @@ eqos_attach(struct eqos_softc *sc) /* Attach ethernet interface */ ether_ifattach(ifp, eaddr); + ether_set_ifflags_cb(&sc->sc_ec, eqos_ifflags_cb); eqos_init_sysctls(sc); Index: src/sys/dev/ic/dwc_eqos_var.h diff -u src/sys/dev/ic/dwc_eqos_var.h:1.10 src/sys/dev/ic/dwc_eqos_var.h:1.11 --- src/sys/dev/ic/dwc_eqos_var.h:1.10 Sun Sep 15 07:33:33 2024 +++ src/sys/dev/ic/dwc_eqos_var.h Fri Oct 4 10:42:12 2024 @@ -1,4 +1,4 @@ -/* $NetBSD: dwc_eqos_var.h,v 1.10 2024/09/15 07:33:33 skrll Exp $ */ +/* $NetBSD: dwc_eqos_var.h,v 1.11 2024/10/04 10:42:12 skrll Exp $ */ /*- * Copyright (c) 2022 Jared McNeill <jmcne...@invisible.ca> @@ -70,9 +70,8 @@ struct eqos_softc { callout_t sc_stat_ch; kmutex_t sc_lock; kmutex_t sc_txlock; - bool sc_running; + u_short sc_if_flags; bool sc_txrunning; - bool sc_promisc; struct eqos_ring sc_tx; struct eqos_ring sc_rx;