diff options
Diffstat (limited to 'net/mac80211/agg-rx.c')
-rw-r--r-- | net/mac80211/agg-rx.c | 80 |
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 | ||
22 | void __ieee80211_stop_rx_ba_session(struct sta_info *sta, u16 tid, | 22 | static 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 | ||
83 | void ieee80211_sta_stop_rx_ba_session(struct ieee80211_sub_if_data *sdata, u8 *ra, u16 tid, | 79 | void __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 | */ |
106 | static void sta_rx_agg_session_timer_expired(unsigned long data) | 89 | static 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 | ||
125 | static void ieee80211_send_addba_resp(struct ieee80211_sub_if_data *sdata, u8 *da, u16 tid, | 107 | static 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; |