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.c52
1 files changed, 45 insertions, 7 deletions
diff --git a/net/mac80211/agg-rx.c b/net/mac80211/agg-rx.c
index 10ad4ac1fa0b..3a8f881b22f1 100644
--- a/net/mac80211/agg-rx.c
+++ b/net/mac80211/agg-rx.c
@@ -7,6 +7,7 @@
7 * Copyright 2006-2007 Jiri Benc <jbenc@suse.cz> 7 * Copyright 2006-2007 Jiri Benc <jbenc@suse.cz>
8 * Copyright 2007, Michael Wu <flamingice@sourmilk.net> 8 * Copyright 2007, Michael Wu <flamingice@sourmilk.net>
9 * Copyright 2007-2010, Intel Corporation 9 * Copyright 2007-2010, Intel Corporation
10 * Copyright(c) 2015 Intel Deutschland GmbH
10 * 11 *
11 * This program is free software; you can redistribute it and/or modify 12 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License version 2 as 13 * it under the terms of the GNU General Public License version 2 as
@@ -61,16 +62,25 @@ void ___ieee80211_stop_rx_ba_session(struct sta_info *sta, u16 tid,
61{ 62{
62 struct ieee80211_local *local = sta->local; 63 struct ieee80211_local *local = sta->local;
63 struct tid_ampdu_rx *tid_rx; 64 struct tid_ampdu_rx *tid_rx;
65 struct ieee80211_ampdu_params params = {
66 .sta = &sta->sta,
67 .action = IEEE80211_AMPDU_RX_STOP,
68 .tid = tid,
69 .amsdu = false,
70 .timeout = 0,
71 .ssn = 0,
72 };
64 73
65 lockdep_assert_held(&sta->ampdu_mlme.mtx); 74 lockdep_assert_held(&sta->ampdu_mlme.mtx);
66 75
67 tid_rx = rcu_dereference_protected(sta->ampdu_mlme.tid_rx[tid], 76 tid_rx = rcu_dereference_protected(sta->ampdu_mlme.tid_rx[tid],
68 lockdep_is_held(&sta->ampdu_mlme.mtx)); 77 lockdep_is_held(&sta->ampdu_mlme.mtx));
69 78
70 if (!tid_rx) 79 if (!test_bit(tid, sta->ampdu_mlme.agg_session_valid))
71 return; 80 return;
72 81
73 RCU_INIT_POINTER(sta->ampdu_mlme.tid_rx[tid], NULL); 82 RCU_INIT_POINTER(sta->ampdu_mlme.tid_rx[tid], NULL);
83 __clear_bit(tid, sta->ampdu_mlme.agg_session_valid);
74 84
75 ht_dbg(sta->sdata, 85 ht_dbg(sta->sdata,
76 "Rx BA session stop requested for %pM tid %u %s reason: %d\n", 86 "Rx BA session stop requested for %pM tid %u %s reason: %d\n",
@@ -78,8 +88,7 @@ void ___ieee80211_stop_rx_ba_session(struct sta_info *sta, u16 tid,
78 initiator == WLAN_BACK_RECIPIENT ? "recipient" : "inititator", 88 initiator == WLAN_BACK_RECIPIENT ? "recipient" : "inititator",
79 (int)reason); 89 (int)reason);
80 90
81 if (drv_ampdu_action(local, sta->sdata, IEEE80211_AMPDU_RX_STOP, 91 if (drv_ampdu_action(local, sta->sdata, &params))
82 &sta->sta, tid, NULL, 0, false))
83 sdata_info(sta->sdata, 92 sdata_info(sta->sdata,
84 "HW problem - can not stop rx aggregation for %pM tid %d\n", 93 "HW problem - can not stop rx aggregation for %pM tid %d\n",
85 sta->sta.addr, tid); 94 sta->sta.addr, tid);
@@ -89,6 +98,13 @@ void ___ieee80211_stop_rx_ba_session(struct sta_info *sta, u16 tid,
89 ieee80211_send_delba(sta->sdata, sta->sta.addr, 98 ieee80211_send_delba(sta->sdata, sta->sta.addr,
90 tid, WLAN_BACK_RECIPIENT, reason); 99 tid, WLAN_BACK_RECIPIENT, reason);
91 100
101 /*
102 * return here in case tid_rx is not assigned - which will happen if
103 * IEEE80211_HW_SUPPORTS_REORDERING_BUFFER is set.
104 */
105 if (!tid_rx)
106 return;
107
92 del_timer_sync(&tid_rx->session_timer); 108 del_timer_sync(&tid_rx->session_timer);
93 109
94 /* make sure ieee80211_sta_reorder_release() doesn't re-arm the timer */ 110 /* make sure ieee80211_sta_reorder_release() doesn't re-arm the timer */
@@ -237,6 +253,15 @@ void __ieee80211_start_rx_ba_session(struct sta_info *sta,
237{ 253{
238 struct ieee80211_local *local = sta->sdata->local; 254 struct ieee80211_local *local = sta->sdata->local;
239 struct tid_ampdu_rx *tid_agg_rx; 255 struct tid_ampdu_rx *tid_agg_rx;
256 struct ieee80211_ampdu_params params = {
257 .sta = &sta->sta,
258 .action = IEEE80211_AMPDU_RX_START,
259 .tid = tid,
260 .amsdu = false,
261 .timeout = timeout,
262 .ssn = start_seq_num,
263 };
264
240 int i, ret = -EOPNOTSUPP; 265 int i, ret = -EOPNOTSUPP;
241 u16 status = WLAN_STATUS_REQUEST_DECLINED; 266 u16 status = WLAN_STATUS_REQUEST_DECLINED;
242 267
@@ -275,11 +300,12 @@ void __ieee80211_start_rx_ba_session(struct sta_info *sta,
275 /* make sure the size doesn't exceed the maximum supported by the hw */ 300 /* make sure the size doesn't exceed the maximum supported by the hw */
276 if (buf_size > local->hw.max_rx_aggregation_subframes) 301 if (buf_size > local->hw.max_rx_aggregation_subframes)
277 buf_size = local->hw.max_rx_aggregation_subframes; 302 buf_size = local->hw.max_rx_aggregation_subframes;
303 params.buf_size = buf_size;
278 304
279 /* examine state machine */ 305 /* examine state machine */
280 mutex_lock(&sta->ampdu_mlme.mtx); 306 mutex_lock(&sta->ampdu_mlme.mtx);
281 307
282 if (sta->ampdu_mlme.tid_rx[tid]) { 308 if (test_bit(tid, sta->ampdu_mlme.agg_session_valid)) {
283 ht_dbg_ratelimited(sta->sdata, 309 ht_dbg_ratelimited(sta->sdata,
284 "unexpected AddBA Req from %pM on tid %u\n", 310 "unexpected AddBA Req from %pM on tid %u\n",
285 sta->sta.addr, tid); 311 sta->sta.addr, tid);
@@ -290,8 +316,18 @@ void __ieee80211_start_rx_ba_session(struct sta_info *sta,
290 false); 316 false);
291 } 317 }
292 318
319 if (ieee80211_hw_check(&local->hw, SUPPORTS_REORDERING_BUFFER)) {
320 ret = drv_ampdu_action(local, sta->sdata, &params);
321 ht_dbg(sta->sdata,
322 "Rx A-MPDU request on %pM tid %d result %d\n",
323 sta->sta.addr, tid, ret);
324 if (!ret)
325 status = WLAN_STATUS_SUCCESS;
326 goto end;
327 }
328
293 /* prepare A-MPDU MLME for Rx aggregation */ 329 /* prepare A-MPDU MLME for Rx aggregation */
294 tid_agg_rx = kmalloc(sizeof(struct tid_ampdu_rx), GFP_KERNEL); 330 tid_agg_rx = kzalloc(sizeof(*tid_agg_rx), GFP_KERNEL);
295 if (!tid_agg_rx) 331 if (!tid_agg_rx)
296 goto end; 332 goto end;
297 333
@@ -322,8 +358,7 @@ void __ieee80211_start_rx_ba_session(struct sta_info *sta,
322 for (i = 0; i < buf_size; i++) 358 for (i = 0; i < buf_size; i++)
323 __skb_queue_head_init(&tid_agg_rx->reorder_buf[i]); 359 __skb_queue_head_init(&tid_agg_rx->reorder_buf[i]);
324 360
325 ret = drv_ampdu_action(local, sta->sdata, IEEE80211_AMPDU_RX_START, 361 ret = drv_ampdu_action(local, sta->sdata, &params);
326 &sta->sta, tid, &start_seq_num, 0, false);
327 ht_dbg(sta->sdata, "Rx A-MPDU request on %pM tid %d result %d\n", 362 ht_dbg(sta->sdata, "Rx A-MPDU request on %pM tid %d result %d\n",
328 sta->sta.addr, tid, ret); 363 sta->sta.addr, tid, ret);
329 if (ret) { 364 if (ret) {
@@ -341,6 +376,7 @@ void __ieee80211_start_rx_ba_session(struct sta_info *sta,
341 tid_agg_rx->timeout = timeout; 376 tid_agg_rx->timeout = timeout;
342 tid_agg_rx->stored_mpdu_num = 0; 377 tid_agg_rx->stored_mpdu_num = 0;
343 tid_agg_rx->auto_seq = auto_seq; 378 tid_agg_rx->auto_seq = auto_seq;
379 tid_agg_rx->reorder_buf_filtered = 0;
344 status = WLAN_STATUS_SUCCESS; 380 status = WLAN_STATUS_SUCCESS;
345 381
346 /* activate it for RX */ 382 /* activate it for RX */
@@ -352,6 +388,8 @@ void __ieee80211_start_rx_ba_session(struct sta_info *sta,
352 } 388 }
353 389
354end: 390end:
391 if (status == WLAN_STATUS_SUCCESS)
392 __set_bit(tid, sta->ampdu_mlme.agg_session_valid);
355 mutex_unlock(&sta->ampdu_mlme.mtx); 393 mutex_unlock(&sta->ampdu_mlme.mtx);
356 394
357end_no_lock: 395end_no_lock: