aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211/agg-rx.c
diff options
context:
space:
mode:
authorJohannes Berg <johannes@sipsolutions.net>2010-04-06 05:18:47 -0400
committerJohn W. Linville <linville@tuxdriver.com>2010-04-07 14:38:05 -0400
commit098a607091426e79178b9a6c318d993fea131791 (patch)
treed62c9993e49f90ca962cd763b096911d22d7e051 /net/mac80211/agg-rx.c
parent618f356b95e37ca0c30b3b513898fda54abd52a6 (diff)
mac80211: clean up/fix aggregation code
The aggregation code has a number of quirks, like inventing an unneeded WLAN_BACK_TIMER value and leaking memory under certain circumstances during station destruction. Fix these issues by using the regular aggregation session teardown code and blocking new aggregation sessions, all before the station is really destructed. As a side effect, this gets rid of the long code block to destroy aggregation safely. Additionally, rename tid_state_rx which can only have the values IDLE and OPERATIONAL to tid_active_rx to make it easier to understand that there is no bitwise stuff going on on the RX side -- the TX side remains because it needs to keep track of the driver and peer states. Signed-off-by: Johannes Berg <johannes@sipsolutions.net> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'net/mac80211/agg-rx.c')
-rw-r--r--net/mac80211/agg-rx.c48
1 files changed, 21 insertions, 27 deletions
diff --git a/net/mac80211/agg-rx.c b/net/mac80211/agg-rx.c
index 7d87f446f030..53233ab50f65 100644
--- a/net/mac80211/agg-rx.c
+++ b/net/mac80211/agg-rx.c
@@ -22,19 +22,20 @@ void __ieee80211_stop_rx_ba_session(struct sta_info *sta, u16 tid,
22 u16 initiator, u16 reason) 22 u16 initiator, u16 reason)
23{ 23{
24 struct ieee80211_local *local = sta->local; 24 struct ieee80211_local *local = sta->local;
25 struct tid_ampdu_rx *tid_rx;
25 int i; 26 int i;
26 27
27 /* check if TID is in operational state */
28 spin_lock_bh(&sta->lock); 28 spin_lock_bh(&sta->lock);
29 if (sta->ampdu_mlme.tid_state_rx[tid] != HT_AGG_STATE_OPERATIONAL) { 29
30 /* check if TID is in operational state */
31 if (!sta->ampdu_mlme.tid_active_rx[tid]) {
30 spin_unlock_bh(&sta->lock); 32 spin_unlock_bh(&sta->lock);
31 return; 33 return;
32 } 34 }
33 35
34 sta->ampdu_mlme.tid_state_rx[tid] = 36 sta->ampdu_mlme.tid_active_rx[tid] = false;
35 HT_AGG_STATE_REQ_STOP_BA_MSK | 37
36 (initiator << HT_AGG_STATE_INITIATOR_SHIFT); 38 tid_rx = sta->ampdu_mlme.tid_rx[tid];
37 spin_unlock_bh(&sta->lock);
38 39
39#ifdef CONFIG_MAC80211_HT_DEBUG 40#ifdef CONFIG_MAC80211_HT_DEBUG
40 printk(KERN_DEBUG "Rx BA session stop requested for %pM tid %u\n", 41 printk(KERN_DEBUG "Rx BA session stop requested for %pM tid %u\n",
@@ -46,37 +47,30 @@ void __ieee80211_stop_rx_ba_session(struct sta_info *sta, u16 tid,
46 printk(KERN_DEBUG "HW problem - can not stop rx " 47 printk(KERN_DEBUG "HW problem - can not stop rx "
47 "aggregation for tid %d\n", tid); 48 "aggregation for tid %d\n", tid);
48 49
49 /* shutdown timer has not expired */
50 if (initiator != WLAN_BACK_TIMER)
51 del_timer_sync(&sta->ampdu_mlme.tid_rx[tid]->session_timer);
52
53 /* check if this is a self generated aggregation halt */ 50 /* check if this is a self generated aggregation halt */
54 if (initiator == WLAN_BACK_RECIPIENT || initiator == WLAN_BACK_TIMER) 51 if (initiator == WLAN_BACK_RECIPIENT)
55 ieee80211_send_delba(sta->sdata, sta->sta.addr, 52 ieee80211_send_delba(sta->sdata, sta->sta.addr,
56 tid, 0, reason); 53 tid, 0, reason);
57 54
58 /* free the reordering buffer */ 55 /* free the reordering buffer */
59 for (i = 0; i < sta->ampdu_mlme.tid_rx[tid]->buf_size; i++) { 56 for (i = 0; i < tid_rx->buf_size; i++) {
60 if (sta->ampdu_mlme.tid_rx[tid]->reorder_buf[i]) { 57 if (tid_rx->reorder_buf[i]) {
61 /* release the reordered frames */ 58 /* release the reordered frames */
62 dev_kfree_skb(sta->ampdu_mlme.tid_rx[tid]->reorder_buf[i]); 59 dev_kfree_skb(tid_rx->reorder_buf[i]);
63 sta->ampdu_mlme.tid_rx[tid]->stored_mpdu_num--; 60 tid_rx->stored_mpdu_num--;
64 sta->ampdu_mlme.tid_rx[tid]->reorder_buf[i] = NULL; 61 tid_rx->reorder_buf[i] = NULL;
65 } 62 }
66 } 63 }
67 64
68 spin_lock_bh(&sta->lock);
69 /* free resources */ 65 /* free resources */
70 kfree(sta->ampdu_mlme.tid_rx[tid]->reorder_buf); 66 kfree(tid_rx->reorder_buf);
71 kfree(sta->ampdu_mlme.tid_rx[tid]->reorder_time); 67 kfree(tid_rx->reorder_time);
72 68 sta->ampdu_mlme.tid_rx[tid] = NULL;
73 if (!sta->ampdu_mlme.tid_rx[tid]->shutdown) {
74 kfree(sta->ampdu_mlme.tid_rx[tid]);
75 sta->ampdu_mlme.tid_rx[tid] = NULL;
76 }
77 69
78 sta->ampdu_mlme.tid_state_rx[tid] = HT_AGG_STATE_IDLE;
79 spin_unlock_bh(&sta->lock); 70 spin_unlock_bh(&sta->lock);
71
72 del_timer_sync(&tid_rx->session_timer);
73 kfree(tid_rx);
80} 74}
81 75
82/* 76/*
@@ -211,7 +205,7 @@ void ieee80211_process_addba_request(struct ieee80211_local *local,
211 /* examine state machine */ 205 /* examine state machine */
212 spin_lock_bh(&sta->lock); 206 spin_lock_bh(&sta->lock);
213 207
214 if (sta->ampdu_mlme.tid_state_rx[tid] != HT_AGG_STATE_IDLE) { 208 if (sta->ampdu_mlme.tid_active_rx[tid]) {
215#ifdef CONFIG_MAC80211_HT_DEBUG 209#ifdef CONFIG_MAC80211_HT_DEBUG
216 if (net_ratelimit()) 210 if (net_ratelimit())
217 printk(KERN_DEBUG "unexpected AddBA Req from " 211 printk(KERN_DEBUG "unexpected AddBA Req from "
@@ -273,7 +267,7 @@ void ieee80211_process_addba_request(struct ieee80211_local *local,
273 } 267 }
274 268
275 /* change state and send addba resp */ 269 /* change state and send addba resp */
276 sta->ampdu_mlme.tid_state_rx[tid] = HT_AGG_STATE_OPERATIONAL; 270 sta->ampdu_mlme.tid_active_rx[tid] = true;
277 tid_agg_rx->dialog_token = dialog_token; 271 tid_agg_rx->dialog_token = dialog_token;
278 tid_agg_rx->ssn = start_seq_num; 272 tid_agg_rx->ssn = start_seq_num;
279 tid_agg_rx->head_seq_num = start_seq_num; 273 tid_agg_rx->head_seq_num = start_seq_num;