]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/blame - drivers/net/wireless/mwifiex/tdls.c
cfg80211: constify MAC addresses in cfg80211 ops
[mirror_ubuntu-bionic-kernel.git] / drivers / net / wireless / mwifiex / tdls.c
CommitLineData
b23bce29
AP
1/* Marvell Wireless LAN device driver: TDLS handling
2 *
3 * Copyright (C) 2014, Marvell International Ltd.
4 *
5 * This software file (the "File") is distributed by Marvell International
6 * Ltd. under the terms of the GNU General Public License Version 2, June 1991
7 * (the "License"). You may use, redistribute and/or modify this File in
8 * accordance with the terms and conditions of the License, a copy of which
9 * is available on the worldwide web at
10 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
11 *
12 * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
13 * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
14 * ARE EXPRESSLY DISCLAIMED. The License provides additional details about
15 * this warranty disclaimer.
16 */
17
18#include "main.h"
5f2caaf3 19#include "wmm.h"
429d90d2
AP
20#include "11n.h"
21#include "11n_rxreorder.h"
5f6d5983 22#include "11ac.h"
5f2caaf3
AP
23
24#define TDLS_REQ_FIX_LEN 6
25#define TDLS_RESP_FIX_LEN 8
26#define TDLS_CONFIRM_FIX_LEN 6
b23bce29 27
3b3a0162
JB
28static void mwifiex_restore_tdls_packets(struct mwifiex_private *priv,
29 const u8 *mac, u8 status)
56bd24a1
AP
30{
31 struct mwifiex_ra_list_tbl *ra_list;
32 struct list_head *tid_list;
33 struct sk_buff *skb, *tmp;
34 struct mwifiex_txinfo *tx_info;
35 unsigned long flags;
36 u32 tid;
37 u8 tid_down;
38
39 dev_dbg(priv->adapter->dev, "%s: %pM\n", __func__, mac);
40 spin_lock_irqsave(&priv->wmm.ra_list_spinlock, flags);
41
42 skb_queue_walk_safe(&priv->tdls_txq, skb, tmp) {
43 if (!ether_addr_equal(mac, skb->data))
44 continue;
45
46 __skb_unlink(skb, &priv->tdls_txq);
47 tx_info = MWIFIEX_SKB_TXCB(skb);
48 tid = skb->priority;
49 tid_down = mwifiex_wmm_downgrade_tid(priv, tid);
50
51 if (status == TDLS_SETUP_COMPLETE) {
52 ra_list = mwifiex_wmm_get_queue_raptr(priv, tid, mac);
daeb5bb4 53 ra_list->tdls_link = true;
56bd24a1
AP
54 tx_info->flags |= MWIFIEX_BUF_FLAG_TDLS_PKT;
55 } else {
56 tid_list = &priv->wmm.tid_tbl_ptr[tid_down].ra_list;
57 if (!list_empty(tid_list))
58 ra_list = list_first_entry(tid_list,
59 struct mwifiex_ra_list_tbl, list);
60 else
61 ra_list = NULL;
62 tx_info->flags &= ~MWIFIEX_BUF_FLAG_TDLS_PKT;
63 }
64
65 if (!ra_list) {
66 mwifiex_write_data_complete(priv->adapter, skb, 0, -1);
67 continue;
68 }
69
70 skb_queue_tail(&ra_list->skb_head, skb);
71
72 ra_list->ba_pkt_count++;
73 ra_list->total_pkt_count++;
74
75 if (atomic_read(&priv->wmm.highest_queued_prio) <
76 tos_to_tid_inv[tid_down])
77 atomic_set(&priv->wmm.highest_queued_prio,
78 tos_to_tid_inv[tid_down]);
79
80 atomic_inc(&priv->wmm.tx_pkts_queued);
81 }
82
83 spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, flags);
84 return;
85}
86
3b3a0162
JB
87static void mwifiex_hold_tdls_packets(struct mwifiex_private *priv,
88 const u8 *mac)
56bd24a1
AP
89{
90 struct mwifiex_ra_list_tbl *ra_list;
91 struct list_head *ra_list_head;
92 struct sk_buff *skb, *tmp;
93 unsigned long flags;
94 int i;
95
96 dev_dbg(priv->adapter->dev, "%s: %pM\n", __func__, mac);
97 spin_lock_irqsave(&priv->wmm.ra_list_spinlock, flags);
98
99 for (i = 0; i < MAX_NUM_TID; i++) {
100 if (!list_empty(&priv->wmm.tid_tbl_ptr[i].ra_list)) {
101 ra_list_head = &priv->wmm.tid_tbl_ptr[i].ra_list;
102 list_for_each_entry(ra_list, ra_list_head, list) {
103 skb_queue_walk_safe(&ra_list->skb_head, skb,
104 tmp) {
105 if (!ether_addr_equal(mac, skb->data))
106 continue;
107 __skb_unlink(skb, &ra_list->skb_head);
108 atomic_dec(&priv->wmm.tx_pkts_queued);
109 ra_list->total_pkt_count--;
110 skb_queue_tail(&priv->tdls_txq, skb);
111 }
112 }
113 }
114 }
115
116 spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, flags);
117 return;
118}
119
b23bce29
AP
120/* This function appends rate TLV to scan config command. */
121static int
122mwifiex_tdls_append_rates_ie(struct mwifiex_private *priv,
123 struct sk_buff *skb)
124{
125 u8 rates[MWIFIEX_SUPPORTED_RATES], *pos;
126 u16 rates_size, supp_rates_size, ext_rates_size;
127
128 memset(rates, 0, sizeof(rates));
129 rates_size = mwifiex_get_supported_rates(priv, rates);
130
131 supp_rates_size = min_t(u16, rates_size, MWIFIEX_TDLS_SUPPORTED_RATES);
132
133 if (skb_tailroom(skb) < rates_size + 4) {
134 dev_err(priv->adapter->dev,
135 "Insuffient space while adding rates\n");
136 return -ENOMEM;
137 }
138
139 pos = skb_put(skb, supp_rates_size + 2);
140 *pos++ = WLAN_EID_SUPP_RATES;
141 *pos++ = supp_rates_size;
142 memcpy(pos, rates, supp_rates_size);
143
144 if (rates_size > MWIFIEX_TDLS_SUPPORTED_RATES) {
145 ext_rates_size = rates_size - MWIFIEX_TDLS_SUPPORTED_RATES;
146 pos = skb_put(skb, ext_rates_size + 2);
147 *pos++ = WLAN_EID_EXT_SUPP_RATES;
148 *pos++ = ext_rates_size;
149 memcpy(pos, rates + MWIFIEX_TDLS_SUPPORTED_RATES,
150 ext_rates_size);
151 }
152
153 return 0;
154}
155
5f6d5983
AP
156static void mwifiex_tdls_add_aid(struct mwifiex_private *priv,
157 struct sk_buff *skb)
158{
159 struct ieee_types_assoc_rsp *assoc_rsp;
160 u8 *pos;
161
162 assoc_rsp = (struct ieee_types_assoc_rsp *)&priv->assoc_rsp_buf;
163 pos = (void *)skb_put(skb, 4);
164 *pos++ = WLAN_EID_AID;
165 *pos++ = 2;
166 *pos++ = le16_to_cpu(assoc_rsp->a_id);
167
168 return;
169}
170
171static int mwifiex_tdls_add_vht_capab(struct mwifiex_private *priv,
172 struct sk_buff *skb)
173{
174 struct ieee80211_vht_cap vht_cap;
175 u8 *pos;
176
177 pos = (void *)skb_put(skb, sizeof(struct ieee80211_vht_cap) + 2);
178 *pos++ = WLAN_EID_VHT_CAPABILITY;
179 *pos++ = sizeof(struct ieee80211_vht_cap);
180
181 memset(&vht_cap, 0, sizeof(struct ieee80211_vht_cap));
182
183 mwifiex_fill_vht_cap_tlv(priv, &vht_cap, priv->curr_bss_params.band);
c42c65c1 184 memcpy(pos, &vht_cap, sizeof(vht_cap));
5f6d5983
AP
185
186 return 0;
187}
188
189static int mwifiex_tdls_add_vht_oper(struct mwifiex_private *priv,
3b3a0162 190 const u8 *mac, struct sk_buff *skb)
5f6d5983
AP
191{
192 struct mwifiex_bssdescriptor *bss_desc;
193 struct ieee80211_vht_operation *vht_oper;
194 struct ieee80211_vht_cap *vht_cap, *ap_vht_cap = NULL;
195 struct mwifiex_sta_node *sta_ptr;
196 struct mwifiex_adapter *adapter = priv->adapter;
197 u8 supp_chwd_set, peer_supp_chwd_set;
198 u8 *pos, ap_supp_chwd_set, chan_bw;
199 u16 mcs_map_user, mcs_map_resp, mcs_map_result;
200 u16 mcs_user, mcs_resp, nss;
201 u32 usr_vht_cap_info;
202
203 bss_desc = &priv->curr_bss_params.bss_descriptor;
204
205 sta_ptr = mwifiex_get_sta_entry(priv, mac);
206 if (unlikely(!sta_ptr)) {
207 dev_warn(adapter->dev, "TDLS peer station not found in list\n");
208 return -1;
209 }
210
211 if (!mwifiex_is_bss_in_11ac_mode(priv)) {
212 if (sta_ptr->tdls_cap.extcap.ext_capab[7] &
213 WLAN_EXT_CAPA8_TDLS_WIDE_BW_ENABLED) {
214 dev_dbg(adapter->dev,
215 "TDLS peer doesn't support wider bandwitdh\n");
216 return 0;
217 }
218 } else {
219 ap_vht_cap = bss_desc->bcn_vht_cap;
220 }
221
222 pos = (void *)skb_put(skb, sizeof(struct ieee80211_vht_operation) + 2);
223 *pos++ = WLAN_EID_VHT_OPERATION;
224 *pos++ = sizeof(struct ieee80211_vht_operation);
225 vht_oper = (struct ieee80211_vht_operation *)pos;
226
227 if (bss_desc->bss_band & BAND_A)
228 usr_vht_cap_info = adapter->usr_dot_11ac_dev_cap_a;
229 else
230 usr_vht_cap_info = adapter->usr_dot_11ac_dev_cap_bg;
231
232 /* find the minmum bandwith between AP/TDLS peers */
233 vht_cap = &sta_ptr->tdls_cap.vhtcap;
234 supp_chwd_set = GET_VHTCAP_CHWDSET(usr_vht_cap_info);
235 peer_supp_chwd_set =
236 GET_VHTCAP_CHWDSET(le32_to_cpu(vht_cap->vht_cap_info));
237 supp_chwd_set = min_t(u8, supp_chwd_set, peer_supp_chwd_set);
238
239 /* We need check AP's bandwidth when TDLS_WIDER_BANDWIDTH is off */
240
241 if (ap_vht_cap && sta_ptr->tdls_cap.extcap.ext_capab[7] &
242 WLAN_EXT_CAPA8_TDLS_WIDE_BW_ENABLED) {
243 ap_supp_chwd_set =
244 GET_VHTCAP_CHWDSET(le32_to_cpu(ap_vht_cap->vht_cap_info));
245 supp_chwd_set = min_t(u8, supp_chwd_set, ap_supp_chwd_set);
246 }
247
248 switch (supp_chwd_set) {
249 case IEEE80211_VHT_CHANWIDTH_80MHZ:
250 vht_oper->chan_width = IEEE80211_VHT_CHANWIDTH_80MHZ;
251 break;
252 case IEEE80211_VHT_CHANWIDTH_160MHZ:
253 vht_oper->chan_width = IEEE80211_VHT_CHANWIDTH_160MHZ;
254 break;
255 case IEEE80211_VHT_CHANWIDTH_80P80MHZ:
256 vht_oper->chan_width = IEEE80211_VHT_CHANWIDTH_80P80MHZ;
257 break;
258 default:
259 vht_oper->chan_width = IEEE80211_VHT_CHANWIDTH_USE_HT;
260 break;
261 }
262
263 mcs_map_user = GET_DEVRXMCSMAP(adapter->usr_dot_11ac_mcs_support);
264 mcs_map_resp = le16_to_cpu(vht_cap->supp_mcs.rx_mcs_map);
265 mcs_map_result = 0;
266
267 for (nss = 1; nss <= 8; nss++) {
268 mcs_user = GET_VHTNSSMCS(mcs_map_user, nss);
269 mcs_resp = GET_VHTNSSMCS(mcs_map_resp, nss);
270
271 if ((mcs_user == IEEE80211_VHT_MCS_NOT_SUPPORTED) ||
272 (mcs_resp == IEEE80211_VHT_MCS_NOT_SUPPORTED))
273 SET_VHTNSSMCS(mcs_map_result, nss,
274 IEEE80211_VHT_MCS_NOT_SUPPORTED);
275 else
276 SET_VHTNSSMCS(mcs_map_result, nss,
277 min_t(u16, mcs_user, mcs_resp));
278 }
279
280 vht_oper->basic_mcs_set = cpu_to_le16(mcs_map_result);
281
282 switch (vht_oper->chan_width) {
283 case IEEE80211_VHT_CHANWIDTH_80MHZ:
284 chan_bw = IEEE80211_VHT_CHANWIDTH_80MHZ;
285 break;
286 case IEEE80211_VHT_CHANWIDTH_160MHZ:
287 chan_bw = IEEE80211_VHT_CHANWIDTH_160MHZ;
288 break;
289 case IEEE80211_VHT_CHANWIDTH_80P80MHZ:
290 chan_bw = IEEE80211_VHT_CHANWIDTH_80MHZ;
291 break;
292 default:
293 chan_bw = IEEE80211_VHT_CHANWIDTH_USE_HT;
294 break;
295 }
296 vht_oper->center_freq_seg1_idx =
297 mwifiex_get_center_freq_index(priv, BAND_AAC,
298 bss_desc->channel,
299 chan_bw);
300
301 return 0;
302}
303
304static void mwifiex_tdls_add_ext_capab(struct mwifiex_private *priv,
305 struct sk_buff *skb)
b23bce29
AP
306{
307 struct ieee_types_extcap *extcap;
308
309 extcap = (void *)skb_put(skb, sizeof(struct ieee_types_extcap));
310 extcap->ieee_hdr.element_id = WLAN_EID_EXT_CAPABILITY;
311 extcap->ieee_hdr.len = 8;
312 memset(extcap->ext_capab, 0, 8);
313 extcap->ext_capab[4] |= WLAN_EXT_CAPA5_TDLS_ENABLED;
5f6d5983
AP
314
315 if (priv->adapter->is_hw_11ac_capable)
316 extcap->ext_capab[7] |= WLAN_EXT_CAPA8_TDLS_WIDE_BW_ENABLED;
b23bce29
AP
317}
318
319static void mwifiex_tdls_add_qos_capab(struct sk_buff *skb)
320{
321 u8 *pos = (void *)skb_put(skb, 3);
322
323 *pos++ = WLAN_EID_QOS_CAPA;
324 *pos++ = 1;
325 *pos++ = MWIFIEX_TDLS_DEF_QOS_CAPAB;
326}
327
328static int mwifiex_prep_tdls_encap_data(struct mwifiex_private *priv,
3b3a0162
JB
329 const u8 *peer, u8 action_code,
330 u8 dialog_token,
331 u16 status_code, struct sk_buff *skb)
b23bce29
AP
332{
333 struct ieee80211_tdls_data *tf;
334 int ret;
335 u16 capab;
336 struct ieee80211_ht_cap *ht_cap;
337 u8 radio, *pos;
338
339 capab = priv->curr_bss_params.bss_descriptor.cap_info_bitmap;
340
341 tf = (void *)skb_put(skb, offsetof(struct ieee80211_tdls_data, u));
342 memcpy(tf->da, peer, ETH_ALEN);
343 memcpy(tf->sa, priv->curr_addr, ETH_ALEN);
344 tf->ether_type = cpu_to_be16(ETH_P_TDLS);
345 tf->payload_type = WLAN_TDLS_SNAP_RFTYPE;
346
347 switch (action_code) {
348 case WLAN_TDLS_SETUP_REQUEST:
349 tf->category = WLAN_CATEGORY_TDLS;
350 tf->action_code = WLAN_TDLS_SETUP_REQUEST;
351 skb_put(skb, sizeof(tf->u.setup_req));
352 tf->u.setup_req.dialog_token = dialog_token;
353 tf->u.setup_req.capability = cpu_to_le16(capab);
354 ret = mwifiex_tdls_append_rates_ie(priv, skb);
355 if (ret) {
356 dev_kfree_skb_any(skb);
357 return ret;
358 }
359
360 pos = (void *)skb_put(skb, sizeof(struct ieee80211_ht_cap) + 2);
361 *pos++ = WLAN_EID_HT_CAPABILITY;
362 *pos++ = sizeof(struct ieee80211_ht_cap);
363 ht_cap = (void *)pos;
364 radio = mwifiex_band_to_radio_type(priv->curr_bss_params.band);
365 ret = mwifiex_fill_cap_info(priv, radio, ht_cap);
366 if (ret) {
367 dev_kfree_skb_any(skb);
368 return ret;
369 }
370
5f6d5983
AP
371 if (priv->adapter->is_hw_11ac_capable) {
372 ret = mwifiex_tdls_add_vht_capab(priv, skb);
373 if (ret) {
374 dev_kfree_skb_any(skb);
375 return ret;
376 }
377 mwifiex_tdls_add_aid(priv, skb);
378 }
379
380 mwifiex_tdls_add_ext_capab(priv, skb);
b23bce29
AP
381 mwifiex_tdls_add_qos_capab(skb);
382 break;
383
384 case WLAN_TDLS_SETUP_RESPONSE:
385 tf->category = WLAN_CATEGORY_TDLS;
386 tf->action_code = WLAN_TDLS_SETUP_RESPONSE;
387 skb_put(skb, sizeof(tf->u.setup_resp));
388 tf->u.setup_resp.status_code = cpu_to_le16(status_code);
389 tf->u.setup_resp.dialog_token = dialog_token;
390 tf->u.setup_resp.capability = cpu_to_le16(capab);
391 ret = mwifiex_tdls_append_rates_ie(priv, skb);
392 if (ret) {
393 dev_kfree_skb_any(skb);
394 return ret;
395 }
396
397 pos = (void *)skb_put(skb, sizeof(struct ieee80211_ht_cap) + 2);
398 *pos++ = WLAN_EID_HT_CAPABILITY;
399 *pos++ = sizeof(struct ieee80211_ht_cap);
400 ht_cap = (void *)pos;
401 radio = mwifiex_band_to_radio_type(priv->curr_bss_params.band);
402 ret = mwifiex_fill_cap_info(priv, radio, ht_cap);
403 if (ret) {
404 dev_kfree_skb_any(skb);
405 return ret;
406 }
407
5f6d5983
AP
408 if (priv->adapter->is_hw_11ac_capable) {
409 ret = mwifiex_tdls_add_vht_capab(priv, skb);
410 if (ret) {
411 dev_kfree_skb_any(skb);
412 return ret;
413 }
414 mwifiex_tdls_add_aid(priv, skb);
415 }
416
417 mwifiex_tdls_add_ext_capab(priv, skb);
b23bce29
AP
418 mwifiex_tdls_add_qos_capab(skb);
419 break;
420
421 case WLAN_TDLS_SETUP_CONFIRM:
422 tf->category = WLAN_CATEGORY_TDLS;
423 tf->action_code = WLAN_TDLS_SETUP_CONFIRM;
424 skb_put(skb, sizeof(tf->u.setup_cfm));
425 tf->u.setup_cfm.status_code = cpu_to_le16(status_code);
426 tf->u.setup_cfm.dialog_token = dialog_token;
5f6d5983
AP
427 if (priv->adapter->is_hw_11ac_capable) {
428 ret = mwifiex_tdls_add_vht_oper(priv, peer, skb);
429 if (ret) {
430 dev_kfree_skb_any(skb);
431 return ret;
432 }
433 }
b23bce29
AP
434 break;
435
436 case WLAN_TDLS_TEARDOWN:
437 tf->category = WLAN_CATEGORY_TDLS;
438 tf->action_code = WLAN_TDLS_TEARDOWN;
439 skb_put(skb, sizeof(tf->u.teardown));
440 tf->u.teardown.reason_code = cpu_to_le16(status_code);
441 break;
442
443 case WLAN_TDLS_DISCOVERY_REQUEST:
444 tf->category = WLAN_CATEGORY_TDLS;
445 tf->action_code = WLAN_TDLS_DISCOVERY_REQUEST;
446 skb_put(skb, sizeof(tf->u.discover_req));
447 tf->u.discover_req.dialog_token = dialog_token;
448 break;
449 default:
450 dev_err(priv->adapter->dev, "Unknown TDLS frame type.\n");
451 return -EINVAL;
452 }
453
454 return 0;
455}
456
457static void
3b3a0162
JB
458mwifiex_tdls_add_link_ie(struct sk_buff *skb, const u8 *src_addr,
459 const u8 *peer, const u8 *bssid)
b23bce29
AP
460{
461 struct ieee80211_tdls_lnkie *lnkid;
462
463 lnkid = (void *)skb_put(skb, sizeof(struct ieee80211_tdls_lnkie));
464 lnkid->ie_type = WLAN_EID_LINK_ID;
465 lnkid->ie_len = sizeof(struct ieee80211_tdls_lnkie) -
466 sizeof(struct ieee_types_header);
467
468 memcpy(lnkid->bssid, bssid, ETH_ALEN);
469 memcpy(lnkid->init_sta, src_addr, ETH_ALEN);
470 memcpy(lnkid->resp_sta, peer, ETH_ALEN);
471}
472
3b3a0162
JB
473int mwifiex_send_tdls_data_frame(struct mwifiex_private *priv, const u8 *peer,
474 u8 action_code, u8 dialog_token,
b23bce29
AP
475 u16 status_code, const u8 *extra_ies,
476 size_t extra_ies_len)
477{
478 struct sk_buff *skb;
479 struct mwifiex_txinfo *tx_info;
480 struct timeval tv;
481 int ret;
482 u16 skb_len;
483
484 skb_len = MWIFIEX_MIN_DATA_HEADER_LEN +
485 max(sizeof(struct ieee80211_mgmt),
486 sizeof(struct ieee80211_tdls_data)) +
487 MWIFIEX_MGMT_FRAME_HEADER_SIZE +
488 MWIFIEX_SUPPORTED_RATES +
489 3 + /* Qos Info */
490 sizeof(struct ieee_types_extcap) +
491 sizeof(struct ieee80211_ht_cap) +
492 sizeof(struct ieee_types_bss_co_2040) +
493 sizeof(struct ieee80211_ht_operation) +
494 sizeof(struct ieee80211_tdls_lnkie) +
495 extra_ies_len;
496
5f6d5983
AP
497 if (priv->adapter->is_hw_11ac_capable)
498 skb_len += sizeof(struct ieee_types_vht_cap) +
499 sizeof(struct ieee_types_vht_oper) +
500 sizeof(struct ieee_types_aid);
501
b23bce29
AP
502 skb = dev_alloc_skb(skb_len);
503 if (!skb) {
504 dev_err(priv->adapter->dev,
505 "allocate skb failed for management frame\n");
506 return -ENOMEM;
507 }
508 skb_reserve(skb, MWIFIEX_MIN_DATA_HEADER_LEN);
509
510 switch (action_code) {
511 case WLAN_TDLS_SETUP_REQUEST:
512 case WLAN_TDLS_SETUP_CONFIRM:
513 case WLAN_TDLS_TEARDOWN:
514 case WLAN_TDLS_DISCOVERY_REQUEST:
515 ret = mwifiex_prep_tdls_encap_data(priv, peer, action_code,
516 dialog_token, status_code,
517 skb);
518 if (ret) {
519 dev_kfree_skb_any(skb);
520 return ret;
521 }
522 if (extra_ies_len)
523 memcpy(skb_put(skb, extra_ies_len), extra_ies,
524 extra_ies_len);
525 mwifiex_tdls_add_link_ie(skb, priv->curr_addr, peer,
526 priv->cfg_bssid);
527 break;
528 case WLAN_TDLS_SETUP_RESPONSE:
529 ret = mwifiex_prep_tdls_encap_data(priv, peer, action_code,
530 dialog_token, status_code,
531 skb);
532 if (ret) {
533 dev_kfree_skb_any(skb);
534 return ret;
535 }
536 if (extra_ies_len)
537 memcpy(skb_put(skb, extra_ies_len), extra_ies,
538 extra_ies_len);
539 mwifiex_tdls_add_link_ie(skb, peer, priv->curr_addr,
540 priv->cfg_bssid);
541 break;
542 }
543
544 switch (action_code) {
545 case WLAN_TDLS_SETUP_REQUEST:
546 case WLAN_TDLS_SETUP_RESPONSE:
547 skb->priority = MWIFIEX_PRIO_BK;
548 break;
549 default:
550 skb->priority = MWIFIEX_PRIO_VI;
551 break;
552 }
553
554 tx_info = MWIFIEX_SKB_TXCB(skb);
555 tx_info->bss_num = priv->bss_num;
556 tx_info->bss_type = priv->bss_type;
557
558 do_gettimeofday(&tv);
559 skb->tstamp = timeval_to_ktime(tv);
560 mwifiex_queue_tx_pkt(priv, skb);
561
562 return 0;
563}
564
565static int
3b3a0162
JB
566mwifiex_construct_tdls_action_frame(struct mwifiex_private *priv,
567 const u8 *peer,
b23bce29
AP
568 u8 action_code, u8 dialog_token,
569 u16 status_code, struct sk_buff *skb)
570{
571 struct ieee80211_mgmt *mgmt;
572 u8 bc_addr[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
573 int ret;
574 u16 capab;
575 struct ieee80211_ht_cap *ht_cap;
576 u8 radio, *pos;
577
578 capab = priv->curr_bss_params.bss_descriptor.cap_info_bitmap;
579
580 mgmt = (void *)skb_put(skb, offsetof(struct ieee80211_mgmt, u));
581
582 memset(mgmt, 0, 24);
583 memcpy(mgmt->da, peer, ETH_ALEN);
584 memcpy(mgmt->sa, priv->curr_addr, ETH_ALEN);
585 memcpy(mgmt->bssid, priv->cfg_bssid, ETH_ALEN);
586 mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
587 IEEE80211_STYPE_ACTION);
588
589 /* add address 4 */
590 pos = skb_put(skb, ETH_ALEN);
591
592 switch (action_code) {
593 case WLAN_PUB_ACTION_TDLS_DISCOVER_RES:
594 skb_put(skb, sizeof(mgmt->u.action.u.tdls_discover_resp) + 1);
595 mgmt->u.action.category = WLAN_CATEGORY_PUBLIC;
596 mgmt->u.action.u.tdls_discover_resp.action_code =
597 WLAN_PUB_ACTION_TDLS_DISCOVER_RES;
598 mgmt->u.action.u.tdls_discover_resp.dialog_token =
599 dialog_token;
600 mgmt->u.action.u.tdls_discover_resp.capability =
601 cpu_to_le16(capab);
602 /* move back for addr4 */
603 memmove(pos + ETH_ALEN, &mgmt->u.action.category,
604 sizeof(mgmt->u.action.u.tdls_discover_resp));
605 /* init address 4 */
606 memcpy(pos, bc_addr, ETH_ALEN);
607
608 ret = mwifiex_tdls_append_rates_ie(priv, skb);
609 if (ret) {
610 dev_kfree_skb_any(skb);
611 return ret;
612 }
613
614 pos = (void *)skb_put(skb, sizeof(struct ieee80211_ht_cap) + 2);
615 *pos++ = WLAN_EID_HT_CAPABILITY;
616 *pos++ = sizeof(struct ieee80211_ht_cap);
617 ht_cap = (void *)pos;
618 radio = mwifiex_band_to_radio_type(priv->curr_bss_params.band);
619 ret = mwifiex_fill_cap_info(priv, radio, ht_cap);
620 if (ret) {
621 dev_kfree_skb_any(skb);
622 return ret;
623 }
624
5f6d5983
AP
625 if (priv->adapter->is_hw_11ac_capable) {
626 ret = mwifiex_tdls_add_vht_capab(priv, skb);
627 if (ret) {
628 dev_kfree_skb_any(skb);
629 return ret;
630 }
631 mwifiex_tdls_add_aid(priv, skb);
632 }
633
634 mwifiex_tdls_add_ext_capab(priv, skb);
b23bce29
AP
635 mwifiex_tdls_add_qos_capab(skb);
636 break;
637 default:
638 dev_err(priv->adapter->dev, "Unknown TDLS action frame type\n");
639 return -EINVAL;
640 }
641
642 return 0;
643}
644
3b3a0162
JB
645int mwifiex_send_tdls_action_frame(struct mwifiex_private *priv, const u8 *peer,
646 u8 action_code, u8 dialog_token,
647 u16 status_code, const u8 *extra_ies,
648 size_t extra_ies_len)
b23bce29
AP
649{
650 struct sk_buff *skb;
651 struct mwifiex_txinfo *tx_info;
652 struct timeval tv;
653 u8 *pos;
654 u32 pkt_type, tx_control;
655 u16 pkt_len, skb_len;
656
657 skb_len = MWIFIEX_MIN_DATA_HEADER_LEN +
658 max(sizeof(struct ieee80211_mgmt),
659 sizeof(struct ieee80211_tdls_data)) +
660 MWIFIEX_MGMT_FRAME_HEADER_SIZE +
661 MWIFIEX_SUPPORTED_RATES +
662 sizeof(struct ieee_types_extcap) +
663 sizeof(struct ieee80211_ht_cap) +
664 sizeof(struct ieee_types_bss_co_2040) +
665 sizeof(struct ieee80211_ht_operation) +
666 sizeof(struct ieee80211_tdls_lnkie) +
667 extra_ies_len +
668 3 + /* Qos Info */
669 ETH_ALEN; /* Address4 */
670
5f6d5983
AP
671 if (priv->adapter->is_hw_11ac_capable)
672 skb_len += sizeof(struct ieee_types_vht_cap) +
673 sizeof(struct ieee_types_vht_oper) +
674 sizeof(struct ieee_types_aid);
675
b23bce29
AP
676 skb = dev_alloc_skb(skb_len);
677 if (!skb) {
678 dev_err(priv->adapter->dev,
679 "allocate skb failed for management frame\n");
680 return -ENOMEM;
681 }
682
683 skb_reserve(skb, MWIFIEX_MIN_DATA_HEADER_LEN);
684
685 pkt_type = PKT_TYPE_MGMT;
686 tx_control = 0;
687 pos = skb_put(skb, MWIFIEX_MGMT_FRAME_HEADER_SIZE + sizeof(pkt_len));
688 memset(pos, 0, MWIFIEX_MGMT_FRAME_HEADER_SIZE + sizeof(pkt_len));
689 memcpy(pos, &pkt_type, sizeof(pkt_type));
690 memcpy(pos + sizeof(pkt_type), &tx_control, sizeof(tx_control));
691
692 if (mwifiex_construct_tdls_action_frame(priv, peer, action_code,
693 dialog_token, status_code,
694 skb)) {
695 dev_kfree_skb_any(skb);
696 return -EINVAL;
697 }
698
699 if (extra_ies_len)
700 memcpy(skb_put(skb, extra_ies_len), extra_ies, extra_ies_len);
701
702 /* the TDLS link IE is always added last we are the responder */
703
704 mwifiex_tdls_add_link_ie(skb, peer, priv->curr_addr,
705 priv->cfg_bssid);
706
707 skb->priority = MWIFIEX_PRIO_VI;
708
709 tx_info = MWIFIEX_SKB_TXCB(skb);
710 tx_info->bss_num = priv->bss_num;
711 tx_info->bss_type = priv->bss_type;
712 tx_info->flags |= MWIFIEX_BUF_FLAG_TDLS_PKT;
713
714 pkt_len = skb->len - MWIFIEX_MGMT_FRAME_HEADER_SIZE - sizeof(pkt_len);
715 memcpy(skb->data + MWIFIEX_MGMT_FRAME_HEADER_SIZE, &pkt_len,
716 sizeof(pkt_len));
717 do_gettimeofday(&tv);
718 skb->tstamp = timeval_to_ktime(tv);
719 mwifiex_queue_tx_pkt(priv, skb);
720
721 return 0;
722}
5f2caaf3
AP
723
724/* This function process tdls action frame from peer.
725 * Peer capabilities are stored into station node structure.
726 */
727void mwifiex_process_tdls_action_frame(struct mwifiex_private *priv,
728 u8 *buf, int len)
729{
730 struct mwifiex_sta_node *sta_ptr;
731 u8 *peer, *pos, *end;
732 u8 i, action, basic;
733 int ie_len = 0;
734
735 if (len < (sizeof(struct ethhdr) + 3))
736 return;
45d18c56 737 if (*(buf + sizeof(struct ethhdr)) != WLAN_TDLS_SNAP_RFTYPE)
5f2caaf3 738 return;
45d18c56 739 if (*(buf + sizeof(struct ethhdr) + 1) != WLAN_CATEGORY_TDLS)
5f2caaf3
AP
740 return;
741
742 peer = buf + ETH_ALEN;
45d18c56 743 action = *(buf + sizeof(struct ethhdr) + 2);
5f2caaf3
AP
744
745 /* just handle TDLS setup request/response/confirm */
746 if (action > WLAN_TDLS_SETUP_CONFIRM)
747 return;
748
749 dev_dbg(priv->adapter->dev,
750 "rx:tdls action: peer=%pM, action=%d\n", peer, action);
751
752 sta_ptr = mwifiex_add_sta_entry(priv, peer);
753 if (!sta_ptr)
754 return;
755
756 switch (action) {
757 case WLAN_TDLS_SETUP_REQUEST:
758 if (len < (sizeof(struct ethhdr) + TDLS_REQ_FIX_LEN))
759 return;
760
761 pos = buf + sizeof(struct ethhdr) + 4;
762 /* payload 1+ category 1 + action 1 + dialog 1 */
763 sta_ptr->tdls_cap.capab = cpu_to_le16(*(u16 *)pos);
764 ie_len = len - sizeof(struct ethhdr) - TDLS_REQ_FIX_LEN;
765 pos += 2;
766 break;
767
768 case WLAN_TDLS_SETUP_RESPONSE:
769 if (len < (sizeof(struct ethhdr) + TDLS_RESP_FIX_LEN))
770 return;
771 /* payload 1+ category 1 + action 1 + dialog 1 + status code 2*/
772 pos = buf + sizeof(struct ethhdr) + 6;
773 sta_ptr->tdls_cap.capab = cpu_to_le16(*(u16 *)pos);
774 ie_len = len - sizeof(struct ethhdr) - TDLS_RESP_FIX_LEN;
775 pos += 2;
776 break;
777
778 case WLAN_TDLS_SETUP_CONFIRM:
779 if (len < (sizeof(struct ethhdr) + TDLS_CONFIRM_FIX_LEN))
780 return;
781 pos = buf + sizeof(struct ethhdr) + TDLS_CONFIRM_FIX_LEN;
782 ie_len = len - sizeof(struct ethhdr) - TDLS_CONFIRM_FIX_LEN;
783 break;
784 default:
785 dev_warn(priv->adapter->dev, "Unknown TDLS frame type.\n");
786 return;
787 }
788
789 for (end = pos + ie_len; pos + 1 < end; pos += 2 + pos[1]) {
790 if (pos + 2 + pos[1] > end)
791 break;
792
793 switch (*pos) {
794 case WLAN_EID_SUPP_RATES:
795 sta_ptr->tdls_cap.rates_len = pos[1];
796 for (i = 0; i < pos[1]; i++)
797 sta_ptr->tdls_cap.rates[i] = pos[i + 2];
798 break;
799
800 case WLAN_EID_EXT_SUPP_RATES:
801 basic = sta_ptr->tdls_cap.rates_len;
802 for (i = 0; i < pos[1]; i++)
803 sta_ptr->tdls_cap.rates[basic + i] = pos[i + 2];
804 sta_ptr->tdls_cap.rates_len += pos[1];
805 break;
806 case WLAN_EID_HT_CAPABILITY:
807 memcpy((u8 *)&sta_ptr->tdls_cap.ht_capb, pos,
808 sizeof(struct ieee80211_ht_cap));
809 sta_ptr->is_11n_enabled = 1;
810 break;
811 case WLAN_EID_HT_OPERATION:
812 memcpy(&sta_ptr->tdls_cap.ht_oper, pos,
813 sizeof(struct ieee80211_ht_operation));
814 break;
815 case WLAN_EID_BSS_COEX_2040:
816 sta_ptr->tdls_cap.coex_2040 = pos[2];
817 break;
818 case WLAN_EID_EXT_CAPABILITY:
819 memcpy((u8 *)&sta_ptr->tdls_cap.extcap, pos,
820 sizeof(struct ieee_types_header) +
821 min_t(u8, pos[1], 8));
822 break;
823 case WLAN_EID_RSN:
824 memcpy((u8 *)&sta_ptr->tdls_cap.rsn_ie, pos,
825 sizeof(struct ieee_types_header) + pos[1]);
826 break;
827 case WLAN_EID_QOS_CAPA:
828 sta_ptr->tdls_cap.qos_info = pos[2];
829 break;
5f6d5983
AP
830 case WLAN_EID_VHT_OPERATION:
831 if (priv->adapter->is_hw_11ac_capable)
832 memcpy(&sta_ptr->tdls_cap.vhtoper, pos,
833 sizeof(struct ieee80211_vht_operation));
834 break;
835 case WLAN_EID_VHT_CAPABILITY:
836 if (priv->adapter->is_hw_11ac_capable) {
837 memcpy((u8 *)&sta_ptr->tdls_cap.vhtcap, pos,
838 sizeof(struct ieee80211_vht_cap));
839 sta_ptr->is_11ac_enabled = 1;
840 }
841 break;
842 case WLAN_EID_AID:
843 if (priv->adapter->is_hw_11ac_capable)
844 sta_ptr->tdls_cap.aid =
845 le16_to_cpu(*(__le16 *)(pos + 2));
5f2caaf3
AP
846 default:
847 break;
848 }
849 }
850
851 return;
852}
429d90d2 853
1f4dfd8a 854static int
3b3a0162 855mwifiex_tdls_process_config_link(struct mwifiex_private *priv, const u8 *peer)
1f4dfd8a
AP
856{
857 struct mwifiex_sta_node *sta_ptr;
858 struct mwifiex_ds_tdls_oper tdls_oper;
859
860 memset(&tdls_oper, 0, sizeof(struct mwifiex_ds_tdls_oper));
861 sta_ptr = mwifiex_get_sta_entry(priv, peer);
862
863 if (!sta_ptr || sta_ptr->tdls_status == TDLS_SETUP_FAILURE) {
864 dev_err(priv->adapter->dev,
865 "link absent for peer %pM; cannot config\n", peer);
866 return -EINVAL;
867 }
868
869 memcpy(&tdls_oper.peer_mac, peer, ETH_ALEN);
870 tdls_oper.tdls_action = MWIFIEX_TDLS_CONFIG_LINK;
fa0ecbb9
BZ
871 return mwifiex_send_cmd(priv, HostCmd_CMD_TDLS_OPER,
872 HostCmd_ACT_GEN_SET, 0, &tdls_oper, true);
1f4dfd8a
AP
873}
874
e48e0de0 875static int
3b3a0162 876mwifiex_tdls_process_create_link(struct mwifiex_private *priv, const u8 *peer)
e48e0de0
AP
877{
878 struct mwifiex_sta_node *sta_ptr;
879 struct mwifiex_ds_tdls_oper tdls_oper;
880
881 memset(&tdls_oper, 0, sizeof(struct mwifiex_ds_tdls_oper));
882 sta_ptr = mwifiex_get_sta_entry(priv, peer);
883
884 if (sta_ptr && sta_ptr->tdls_status == TDLS_SETUP_INPROGRESS) {
885 dev_dbg(priv->adapter->dev,
886 "Setup already in progress for peer %pM\n", peer);
887 return 0;
888 }
889
890 sta_ptr = mwifiex_add_sta_entry(priv, peer);
891 if (!sta_ptr)
892 return -ENOMEM;
893
894 sta_ptr->tdls_status = TDLS_SETUP_INPROGRESS;
56bd24a1 895 mwifiex_hold_tdls_packets(priv, peer);
e48e0de0
AP
896 memcpy(&tdls_oper.peer_mac, peer, ETH_ALEN);
897 tdls_oper.tdls_action = MWIFIEX_TDLS_CREATE_LINK;
fa0ecbb9
BZ
898 return mwifiex_send_cmd(priv, HostCmd_CMD_TDLS_OPER,
899 HostCmd_ACT_GEN_SET, 0, &tdls_oper, true);
e48e0de0
AP
900}
901
429d90d2 902static int
3b3a0162 903mwifiex_tdls_process_disable_link(struct mwifiex_private *priv, const u8 *peer)
429d90d2
AP
904{
905 struct mwifiex_sta_node *sta_ptr;
906 struct mwifiex_ds_tdls_oper tdls_oper;
907 unsigned long flags;
908
909 memset(&tdls_oper, 0, sizeof(struct mwifiex_ds_tdls_oper));
910 sta_ptr = mwifiex_get_sta_entry(priv, peer);
911
912 if (sta_ptr) {
913 if (sta_ptr->is_11n_enabled) {
914 mwifiex_11n_cleanup_reorder_tbl(priv);
915 spin_lock_irqsave(&priv->wmm.ra_list_spinlock,
916 flags);
917 mwifiex_11n_delete_all_tx_ba_stream_tbl(priv);
918 spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock,
919 flags);
920 }
921 mwifiex_del_sta_entry(priv, peer);
922 }
923
56bd24a1 924 mwifiex_restore_tdls_packets(priv, peer, TDLS_LINK_TEARDOWN);
429d90d2
AP
925 memcpy(&tdls_oper.peer_mac, peer, ETH_ALEN);
926 tdls_oper.tdls_action = MWIFIEX_TDLS_DISABLE_LINK;
fa0ecbb9
BZ
927 return mwifiex_send_cmd(priv, HostCmd_CMD_TDLS_OPER,
928 HostCmd_ACT_GEN_SET, 0, &tdls_oper, true);
429d90d2
AP
929}
930
931static int
3b3a0162 932mwifiex_tdls_process_enable_link(struct mwifiex_private *priv, const u8 *peer)
429d90d2
AP
933{
934 struct mwifiex_sta_node *sta_ptr;
935 struct ieee80211_mcs_info mcs;
936 unsigned long flags;
937 int i;
938
939 sta_ptr = mwifiex_get_sta_entry(priv, peer);
940
941 if (sta_ptr && (sta_ptr->tdls_status != TDLS_SETUP_FAILURE)) {
942 dev_dbg(priv->adapter->dev,
943 "tdls: enable link %pM success\n", peer);
944
945 sta_ptr->tdls_status = TDLS_SETUP_COMPLETE;
946
947 mcs = sta_ptr->tdls_cap.ht_capb.mcs;
948 if (mcs.rx_mask[0] != 0xff)
949 sta_ptr->is_11n_enabled = true;
950 if (sta_ptr->is_11n_enabled) {
951 if (le16_to_cpu(sta_ptr->tdls_cap.ht_capb.cap_info) &
952 IEEE80211_HT_CAP_MAX_AMSDU)
953 sta_ptr->max_amsdu =
954 MWIFIEX_TX_DATA_BUF_SIZE_8K;
955 else
956 sta_ptr->max_amsdu =
957 MWIFIEX_TX_DATA_BUF_SIZE_4K;
958
959 for (i = 0; i < MAX_NUM_TID; i++)
960 sta_ptr->ampdu_sta[i] =
961 priv->aggr_prio_tbl[i].ampdu_user;
962 } else {
963 for (i = 0; i < MAX_NUM_TID; i++)
964 sta_ptr->ampdu_sta[i] = BA_STREAM_NOT_ALLOWED;
965 }
966
967 memset(sta_ptr->rx_seq, 0xff, sizeof(sta_ptr->rx_seq));
56bd24a1 968 mwifiex_restore_tdls_packets(priv, peer, TDLS_SETUP_COMPLETE);
429d90d2
AP
969 } else {
970 dev_dbg(priv->adapter->dev,
971 "tdls: enable link %pM failed\n", peer);
972 if (sta_ptr) {
973 mwifiex_11n_cleanup_reorder_tbl(priv);
974 spin_lock_irqsave(&priv->wmm.ra_list_spinlock,
975 flags);
976 mwifiex_11n_delete_all_tx_ba_stream_tbl(priv);
977 spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock,
978 flags);
979 mwifiex_del_sta_entry(priv, peer);
980 }
56bd24a1 981 mwifiex_restore_tdls_packets(priv, peer, TDLS_LINK_TEARDOWN);
429d90d2
AP
982
983 return -1;
984 }
985
986 return 0;
987}
988
3b3a0162 989int mwifiex_tdls_oper(struct mwifiex_private *priv, const u8 *peer, u8 action)
429d90d2
AP
990{
991 switch (action) {
992 case MWIFIEX_TDLS_ENABLE_LINK:
993 return mwifiex_tdls_process_enable_link(priv, peer);
994 case MWIFIEX_TDLS_DISABLE_LINK:
995 return mwifiex_tdls_process_disable_link(priv, peer);
e48e0de0
AP
996 case MWIFIEX_TDLS_CREATE_LINK:
997 return mwifiex_tdls_process_create_link(priv, peer);
1f4dfd8a
AP
998 case MWIFIEX_TDLS_CONFIG_LINK:
999 return mwifiex_tdls_process_config_link(priv, peer);
429d90d2
AP
1000 }
1001 return 0;
1002}
d63bf5e5 1003
3b3a0162 1004int mwifiex_get_tdls_link_status(struct mwifiex_private *priv, const u8 *mac)
d63bf5e5
AP
1005{
1006 struct mwifiex_sta_node *sta_ptr;
1007
1008 sta_ptr = mwifiex_get_sta_entry(priv, mac);
1009 if (sta_ptr)
1010 return sta_ptr->tdls_status;
1011
1012 return TDLS_NOT_SETUP;
1013}
be104b91
AP
1014
1015void mwifiex_disable_all_tdls_links(struct mwifiex_private *priv)
1016{
1017 struct mwifiex_sta_node *sta_ptr;
1018 struct mwifiex_ds_tdls_oper tdls_oper;
1019 unsigned long flags;
1020
1021 if (list_empty(&priv->sta_list))
1022 return;
1023
1024 list_for_each_entry(sta_ptr, &priv->sta_list, list) {
1025 memset(&tdls_oper, 0, sizeof(struct mwifiex_ds_tdls_oper));
1026
1027 if (sta_ptr->is_11n_enabled) {
1028 mwifiex_11n_cleanup_reorder_tbl(priv);
1029 spin_lock_irqsave(&priv->wmm.ra_list_spinlock,
1030 flags);
1031 mwifiex_11n_delete_all_tx_ba_stream_tbl(priv);
1032 spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock,
1033 flags);
1034 }
1035
1036 mwifiex_restore_tdls_packets(priv, sta_ptr->mac_addr,
1037 TDLS_LINK_TEARDOWN);
1038 memcpy(&tdls_oper.peer_mac, sta_ptr->mac_addr, ETH_ALEN);
1039 tdls_oper.tdls_action = MWIFIEX_TDLS_DISABLE_LINK;
fa0ecbb9
BZ
1040 if (mwifiex_send_cmd(priv, HostCmd_CMD_TDLS_OPER,
1041 HostCmd_ACT_GEN_SET, 0, &tdls_oper, false))
be104b91
AP
1042 dev_warn(priv->adapter->dev,
1043 "Disable link failed for TDLS peer %pM",
1044 sta_ptr->mac_addr);
1045 }
1046
1047 mwifiex_del_all_sta_list(priv);
1048}