svn commit: r226400 - user/adrian/if_ath_tx/sys/dev/ath

Adrian Chadd adrian at FreeBSD.org
Sat Oct 15 16:18:36 UTC 2011


Author: adrian
Date: Sat Oct 15 16:18:35 2011
New Revision: 226400
URL: http://svn.freebsd.org/changeset/base/226400

Log:
  Hide ath_rx_proc() behind the ATH_LOCK, and start using it before resetting
  the hardware.
  
  When resetting the NIC (eg when a stuck beacon occurs), there may be received
  frames in the RX queue. This should happen:
  
  * disable interrupts;
  * stop pcu receive;
  * handle frames in the RX queue;
  * reset the hardware as needed;
  * start the PCU RX (which purges the queue.)
  
  This prevents RX frames from disappearing after an interface reset (eg
  ANI config change, forced beacon stuck) and thus the RX AMPDU tracking
  getting out of whack with the TX'ing side. Since PCU receive has stopped,
  
  This doesn't entirely fix things, as the TX side can and will drop frames
  on an interface reset or node flush. I'll worry about this in a subsequent
  commit.
  
  TODO:
  
  * see whether the pcu rx should be stopped before disabling interrupts,
    that way the MAC definitely stops ACKing frames. Instead, right now
    with the above order, frames coming after intr disable but before pcu
    stop may overflow the RX fifo and cause some issues.

Modified:
  user/adrian/if_ath_tx/sys/dev/ath/if_ath.c

Modified: user/adrian/if_ath_tx/sys/dev/ath/if_ath.c
==============================================================================
--- user/adrian/if_ath_tx/sys/dev/ath/if_ath.c	Sat Oct 15 16:05:27 2011	(r226399)
+++ user/adrian/if_ath_tx/sys/dev/ath/if_ath.c	Sat Oct 15 16:18:35 2011	(r226400)
@@ -1131,6 +1131,7 @@ ath_vap_delete(struct ieee80211vap *vap)
 	DPRINTF(sc, ATH_DEBUG_RESET, "%s: called\n", __func__);
 
 	if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
+		ATH_LOCK(sc);
 		/*
 		 * Quiesce the hardware while we remove the vap.  In
 		 * particular we need to reclaim all references to
@@ -1140,6 +1141,8 @@ ath_vap_delete(struct ieee80211vap *vap)
 		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 */
+		ath_rx_proc(sc, 0);
+		ATH_UNLOCK(sc);
 	}
 
 	ieee80211_vap_detach(vap);
@@ -1795,6 +1798,7 @@ ath_stop_locked(struct ifnet *ifp)
 		ath_draintxq(sc, ATH_RESET_DEFAULT);
 		if (!sc->sc_invalid) {
 			ath_stoprecv(sc);
+			ath_rx_proc(sc, 0);
 			ath_hal_phydisable(ah);
 		} else
 			sc->sc_rxlink = NULL;
@@ -1851,6 +1855,7 @@ ath_reset_locked(struct ifnet *ifp, ATH_
 	 * XXX taskqueue call.
 	 */
 	ath_stoprecv(sc);		/* stop recv side */
+	ath_rx_proc(sc, 0);		/* process RX'ed frames in the queue */
 	ath_settkipmic(sc);		/* configure TKIP MIC handling */
 	/* NB: indicate channel change so we do a full reset */
 	if (!ath_hal_reset(ah, sc->sc_opmode, ic->ic_curchan, AH_TRUE, &status))
@@ -3721,9 +3726,11 @@ ath_rx_tasklet(void *arg, int npending)
 {
 	struct ath_softc *sc = arg;
 
+	ATH_LOCK(sc);
 	CTR1(ATH_KTR_INTR, "ath_rx_proc: pending=%d", npending);
 	DPRINTF(sc, ATH_DEBUG_RX_PROC, "%s: pending %u\n", __func__, npending);
 	ath_rx_proc(sc, 1);
+	ATH_UNLOCK(sc);
 }
 
 static void
@@ -3746,6 +3753,8 @@ ath_rx_proc(struct ath_softc *sc, int re
 	u_int64_t tsf;
 	int npkts = 0;
 
+	ATH_LOCK_ASSERT(sc);
+
 	DPRINTF(sc, ATH_DEBUG_RX_PROC, "%s: called\n", __func__);
 	ngood = 0;
 	nf = ath_hal_getchannoise(ah, sc->sc_curchan);
@@ -5061,6 +5070,7 @@ ath_chan_set(struct ath_softc *sc, struc
 		ath_hal_intrset(ah, 0);		/* disable interrupts */
 		ath_draintxq(sc, ATH_RESET_FULL);	/* clear pending tx frames */
 		ath_stoprecv(sc);		/* turn off frame recv */
+		ath_rx_proc(sc, 0);		/* handle RX'ed frames */
 		if (!ath_hal_reset(ah, sc->sc_opmode, chan, AH_TRUE, &status)) {
 			if_printf(ifp, "%s: unable to reset "
 			    "channel %u (%u MHz, flags 0x%x), hal status %u\n",


More information about the svn-src-user mailing list