]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/blame - releases/2.6.36.2/ath9k-fix-an-aggregation-start-related-race-condition.patch
fixes for 4.19
[thirdparty/kernel/stable-queue.git] / releases / 2.6.36.2 / ath9k-fix-an-aggregation-start-related-race-condition.patch
CommitLineData
c06f7f46
GKH
1From 231c3a1f0630c07a584905507a1cb7b705a56ab7 Mon Sep 17 00:00:00 2001
2From: Felix Fietkau <nbd@openwrt.org>
3Date: Mon, 20 Sep 2010 19:35:28 +0200
4Subject: ath9k: fix an aggregation start related race condition
5
6From: Felix Fietkau <nbd@openwrt.org>
7
8commit 231c3a1f0630c07a584905507a1cb7b705a56ab7 upstream.
9
10A new aggregation session start can be issued by mac80211, even when the
11cleanup of the previous session has not completed yet. Since the data structure
12for the session is not recreated, this could corrupt the block ack window
13and lock up the aggregation session. Fix this by delaying the new session
14until the old one has been cleaned up.
15
16Signed-off-by: Felix Fietkau <nbd@openwrt.org>
17Signed-off-by: John W. Linville <linville@tuxdriver.com>
18Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
19
20---
21 drivers/net/wireless/ath/ath9k/ath9k.h | 4 ++--
22 drivers/net/wireless/ath/ath9k/main.c | 5 +++--
23 drivers/net/wireless/ath/ath9k/xmit.c | 10 ++++++++--
24 3 files changed, 13 insertions(+), 6 deletions(-)
25
26--- a/drivers/net/wireless/ath/ath9k/ath9k.h
27+++ b/drivers/net/wireless/ath/ath9k/ath9k.h
28@@ -346,8 +346,8 @@ void ath_tx_tasklet(struct ath_softc *sc
29 void ath_tx_edma_tasklet(struct ath_softc *sc);
30 void ath_tx_cabq(struct ieee80211_hw *hw, struct sk_buff *skb);
31 bool ath_tx_aggr_check(struct ath_softc *sc, struct ath_node *an, u8 tidno);
32-void ath_tx_aggr_start(struct ath_softc *sc, struct ieee80211_sta *sta,
33- u16 tid, u16 *ssn);
34+int ath_tx_aggr_start(struct ath_softc *sc, struct ieee80211_sta *sta,
35+ u16 tid, u16 *ssn);
36 void ath_tx_aggr_stop(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid);
37 void ath_tx_aggr_resume(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid);
38 void ath9k_enable_ps(struct ath_softc *sc);
39--- a/drivers/net/wireless/ath/ath9k/main.c
40+++ b/drivers/net/wireless/ath/ath9k/main.c
41@@ -1973,8 +1973,9 @@ static int ath9k_ampdu_action(struct iee
42 break;
43 case IEEE80211_AMPDU_TX_START:
44 ath9k_ps_wakeup(sc);
45- ath_tx_aggr_start(sc, sta, tid, ssn);
46- ieee80211_start_tx_ba_cb_irqsafe(vif, sta->addr, tid);
47+ ret = ath_tx_aggr_start(sc, sta, tid, ssn);
48+ if (!ret)
49+ ieee80211_start_tx_ba_cb_irqsafe(vif, sta->addr, tid);
50 ath9k_ps_restore(sc);
51 break;
52 case IEEE80211_AMPDU_TX_STOP:
53--- a/drivers/net/wireless/ath/ath9k/xmit.c
54+++ b/drivers/net/wireless/ath/ath9k/xmit.c
55@@ -792,17 +792,23 @@ static void ath_tx_sched_aggr(struct ath
56 status != ATH_AGGR_BAW_CLOSED);
57 }
58
59-void ath_tx_aggr_start(struct ath_softc *sc, struct ieee80211_sta *sta,
60- u16 tid, u16 *ssn)
61+int ath_tx_aggr_start(struct ath_softc *sc, struct ieee80211_sta *sta,
62+ u16 tid, u16 *ssn)
63 {
64 struct ath_atx_tid *txtid;
65 struct ath_node *an;
66
67 an = (struct ath_node *)sta->drv_priv;
68 txtid = ATH_AN_2_TID(an, tid);
69+
70+ if (txtid->state & (AGGR_CLEANUP | AGGR_ADDBA_COMPLETE))
71+ return -EAGAIN;
72+
73 txtid->state |= AGGR_ADDBA_PROGRESS;
74 txtid->paused = true;
75 *ssn = txtid->seq_start;
76+
77+ return 0;
78 }
79
80 void ath_tx_aggr_stop(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid)