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