ath9k: fix rx flush handling

Right now the rx flush is not doing anything useful on AR9003+, as it only
works if the buffers in the rx FIFO have not been purged yet, as is done
by ath_stoprecv.

To fix this, always call ath_flushrecv from within ath_stoprecv before
the FIFO is emptied, but still after the hw receive path has been stopped.

This ensures that frames received (and ACKed by the hardware) shortly before
a reset will be seen by the software, which should improve A-MPDU session
stability.

Cc: stable@vger.kernel.org
Signed-off-by: Felix Fietkau <nbd@openwrt.org>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
This commit is contained in:
Felix Fietkau
2013-01-09 16:16:56 +01:00
committed by John W. Linville
parent 7fc00a3054
commit 4b883f021b
3 changed files with 12 additions and 21 deletions

View File

@@ -182,7 +182,7 @@ static void ath_restart_work(struct ath_softc *sc)
ath_start_ani(sc);
}
static bool ath_prepare_reset(struct ath_softc *sc, bool retry_tx, bool flush)
static bool ath_prepare_reset(struct ath_softc *sc, bool retry_tx)
{
struct ath_hw *ah = sc->sc_ah;
bool ret = true;
@@ -204,14 +204,6 @@ static bool ath_prepare_reset(struct ath_softc *sc, bool retry_tx, bool flush)
if (!ath_drain_all_txq(sc, retry_tx))
ret = false;
if (!flush) {
if (ah->caps.hw_caps & ATH9K_HW_CAP_EDMA)
ath_rx_tasklet(sc, 1, true);
ath_rx_tasklet(sc, 1, false);
} else {
ath_flushrecv(sc);
}
tasklet_enable(&sc->intr_tq);
return ret;
@@ -266,7 +258,6 @@ static int ath_reset_internal(struct ath_softc *sc, struct ath9k_channel *hchan,
struct ath_common *common = ath9k_hw_common(ah);
struct ath9k_hw_cal_data *caldata = NULL;
bool fastcc = true;
bool flush = false;
int r;
__ath_cancel_work(sc);
@@ -280,11 +271,10 @@ static int ath_reset_internal(struct ath_softc *sc, struct ath9k_channel *hchan,
if (!hchan) {
fastcc = false;
flush = true;
hchan = ah->curchan;
}
if (!ath_prepare_reset(sc, retry_tx, flush))
if (!ath_prepare_reset(sc, retry_tx))
fastcc = false;
ath_dbg(common, CONFIG, "Reset to %u MHz, HT40: %d fastcc: %d\n",
@@ -808,7 +798,7 @@ static void ath9k_stop(struct ieee80211_hw *hw)
ath9k_hw_cfg_gpio_input(ah, ah->led_pin);
}
ath_prepare_reset(sc, false, true);
ath_prepare_reset(sc, false);
if (sc->rx.frag) {
dev_kfree_skb_any(sc->rx.frag);