aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/ath/ath9k/recv.c
diff options
context:
space:
mode:
authorFelix Fietkau <nbd@openwrt.org>2013-01-09 10:16:55 -0500
committerJohn W. Linville <linville@tuxdriver.com>2013-01-11 14:12:02 -0500
commit7fc00a3054b70b1794c2d64db703eb467ad0365c (patch)
tree3a8c6672e339337b16a6e4bb736d3c6f2d3bb238 /drivers/net/wireless/ath/ath9k/recv.c
parent3adcf20afb585993ffee24de36d1975f6b26b120 (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/ath9k/recv.c')
-rw-r--r--drivers/net/wireless/ath/ath9k/recv.c15
1 files changed, 0 insertions, 15 deletions
diff --git a/drivers/net/wireless/ath/ath9k/recv.c b/drivers/net/wireless/ath/ath9k/recv.c
index 01c3ba47a5b9..6b83b3bbfe8c 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)
286 286
287 spin_lock_init(&sc->sc_pcu_lock); 287 spin_lock_init(&sc->sc_pcu_lock);
288 spin_lock_init(&sc->rx.rxbuflock); 288 spin_lock_init(&sc->rx.rxbuflock);
289 clear_bit(SC_OP_RXFLUSH, &sc->sc_flags);
290 289
291 common->rx_bufsize = IEEE80211_MAX_MPDU_LEN / 2 + 290 common->rx_bufsize = IEEE80211_MAX_MPDU_LEN / 2 +
292 sc->sc_ah->caps.rx_status_len; 291 sc->sc_ah->caps.rx_status_len;
@@ -501,11 +500,9 @@ bool ath_stoprecv(struct ath_softc *sc)
501 500
502void ath_flushrecv(struct ath_softc *sc) 501void ath_flushrecv(struct ath_softc *sc)
503{ 502{
504 set_bit(SC_OP_RXFLUSH, &sc->sc_flags);
505 if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) 503 if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA)
506 ath_rx_tasklet(sc, 1, true); 504 ath_rx_tasklet(sc, 1, true);
507 ath_rx_tasklet(sc, 1, false); 505 ath_rx_tasklet(sc, 1, false);
508 clear_bit(SC_OP_RXFLUSH, &sc->sc_flags);
509} 506}
510 507
511static bool ath_beacon_dtim_pending_cab(struct sk_buff *skb) 508static 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)
1067 1064
1068 do { 1065 do {
1069 bool decrypt_error = false; 1066 bool decrypt_error = false;
1070 /* If handling rx interrupt and flush is in progress => exit */
1071 if (test_bit(SC_OP_RXFLUSH, &sc->sc_flags) && (flush == 0))
1072 break;
1073 1067
1074 memset(&rs, 0, sizeof(rs)); 1068 memset(&rs, 0, sizeof(rs));
1075 if (edma) 1069 if (edma)
@@ -1112,15 +1106,6 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp)
1112 1106
1113 ath_debug_stat_rx(sc, &rs); 1107 ath_debug_stat_rx(sc, &rs);
1114 1108
1115 /*
1116 * If we're asked to flush receive queue, directly
1117 * chain it back at the queue without processing it.
1118 */
1119 if (test_bit(SC_OP_RXFLUSH, &sc->sc_flags)) {
1120 RX_STAT_INC(rx_drop_rxflush);
1121 goto requeue_drop_frag;
1122 }
1123
1124 memset(rxs, 0, sizeof(struct ieee80211_rx_status)); 1109 memset(rxs, 0, sizeof(struct ieee80211_rx_status));
1125 1110
1126 rxs->mactime = (tsf & ~0xffffffffULL) | rs.rs_tstamp; 1111 rxs->mactime = (tsf & ~0xffffffffULL) | rs.rs_tstamp;