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.c80
1 files changed, 31 insertions, 49 deletions
diff --git a/net/mac80211/agg-rx.c b/net/mac80211/agg-rx.c
index f9516a27e233..6bb9a9a94960 100644
--- a/net/mac80211/agg-rx.c
+++ b/net/mac80211/agg-rx.c
@@ -19,23 +19,25 @@
19#include "ieee80211_i.h" 19#include "ieee80211_i.h"
20#include "driver-ops.h" 20#include "driver-ops.h"
21 21
22void __ieee80211_stop_rx_ba_session(struct sta_info *sta, u16 tid, 22static void ___ieee80211_stop_rx_ba_session(struct sta_info *sta, u16 tid,
23 u16 initiator, u16 reason) 23 u16 initiator, u16 reason,
24 bool from_timer)
24{ 25{
25 struct ieee80211_local *local = sta->local; 26 struct ieee80211_local *local = sta->local;
27 struct tid_ampdu_rx *tid_rx;
26 int i; 28 int i;
27 29
28 /* check if TID is in operational state */
29 spin_lock_bh(&sta->lock); 30 spin_lock_bh(&sta->lock);
30 if (sta->ampdu_mlme.tid_state_rx[tid] != HT_AGG_STATE_OPERATIONAL) { 31
32 /* check if TID is in operational state */
33 if (!sta->ampdu_mlme.tid_active_rx[tid]) {
31 spin_unlock_bh(&sta->lock); 34 spin_unlock_bh(&sta->lock);
32 return; 35 return;
33 } 36 }
34 37
35 sta->ampdu_mlme.tid_state_rx[tid] = 38 sta->ampdu_mlme.tid_active_rx[tid] = false;
36 HT_AGG_STATE_REQ_STOP_BA_MSK | 39
37 (initiator << HT_AGG_STATE_INITIATOR_SHIFT); 40 tid_rx = sta->ampdu_mlme.tid_rx[tid];
38 spin_unlock_bh(&sta->lock);
39 41
40#ifdef CONFIG_MAC80211_HT_DEBUG 42#ifdef CONFIG_MAC80211_HT_DEBUG
41 printk(KERN_DEBUG "Rx BA session stop requested for %pM tid %u\n", 43 printk(KERN_DEBUG "Rx BA session stop requested for %pM tid %u\n",
@@ -47,61 +49,42 @@ void __ieee80211_stop_rx_ba_session(struct sta_info *sta, u16 tid,
47 printk(KERN_DEBUG "HW problem - can not stop rx " 49 printk(KERN_DEBUG "HW problem - can not stop rx "
48 "aggregation for tid %d\n", tid); 50 "aggregation for tid %d\n", tid);
49 51
50 /* shutdown timer has not expired */
51 if (initiator != WLAN_BACK_TIMER)
52 del_timer_sync(&sta->ampdu_mlme.tid_rx[tid]->session_timer);
53
54 /* check if this is a self generated aggregation halt */ 52 /* check if this is a self generated aggregation halt */
55 if (initiator == WLAN_BACK_RECIPIENT || initiator == WLAN_BACK_TIMER) 53 if (initiator == WLAN_BACK_RECIPIENT)
56 ieee80211_send_delba(sta->sdata, sta->sta.addr, 54 ieee80211_send_delba(sta->sdata, sta->sta.addr,
57 tid, 0, reason); 55 tid, 0, reason);
58 56
59 /* free the reordering buffer */ 57 /* free the reordering buffer */
60 for (i = 0; i < sta->ampdu_mlme.tid_rx[tid]->buf_size; i++) { 58 for (i = 0; i < tid_rx->buf_size; i++) {
61 if (sta->ampdu_mlme.tid_rx[tid]->reorder_buf[i]) { 59 if (tid_rx->reorder_buf[i]) {
62 /* release the reordered frames */ 60 /* release the reordered frames */
63 dev_kfree_skb(sta->ampdu_mlme.tid_rx[tid]->reorder_buf[i]); 61 dev_kfree_skb(tid_rx->reorder_buf[i]);
64 sta->ampdu_mlme.tid_rx[tid]->stored_mpdu_num--; 62 tid_rx->stored_mpdu_num--;
65 sta->ampdu_mlme.tid_rx[tid]->reorder_buf[i] = NULL; 63 tid_rx->reorder_buf[i] = NULL;
66 } 64 }
67 } 65 }
68 66
69 spin_lock_bh(&sta->lock);
70 /* free resources */ 67 /* free resources */
71 kfree(sta->ampdu_mlme.tid_rx[tid]->reorder_buf); 68 kfree(tid_rx->reorder_buf);
72 kfree(sta->ampdu_mlme.tid_rx[tid]->reorder_time); 69 kfree(tid_rx->reorder_time);
73 70 sta->ampdu_mlme.tid_rx[tid] = NULL;
74 if (!sta->ampdu_mlme.tid_rx[tid]->shutdown) {
75 kfree(sta->ampdu_mlme.tid_rx[tid]);
76 sta->ampdu_mlme.tid_rx[tid] = NULL;
77 }
78 71
79 sta->ampdu_mlme.tid_state_rx[tid] = HT_AGG_STATE_IDLE;
80 spin_unlock_bh(&sta->lock); 72 spin_unlock_bh(&sta->lock);
73
74 if (!from_timer)
75 del_timer_sync(&tid_rx->session_timer);
76 kfree(tid_rx);
81} 77}
82 78
83void ieee80211_sta_stop_rx_ba_session(struct ieee80211_sub_if_data *sdata, u8 *ra, u16 tid, 79void __ieee80211_stop_rx_ba_session(struct sta_info *sta, u16 tid,
84 u16 initiator, u16 reason) 80 u16 initiator, u16 reason)
85{ 81{
86 struct sta_info *sta; 82 ___ieee80211_stop_rx_ba_session(sta, tid, initiator, reason, false);
87
88 rcu_read_lock();
89
90 sta = sta_info_get(sdata, ra);
91 if (!sta) {
92 rcu_read_unlock();
93 return;
94 }
95
96 __ieee80211_stop_rx_ba_session(sta, tid, initiator, reason);
97
98 rcu_read_unlock();
99} 83}
100 84
101/* 85/*
102 * After accepting the AddBA Request we activated a timer, 86 * After accepting the AddBA Request we activated a timer,
103 * resetting it after each frame that arrives from the originator. 87 * resetting it after each frame that arrives from the originator.
104 * if this timer expires ieee80211_sta_stop_rx_ba_session will be executed.
105 */ 88 */
106static void sta_rx_agg_session_timer_expired(unsigned long data) 89static void sta_rx_agg_session_timer_expired(unsigned long data)
107{ 90{
@@ -117,9 +100,8 @@ static void sta_rx_agg_session_timer_expired(unsigned long data)
117#ifdef CONFIG_MAC80211_HT_DEBUG 100#ifdef CONFIG_MAC80211_HT_DEBUG
118 printk(KERN_DEBUG "rx session timer expired on tid %d\n", (u16)*ptid); 101 printk(KERN_DEBUG "rx session timer expired on tid %d\n", (u16)*ptid);
119#endif 102#endif
120 ieee80211_sta_stop_rx_ba_session(sta->sdata, sta->sta.addr, 103 ___ieee80211_stop_rx_ba_session(sta, *ptid, WLAN_BACK_RECIPIENT,
121 (u16)*ptid, WLAN_BACK_TIMER, 104 WLAN_REASON_QSTA_TIMEOUT, true);
122 WLAN_REASON_QSTA_TIMEOUT);
123} 105}
124 106
125static void ieee80211_send_addba_resp(struct ieee80211_sub_if_data *sdata, u8 *da, u16 tid, 107static void ieee80211_send_addba_resp(struct ieee80211_sub_if_data *sdata, u8 *da, u16 tid,
@@ -194,7 +176,7 @@ void ieee80211_process_addba_request(struct ieee80211_local *local,
194 176
195 status = WLAN_STATUS_REQUEST_DECLINED; 177 status = WLAN_STATUS_REQUEST_DECLINED;
196 178
197 if (test_sta_flags(sta, WLAN_STA_SUSPEND)) { 179 if (test_sta_flags(sta, WLAN_STA_BLOCK_BA)) {
198#ifdef CONFIG_MAC80211_HT_DEBUG 180#ifdef CONFIG_MAC80211_HT_DEBUG
199 printk(KERN_DEBUG "Suspend in progress. " 181 printk(KERN_DEBUG "Suspend in progress. "
200 "Denying ADDBA request\n"); 182 "Denying ADDBA request\n");
@@ -232,7 +214,7 @@ void ieee80211_process_addba_request(struct ieee80211_local *local,
232 /* examine state machine */ 214 /* examine state machine */
233 spin_lock_bh(&sta->lock); 215 spin_lock_bh(&sta->lock);
234 216
235 if (sta->ampdu_mlme.tid_state_rx[tid] != HT_AGG_STATE_IDLE) { 217 if (sta->ampdu_mlme.tid_active_rx[tid]) {
236#ifdef CONFIG_MAC80211_HT_DEBUG 218#ifdef CONFIG_MAC80211_HT_DEBUG
237 if (net_ratelimit()) 219 if (net_ratelimit())
238 printk(KERN_DEBUG "unexpected AddBA Req from " 220 printk(KERN_DEBUG "unexpected AddBA Req from "
@@ -294,7 +276,7 @@ void ieee80211_process_addba_request(struct ieee80211_local *local,
294 } 276 }
295 277
296 /* change state and send addba resp */ 278 /* change state and send addba resp */
297 sta->ampdu_mlme.tid_state_rx[tid] = HT_AGG_STATE_OPERATIONAL; 279 sta->ampdu_mlme.tid_active_rx[tid] = true;
298 tid_agg_rx->dialog_token = dialog_token; 280 tid_agg_rx->dialog_token = dialog_token;
299 tid_agg_rx->ssn = start_seq_num; 281 tid_agg_rx->ssn = start_seq_num;
300 tid_agg_rx->head_seq_num = start_seq_num; 282 tid_agg_rx->head_seq_num = start_seq_num;