Module Name:    src
Committed By:   skrll
Date:           Fri Oct  4 10:41:58 UTC 2024

Modified Files:
        src/sys/dev/ic: bcmgenet.c bcmgenetvar.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.20 -r1.21 src/sys/dev/ic/bcmgenet.c
cvs rdiff -u -r1.5 -r1.6 src/sys/dev/ic/bcmgenetvar.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/bcmgenet.c
diff -u src/sys/dev/ic/bcmgenet.c:1.20 src/sys/dev/ic/bcmgenet.c:1.21
--- src/sys/dev/ic/bcmgenet.c:1.20	Sun Sep 15 07:38:08 2024
+++ src/sys/dev/ic/bcmgenet.c	Fri Oct  4 10:41:58 2024
@@ -1,4 +1,4 @@
-/* $NetBSD: bcmgenet.c,v 1.20 2024/09/15 07:38:08 skrll Exp $ */
+/* $NetBSD: bcmgenet.c,v 1.21 2024/10/04 10:41:58 skrll Exp $ */
 
 /*-
  * Copyright (c) 2020 Jared McNeill <jmcne...@invisible.ca>
@@ -33,7 +33,7 @@
 #include "opt_ddb.h"
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: bcmgenet.c,v 1.20 2024/09/15 07:38:08 skrll Exp $");
+__KERNEL_RCSID(0, "$NetBSD: bcmgenet.c,v 1.21 2024/10/04 10:41:58 skrll Exp $");
 
 #include <sys/param.h>
 #include <sys/bus.h>
@@ -319,7 +319,7 @@ genet_tick(void *softc)
 
 	GENET_LOCK(sc);
 	mii_tick(mii);
-	if (sc->sc_running)
+	if ((sc->sc_if_flags & IFF_RUNNING) != 0)
 		callout_schedule(&sc->sc_stat_ch, hz);
 	GENET_UNLOCK(sc);
 }
@@ -570,7 +570,7 @@ genet_init_locked(struct genet_softc *sc
 	WR4(sc, GENET_UMAC_MAC1, val);
 
 	/* Setup RX filter */
-	sc->sc_promisc = ifp->if_flags & IFF_PROMISC;
+	sc->sc_if_flags = ifp->if_flags;
 	genet_setup_rxfilter(sc);
 
 	/* Setup TX/RX rings */
@@ -588,8 +588,8 @@ genet_init_locked(struct genet_softc *sc
 	GENET_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);
@@ -646,7 +646,6 @@ genet_stop_locked(struct genet_softc *sc
 	sc->sc_txrunning = false;
 	GENET_TXUNLOCK(sc);
 
-	sc->sc_running = false;
 	callout_halt(&sc->sc_stat_ch, &sc->sc_lock);
 
 	mii_down(&sc->sc_mii);
@@ -683,6 +682,7 @@ genet_stop_locked(struct genet_softc *sc
 	for (i=0; i<TX_DESC_COUNT; ++i)
 		genet_free_txbuf(sc, i);
 
+	sc->sc_if_flags &= ~IFF_RUNNING;
 	ifp->if_flags &= ~IFF_RUNNING;
 }
 
@@ -902,6 +902,14 @@ genet_ioctl(struct ifnet *ifp, u_long cm
 	struct genet_softc *sc = ifp->if_softc;
 	int error;
 
+	switch (cmd) {
+	case SIOCADDMULTI:
+	case SIOCDELMULTI:
+		break;
+	default:
+		KASSERT(IFNET_LOCKED(ifp));
+	}
+
 	const int s = splnet();
 	error = ether_ioctl(ifp, cmd, data);
 	splx(s);
@@ -915,14 +923,37 @@ genet_ioctl(struct ifnet *ifp, u_long cm
 		error = if_init(ifp);
 	else if (cmd == SIOCADDMULTI || cmd == SIOCDELMULTI) {
 		GENET_LOCK(sc);
-		sc->sc_promisc = ifp->if_flags & IFF_PROMISC;
-		if (sc->sc_running)
+		if ((sc->sc_if_flags & IFF_RUNNING) != 0)
 			genet_setup_rxfilter(sc);
 		GENET_UNLOCK(sc);
 	}
 	return error;
 }
 
+static int
+genet_ifflags_cb(struct ethercom *ec)
+{
+	struct ifnet * const ifp = &ec->ec_if;
+	struct genet_softc * const sc = ifp->if_softc;
+	int ret = 0;
+
+	KASSERT(IFNET_LOCKED(ifp));
+	GENET_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)
+			genet_setup_rxfilter(sc);
+	}
+	GENET_UNLOCK(sc);
+
+	return ret;
+}
+
 static void
 genet_get_eaddr(struct genet_softc *sc, uint8_t *eaddr)
 {
@@ -1116,6 +1147,8 @@ genet_attach(struct genet_softc *sc)
 
 	/* Attach ethernet interface */
 	ether_ifattach(ifp, eaddr);
+	ether_set_ifflags_cb(&sc->sc_ec, genet_ifflags_cb);
+
 
 	/* MBUFTRACE */
 	genet_claim_rxring(sc, GENET_DMA_DEFAULT_QUEUE);

Index: src/sys/dev/ic/bcmgenetvar.h
diff -u src/sys/dev/ic/bcmgenetvar.h:1.5 src/sys/dev/ic/bcmgenetvar.h:1.6
--- src/sys/dev/ic/bcmgenetvar.h:1.5	Sun Sep 15 07:38:08 2024
+++ src/sys/dev/ic/bcmgenetvar.h	Fri Oct  4 10:41:58 2024
@@ -1,4 +1,4 @@
-/* $NetBSD: bcmgenetvar.h,v 1.5 2024/09/15 07:38:08 skrll Exp $ */
+/* $NetBSD: bcmgenetvar.h,v 1.6 2024/10/04 10:41:58 skrll Exp $ */
 
 /*-
  * Copyright (c) 2020 Jared McNeill <jmcne...@invisible.ca>
@@ -68,9 +68,8 @@ struct genet_softc {
 	kmutex_t		sc_lock;
 	kmutex_t		sc_txlock;
 
-	bool			sc_running;
+	u_short			sc_if_flags;
 	bool			sc_txrunning;
-	bool			sc_promisc;
 
 	struct genet_ring	sc_tx;
 	struct genet_ring	sc_rx;

Reply via email to