diff options
Diffstat (limited to 'net/mac80211/agg-rx.c')
-rw-r--r-- | net/mac80211/agg-rx.c | 70 |
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 | ||
22 | static 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 | |||
22 | static void ___ieee80211_stop_rx_ba_session(struct sta_info *sta, u16 tid, | 35 | static 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 | ||
79 | void __ieee80211_stop_rx_ba_session(struct sta_info *sta, u16 tid, | 76 | void __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); | ||
287 | end: | 281 | end: |
288 | spin_unlock_bh(&sta->lock); | 282 | spin_unlock_bh(&sta->lock); |
289 | 283 | ||