Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 7 Dec 2003 15:56:51 -0800 (PST)
From:      Sam Leffler <sam@FreeBSD.org>
To:        Perforce Change Reviews <perforce@freebsd.org>
Subject:   PERFORCE change 43591 for review
Message-ID:  <200312072356.hB7NupSc011478@repoman.freebsd.org>

next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=43591

Change 43591 by sam@sam_ebb on 2003/12/07 15:55:58

	call ath_reset instead of ath_init on ioctl calls to avoid
	stirring the 802.11 state machine; this is unfinished, we need
	to get the 802.11 code to inform us when a rescan is needed
	(or have it start it itself)

Affected files ...

.. //depot/projects/netperf/sys/dev/ath/if_ath.c#46 edit

Differences ...

==== //depot/projects/netperf/sys/dev/ath/if_ath.c#46 (text+ko) ====

@@ -95,7 +95,7 @@
 static void	ath_init(void *);
 static void	ath_stop(struct ifnet *);
 static void	ath_start(struct ifnet *);
-static void	ath_reset(struct ath_softc *);
+static void	ath_reset(struct ath_softc *, int);
 static int	ath_media_change(struct ifnet *);
 static void	ath_watchdog(struct ifnet *);
 static int	ath_ioctl(struct ifnet *, u_long, caddr_t);
@@ -471,7 +471,7 @@
 	struct ath_softc *sc = arg;
 
 	device_printf(sc->sc_dev, "hardware error; resetting\n");
-	ath_reset(sc);
+	ath_reset(sc, 0);
 }
 
 static void
@@ -480,7 +480,7 @@
 	struct ath_softc *sc = arg;
 
 	device_printf(sc->sc_dev, "rx FIFO overrun; resetting\n");
-	ath_reset(sc);
+	ath_reset(sc, 0);
 }
 
 static void
@@ -647,7 +647,7 @@
  * and to reset the hardware when rf gain settings must be reset.
  */
 static void
-ath_reset(struct ath_softc *sc)
+ath_reset(struct ath_softc *sc, int full)
 {
 	struct ieee80211com *ic = &sc->sc_ic;
 	struct ifnet *ifp = &ic->ic_if;
@@ -671,6 +671,9 @@
 	if (!ath_hal_reset(ah, ic->ic_opmode, &hchan, AH_TRUE, &status))
 		if_printf(ifp, "%s: unable to reset hardware; hal status %u\n",
 			__func__, status);
+	/* NB: only needed when called from ath_ioctl */
+	if (full && (ic->ic_flags & IEEE80211_F_WEPON))
+		ath_initkeytable(sc);
 	ath_hal_intrset(ah, sc->sc_imask);
 	if (ath_startrecv(sc) != 0)	/* restart recv */
 		if_printf(ifp, "%s: unable to start recv logic\n", __func__);
@@ -822,7 +825,7 @@
 			if (ath_debug)
 				ath_hal_dumpstate(sc->sc_ah);
 #endif /* AR_DEBUG */
-			ath_init(ifp);		/* XXX ath_reset??? */
+			ath_reset(sc, 0);
 			ifp->if_oerrors++;
 			sc->sc_stats.ast_watchdog++;
 			return;
@@ -845,6 +848,8 @@
 static int
 ath_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
 {
+#define	UP_RUNNING(_ifp) \
+	(((_ifp)->if_flags & (IFF_UP|IFF_RUNNING)) == (IFF_UP|IFF_RUNNING))
 	struct ath_softc *sc = ifp->if_softc;
 	struct ifreq *ifr = (struct ifreq *)data;
 	int error = 0;
@@ -852,29 +857,31 @@
 	ATH_LOCK(sc);
 	switch (cmd) {
 	case SIOCSIFFLAGS:
-		if (ifp->if_flags & IFF_UP) {
-			if (ifp->if_flags & IFF_RUNNING) {
-				/*
-				 * To avoid rescanning another access point,
-				 * do not call ath_init() here.  Instead,
-				 * only reflect promisc mode settings.
-				 */
-				ath_mode_init(sc);
-			} else {
-				/*
-				 * Beware of being called during detach to
-				 * reset promiscuous mode.  In that case we
-				 * will still be marked UP but not RUNNING.
-				 * However trying to re-init the interface
-				 * is the wrong thing to do as we've already
-				 * torn down much of our state.  There's
-				 * probably a better way to deal with this.
-				 */
-				if (!sc->sc_invalid)
-					ath_init(ifp);	/* XXX lose error */
-			}
-		} else
+		if (UP_RUNNING(ifp)) {
+			/*
+			 * To avoid rescanning another access point,
+			 * do not call ath_init() here.  Instead,
+			 * only reflect promisc mode settings.
+			 */
+			ath_mode_init(sc);
+		} else if (ifp->if_flags & IFF_UP) {
+			/*
+			 * Beware of being called during detach to
+			 * reset promiscuous mode.  In that case we
+			 * will still be marked UP but not RUNNING.
+			 * However trying to re-init the interface
+			 * is the wrong thing to do as we've already
+			 * torn down much of our state.  There's
+			 * probably a better way to deal with this.
+			 */
+			if (!sc->sc_invalid)
+				ath_init(ifp);	/* XXX lose error */
+		} else {
+			/*
+			 * Interface marked down; clear the hardware.
+			 */
 			ath_stop(ifp);
+		}
 		break;
 	case SIOCADDMULTI:
 	case SIOCDELMULTI:
@@ -908,9 +915,20 @@
 	default:
 		error = ieee80211_ioctl(ifp, cmd, data);
 		if (error == ENETRESET) {
-			if ((ifp->if_flags & (IFF_RUNNING|IFF_UP)) ==
-			    (IFF_RUNNING|IFF_UP))
-				ath_init(ifp);		/* XXX lose error */
+			/*
+			 * If the interface is up and running then we
+			 * want the parameter changes to take effect
+			 * immediately, so reset hardware state to
+			 * reflect parameter change(s).  We don't try to
+			 * intuit exactly what changed here; we just
+			 * bludgeon state which can have unfortunate
+			 * side effects.
+			 *
+			 * XXX doesn't recognize when a rescan is needed;
+			 *     e.g. for ssid or channel change
+			 */
+			if (UP_RUNNING(ifp))
+				ath_reset(sc, 1);
 			error = 0;
 		}
 		break;
@@ -2448,7 +2466,7 @@
 		 * to load new gain values.
 		 */
 		sc->sc_stats.ast_per_rfgain++;
-		ath_reset(sc);
+		ath_reset(sc, 0);
 	}
 	if (!ath_hal_calibrate(ah, &hchan)) {
 		DPRINTF(("%s: calibration of channel %u failed\n",



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200312072356.hB7NupSc011478>