diff options
Diffstat (limited to 'net/mac80211/agg-rx.c')
-rw-r--r-- | net/mac80211/agg-rx.c | 52 |
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, ¶ms)) |
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, ¶ms); | ||
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, ¶ms); |
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 | ||
354 | end: | 390 | end: |
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 | ||
357 | end_no_lock: | 395 | end_no_lock: |