aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJohannes Berg <johannes@sipsolutions.net>2008-09-08 11:44:28 -0400
committerJohn W. Linville <linville@tuxdriver.com>2008-09-11 15:53:37 -0400
commit44d414dbff9d5bf46fc09f2e68567b5848cbbfd3 (patch)
tree9e55cb581602867a3d8365666b33dd9469ccc084
parent5484e23749e78d5a4f56928efaf3c4b0d862b7a6 (diff)
mac80211: move some HT code out of mlme.c
Some of the HT code in mlme.c is misplaced: * constants/definitions belong to the ieee80211.h header * code being used in other modes as well shouldn't be there Signed-off-by: Johannes Berg <johannes@sipsolutions.net> Signed-off-by: John W. Linville <linville@tuxdriver.com>
-rw-r--r--include/linux/ieee80211.h18
-rw-r--r--net/mac80211/Makefile1
-rw-r--r--net/mac80211/ht.c328
-rw-r--r--net/mac80211/mlme.c321
4 files changed, 347 insertions, 321 deletions
diff --git a/include/linux/ieee80211.h b/include/linux/ieee80211.h
index 333d3ae76883..abc1abc63bf0 100644
--- a/include/linux/ieee80211.h
+++ b/include/linux/ieee80211.h
@@ -643,6 +643,9 @@ struct ieee80211_mgmt {
643 } u; 643 } u;
644} __attribute__ ((packed)); 644} __attribute__ ((packed));
645 645
646/* mgmt header + 1 byte category code */
647#define IEEE80211_MIN_ACTION_SIZE offsetof(struct ieee80211_mgmt, u.action.u)
648
646 649
647/* Control frames */ 650/* Control frames */
648struct ieee80211_rts { 651struct ieee80211_rts {
@@ -737,6 +740,21 @@ struct ieee80211_ht_addt_info {
737#define IEEE80211_HT_IE_NON_GF_STA_PRSNT 0x0004 740#define IEEE80211_HT_IE_NON_GF_STA_PRSNT 0x0004
738#define IEEE80211_HT_IE_NON_HT_STA_PRSNT 0x0010 741#define IEEE80211_HT_IE_NON_HT_STA_PRSNT 0x0010
739 742
743/* block-ack parameters */
744#define IEEE80211_ADDBA_PARAM_POLICY_MASK 0x0002
745#define IEEE80211_ADDBA_PARAM_TID_MASK 0x003C
746#define IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK 0xFFA0
747#define IEEE80211_DELBA_PARAM_TID_MASK 0xF000
748#define IEEE80211_DELBA_PARAM_INITIATOR_MASK 0x0800
749
750/*
751 * A-PMDU buffer sizes
752 * According to IEEE802.11n spec size varies from 8K to 64K (in powers of 2)
753 */
754#define IEEE80211_MIN_AMPDU_BUF 0x8
755#define IEEE80211_MAX_AMPDU_BUF 0x40
756
757
740/* Spatial Multiplexing Power Save Modes */ 758/* Spatial Multiplexing Power Save Modes */
741#define WLAN_HT_CAP_SM_PS_STATIC 0 759#define WLAN_HT_CAP_SM_PS_STATIC 0
742#define WLAN_HT_CAP_SM_PS_DYNAMIC 1 760#define WLAN_HT_CAP_SM_PS_DYNAMIC 1
diff --git a/net/mac80211/Makefile b/net/mac80211/Makefile
index 376280a420ac..1a7ac50910c3 100644
--- a/net/mac80211/Makefile
+++ b/net/mac80211/Makefile
@@ -8,6 +8,7 @@ mac80211-y := \
8 wep.o \ 8 wep.o \
9 wpa.o \ 9 wpa.o \
10 scan.o \ 10 scan.o \
11 ht.o \
11 mlme.o \ 12 mlme.o \
12 iface.o \ 13 iface.o \
13 rate.o \ 14 rate.o \
diff --git a/net/mac80211/ht.c b/net/mac80211/ht.c
new file mode 100644
index 000000000000..5ccf1bc17466
--- /dev/null
+++ b/net/mac80211/ht.c
@@ -0,0 +1,328 @@
1/*
2 * HT handling
3 *
4 * Copyright 2003, Jouni Malinen <jkmaline@cc.hut.fi>
5 * Copyright 2004, Instant802 Networks, Inc.
6 * Copyright 2005, Devicescape Software, Inc.
7 * Copyright 2006-2007 Jiri Benc <jbenc@suse.cz>
8 * Copyright 2007, Michael Wu <flamingice@sourmilk.net>
9 * Copyright 2007-2008, Intel Corporation
10 *
11 * 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 * published by the Free Software Foundation.
14 */
15
16#include <linux/ieee80211.h>
17#include <net/wireless.h>
18#include <net/mac80211.h>
19#include "ieee80211_i.h"
20#include "sta_info.h"
21
22int ieee80211_ht_cap_ie_to_ht_info(struct ieee80211_ht_cap *ht_cap_ie,
23 struct ieee80211_ht_info *ht_info)
24{
25
26 if (ht_info == NULL)
27 return -EINVAL;
28
29 memset(ht_info, 0, sizeof(*ht_info));
30
31 if (ht_cap_ie) {
32 u8 ampdu_info = ht_cap_ie->ampdu_params_info;
33
34 ht_info->ht_supported = 1;
35 ht_info->cap = le16_to_cpu(ht_cap_ie->cap_info);
36 ht_info->ampdu_factor =
37 ampdu_info & IEEE80211_HT_CAP_AMPDU_FACTOR;
38 ht_info->ampdu_density =
39 (ampdu_info & IEEE80211_HT_CAP_AMPDU_DENSITY) >> 2;
40 memcpy(ht_info->supp_mcs_set, ht_cap_ie->supp_mcs_set, 16);
41 } else
42 ht_info->ht_supported = 0;
43
44 return 0;
45}
46
47int ieee80211_ht_addt_info_ie_to_ht_bss_info(
48 struct ieee80211_ht_addt_info *ht_add_info_ie,
49 struct ieee80211_ht_bss_info *bss_info)
50{
51 if (bss_info == NULL)
52 return -EINVAL;
53
54 memset(bss_info, 0, sizeof(*bss_info));
55
56 if (ht_add_info_ie) {
57 u16 op_mode;
58 op_mode = le16_to_cpu(ht_add_info_ie->operation_mode);
59
60 bss_info->primary_channel = ht_add_info_ie->control_chan;
61 bss_info->bss_cap = ht_add_info_ie->ht_param;
62 bss_info->bss_op_mode = (u8)(op_mode & 0xff);
63 }
64
65 return 0;
66}
67
68void ieee80211_send_addba_request(struct ieee80211_sub_if_data *sdata, const u8 *da,
69 u16 tid, u8 dialog_token, u16 start_seq_num,
70 u16 agg_size, u16 timeout)
71{
72 struct ieee80211_local *local = sdata->local;
73 struct ieee80211_if_sta *ifsta = &sdata->u.sta;
74 struct sk_buff *skb;
75 struct ieee80211_mgmt *mgmt;
76 u16 capab;
77
78 skb = dev_alloc_skb(sizeof(*mgmt) + local->hw.extra_tx_headroom);
79
80 if (!skb) {
81 printk(KERN_ERR "%s: failed to allocate buffer "
82 "for addba request frame\n", sdata->dev->name);
83 return;
84 }
85 skb_reserve(skb, local->hw.extra_tx_headroom);
86 mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24);
87 memset(mgmt, 0, 24);
88 memcpy(mgmt->da, da, ETH_ALEN);
89 memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN);
90 if (sdata->vif.type == IEEE80211_IF_TYPE_AP)
91 memcpy(mgmt->bssid, sdata->dev->dev_addr, ETH_ALEN);
92 else
93 memcpy(mgmt->bssid, ifsta->bssid, ETH_ALEN);
94
95 mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
96 IEEE80211_STYPE_ACTION);
97
98 skb_put(skb, 1 + sizeof(mgmt->u.action.u.addba_req));
99
100 mgmt->u.action.category = WLAN_CATEGORY_BACK;
101 mgmt->u.action.u.addba_req.action_code = WLAN_ACTION_ADDBA_REQ;
102
103 mgmt->u.action.u.addba_req.dialog_token = dialog_token;
104 capab = (u16)(1 << 1); /* bit 1 aggregation policy */
105 capab |= (u16)(tid << 2); /* bit 5:2 TID number */
106 capab |= (u16)(agg_size << 6); /* bit 15:6 max size of aggergation */
107
108 mgmt->u.action.u.addba_req.capab = cpu_to_le16(capab);
109
110 mgmt->u.action.u.addba_req.timeout = cpu_to_le16(timeout);
111 mgmt->u.action.u.addba_req.start_seq_num =
112 cpu_to_le16(start_seq_num << 4);
113
114 ieee80211_sta_tx(sdata, skb, 0);
115}
116
117void ieee80211_send_delba(struct ieee80211_sub_if_data *sdata, const u8 *da, u16 tid,
118 u16 initiator, u16 reason_code)
119{
120 struct ieee80211_local *local = sdata->local;
121 struct ieee80211_if_sta *ifsta = &sdata->u.sta;
122 struct sk_buff *skb;
123 struct ieee80211_mgmt *mgmt;
124 u16 params;
125
126 skb = dev_alloc_skb(sizeof(*mgmt) + local->hw.extra_tx_headroom);
127
128 if (!skb) {
129 printk(KERN_ERR "%s: failed to allocate buffer "
130 "for delba frame\n", sdata->dev->name);
131 return;
132 }
133
134 skb_reserve(skb, local->hw.extra_tx_headroom);
135 mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24);
136 memset(mgmt, 0, 24);
137 memcpy(mgmt->da, da, ETH_ALEN);
138 memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN);
139 if (sdata->vif.type == IEEE80211_IF_TYPE_AP)
140 memcpy(mgmt->bssid, sdata->dev->dev_addr, ETH_ALEN);
141 else
142 memcpy(mgmt->bssid, ifsta->bssid, ETH_ALEN);
143 mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
144 IEEE80211_STYPE_ACTION);
145
146 skb_put(skb, 1 + sizeof(mgmt->u.action.u.delba));
147
148 mgmt->u.action.category = WLAN_CATEGORY_BACK;
149 mgmt->u.action.u.delba.action_code = WLAN_ACTION_DELBA;
150 params = (u16)(initiator << 11); /* bit 11 initiator */
151 params |= (u16)(tid << 12); /* bit 15:12 TID number */
152
153 mgmt->u.action.u.delba.params = cpu_to_le16(params);
154 mgmt->u.action.u.delba.reason_code = cpu_to_le16(reason_code);
155
156 ieee80211_sta_tx(sdata, skb, 0);
157}
158
159void ieee80211_send_bar(struct ieee80211_sub_if_data *sdata, u8 *ra, u16 tid, u16 ssn)
160{
161 struct ieee80211_local *local = sdata->local;
162 struct sk_buff *skb;
163 struct ieee80211_bar *bar;
164 u16 bar_control = 0;
165
166 skb = dev_alloc_skb(sizeof(*bar) + local->hw.extra_tx_headroom);
167 if (!skb) {
168 printk(KERN_ERR "%s: failed to allocate buffer for "
169 "bar frame\n", sdata->dev->name);
170 return;
171 }
172 skb_reserve(skb, local->hw.extra_tx_headroom);
173 bar = (struct ieee80211_bar *)skb_put(skb, sizeof(*bar));
174 memset(bar, 0, sizeof(*bar));
175 bar->frame_control = cpu_to_le16(IEEE80211_FTYPE_CTL |
176 IEEE80211_STYPE_BACK_REQ);
177 memcpy(bar->ra, ra, ETH_ALEN);
178 memcpy(bar->ta, sdata->dev->dev_addr, ETH_ALEN);
179 bar_control |= (u16)IEEE80211_BAR_CTRL_ACK_POLICY_NORMAL;
180 bar_control |= (u16)IEEE80211_BAR_CTRL_CBMTID_COMPRESSED_BA;
181 bar_control |= (u16)(tid << 12);
182 bar->control = cpu_to_le16(bar_control);
183 bar->start_seq_num = cpu_to_le16(ssn);
184
185 ieee80211_sta_tx(sdata, skb, 0);
186}
187
188void ieee80211_sta_stop_rx_ba_session(struct ieee80211_sub_if_data *sdata, u8 *ra, u16 tid,
189 u16 initiator, u16 reason)
190{
191 struct ieee80211_local *local = sdata->local;
192 struct ieee80211_hw *hw = &local->hw;
193 struct sta_info *sta;
194 int ret, i;
195 DECLARE_MAC_BUF(mac);
196
197 rcu_read_lock();
198
199 sta = sta_info_get(local, ra);
200 if (!sta) {
201 rcu_read_unlock();
202 return;
203 }
204
205 /* check if TID is in operational state */
206 spin_lock_bh(&sta->lock);
207 if (sta->ampdu_mlme.tid_state_rx[tid]
208 != HT_AGG_STATE_OPERATIONAL) {
209 spin_unlock_bh(&sta->lock);
210 rcu_read_unlock();
211 return;
212 }
213 sta->ampdu_mlme.tid_state_rx[tid] =
214 HT_AGG_STATE_REQ_STOP_BA_MSK |
215 (initiator << HT_AGG_STATE_INITIATOR_SHIFT);
216 spin_unlock_bh(&sta->lock);
217
218 /* stop HW Rx aggregation. ampdu_action existence
219 * already verified in session init so we add the BUG_ON */
220 BUG_ON(!local->ops->ampdu_action);
221
222#ifdef CONFIG_MAC80211_HT_DEBUG
223 printk(KERN_DEBUG "Rx BA session stop requested for %s tid %u\n",
224 print_mac(mac, ra), tid);
225#endif /* CONFIG_MAC80211_HT_DEBUG */
226
227 ret = local->ops->ampdu_action(hw, IEEE80211_AMPDU_RX_STOP,
228 ra, tid, NULL);
229 if (ret)
230 printk(KERN_DEBUG "HW problem - can not stop rx "
231 "aggregation for tid %d\n", tid);
232
233 /* shutdown timer has not expired */
234 if (initiator != WLAN_BACK_TIMER)
235 del_timer_sync(&sta->ampdu_mlme.tid_rx[tid]->session_timer);
236
237 /* check if this is a self generated aggregation halt */
238 if (initiator == WLAN_BACK_RECIPIENT || initiator == WLAN_BACK_TIMER)
239 ieee80211_send_delba(sdata, ra, tid, 0, reason);
240
241 /* free the reordering buffer */
242 for (i = 0; i < sta->ampdu_mlme.tid_rx[tid]->buf_size; i++) {
243 if (sta->ampdu_mlme.tid_rx[tid]->reorder_buf[i]) {
244 /* release the reordered frames */
245 dev_kfree_skb(sta->ampdu_mlme.tid_rx[tid]->reorder_buf[i]);
246 sta->ampdu_mlme.tid_rx[tid]->stored_mpdu_num--;
247 sta->ampdu_mlme.tid_rx[tid]->reorder_buf[i] = NULL;
248 }
249 }
250 /* free resources */
251 kfree(sta->ampdu_mlme.tid_rx[tid]->reorder_buf);
252 kfree(sta->ampdu_mlme.tid_rx[tid]);
253 sta->ampdu_mlme.tid_rx[tid] = NULL;
254 sta->ampdu_mlme.tid_state_rx[tid] = HT_AGG_STATE_IDLE;
255
256 rcu_read_unlock();
257}
258
259
260/*
261 * After sending add Block Ack request we activated a timer until
262 * add Block Ack response will arrive from the recipient.
263 * If this timer expires sta_addba_resp_timer_expired will be executed.
264 */
265void sta_addba_resp_timer_expired(unsigned long data)
266{
267 /* not an elegant detour, but there is no choice as the timer passes
268 * only one argument, and both sta_info and TID are needed, so init
269 * flow in sta_info_create gives the TID as data, while the timer_to_id
270 * array gives the sta through container_of */
271 u16 tid = *(u8 *)data;
272 struct sta_info *temp_sta = container_of((void *)data,
273 struct sta_info, timer_to_tid[tid]);
274
275 struct ieee80211_local *local = temp_sta->local;
276 struct ieee80211_hw *hw = &local->hw;
277 struct sta_info *sta;
278 u8 *state;
279
280 rcu_read_lock();
281
282 sta = sta_info_get(local, temp_sta->addr);
283 if (!sta) {
284 rcu_read_unlock();
285 return;
286 }
287
288 state = &sta->ampdu_mlme.tid_state_tx[tid];
289 /* check if the TID waits for addBA response */
290 spin_lock_bh(&sta->lock);
291 if (!(*state & HT_ADDBA_REQUESTED_MSK)) {
292 spin_unlock_bh(&sta->lock);
293 *state = HT_AGG_STATE_IDLE;
294#ifdef CONFIG_MAC80211_HT_DEBUG
295 printk(KERN_DEBUG "timer expired on tid %d but we are not "
296 "expecting addBA response there", tid);
297#endif
298 goto timer_expired_exit;
299 }
300
301#ifdef CONFIG_MAC80211_HT_DEBUG
302 printk(KERN_DEBUG "addBA response timer expired on tid %d\n", tid);
303#endif
304
305 /* go through the state check in stop_BA_session */
306 *state = HT_AGG_STATE_OPERATIONAL;
307 spin_unlock_bh(&sta->lock);
308 ieee80211_stop_tx_ba_session(hw, temp_sta->addr, tid,
309 WLAN_BACK_INITIATOR);
310
311timer_expired_exit:
312 rcu_read_unlock();
313}
314
315void ieee80211_sta_tear_down_BA_sessions(struct ieee80211_sub_if_data *sdata, u8 *addr)
316{
317 struct ieee80211_local *local = sdata->local;
318 int i;
319
320 for (i = 0; i < STA_TID_NUM; i++) {
321 ieee80211_stop_tx_ba_session(&local->hw, addr, i,
322 WLAN_BACK_INITIATOR);
323 ieee80211_sta_stop_rx_ba_session(sdata, addr, i,
324 WLAN_BACK_RECIPIENT,
325 WLAN_REASON_QSTA_LEAVE_QBSS);
326 }
327}
328
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index be3292bfabe3..f43ca7b88d57 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -48,20 +48,6 @@
48#define IEEE80211_IBSS_MAX_STA_ENTRIES 128 48#define IEEE80211_IBSS_MAX_STA_ENTRIES 128
49 49
50 50
51/* mgmt header + 1 byte category code */
52#define IEEE80211_MIN_ACTION_SIZE (24 + 1)
53
54#define IEEE80211_ADDBA_PARAM_POLICY_MASK 0x0002
55#define IEEE80211_ADDBA_PARAM_TID_MASK 0x003C
56#define IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK 0xFFA0
57#define IEEE80211_DELBA_PARAM_TID_MASK 0xF000
58#define IEEE80211_DELBA_PARAM_INITIATOR_MASK 0x0800
59
60/* next values represent the buffer size for A-MPDU frame.
61 * According to IEEE802.11n spec size varies from 8K to 64K (in powers of 2) */
62#define IEEE80211_MIN_AMPDU_BUF 0x8
63#define IEEE80211_MAX_AMPDU_BUF 0x40
64
65/* utils */ 51/* utils */
66static int ecw2cw(int ecw) 52static int ecw2cw(int ecw)
67{ 53{
@@ -389,52 +375,6 @@ static u32 ieee80211_handle_bss_capability(struct ieee80211_sub_if_data *sdata,
389 return changed; 375 return changed;
390} 376}
391 377
392int ieee80211_ht_cap_ie_to_ht_info(struct ieee80211_ht_cap *ht_cap_ie,
393 struct ieee80211_ht_info *ht_info)
394{
395
396 if (ht_info == NULL)
397 return -EINVAL;
398
399 memset(ht_info, 0, sizeof(*ht_info));
400
401 if (ht_cap_ie) {
402 u8 ampdu_info = ht_cap_ie->ampdu_params_info;
403
404 ht_info->ht_supported = 1;
405 ht_info->cap = le16_to_cpu(ht_cap_ie->cap_info);
406 ht_info->ampdu_factor =
407 ampdu_info & IEEE80211_HT_CAP_AMPDU_FACTOR;
408 ht_info->ampdu_density =
409 (ampdu_info & IEEE80211_HT_CAP_AMPDU_DENSITY) >> 2;
410 memcpy(ht_info->supp_mcs_set, ht_cap_ie->supp_mcs_set, 16);
411 } else
412 ht_info->ht_supported = 0;
413
414 return 0;
415}
416
417int ieee80211_ht_addt_info_ie_to_ht_bss_info(
418 struct ieee80211_ht_addt_info *ht_add_info_ie,
419 struct ieee80211_ht_bss_info *bss_info)
420{
421 if (bss_info == NULL)
422 return -EINVAL;
423
424 memset(bss_info, 0, sizeof(*bss_info));
425
426 if (ht_add_info_ie) {
427 u16 op_mode;
428 op_mode = le16_to_cpu(ht_add_info_ie->operation_mode);
429
430 bss_info->primary_channel = ht_add_info_ie->control_chan;
431 bss_info->bss_cap = ht_add_info_ie->ht_param;
432 bss_info->bss_op_mode = (u8)(op_mode & 0xff);
433 }
434
435 return 0;
436}
437
438static void ieee80211_sta_send_apinfo(struct ieee80211_sub_if_data *sdata, 378static void ieee80211_sta_send_apinfo(struct ieee80211_sub_if_data *sdata,
439 struct ieee80211_if_sta *ifsta) 379 struct ieee80211_if_sta *ifsta)
440{ 380{
@@ -1118,55 +1058,6 @@ static void ieee80211_send_addba_resp(struct ieee80211_sub_if_data *sdata, u8 *d
1118 return; 1058 return;
1119} 1059}
1120 1060
1121void ieee80211_send_addba_request(struct ieee80211_sub_if_data *sdata, const u8 *da,
1122 u16 tid, u8 dialog_token, u16 start_seq_num,
1123 u16 agg_size, u16 timeout)
1124{
1125 struct ieee80211_local *local = sdata->local;
1126 struct ieee80211_if_sta *ifsta = &sdata->u.sta;
1127 struct sk_buff *skb;
1128 struct ieee80211_mgmt *mgmt;
1129 u16 capab;
1130
1131 skb = dev_alloc_skb(sizeof(*mgmt) + local->hw.extra_tx_headroom);
1132
1133 if (!skb) {
1134 printk(KERN_ERR "%s: failed to allocate buffer "
1135 "for addba request frame\n", sdata->dev->name);
1136 return;
1137 }
1138 skb_reserve(skb, local->hw.extra_tx_headroom);
1139 mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24);
1140 memset(mgmt, 0, 24);
1141 memcpy(mgmt->da, da, ETH_ALEN);
1142 memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN);
1143 if (sdata->vif.type == IEEE80211_IF_TYPE_AP)
1144 memcpy(mgmt->bssid, sdata->dev->dev_addr, ETH_ALEN);
1145 else
1146 memcpy(mgmt->bssid, ifsta->bssid, ETH_ALEN);
1147
1148 mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
1149 IEEE80211_STYPE_ACTION);
1150
1151 skb_put(skb, 1 + sizeof(mgmt->u.action.u.addba_req));
1152
1153 mgmt->u.action.category = WLAN_CATEGORY_BACK;
1154 mgmt->u.action.u.addba_req.action_code = WLAN_ACTION_ADDBA_REQ;
1155
1156 mgmt->u.action.u.addba_req.dialog_token = dialog_token;
1157 capab = (u16)(1 << 1); /* bit 1 aggregation policy */
1158 capab |= (u16)(tid << 2); /* bit 5:2 TID number */
1159 capab |= (u16)(agg_size << 6); /* bit 15:6 max size of aggergation */
1160
1161 mgmt->u.action.u.addba_req.capab = cpu_to_le16(capab);
1162
1163 mgmt->u.action.u.addba_req.timeout = cpu_to_le16(timeout);
1164 mgmt->u.action.u.addba_req.start_seq_num =
1165 cpu_to_le16(start_seq_num << 4);
1166
1167 ieee80211_sta_tx(sdata, skb, 0);
1168}
1169
1170/* 1061/*
1171 * After accepting the AddBA Request we activated a timer, 1062 * After accepting the AddBA Request we activated a timer,
1172 * resetting it after each frame that arrives from the originator. 1063 * resetting it after each frame that arrives from the originator.
@@ -1396,149 +1287,6 @@ addba_resp_exit:
1396 rcu_read_unlock(); 1287 rcu_read_unlock();
1397} 1288}
1398 1289
1399void ieee80211_send_delba(struct ieee80211_sub_if_data *sdata, const u8 *da, u16 tid,
1400 u16 initiator, u16 reason_code)
1401{
1402 struct ieee80211_local *local = sdata->local;
1403 struct ieee80211_if_sta *ifsta = &sdata->u.sta;
1404 struct sk_buff *skb;
1405 struct ieee80211_mgmt *mgmt;
1406 u16 params;
1407
1408 skb = dev_alloc_skb(sizeof(*mgmt) + local->hw.extra_tx_headroom);
1409
1410 if (!skb) {
1411 printk(KERN_ERR "%s: failed to allocate buffer "
1412 "for delba frame\n", sdata->dev->name);
1413 return;
1414 }
1415
1416 skb_reserve(skb, local->hw.extra_tx_headroom);
1417 mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24);
1418 memset(mgmt, 0, 24);
1419 memcpy(mgmt->da, da, ETH_ALEN);
1420 memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN);
1421 if (sdata->vif.type == IEEE80211_IF_TYPE_AP)
1422 memcpy(mgmt->bssid, sdata->dev->dev_addr, ETH_ALEN);
1423 else
1424 memcpy(mgmt->bssid, ifsta->bssid, ETH_ALEN);
1425 mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
1426 IEEE80211_STYPE_ACTION);
1427
1428 skb_put(skb, 1 + sizeof(mgmt->u.action.u.delba));
1429
1430 mgmt->u.action.category = WLAN_CATEGORY_BACK;
1431 mgmt->u.action.u.delba.action_code = WLAN_ACTION_DELBA;
1432 params = (u16)(initiator << 11); /* bit 11 initiator */
1433 params |= (u16)(tid << 12); /* bit 15:12 TID number */
1434
1435 mgmt->u.action.u.delba.params = cpu_to_le16(params);
1436 mgmt->u.action.u.delba.reason_code = cpu_to_le16(reason_code);
1437
1438 ieee80211_sta_tx(sdata, skb, 0);
1439}
1440
1441void ieee80211_send_bar(struct ieee80211_sub_if_data *sdata, u8 *ra, u16 tid, u16 ssn)
1442{
1443 struct ieee80211_local *local = sdata->local;
1444 struct sk_buff *skb;
1445 struct ieee80211_bar *bar;
1446 u16 bar_control = 0;
1447
1448 skb = dev_alloc_skb(sizeof(*bar) + local->hw.extra_tx_headroom);
1449 if (!skb) {
1450 printk(KERN_ERR "%s: failed to allocate buffer for "
1451 "bar frame\n", sdata->dev->name);
1452 return;
1453 }
1454 skb_reserve(skb, local->hw.extra_tx_headroom);
1455 bar = (struct ieee80211_bar *)skb_put(skb, sizeof(*bar));
1456 memset(bar, 0, sizeof(*bar));
1457 bar->frame_control = cpu_to_le16(IEEE80211_FTYPE_CTL |
1458 IEEE80211_STYPE_BACK_REQ);
1459 memcpy(bar->ra, ra, ETH_ALEN);
1460 memcpy(bar->ta, sdata->dev->dev_addr, ETH_ALEN);
1461 bar_control |= (u16)IEEE80211_BAR_CTRL_ACK_POLICY_NORMAL;
1462 bar_control |= (u16)IEEE80211_BAR_CTRL_CBMTID_COMPRESSED_BA;
1463 bar_control |= (u16)(tid << 12);
1464 bar->control = cpu_to_le16(bar_control);
1465 bar->start_seq_num = cpu_to_le16(ssn);
1466
1467 ieee80211_sta_tx(sdata, skb, 0);
1468}
1469
1470void ieee80211_sta_stop_rx_ba_session(struct ieee80211_sub_if_data *sdata, u8 *ra, u16 tid,
1471 u16 initiator, u16 reason)
1472{
1473 struct ieee80211_local *local = sdata->local;
1474 struct ieee80211_hw *hw = &local->hw;
1475 struct sta_info *sta;
1476 int ret, i;
1477 DECLARE_MAC_BUF(mac);
1478
1479 rcu_read_lock();
1480
1481 sta = sta_info_get(local, ra);
1482 if (!sta) {
1483 rcu_read_unlock();
1484 return;
1485 }
1486
1487 /* check if TID is in operational state */
1488 spin_lock_bh(&sta->lock);
1489 if (sta->ampdu_mlme.tid_state_rx[tid]
1490 != HT_AGG_STATE_OPERATIONAL) {
1491 spin_unlock_bh(&sta->lock);
1492 rcu_read_unlock();
1493 return;
1494 }
1495 sta->ampdu_mlme.tid_state_rx[tid] =
1496 HT_AGG_STATE_REQ_STOP_BA_MSK |
1497 (initiator << HT_AGG_STATE_INITIATOR_SHIFT);
1498 spin_unlock_bh(&sta->lock);
1499
1500 /* stop HW Rx aggregation. ampdu_action existence
1501 * already verified in session init so we add the BUG_ON */
1502 BUG_ON(!local->ops->ampdu_action);
1503
1504#ifdef CONFIG_MAC80211_HT_DEBUG
1505 printk(KERN_DEBUG "Rx BA session stop requested for %s tid %u\n",
1506 print_mac(mac, ra), tid);
1507#endif /* CONFIG_MAC80211_HT_DEBUG */
1508
1509 ret = local->ops->ampdu_action(hw, IEEE80211_AMPDU_RX_STOP,
1510 ra, tid, NULL);
1511 if (ret)
1512 printk(KERN_DEBUG "HW problem - can not stop rx "
1513 "aggregation for tid %d\n", tid);
1514
1515 /* shutdown timer has not expired */
1516 if (initiator != WLAN_BACK_TIMER)
1517 del_timer_sync(&sta->ampdu_mlme.tid_rx[tid]->session_timer);
1518
1519 /* check if this is a self generated aggregation halt */
1520 if (initiator == WLAN_BACK_RECIPIENT || initiator == WLAN_BACK_TIMER)
1521 ieee80211_send_delba(sdata, ra, tid, 0, reason);
1522
1523 /* free the reordering buffer */
1524 for (i = 0; i < sta->ampdu_mlme.tid_rx[tid]->buf_size; i++) {
1525 if (sta->ampdu_mlme.tid_rx[tid]->reorder_buf[i]) {
1526 /* release the reordered frames */
1527 dev_kfree_skb(sta->ampdu_mlme.tid_rx[tid]->reorder_buf[i]);
1528 sta->ampdu_mlme.tid_rx[tid]->stored_mpdu_num--;
1529 sta->ampdu_mlme.tid_rx[tid]->reorder_buf[i] = NULL;
1530 }
1531 }
1532 /* free resources */
1533 kfree(sta->ampdu_mlme.tid_rx[tid]->reorder_buf);
1534 kfree(sta->ampdu_mlme.tid_rx[tid]);
1535 sta->ampdu_mlme.tid_rx[tid] = NULL;
1536 sta->ampdu_mlme.tid_state_rx[tid] = HT_AGG_STATE_IDLE;
1537
1538 rcu_read_unlock();
1539}
1540
1541
1542static void ieee80211_sta_process_delba(struct ieee80211_sub_if_data *sdata, 1290static void ieee80211_sta_process_delba(struct ieee80211_sub_if_data *sdata,
1543 struct ieee80211_mgmt *mgmt, size_t len) 1291 struct ieee80211_mgmt *mgmt, size_t len)
1544{ 1292{
@@ -1582,75 +1330,6 @@ static void ieee80211_sta_process_delba(struct ieee80211_sub_if_data *sdata,
1582 rcu_read_unlock(); 1330 rcu_read_unlock();
1583} 1331}
1584 1332
1585/*
1586 * After sending add Block Ack request we activated a timer until
1587 * add Block Ack response will arrive from the recipient.
1588 * If this timer expires sta_addba_resp_timer_expired will be executed.
1589 */
1590void sta_addba_resp_timer_expired(unsigned long data)
1591{
1592 /* not an elegant detour, but there is no choice as the timer passes
1593 * only one argument, and both sta_info and TID are needed, so init
1594 * flow in sta_info_create gives the TID as data, while the timer_to_id
1595 * array gives the sta through container_of */
1596 u16 tid = *(u8 *)data;
1597 struct sta_info *temp_sta = container_of((void *)data,
1598 struct sta_info, timer_to_tid[tid]);
1599
1600 struct ieee80211_local *local = temp_sta->local;
1601 struct ieee80211_hw *hw = &local->hw;
1602 struct sta_info *sta;
1603 u8 *state;
1604
1605 rcu_read_lock();
1606
1607 sta = sta_info_get(local, temp_sta->addr);
1608 if (!sta) {
1609 rcu_read_unlock();
1610 return;
1611 }
1612
1613 state = &sta->ampdu_mlme.tid_state_tx[tid];
1614 /* check if the TID waits for addBA response */
1615 spin_lock_bh(&sta->lock);
1616 if (!(*state & HT_ADDBA_REQUESTED_MSK)) {
1617 spin_unlock_bh(&sta->lock);
1618 *state = HT_AGG_STATE_IDLE;
1619#ifdef CONFIG_MAC80211_HT_DEBUG
1620 printk(KERN_DEBUG "timer expired on tid %d but we are not "
1621 "expecting addBA response there", tid);
1622#endif
1623 goto timer_expired_exit;
1624 }
1625
1626#ifdef CONFIG_MAC80211_HT_DEBUG
1627 printk(KERN_DEBUG "addBA response timer expired on tid %d\n", tid);
1628#endif
1629
1630 /* go through the state check in stop_BA_session */
1631 *state = HT_AGG_STATE_OPERATIONAL;
1632 spin_unlock_bh(&sta->lock);
1633 ieee80211_stop_tx_ba_session(hw, temp_sta->addr, tid,
1634 WLAN_BACK_INITIATOR);
1635
1636timer_expired_exit:
1637 rcu_read_unlock();
1638}
1639
1640void ieee80211_sta_tear_down_BA_sessions(struct ieee80211_sub_if_data *sdata, u8 *addr)
1641{
1642 struct ieee80211_local *local = sdata->local;
1643 int i;
1644
1645 for (i = 0; i < STA_TID_NUM; i++) {
1646 ieee80211_stop_tx_ba_session(&local->hw, addr, i,
1647 WLAN_BACK_INITIATOR);
1648 ieee80211_sta_stop_rx_ba_session(sdata, addr, i,
1649 WLAN_BACK_RECIPIENT,
1650 WLAN_REASON_QSTA_LEAVE_QBSS);
1651 }
1652}
1653
1654static void ieee80211_send_refuse_measurement_request(struct ieee80211_sub_if_data *sdata, 1333static void ieee80211_send_refuse_measurement_request(struct ieee80211_sub_if_data *sdata,
1655 struct ieee80211_msrment_ie *request_ie, 1334 struct ieee80211_msrment_ie *request_ie,
1656 const u8 *da, const u8 *bssid, 1335 const u8 *da, const u8 *bssid,