Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 8 Nov 2011 18:56:52 +0000 (UTC)
From:      Adrian Chadd <adrian@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r227353 - head/sys/dev/ath
Message-ID:  <201111081856.pA8IuqpN044295@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: adrian
Date: Tue Nov  8 18:56:52 2011
New Revision: 227353
URL: http://svn.freebsd.org/changeset/base/227353

Log:
  In preparation for supporting 11n TX/RX properly, allow for TX queue draining
  and interface resets to be marked as ATH_RESET_DEFAULT, ATH_RESET_FULL,
  ATH_RESET_NOLOSS.
  
  Currently a reset is still a reset - ie, all tx/rx frames in the hardware
  queues are purged. This means that those frames will be lost to the 11n TX
  and RX aggregation state tracking, breaking AMPDU sessions.
  
  The (eventual) new semantics:
  
  * ATH_RESET_DEFAULT:
        full reset, this is the default for reset situations
        which I haven't yet figured out what they should be.
  * ATH_RESET_FULL:
        A full reset - for things such as channel changes.
  * ATH_RESET_NOLOSS:
        Don't flush TX/RX queues - handle pending RX frames and leave TX
        frames where they are; restart TX DMA from where it was.

Modified:
  head/sys/dev/ath/if_ath.c
  head/sys/dev/ath/if_ath_misc.h
  head/sys/dev/ath/if_ath_sysctl.c

Modified: head/sys/dev/ath/if_ath.c
==============================================================================
--- head/sys/dev/ath/if_ath.c	Tue Nov  8 18:48:26 2011	(r227352)
+++ head/sys/dev/ath/if_ath.c	Tue Nov  8 18:56:52 2011	(r227353)
@@ -184,7 +184,7 @@ static void	ath_tx_proc_q0123(void *, in
 static void	ath_tx_proc(void *, int);
 static void	ath_tx_draintxq(struct ath_softc *, struct ath_txq *);
 static int	ath_chan_set(struct ath_softc *, struct ieee80211_channel *);
-static void	ath_draintxq(struct ath_softc *);
+static void	ath_draintxq(struct ath_softc *, ATH_RESET_TYPE reset_type);
 static void	ath_stoprecv(struct ath_softc *);
 static int	ath_startrecv(struct ath_softc *);
 static void	ath_chan_change(struct ath_softc *, struct ieee80211_channel *);
@@ -1123,7 +1123,8 @@ ath_vap_delete(struct ieee80211vap *vap)
 		 * the vap state by any frames pending on the tx queues.
 		 */
 		ath_hal_intrset(ah, 0);		/* disable interrupts */
-		ath_draintxq(sc);		/* stop xmit side */
+		ath_draintxq(sc, ATH_RESET_DEFAULT);		/* stop hw xmit side */
+		/* XXX Do all frames from all vaps/nodes need draining here? */
 		ath_stoprecv(sc);		/* stop recv side */
 	}
 
@@ -1507,7 +1508,7 @@ ath_fatal_proc(void *arg, int pending)
 		    state[0], state[1] , state[2], state[3],
 		    state[4], state[5]);
 	}
-	ath_reset(ifp);
+	ath_reset(ifp, ATH_RESET_NOLOSS);
 }
 
 static void
@@ -1567,7 +1568,7 @@ ath_bmiss_proc(void *arg, int pending)
 
 	if (ath_hal_gethangstate(sc->sc_ah, 0xff, &hangs) && hangs != 0) {
 		if_printf(ifp, "bb hang detected (0x%x), resetting\n", hangs);
-		ath_reset(ifp);
+		ath_reset(ifp, ATH_RESET_NOLOSS);
 	} else
 		ieee80211_beacon_miss(ifp->if_l2com);
 }
@@ -1747,7 +1748,7 @@ ath_stop_locked(struct ifnet *ifp)
 			}
 			ath_hal_intrset(ah, 0);
 		}
-		ath_draintxq(sc);
+		ath_draintxq(sc, ATH_RESET_DEFAULT);
 		if (!sc->sc_invalid) {
 			ath_stoprecv(sc);
 			ath_hal_phydisable(ah);
@@ -1775,7 +1776,7 @@ ath_stop(struct ifnet *ifp)
  * to reset or reload hardware state.
  */
 int
-ath_reset(struct ifnet *ifp)
+ath_reset(struct ifnet *ifp, ATH_RESET_TYPE reset_type)
 {
 	struct ath_softc *sc = ifp->if_softc;
 	struct ieee80211com *ic = ifp->if_l2com;
@@ -1783,7 +1784,7 @@ ath_reset(struct ifnet *ifp)
 	HAL_STATUS status;
 
 	ath_hal_intrset(ah, 0);		/* disable interrupts */
-	ath_draintxq(sc);		/* stop xmit side */
+	ath_draintxq(sc, reset_type);	/* stop xmit side */
 	ath_stoprecv(sc);		/* stop recv side */
 	ath_settkipmic(sc);		/* configure TKIP MIC handling */
 	/* NB: indicate channel change so we do a full reset */
@@ -1836,7 +1837,8 @@ ath_reset_vap(struct ieee80211vap *vap, 
 			ath_hal_settxpowlimit(ah, ic->ic_txpowlimit);
 		return 0;
 	}
-	return ath_reset(ifp);
+	/* XXX? Full or NOLOSS? */
+	return ath_reset(ifp, ATH_RESET_FULL);
 }
 
 struct ath_buf *
@@ -2730,7 +2732,7 @@ ath_bstuck_proc(void *arg, int pending)
 	if_printf(ifp, "stuck beacon; resetting (bmiss count %u)\n",
 		sc->sc_bmisscount);
 	sc->sc_stats.ast_bstuck++;
-	ath_reset(ifp);
+	ath_reset(ifp, ATH_RESET_NOLOSS);
 }
 
 /*
@@ -4484,7 +4486,7 @@ ath_tx_stopdma(struct ath_softc *sc, str
  * Drain the transmit queues and reclaim resources.
  */
 static void
-ath_draintxq(struct ath_softc *sc)
+ath_draintxq(struct ath_softc *sc, ATH_RESET_TYPE reset_type)
 {
 	struct ath_hal *ah = sc->sc_ah;
 	struct ifnet *ifp = sc->sc_ifp;
@@ -4636,7 +4638,7 @@ ath_chan_set(struct ath_softc *sc, struc
 		 * the relevant bits of the h/w.
 		 */
 		ath_hal_intrset(ah, 0);		/* disable interrupts */
-		ath_draintxq(sc);		/* clear pending tx frames */
+		ath_draintxq(sc, ATH_RESET_FULL);		/* clear pending tx frames */
 		ath_stoprecv(sc);		/* turn off frame recv */
 		if (!ath_hal_reset(ah, sc->sc_opmode, chan, AH_TRUE, &status)) {
 			if_printf(ifp, "%s: unable to reset "
@@ -4726,7 +4728,7 @@ ath_calibrate(void *arg)
 			DPRINTF(sc, ATH_DEBUG_CALIBRATE,
 				"%s: rfgain change\n", __func__);
 			sc->sc_stats.ast_per_rfgain++;
-			ath_reset(ifp);
+			ath_reset(ifp, ATH_RESET_NOLOSS);
 		}
 		/*
 		 * If this long cal is after an idle period, then
@@ -5392,7 +5394,7 @@ ath_watchdog(void *arg)
 			    hangs & 0xff ? "bb" : "mac", hangs);
 		} else
 			if_printf(ifp, "device timeout\n");
-		ath_reset(ifp);
+		ath_reset(ifp, ATH_RESET_NOLOSS);
 		ifp->if_oerrors++;
 		sc->sc_stats.ast_watchdog++;
 	}

Modified: head/sys/dev/ath/if_ath_misc.h
==============================================================================
--- head/sys/dev/ath/if_ath_misc.h	Tue Nov  8 18:48:26 2011	(r227352)
+++ head/sys/dev/ath/if_ath_misc.h	Tue Nov  8 18:56:52 2011	(r227353)
@@ -53,6 +53,6 @@ extern int ath_tx_findrix(const struct a
 extern struct ath_buf * ath_getbuf(struct ath_softc *sc);
 extern struct ath_buf * _ath_getbuf_locked(struct ath_softc *sc);
 
-extern int ath_reset(struct ifnet *);
+extern int ath_reset(struct ifnet *, ATH_RESET_TYPE);
 
 #endif

Modified: head/sys/dev/ath/if_ath_sysctl.c
==============================================================================
--- head/sys/dev/ath/if_ath_sysctl.c	Tue Nov  8 18:48:26 2011	(r227352)
+++ head/sys/dev/ath/if_ath_sysctl.c	Tue Nov  8 18:56:52 2011	(r227353)
@@ -263,7 +263,8 @@ ath_sysctl_tpscale(SYSCTL_HANDLER_ARGS)
 	if (error || !req->newptr)
 		return error;
 	return !ath_hal_settpscale(sc->sc_ah, scale) ? EINVAL :
-	    (ifp->if_drv_flags & IFF_DRV_RUNNING) ? ath_reset(ifp) : 0;
+	    (ifp->if_drv_flags & IFF_DRV_RUNNING) ?
+	      ath_reset(ifp, ATH_RESET_NOLOSS) : 0;
 }
 
 static int
@@ -295,7 +296,8 @@ ath_sysctl_rfkill(SYSCTL_HANDLER_ARGS)
 		return 0;
 	if (!ath_hal_setrfkill(ah, rfkill))
 		return EINVAL;
-	return (ifp->if_drv_flags & IFF_DRV_RUNNING) ? ath_reset(ifp) : 0;
+	return (ifp->if_drv_flags & IFF_DRV_RUNNING) ?
+	    ath_reset(ifp, ATH_RESET_FULL) : 0;
 }
 
 static int
@@ -428,7 +430,7 @@ ath_sysctl_intmit(SYSCTL_HANDLER_ARGS)
 	 * things in an inconsistent state.
 	 */
 	if (sc->sc_ifp->if_drv_flags & IFF_DRV_RUNNING)
-		ath_reset(sc->sc_ifp);
+		ath_reset(sc->sc_ifp, ATH_RESET_NOLOSS);
 
 	return 0;
 }



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