diff options
author | Felix Fietkau <nbd@openwrt.org> | 2013-01-09 16:16:55 +0100 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2013-01-11 14:12:02 -0500 |
commit | 7fc00a3054b70b1794c2d64db703eb467ad0365c (patch) | |
tree | 3a8c6672e339337b16a6e4bb736d3c6f2d3bb238 /drivers/net/wireless/ath | |
parent | 3adcf20afb585993ffee24de36d1975f6b26b120 (diff) |
ath9k: add a better fix for the rx tasklet vs rx flush race
Ensure that the rx tasklet is no longer running when entering the reset path.
Also remove the distinction between flush and no-flush frame processing.
If a frame has been received and ACKed by the hardware, the stack needs to see
it, so that the BA receive window does not go out of sync.
Cc: stable@vger.kernel.org
Signed-off-by: Felix Fietkau <nbd@openwrt.org>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/ath')
-rw-r--r-- | drivers/net/wireless/ath/ath9k/ath9k.h | 1 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/debug.c | 1 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/debug.h | 2 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/main.c | 4 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/recv.c | 15 |
5 files changed, 4 insertions, 19 deletions
diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h index 86e26a19efd..7335e9ef024 100644 --- a/drivers/net/wireless/ath/ath9k/ath9k.h +++ b/drivers/net/wireless/ath/ath9k/ath9k.h @@ -646,7 +646,6 @@ void ath_ant_comb_update(struct ath_softc *sc); enum sc_op_flags { SC_OP_INVALID, SC_OP_BEACONS, - SC_OP_RXFLUSH, SC_OP_ANI_RUN, SC_OP_PRIM_STA_VIF, SC_OP_HW_RESET, diff --git a/drivers/net/wireless/ath/ath9k/debug.c b/drivers/net/wireless/ath/ath9k/debug.c index 13ff9edc240..e585fc827c5 100644 --- a/drivers/net/wireless/ath/ath9k/debug.c +++ b/drivers/net/wireless/ath/ath9k/debug.c @@ -861,7 +861,6 @@ static ssize_t read_file_recv(struct file *file, char __user *user_buf, RXS_ERR("RX-LENGTH-ERR", rx_len_err); RXS_ERR("RX-OOM-ERR", rx_oom_err); RXS_ERR("RX-RATE-ERR", rx_rate_err); - RXS_ERR("RX-DROP-RXFLUSH", rx_drop_rxflush); RXS_ERR("RX-TOO-MANY-FRAGS", rx_too_many_frags_err); PHY_ERR("UNDERRUN ERR", ATH9K_PHYERR_UNDERRUN); diff --git a/drivers/net/wireless/ath/ath9k/debug.h b/drivers/net/wireless/ath/ath9k/debug.h index 375c3b46411..6df2ab62dcb 100644 --- a/drivers/net/wireless/ath/ath9k/debug.h +++ b/drivers/net/wireless/ath/ath9k/debug.h @@ -216,7 +216,6 @@ struct ath_tx_stats { * @rx_oom_err: No. of frames dropped due to OOM issues. * @rx_rate_err: No. of frames dropped due to rate errors. * @rx_too_many_frags_err: Frames dropped due to too-many-frags received. - * @rx_drop_rxflush: No. of frames dropped due to RX-FLUSH. * @rx_beacons: No. of beacons received. * @rx_frags: No. of rx-fragements received. */ @@ -235,7 +234,6 @@ struct ath_rx_stats { u32 rx_oom_err; u32 rx_rate_err; u32 rx_too_many_frags_err; - u32 rx_drop_rxflush; u32 rx_beacons; u32 rx_frags; }; diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index be30a9af152..d3cf01ec2d1 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c @@ -196,6 +196,8 @@ static bool ath_prepare_reset(struct ath_softc *sc, bool retry_tx, bool flush) ath9k_debug_samp_bb_mac(sc); ath9k_hw_disable_interrupts(ah); + tasklet_disable(&sc->intr_tq); + if (!ath_stoprecv(sc)) ret = false; @@ -210,6 +212,8 @@ static bool ath_prepare_reset(struct ath_softc *sc, bool retry_tx, bool flush) ath_flushrecv(sc); } + tasklet_enable(&sc->intr_tq); + return ret; } diff --git a/drivers/net/wireless/ath/ath9k/recv.c b/drivers/net/wireless/ath/ath9k/recv.c index 01c3ba47a5b..6b83b3bbfe8 100644 --- a/drivers/net/wireless/ath/ath9k/recv.c +++ b/drivers/net/wireless/ath/ath9k/recv.c @@ -286,7 +286,6 @@ int ath_rx_init(struct ath_softc *sc, int nbufs) spin_lock_init(&sc->sc_pcu_lock); spin_lock_init(&sc->rx.rxbuflock); - clear_bit(SC_OP_RXFLUSH, &sc->sc_flags); common->rx_bufsize = IEEE80211_MAX_MPDU_LEN / 2 + sc->sc_ah->caps.rx_status_len; @@ -501,11 +500,9 @@ bool ath_stoprecv(struct ath_softc *sc) void ath_flushrecv(struct ath_softc *sc) { - set_bit(SC_OP_RXFLUSH, &sc->sc_flags); if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) ath_rx_tasklet(sc, 1, true); ath_rx_tasklet(sc, 1, false); - clear_bit(SC_OP_RXFLUSH, &sc->sc_flags); } static bool ath_beacon_dtim_pending_cab(struct sk_buff *skb) @@ -1067,9 +1064,6 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp) do { bool decrypt_error = false; - /* If handling rx interrupt and flush is in progress => exit */ - if (test_bit(SC_OP_RXFLUSH, &sc->sc_flags) && (flush == 0)) - break; memset(&rs, 0, sizeof(rs)); if (edma) @@ -1112,15 +1106,6 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp) ath_debug_stat_rx(sc, &rs); - /* - * If we're asked to flush receive queue, directly - * chain it back at the queue without processing it. - */ - if (test_bit(SC_OP_RXFLUSH, &sc->sc_flags)) { - RX_STAT_INC(rx_drop_rxflush); - goto requeue_drop_frag; - } - memset(rxs, 0, sizeof(struct ieee80211_rx_status)); rxs->mactime = (tsf & ~0xffffffffULL) | rs.rs_tstamp; |