aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211/agg-rx.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/mac80211/agg-rx.c')
-rw-r--r--net/mac80211/agg-rx.c70
1 files changed, 32 insertions, 38 deletions
diff --git a/net/mac80211/agg-rx.c b/net/mac80211/agg-rx.c
index 6bb9a9a94960..bbf36d980232 100644
--- a/net/mac80211/agg-rx.c
+++ b/net/mac80211/agg-rx.c
@@ -19,25 +19,36 @@
19#include "ieee80211_i.h" 19#include "ieee80211_i.h"
20#include "driver-ops.h" 20#include "driver-ops.h"
21 21
22static void ieee80211_free_tid_rx(struct rcu_head *h)
23{
24 struct tid_ampdu_rx *tid_rx =
25 container_of(h, struct tid_ampdu_rx, rcu_head);
26 int i;
27
28 for (i = 0; i < tid_rx->buf_size; i++)
29 dev_kfree_skb(tid_rx->reorder_buf[i]);
30 kfree(tid_rx->reorder_buf);
31 kfree(tid_rx->reorder_time);
32 kfree(tid_rx);
33}
34
22static void ___ieee80211_stop_rx_ba_session(struct sta_info *sta, u16 tid, 35static void ___ieee80211_stop_rx_ba_session(struct sta_info *sta, u16 tid,
23 u16 initiator, u16 reason, 36 u16 initiator, u16 reason,
24 bool from_timer) 37 bool from_timer)
25{ 38{
26 struct ieee80211_local *local = sta->local; 39 struct ieee80211_local *local = sta->local;
27 struct tid_ampdu_rx *tid_rx; 40 struct tid_ampdu_rx *tid_rx;
28 int i;
29 41
30 spin_lock_bh(&sta->lock); 42 spin_lock_bh(&sta->lock);
31 43
32 /* check if TID is in operational state */ 44 tid_rx = sta->ampdu_mlme.tid_rx[tid];
33 if (!sta->ampdu_mlme.tid_active_rx[tid]) { 45
46 if (!tid_rx) {
34 spin_unlock_bh(&sta->lock); 47 spin_unlock_bh(&sta->lock);
35 return; 48 return;
36 } 49 }
37 50
38 sta->ampdu_mlme.tid_active_rx[tid] = false; 51 rcu_assign_pointer(sta->ampdu_mlme.tid_rx[tid], NULL);
39
40 tid_rx = sta->ampdu_mlme.tid_rx[tid];
41 52
42#ifdef CONFIG_MAC80211_HT_DEBUG 53#ifdef CONFIG_MAC80211_HT_DEBUG
43 printk(KERN_DEBUG "Rx BA session stop requested for %pM tid %u\n", 54 printk(KERN_DEBUG "Rx BA session stop requested for %pM tid %u\n",
@@ -54,26 +65,12 @@ static void ___ieee80211_stop_rx_ba_session(struct sta_info *sta, u16 tid,
54 ieee80211_send_delba(sta->sdata, sta->sta.addr, 65 ieee80211_send_delba(sta->sdata, sta->sta.addr,
55 tid, 0, reason); 66 tid, 0, reason);
56 67
57 /* free the reordering buffer */
58 for (i = 0; i < tid_rx->buf_size; i++) {
59 if (tid_rx->reorder_buf[i]) {
60 /* release the reordered frames */
61 dev_kfree_skb(tid_rx->reorder_buf[i]);
62 tid_rx->stored_mpdu_num--;
63 tid_rx->reorder_buf[i] = NULL;
64 }
65 }
66
67 /* free resources */
68 kfree(tid_rx->reorder_buf);
69 kfree(tid_rx->reorder_time);
70 sta->ampdu_mlme.tid_rx[tid] = NULL;
71
72 spin_unlock_bh(&sta->lock); 68 spin_unlock_bh(&sta->lock);
73 69
74 if (!from_timer) 70 if (!from_timer)
75 del_timer_sync(&tid_rx->session_timer); 71 del_timer_sync(&tid_rx->session_timer);
76 kfree(tid_rx); 72
73 call_rcu(&tid_rx->rcu_head, ieee80211_free_tid_rx);
77} 74}
78 75
79void __ieee80211_stop_rx_ba_session(struct sta_info *sta, u16 tid, 76void __ieee80211_stop_rx_ba_session(struct sta_info *sta, u16 tid,
@@ -214,7 +211,7 @@ void ieee80211_process_addba_request(struct ieee80211_local *local,
214 /* examine state machine */ 211 /* examine state machine */
215 spin_lock_bh(&sta->lock); 212 spin_lock_bh(&sta->lock);
216 213
217 if (sta->ampdu_mlme.tid_active_rx[tid]) { 214 if (sta->ampdu_mlme.tid_rx[tid]) {
218#ifdef CONFIG_MAC80211_HT_DEBUG 215#ifdef CONFIG_MAC80211_HT_DEBUG
219 if (net_ratelimit()) 216 if (net_ratelimit())
220 printk(KERN_DEBUG "unexpected AddBA Req from " 217 printk(KERN_DEBUG "unexpected AddBA Req from "
@@ -225,9 +222,8 @@ void ieee80211_process_addba_request(struct ieee80211_local *local,
225 } 222 }
226 223
227 /* prepare A-MPDU MLME for Rx aggregation */ 224 /* prepare A-MPDU MLME for Rx aggregation */
228 sta->ampdu_mlme.tid_rx[tid] = 225 tid_agg_rx = kmalloc(sizeof(struct tid_ampdu_rx), GFP_ATOMIC);
229 kmalloc(sizeof(struct tid_ampdu_rx), GFP_ATOMIC); 226 if (!tid_agg_rx) {
230 if (!sta->ampdu_mlme.tid_rx[tid]) {
231#ifdef CONFIG_MAC80211_HT_DEBUG 227#ifdef CONFIG_MAC80211_HT_DEBUG
232 if (net_ratelimit()) 228 if (net_ratelimit())
233 printk(KERN_ERR "allocate rx mlme to tid %d failed\n", 229 printk(KERN_ERR "allocate rx mlme to tid %d failed\n",
@@ -235,14 +231,11 @@ void ieee80211_process_addba_request(struct ieee80211_local *local,
235#endif 231#endif
236 goto end; 232 goto end;
237 } 233 }
238 /* rx timer */
239 sta->ampdu_mlme.tid_rx[tid]->session_timer.function =
240 sta_rx_agg_session_timer_expired;
241 sta->ampdu_mlme.tid_rx[tid]->session_timer.data =
242 (unsigned long)&sta->timer_to_tid[tid];
243 init_timer(&sta->ampdu_mlme.tid_rx[tid]->session_timer);
244 234
245 tid_agg_rx = sta->ampdu_mlme.tid_rx[tid]; 235 /* rx timer */
236 tid_agg_rx->session_timer.function = sta_rx_agg_session_timer_expired;
237 tid_agg_rx->session_timer.data = (unsigned long)&sta->timer_to_tid[tid];
238 init_timer(&tid_agg_rx->session_timer);
246 239
247 /* prepare reordering buffer */ 240 /* prepare reordering buffer */
248 tid_agg_rx->reorder_buf = 241 tid_agg_rx->reorder_buf =
@@ -257,8 +250,7 @@ void ieee80211_process_addba_request(struct ieee80211_local *local,
257#endif 250#endif
258 kfree(tid_agg_rx->reorder_buf); 251 kfree(tid_agg_rx->reorder_buf);
259 kfree(tid_agg_rx->reorder_time); 252 kfree(tid_agg_rx->reorder_time);
260 kfree(sta->ampdu_mlme.tid_rx[tid]); 253 kfree(tid_agg_rx);
261 sta->ampdu_mlme.tid_rx[tid] = NULL;
262 goto end; 254 goto end;
263 } 255 }
264 256
@@ -270,13 +262,12 @@ void ieee80211_process_addba_request(struct ieee80211_local *local,
270 262
271 if (ret) { 263 if (ret) {
272 kfree(tid_agg_rx->reorder_buf); 264 kfree(tid_agg_rx->reorder_buf);
265 kfree(tid_agg_rx->reorder_time);
273 kfree(tid_agg_rx); 266 kfree(tid_agg_rx);
274 sta->ampdu_mlme.tid_rx[tid] = NULL;
275 goto end; 267 goto end;
276 } 268 }
277 269
278 /* change state and send addba resp */ 270 /* update data */
279 sta->ampdu_mlme.tid_active_rx[tid] = true;
280 tid_agg_rx->dialog_token = dialog_token; 271 tid_agg_rx->dialog_token = dialog_token;
281 tid_agg_rx->ssn = start_seq_num; 272 tid_agg_rx->ssn = start_seq_num;
282 tid_agg_rx->head_seq_num = start_seq_num; 273 tid_agg_rx->head_seq_num = start_seq_num;
@@ -284,6 +275,9 @@ void ieee80211_process_addba_request(struct ieee80211_local *local,
284 tid_agg_rx->timeout = timeout; 275 tid_agg_rx->timeout = timeout;
285 tid_agg_rx->stored_mpdu_num = 0; 276 tid_agg_rx->stored_mpdu_num = 0;
286 status = WLAN_STATUS_SUCCESS; 277 status = WLAN_STATUS_SUCCESS;
278
279 /* activate it for RX */
280 rcu_assign_pointer(sta->ampdu_mlme.tid_rx[tid], tid_agg_rx);
287end: 281end:
288 spin_unlock_bh(&sta->lock); 282 spin_unlock_bh(&sta->lock);
289 283