Shut down RX before TX - in theory, this should make the chip less likely

to get upset.

The Qualcomm Atheros reference design code goes through significant
hacks to shut down RX before TX.  It doesn't even try do do it in the
driver - it actually makes the DMA stop routines in the HAL shut down
RX before shutting down TX.

So, to make this work for chips that aren't the AR9380 and later, do
it in the driver.  Shuffle the TX stop/drain HAL calls to be called
*after* the RX stop HAL call.

Tested:

* AR5413 (STA)
* AR5212 (STA)
* AR5416 (STA)
* AR9380 (STA)
* AR9331 (AP)
* AR9341 (AP)

TODO:

* test ar92xx series NIC and the AR5210/AR5211, in case there's something
  even odder about those.
This commit is contained in:
Adrian Chadd 2014-08-23 18:55:51 +00:00
parent 8158a32900
commit 062cf7d90a
2 changed files with 15 additions and 9 deletions

View File

@ -1599,9 +1599,9 @@ 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, ATH_RESET_DEFAULT); /* stop hw xmit side */
/* XXX Do all frames from all vaps/nodes need draining here? */
ath_stoprecv(sc, 1); /* stop recv side */
ath_draintxq(sc, ATH_RESET_DEFAULT); /* stop hw xmit side */
}
/* .. leave the hardware awake for now. */
@ -2503,12 +2503,13 @@ ath_stop_locked(struct ifnet *ifp)
}
ath_hal_intrset(ah, 0);
}
ath_draintxq(sc, ATH_RESET_DEFAULT);
/* XXX we should stop RX regardless of whether it's valid */
if (!sc->sc_invalid) {
ath_stoprecv(sc, 1);
ath_hal_phydisable(ah);
} else
sc->sc_rxlink = NULL;
ath_draintxq(sc, ATH_RESET_DEFAULT);
ath_beacon_free(sc); /* XXX not needed */
}
@ -2709,13 +2710,6 @@ ath_reset(struct ifnet *ifp, ATH_RESET_TYPE reset_type)
ATH_PCU_UNLOCK(sc);
/*
* Should now wait for pending TX/RX to complete
* and block future ones from occuring. This needs to be
* done before the TX queue is drained.
*/
ath_draintxq(sc, reset_type); /* stop xmit side */
/*
* Regardless of whether we're doing a no-loss flush or
* not, stop the PCU and handle what's in the RX queue.
@ -2724,6 +2718,13 @@ ath_reset(struct ifnet *ifp, ATH_RESET_TYPE reset_type)
ath_stoprecv(sc, (reset_type != ATH_RESET_NOLOSS));
ath_rx_flush(sc);
/*
* Should now wait for pending TX/RX to complete
* and block future ones from occuring. This needs to be
* done before the TX queue is drained.
*/
ath_draintxq(sc, reset_type); /* stop xmit side */
ath_settkipmic(sc); /* configure TKIP MIC handling */
/* NB: indicate channel change so we do a full reset */
ath_update_chainmasks(sc, ic->ic_curchan);

View File

@ -749,6 +749,11 @@ ath_beacon_generate(struct ath_softc *sc, struct ieee80211vap *vap)
*
* More thought is required here.
*/
/*
* XXX can we even stop TX DMA here? Check what the
* reference driver does for cabq for beacons, given
* that stopping TX requires RX is paused.
*/
ath_tx_draintxq(sc, cabq);
}
}