1 /* Marvell Wireless LAN device driver: TDLS handling
3 * Copyright (C) 2014, Marvell International Ltd.
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.
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.
21 #include "11n_rxreorder.h"
24 #define TDLS_REQ_FIX_LEN 6
25 #define TDLS_RESP_FIX_LEN 8
26 #define TDLS_CONFIRM_FIX_LEN 6
27 #define MWIFIEX_TDLS_WMM_INFO_SIZE 7
29 static void mwifiex_restore_tdls_packets(struct mwifiex_private
*priv
,
30 const u8
*mac
, u8 status
)
32 struct mwifiex_ra_list_tbl
*ra_list
;
33 struct list_head
*tid_list
;
34 struct sk_buff
*skb
, *tmp
;
35 struct mwifiex_txinfo
*tx_info
;
40 mwifiex_dbg(priv
->adapter
, DATA
, "%s: %pM\n", __func__
, mac
);
41 spin_lock_irqsave(&priv
->wmm
.ra_list_spinlock
, flags
);
43 skb_queue_walk_safe(&priv
->tdls_txq
, skb
, tmp
) {
44 if (!ether_addr_equal(mac
, skb
->data
))
47 __skb_unlink(skb
, &priv
->tdls_txq
);
48 tx_info
= MWIFIEX_SKB_TXCB(skb
);
50 tid_down
= mwifiex_wmm_downgrade_tid(priv
, tid
);
52 if (mwifiex_is_tdls_link_setup(status
)) {
53 ra_list
= mwifiex_wmm_get_queue_raptr(priv
, tid
, mac
);
54 ra_list
->tdls_link
= true;
55 tx_info
->flags
|= MWIFIEX_BUF_FLAG_TDLS_PKT
;
57 tid_list
= &priv
->wmm
.tid_tbl_ptr
[tid_down
].ra_list
;
58 if (!list_empty(tid_list
))
59 ra_list
= list_first_entry(tid_list
,
60 struct mwifiex_ra_list_tbl
, list
);
63 tx_info
->flags
&= ~MWIFIEX_BUF_FLAG_TDLS_PKT
;
67 mwifiex_write_data_complete(priv
->adapter
, skb
, 0, -1);
71 skb_queue_tail(&ra_list
->skb_head
, skb
);
73 ra_list
->ba_pkt_count
++;
74 ra_list
->total_pkt_count
++;
76 if (atomic_read(&priv
->wmm
.highest_queued_prio
) <
77 tos_to_tid_inv
[tid_down
])
78 atomic_set(&priv
->wmm
.highest_queued_prio
,
79 tos_to_tid_inv
[tid_down
]);
81 atomic_inc(&priv
->wmm
.tx_pkts_queued
);
84 spin_unlock_irqrestore(&priv
->wmm
.ra_list_spinlock
, flags
);
88 static void mwifiex_hold_tdls_packets(struct mwifiex_private
*priv
,
91 struct mwifiex_ra_list_tbl
*ra_list
;
92 struct list_head
*ra_list_head
;
93 struct sk_buff
*skb
, *tmp
;
97 mwifiex_dbg(priv
->adapter
, DATA
, "%s: %pM\n", __func__
, mac
);
98 spin_lock_irqsave(&priv
->wmm
.ra_list_spinlock
, flags
);
100 for (i
= 0; i
< MAX_NUM_TID
; i
++) {
101 if (!list_empty(&priv
->wmm
.tid_tbl_ptr
[i
].ra_list
)) {
102 ra_list_head
= &priv
->wmm
.tid_tbl_ptr
[i
].ra_list
;
103 list_for_each_entry(ra_list
, ra_list_head
, list
) {
104 skb_queue_walk_safe(&ra_list
->skb_head
, skb
,
106 if (!ether_addr_equal(mac
, skb
->data
))
108 __skb_unlink(skb
, &ra_list
->skb_head
);
109 atomic_dec(&priv
->wmm
.tx_pkts_queued
);
110 ra_list
->total_pkt_count
--;
111 skb_queue_tail(&priv
->tdls_txq
, skb
);
117 spin_unlock_irqrestore(&priv
->wmm
.ra_list_spinlock
, flags
);
121 /* This function appends rate TLV to scan config command. */
123 mwifiex_tdls_append_rates_ie(struct mwifiex_private
*priv
,
126 u8 rates
[MWIFIEX_SUPPORTED_RATES
], *pos
;
127 u16 rates_size
, supp_rates_size
, ext_rates_size
;
129 memset(rates
, 0, sizeof(rates
));
130 rates_size
= mwifiex_get_supported_rates(priv
, rates
);
132 supp_rates_size
= min_t(u16
, rates_size
, MWIFIEX_TDLS_SUPPORTED_RATES
);
134 if (skb_tailroom(skb
) < rates_size
+ 4) {
135 mwifiex_dbg(priv
->adapter
, ERROR
,
136 "Insuffient space while adding rates\n");
140 pos
= skb_put(skb
, supp_rates_size
+ 2);
141 *pos
++ = WLAN_EID_SUPP_RATES
;
142 *pos
++ = supp_rates_size
;
143 memcpy(pos
, rates
, supp_rates_size
);
145 if (rates_size
> MWIFIEX_TDLS_SUPPORTED_RATES
) {
146 ext_rates_size
= rates_size
- MWIFIEX_TDLS_SUPPORTED_RATES
;
147 pos
= skb_put(skb
, ext_rates_size
+ 2);
148 *pos
++ = WLAN_EID_EXT_SUPP_RATES
;
149 *pos
++ = ext_rates_size
;
150 memcpy(pos
, rates
+ MWIFIEX_TDLS_SUPPORTED_RATES
,
157 static void mwifiex_tdls_add_aid(struct mwifiex_private
*priv
,
160 struct ieee_types_assoc_rsp
*assoc_rsp
;
163 assoc_rsp
= (struct ieee_types_assoc_rsp
*)&priv
->assoc_rsp_buf
;
164 pos
= (void *)skb_put(skb
, 4);
165 *pos
++ = WLAN_EID_AID
;
167 memcpy(pos
, &assoc_rsp
->a_id
, sizeof(assoc_rsp
->a_id
));
172 static int mwifiex_tdls_add_vht_capab(struct mwifiex_private
*priv
,
175 struct ieee80211_vht_cap vht_cap
;
178 pos
= (void *)skb_put(skb
, sizeof(struct ieee80211_vht_cap
) + 2);
179 *pos
++ = WLAN_EID_VHT_CAPABILITY
;
180 *pos
++ = sizeof(struct ieee80211_vht_cap
);
182 memset(&vht_cap
, 0, sizeof(struct ieee80211_vht_cap
));
184 mwifiex_fill_vht_cap_tlv(priv
, &vht_cap
, priv
->curr_bss_params
.band
);
185 memcpy(pos
, &vht_cap
, sizeof(vht_cap
));
191 mwifiex_tdls_add_ht_oper(struct mwifiex_private
*priv
, const u8
*mac
,
192 u8 vht_enabled
, struct sk_buff
*skb
)
194 struct ieee80211_ht_operation
*ht_oper
;
195 struct mwifiex_sta_node
*sta_ptr
;
196 struct mwifiex_bssdescriptor
*bss_desc
=
197 &priv
->curr_bss_params
.bss_descriptor
;
200 sta_ptr
= mwifiex_get_sta_entry(priv
, mac
);
201 if (unlikely(!sta_ptr
)) {
202 mwifiex_dbg(priv
->adapter
, ERROR
,
203 "TDLS peer station not found in list\n");
207 if (!(le16_to_cpu(sta_ptr
->tdls_cap
.ht_capb
.cap_info
))) {
208 mwifiex_dbg(priv
->adapter
, WARN
,
209 "TDLS peer doesn't support ht capabilities\n");
213 pos
= (void *)skb_put(skb
, sizeof(struct ieee80211_ht_operation
) + 2);
214 *pos
++ = WLAN_EID_HT_OPERATION
;
215 *pos
++ = sizeof(struct ieee80211_ht_operation
);
216 ht_oper
= (void *)pos
;
218 ht_oper
->primary_chan
= bss_desc
->channel
;
220 /* follow AP's channel bandwidth */
221 if (ISSUPP_CHANWIDTH40(priv
->adapter
->hw_dot_11n_dev_cap
) &&
222 bss_desc
->bcn_ht_cap
&&
223 ISALLOWED_CHANWIDTH40(bss_desc
->bcn_ht_oper
->ht_param
))
224 ht_oper
->ht_param
= bss_desc
->bcn_ht_oper
->ht_param
;
228 mwifiex_get_sec_chan_offset(bss_desc
->channel
);
229 ht_oper
->ht_param
|= BIT(2);
232 memcpy(&sta_ptr
->tdls_cap
.ht_oper
, ht_oper
,
233 sizeof(struct ieee80211_ht_operation
));
238 static int mwifiex_tdls_add_vht_oper(struct mwifiex_private
*priv
,
239 const u8
*mac
, struct sk_buff
*skb
)
241 struct mwifiex_bssdescriptor
*bss_desc
;
242 struct ieee80211_vht_operation
*vht_oper
;
243 struct ieee80211_vht_cap
*vht_cap
, *ap_vht_cap
= NULL
;
244 struct mwifiex_sta_node
*sta_ptr
;
245 struct mwifiex_adapter
*adapter
= priv
->adapter
;
246 u8 supp_chwd_set
, peer_supp_chwd_set
;
247 u8
*pos
, ap_supp_chwd_set
, chan_bw
;
248 u16 mcs_map_user
, mcs_map_resp
, mcs_map_result
;
249 u16 mcs_user
, mcs_resp
, nss
;
250 u32 usr_vht_cap_info
;
252 bss_desc
= &priv
->curr_bss_params
.bss_descriptor
;
254 sta_ptr
= mwifiex_get_sta_entry(priv
, mac
);
255 if (unlikely(!sta_ptr
)) {
256 mwifiex_dbg(adapter
, ERROR
,
257 "TDLS peer station not found in list\n");
261 if (!(le32_to_cpu(sta_ptr
->tdls_cap
.vhtcap
.vht_cap_info
))) {
262 mwifiex_dbg(adapter
, WARN
,
263 "TDLS peer doesn't support vht capabilities\n");
267 if (!mwifiex_is_bss_in_11ac_mode(priv
)) {
268 if (sta_ptr
->tdls_cap
.extcap
.ext_capab
[7] &
269 WLAN_EXT_CAPA8_TDLS_WIDE_BW_ENABLED
) {
270 mwifiex_dbg(adapter
, WARN
,
271 "TDLS peer doesn't support wider bandwidth\n");
275 ap_vht_cap
= bss_desc
->bcn_vht_cap
;
278 pos
= (void *)skb_put(skb
, sizeof(struct ieee80211_vht_operation
) + 2);
279 *pos
++ = WLAN_EID_VHT_OPERATION
;
280 *pos
++ = sizeof(struct ieee80211_vht_operation
);
281 vht_oper
= (struct ieee80211_vht_operation
*)pos
;
283 if (bss_desc
->bss_band
& BAND_A
)
284 usr_vht_cap_info
= adapter
->usr_dot_11ac_dev_cap_a
;
286 usr_vht_cap_info
= adapter
->usr_dot_11ac_dev_cap_bg
;
288 /* find the minmum bandwith between AP/TDLS peers */
289 vht_cap
= &sta_ptr
->tdls_cap
.vhtcap
;
290 supp_chwd_set
= GET_VHTCAP_CHWDSET(usr_vht_cap_info
);
292 GET_VHTCAP_CHWDSET(le32_to_cpu(vht_cap
->vht_cap_info
));
293 supp_chwd_set
= min_t(u8
, supp_chwd_set
, peer_supp_chwd_set
);
295 /* We need check AP's bandwidth when TDLS_WIDER_BANDWIDTH is off */
297 if (ap_vht_cap
&& sta_ptr
->tdls_cap
.extcap
.ext_capab
[7] &
298 WLAN_EXT_CAPA8_TDLS_WIDE_BW_ENABLED
) {
300 GET_VHTCAP_CHWDSET(le32_to_cpu(ap_vht_cap
->vht_cap_info
));
301 supp_chwd_set
= min_t(u8
, supp_chwd_set
, ap_supp_chwd_set
);
304 switch (supp_chwd_set
) {
305 case IEEE80211_VHT_CHANWIDTH_80MHZ
:
306 vht_oper
->chan_width
= IEEE80211_VHT_CHANWIDTH_80MHZ
;
308 case IEEE80211_VHT_CHANWIDTH_160MHZ
:
309 vht_oper
->chan_width
= IEEE80211_VHT_CHANWIDTH_160MHZ
;
311 case IEEE80211_VHT_CHANWIDTH_80P80MHZ
:
312 vht_oper
->chan_width
= IEEE80211_VHT_CHANWIDTH_80P80MHZ
;
315 vht_oper
->chan_width
= IEEE80211_VHT_CHANWIDTH_USE_HT
;
319 mcs_map_user
= GET_DEVRXMCSMAP(adapter
->usr_dot_11ac_mcs_support
);
320 mcs_map_resp
= le16_to_cpu(vht_cap
->supp_mcs
.rx_mcs_map
);
323 for (nss
= 1; nss
<= 8; nss
++) {
324 mcs_user
= GET_VHTNSSMCS(mcs_map_user
, nss
);
325 mcs_resp
= GET_VHTNSSMCS(mcs_map_resp
, nss
);
327 if ((mcs_user
== IEEE80211_VHT_MCS_NOT_SUPPORTED
) ||
328 (mcs_resp
== IEEE80211_VHT_MCS_NOT_SUPPORTED
))
329 SET_VHTNSSMCS(mcs_map_result
, nss
,
330 IEEE80211_VHT_MCS_NOT_SUPPORTED
);
332 SET_VHTNSSMCS(mcs_map_result
, nss
,
333 min_t(u16
, mcs_user
, mcs_resp
));
336 vht_oper
->basic_mcs_set
= cpu_to_le16(mcs_map_result
);
338 switch (vht_oper
->chan_width
) {
339 case IEEE80211_VHT_CHANWIDTH_80MHZ
:
340 chan_bw
= IEEE80211_VHT_CHANWIDTH_80MHZ
;
342 case IEEE80211_VHT_CHANWIDTH_160MHZ
:
343 chan_bw
= IEEE80211_VHT_CHANWIDTH_160MHZ
;
345 case IEEE80211_VHT_CHANWIDTH_80P80MHZ
:
346 chan_bw
= IEEE80211_VHT_CHANWIDTH_80MHZ
;
349 chan_bw
= IEEE80211_VHT_CHANWIDTH_USE_HT
;
352 vht_oper
->center_freq_seg1_idx
=
353 mwifiex_get_center_freq_index(priv
, BAND_AAC
,
360 static void mwifiex_tdls_add_ext_capab(struct mwifiex_private
*priv
,
363 struct ieee_types_extcap
*extcap
;
365 extcap
= (void *)skb_put(skb
, sizeof(struct ieee_types_extcap
));
366 extcap
->ieee_hdr
.element_id
= WLAN_EID_EXT_CAPABILITY
;
367 extcap
->ieee_hdr
.len
= 8;
368 memset(extcap
->ext_capab
, 0, 8);
369 extcap
->ext_capab
[4] |= WLAN_EXT_CAPA5_TDLS_ENABLED
;
370 extcap
->ext_capab
[3] |= WLAN_EXT_CAPA4_TDLS_CHAN_SWITCH
;
372 if (priv
->adapter
->is_hw_11ac_capable
)
373 extcap
->ext_capab
[7] |= WLAN_EXT_CAPA8_TDLS_WIDE_BW_ENABLED
;
376 static void mwifiex_tdls_add_qos_capab(struct sk_buff
*skb
)
378 u8
*pos
= (void *)skb_put(skb
, 3);
380 *pos
++ = WLAN_EID_QOS_CAPA
;
382 *pos
++ = MWIFIEX_TDLS_DEF_QOS_CAPAB
;
386 mwifiex_tdls_add_wmm_param_ie(struct mwifiex_private
*priv
, struct sk_buff
*skb
)
388 struct ieee80211_wmm_param_ie
*wmm
;
389 u8 ac_vi
[] = {0x42, 0x43, 0x5e, 0x00};
390 u8 ac_vo
[] = {0x62, 0x32, 0x2f, 0x00};
391 u8 ac_be
[] = {0x03, 0xa4, 0x00, 0x00};
392 u8 ac_bk
[] = {0x27, 0xa4, 0x00, 0x00};
394 wmm
= (void *)skb_put(skb
, sizeof(*wmm
));
395 memset(wmm
, 0, sizeof(*wmm
));
397 wmm
->element_id
= WLAN_EID_VENDOR_SPECIFIC
;
398 wmm
->len
= sizeof(*wmm
) - 2;
399 wmm
->oui
[0] = 0x00; /* Microsoft OUI 00:50:F2 */
402 wmm
->oui_type
= 2; /* WME */
403 wmm
->oui_subtype
= 1; /* WME param */
404 wmm
->version
= 1; /* WME ver */
405 wmm
->qos_info
= 0; /* U-APSD not in use */
407 /* use default WMM AC parameters for TDLS link*/
408 memcpy(&wmm
->ac
[0], ac_be
, sizeof(ac_be
));
409 memcpy(&wmm
->ac
[1], ac_bk
, sizeof(ac_bk
));
410 memcpy(&wmm
->ac
[2], ac_vi
, sizeof(ac_vi
));
411 memcpy(&wmm
->ac
[3], ac_vo
, sizeof(ac_vo
));
415 mwifiex_add_wmm_info_ie(struct mwifiex_private
*priv
, struct sk_buff
*skb
,
420 buf
= (void *)skb_put(skb
, MWIFIEX_TDLS_WMM_INFO_SIZE
+
421 sizeof(struct ieee_types_header
));
423 *buf
++ = WLAN_EID_VENDOR_SPECIFIC
;
424 *buf
++ = 7; /* len */
425 *buf
++ = 0x00; /* Microsoft OUI 00:50:F2 */
428 *buf
++ = 2; /* WME */
429 *buf
++ = 0; /* WME info */
430 *buf
++ = 1; /* WME ver */
431 *buf
++ = qosinfo
; /* U-APSD no in use */
434 static int mwifiex_prep_tdls_encap_data(struct mwifiex_private
*priv
,
435 const u8
*peer
, u8 action_code
,
437 u16 status_code
, struct sk_buff
*skb
)
439 struct ieee80211_tdls_data
*tf
;
442 struct ieee80211_ht_cap
*ht_cap
;
445 capab
= priv
->curr_bss_params
.bss_descriptor
.cap_info_bitmap
;
447 tf
= (void *)skb_put(skb
, offsetof(struct ieee80211_tdls_data
, u
));
448 memcpy(tf
->da
, peer
, ETH_ALEN
);
449 memcpy(tf
->sa
, priv
->curr_addr
, ETH_ALEN
);
450 tf
->ether_type
= cpu_to_be16(ETH_P_TDLS
);
451 tf
->payload_type
= WLAN_TDLS_SNAP_RFTYPE
;
453 switch (action_code
) {
454 case WLAN_TDLS_SETUP_REQUEST
:
455 tf
->category
= WLAN_CATEGORY_TDLS
;
456 tf
->action_code
= WLAN_TDLS_SETUP_REQUEST
;
457 skb_put(skb
, sizeof(tf
->u
.setup_req
));
458 tf
->u
.setup_req
.dialog_token
= dialog_token
;
459 tf
->u
.setup_req
.capability
= cpu_to_le16(capab
);
460 ret
= mwifiex_tdls_append_rates_ie(priv
, skb
);
462 dev_kfree_skb_any(skb
);
466 pos
= (void *)skb_put(skb
, sizeof(struct ieee80211_ht_cap
) + 2);
467 *pos
++ = WLAN_EID_HT_CAPABILITY
;
468 *pos
++ = sizeof(struct ieee80211_ht_cap
);
469 ht_cap
= (void *)pos
;
470 radio
= mwifiex_band_to_radio_type(priv
->curr_bss_params
.band
);
471 ret
= mwifiex_fill_cap_info(priv
, radio
, ht_cap
);
473 dev_kfree_skb_any(skb
);
477 if (priv
->adapter
->is_hw_11ac_capable
) {
478 ret
= mwifiex_tdls_add_vht_capab(priv
, skb
);
480 dev_kfree_skb_any(skb
);
483 mwifiex_tdls_add_aid(priv
, skb
);
486 mwifiex_tdls_add_ext_capab(priv
, skb
);
487 mwifiex_tdls_add_qos_capab(skb
);
488 mwifiex_add_wmm_info_ie(priv
, skb
, 0);
491 case WLAN_TDLS_SETUP_RESPONSE
:
492 tf
->category
= WLAN_CATEGORY_TDLS
;
493 tf
->action_code
= WLAN_TDLS_SETUP_RESPONSE
;
494 skb_put(skb
, sizeof(tf
->u
.setup_resp
));
495 tf
->u
.setup_resp
.status_code
= cpu_to_le16(status_code
);
496 tf
->u
.setup_resp
.dialog_token
= dialog_token
;
497 tf
->u
.setup_resp
.capability
= cpu_to_le16(capab
);
498 ret
= mwifiex_tdls_append_rates_ie(priv
, skb
);
500 dev_kfree_skb_any(skb
);
504 pos
= (void *)skb_put(skb
, sizeof(struct ieee80211_ht_cap
) + 2);
505 *pos
++ = WLAN_EID_HT_CAPABILITY
;
506 *pos
++ = sizeof(struct ieee80211_ht_cap
);
507 ht_cap
= (void *)pos
;
508 radio
= mwifiex_band_to_radio_type(priv
->curr_bss_params
.band
);
509 ret
= mwifiex_fill_cap_info(priv
, radio
, ht_cap
);
511 dev_kfree_skb_any(skb
);
515 if (priv
->adapter
->is_hw_11ac_capable
) {
516 ret
= mwifiex_tdls_add_vht_capab(priv
, skb
);
518 dev_kfree_skb_any(skb
);
521 mwifiex_tdls_add_aid(priv
, skb
);
524 mwifiex_tdls_add_ext_capab(priv
, skb
);
525 mwifiex_tdls_add_qos_capab(skb
);
526 mwifiex_add_wmm_info_ie(priv
, skb
, 0);
529 case WLAN_TDLS_SETUP_CONFIRM
:
530 tf
->category
= WLAN_CATEGORY_TDLS
;
531 tf
->action_code
= WLAN_TDLS_SETUP_CONFIRM
;
532 skb_put(skb
, sizeof(tf
->u
.setup_cfm
));
533 tf
->u
.setup_cfm
.status_code
= cpu_to_le16(status_code
);
534 tf
->u
.setup_cfm
.dialog_token
= dialog_token
;
536 mwifiex_tdls_add_wmm_param_ie(priv
, skb
);
537 if (priv
->adapter
->is_hw_11ac_capable
) {
538 ret
= mwifiex_tdls_add_vht_oper(priv
, peer
, skb
);
540 dev_kfree_skb_any(skb
);
543 ret
= mwifiex_tdls_add_ht_oper(priv
, peer
, 1, skb
);
545 dev_kfree_skb_any(skb
);
549 ret
= mwifiex_tdls_add_ht_oper(priv
, peer
, 0, skb
);
551 dev_kfree_skb_any(skb
);
557 case WLAN_TDLS_TEARDOWN
:
558 tf
->category
= WLAN_CATEGORY_TDLS
;
559 tf
->action_code
= WLAN_TDLS_TEARDOWN
;
560 skb_put(skb
, sizeof(tf
->u
.teardown
));
561 tf
->u
.teardown
.reason_code
= cpu_to_le16(status_code
);
564 case WLAN_TDLS_DISCOVERY_REQUEST
:
565 tf
->category
= WLAN_CATEGORY_TDLS
;
566 tf
->action_code
= WLAN_TDLS_DISCOVERY_REQUEST
;
567 skb_put(skb
, sizeof(tf
->u
.discover_req
));
568 tf
->u
.discover_req
.dialog_token
= dialog_token
;
571 mwifiex_dbg(priv
->adapter
, ERROR
, "Unknown TDLS frame type.\n");
579 mwifiex_tdls_add_link_ie(struct sk_buff
*skb
, const u8
*src_addr
,
580 const u8
*peer
, const u8
*bssid
)
582 struct ieee80211_tdls_lnkie
*lnkid
;
584 lnkid
= (void *)skb_put(skb
, sizeof(struct ieee80211_tdls_lnkie
));
585 lnkid
->ie_type
= WLAN_EID_LINK_ID
;
586 lnkid
->ie_len
= sizeof(struct ieee80211_tdls_lnkie
) -
587 sizeof(struct ieee_types_header
);
589 memcpy(lnkid
->bssid
, bssid
, ETH_ALEN
);
590 memcpy(lnkid
->init_sta
, src_addr
, ETH_ALEN
);
591 memcpy(lnkid
->resp_sta
, peer
, ETH_ALEN
);
594 int mwifiex_send_tdls_data_frame(struct mwifiex_private
*priv
, const u8
*peer
,
595 u8 action_code
, u8 dialog_token
,
596 u16 status_code
, const u8
*extra_ies
,
597 size_t extra_ies_len
)
600 struct mwifiex_txinfo
*tx_info
;
604 skb_len
= MWIFIEX_MIN_DATA_HEADER_LEN
+
605 max(sizeof(struct ieee80211_mgmt
),
606 sizeof(struct ieee80211_tdls_data
)) +
607 MWIFIEX_MGMT_FRAME_HEADER_SIZE
+
608 MWIFIEX_SUPPORTED_RATES
+
610 sizeof(struct ieee_types_extcap
) +
611 sizeof(struct ieee80211_ht_cap
) +
612 sizeof(struct ieee_types_bss_co_2040
) +
613 sizeof(struct ieee80211_ht_operation
) +
614 sizeof(struct ieee80211_tdls_lnkie
) +
615 sizeof(struct ieee80211_wmm_param_ie
) +
618 if (priv
->adapter
->is_hw_11ac_capable
)
619 skb_len
+= sizeof(struct ieee_types_vht_cap
) +
620 sizeof(struct ieee_types_vht_oper
) +
621 sizeof(struct ieee_types_aid
);
623 skb
= dev_alloc_skb(skb_len
);
625 mwifiex_dbg(priv
->adapter
, ERROR
,
626 "allocate skb failed for management frame\n");
629 skb_reserve(skb
, MWIFIEX_MIN_DATA_HEADER_LEN
);
631 switch (action_code
) {
632 case WLAN_TDLS_SETUP_REQUEST
:
633 case WLAN_TDLS_SETUP_CONFIRM
:
634 case WLAN_TDLS_TEARDOWN
:
635 case WLAN_TDLS_DISCOVERY_REQUEST
:
636 ret
= mwifiex_prep_tdls_encap_data(priv
, peer
, action_code
,
637 dialog_token
, status_code
,
640 dev_kfree_skb_any(skb
);
644 memcpy(skb_put(skb
, extra_ies_len
), extra_ies
,
646 mwifiex_tdls_add_link_ie(skb
, priv
->curr_addr
, peer
,
649 case WLAN_TDLS_SETUP_RESPONSE
:
650 ret
= mwifiex_prep_tdls_encap_data(priv
, peer
, action_code
,
651 dialog_token
, status_code
,
654 dev_kfree_skb_any(skb
);
658 memcpy(skb_put(skb
, extra_ies_len
), extra_ies
,
660 mwifiex_tdls_add_link_ie(skb
, peer
, priv
->curr_addr
,
665 switch (action_code
) {
666 case WLAN_TDLS_SETUP_REQUEST
:
667 case WLAN_TDLS_SETUP_RESPONSE
:
668 skb
->priority
= MWIFIEX_PRIO_BK
;
671 skb
->priority
= MWIFIEX_PRIO_VI
;
675 tx_info
= MWIFIEX_SKB_TXCB(skb
);
676 memset(tx_info
, 0, sizeof(*tx_info
));
677 tx_info
->bss_num
= priv
->bss_num
;
678 tx_info
->bss_type
= priv
->bss_type
;
680 __net_timestamp(skb
);
681 mwifiex_queue_tx_pkt(priv
, skb
);
687 mwifiex_construct_tdls_action_frame(struct mwifiex_private
*priv
,
689 u8 action_code
, u8 dialog_token
,
690 u16 status_code
, struct sk_buff
*skb
)
692 struct ieee80211_mgmt
*mgmt
;
693 u8 bc_addr
[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
696 struct ieee80211_ht_cap
*ht_cap
;
699 capab
= priv
->curr_bss_params
.bss_descriptor
.cap_info_bitmap
;
701 mgmt
= (void *)skb_put(skb
, offsetof(struct ieee80211_mgmt
, u
));
704 memcpy(mgmt
->da
, peer
, ETH_ALEN
);
705 memcpy(mgmt
->sa
, priv
->curr_addr
, ETH_ALEN
);
706 memcpy(mgmt
->bssid
, priv
->cfg_bssid
, ETH_ALEN
);
707 mgmt
->frame_control
= cpu_to_le16(IEEE80211_FTYPE_MGMT
|
708 IEEE80211_STYPE_ACTION
);
711 pos
= skb_put(skb
, ETH_ALEN
);
713 switch (action_code
) {
714 case WLAN_PUB_ACTION_TDLS_DISCOVER_RES
:
715 skb_put(skb
, sizeof(mgmt
->u
.action
.u
.tdls_discover_resp
) + 1);
716 mgmt
->u
.action
.category
= WLAN_CATEGORY_PUBLIC
;
717 mgmt
->u
.action
.u
.tdls_discover_resp
.action_code
=
718 WLAN_PUB_ACTION_TDLS_DISCOVER_RES
;
719 mgmt
->u
.action
.u
.tdls_discover_resp
.dialog_token
=
721 mgmt
->u
.action
.u
.tdls_discover_resp
.capability
=
723 /* move back for addr4 */
724 memmove(pos
+ ETH_ALEN
, &mgmt
->u
.action
.category
,
725 sizeof(mgmt
->u
.action
.u
.tdls_discover_resp
));
727 memcpy(pos
, bc_addr
, ETH_ALEN
);
729 ret
= mwifiex_tdls_append_rates_ie(priv
, skb
);
731 dev_kfree_skb_any(skb
);
735 pos
= (void *)skb_put(skb
, sizeof(struct ieee80211_ht_cap
) + 2);
736 *pos
++ = WLAN_EID_HT_CAPABILITY
;
737 *pos
++ = sizeof(struct ieee80211_ht_cap
);
738 ht_cap
= (void *)pos
;
739 radio
= mwifiex_band_to_radio_type(priv
->curr_bss_params
.band
);
740 ret
= mwifiex_fill_cap_info(priv
, radio
, ht_cap
);
742 dev_kfree_skb_any(skb
);
746 if (priv
->adapter
->is_hw_11ac_capable
) {
747 ret
= mwifiex_tdls_add_vht_capab(priv
, skb
);
749 dev_kfree_skb_any(skb
);
752 mwifiex_tdls_add_aid(priv
, skb
);
755 mwifiex_tdls_add_ext_capab(priv
, skb
);
756 mwifiex_tdls_add_qos_capab(skb
);
759 mwifiex_dbg(priv
->adapter
, ERROR
, "Unknown TDLS action frame type\n");
766 int mwifiex_send_tdls_action_frame(struct mwifiex_private
*priv
, const u8
*peer
,
767 u8 action_code
, u8 dialog_token
,
768 u16 status_code
, const u8
*extra_ies
,
769 size_t extra_ies_len
)
772 struct mwifiex_txinfo
*tx_info
;
774 u32 pkt_type
, tx_control
;
775 u16 pkt_len
, skb_len
;
777 skb_len
= MWIFIEX_MIN_DATA_HEADER_LEN
+
778 max(sizeof(struct ieee80211_mgmt
),
779 sizeof(struct ieee80211_tdls_data
)) +
780 MWIFIEX_MGMT_FRAME_HEADER_SIZE
+
781 MWIFIEX_SUPPORTED_RATES
+
782 sizeof(struct ieee_types_extcap
) +
783 sizeof(struct ieee80211_ht_cap
) +
784 sizeof(struct ieee_types_bss_co_2040
) +
785 sizeof(struct ieee80211_ht_operation
) +
786 sizeof(struct ieee80211_tdls_lnkie
) +
789 ETH_ALEN
; /* Address4 */
791 if (priv
->adapter
->is_hw_11ac_capable
)
792 skb_len
+= sizeof(struct ieee_types_vht_cap
) +
793 sizeof(struct ieee_types_vht_oper
) +
794 sizeof(struct ieee_types_aid
);
796 skb
= dev_alloc_skb(skb_len
);
798 mwifiex_dbg(priv
->adapter
, ERROR
,
799 "allocate skb failed for management frame\n");
803 skb_reserve(skb
, MWIFIEX_MIN_DATA_HEADER_LEN
);
805 pkt_type
= PKT_TYPE_MGMT
;
807 pos
= skb_put(skb
, MWIFIEX_MGMT_FRAME_HEADER_SIZE
+ sizeof(pkt_len
));
808 memset(pos
, 0, MWIFIEX_MGMT_FRAME_HEADER_SIZE
+ sizeof(pkt_len
));
809 memcpy(pos
, &pkt_type
, sizeof(pkt_type
));
810 memcpy(pos
+ sizeof(pkt_type
), &tx_control
, sizeof(tx_control
));
812 if (mwifiex_construct_tdls_action_frame(priv
, peer
, action_code
,
813 dialog_token
, status_code
,
815 dev_kfree_skb_any(skb
);
820 memcpy(skb_put(skb
, extra_ies_len
), extra_ies
, extra_ies_len
);
822 /* the TDLS link IE is always added last we are the responder */
824 mwifiex_tdls_add_link_ie(skb
, peer
, priv
->curr_addr
,
827 skb
->priority
= MWIFIEX_PRIO_VI
;
829 tx_info
= MWIFIEX_SKB_TXCB(skb
);
830 memset(tx_info
, 0, sizeof(*tx_info
));
831 tx_info
->bss_num
= priv
->bss_num
;
832 tx_info
->bss_type
= priv
->bss_type
;
833 tx_info
->flags
|= MWIFIEX_BUF_FLAG_TDLS_PKT
;
835 pkt_len
= skb
->len
- MWIFIEX_MGMT_FRAME_HEADER_SIZE
- sizeof(pkt_len
);
836 memcpy(skb
->data
+ MWIFIEX_MGMT_FRAME_HEADER_SIZE
, &pkt_len
,
838 __net_timestamp(skb
);
839 mwifiex_queue_tx_pkt(priv
, skb
);
844 /* This function process tdls action frame from peer.
845 * Peer capabilities are stored into station node structure.
847 void mwifiex_process_tdls_action_frame(struct mwifiex_private
*priv
,
850 struct mwifiex_sta_node
*sta_ptr
;
851 u8
*peer
, *pos
, *end
;
856 if (len
< (sizeof(struct ethhdr
) + 3))
858 if (*(buf
+ sizeof(struct ethhdr
)) != WLAN_TDLS_SNAP_RFTYPE
)
860 if (*(buf
+ sizeof(struct ethhdr
) + 1) != WLAN_CATEGORY_TDLS
)
863 peer
= buf
+ ETH_ALEN
;
864 action
= *(buf
+ sizeof(struct ethhdr
) + 2);
865 mwifiex_dbg(priv
->adapter
, DATA
,
866 "rx:tdls action: peer=%pM, action=%d\n", peer
, action
);
869 case WLAN_TDLS_SETUP_REQUEST
:
870 if (len
< (sizeof(struct ethhdr
) + TDLS_REQ_FIX_LEN
))
873 pos
= buf
+ sizeof(struct ethhdr
) + 4;
874 /* payload 1+ category 1 + action 1 + dialog 1 */
875 cap
= cpu_to_le16(*(u16
*)pos
);
876 ie_len
= len
- sizeof(struct ethhdr
) - TDLS_REQ_FIX_LEN
;
880 case WLAN_TDLS_SETUP_RESPONSE
:
881 if (len
< (sizeof(struct ethhdr
) + TDLS_RESP_FIX_LEN
))
883 /* payload 1+ category 1 + action 1 + dialog 1 + status code 2*/
884 pos
= buf
+ sizeof(struct ethhdr
) + 6;
885 cap
= cpu_to_le16(*(u16
*)pos
);
886 ie_len
= len
- sizeof(struct ethhdr
) - TDLS_RESP_FIX_LEN
;
890 case WLAN_TDLS_SETUP_CONFIRM
:
891 if (len
< (sizeof(struct ethhdr
) + TDLS_CONFIRM_FIX_LEN
))
893 pos
= buf
+ sizeof(struct ethhdr
) + TDLS_CONFIRM_FIX_LEN
;
894 ie_len
= len
- sizeof(struct ethhdr
) - TDLS_CONFIRM_FIX_LEN
;
897 mwifiex_dbg(priv
->adapter
, ERROR
, "Unknown TDLS frame type.\n");
901 sta_ptr
= mwifiex_add_sta_entry(priv
, peer
);
905 sta_ptr
->tdls_cap
.capab
= cap
;
907 for (end
= pos
+ ie_len
; pos
+ 1 < end
; pos
+= 2 + pos
[1]) {
908 if (pos
+ 2 + pos
[1] > end
)
912 case WLAN_EID_SUPP_RATES
:
913 sta_ptr
->tdls_cap
.rates_len
= pos
[1];
914 for (i
= 0; i
< pos
[1]; i
++)
915 sta_ptr
->tdls_cap
.rates
[i
] = pos
[i
+ 2];
918 case WLAN_EID_EXT_SUPP_RATES
:
919 basic
= sta_ptr
->tdls_cap
.rates_len
;
920 for (i
= 0; i
< pos
[1]; i
++)
921 sta_ptr
->tdls_cap
.rates
[basic
+ i
] = pos
[i
+ 2];
922 sta_ptr
->tdls_cap
.rates_len
+= pos
[1];
924 case WLAN_EID_HT_CAPABILITY
:
925 memcpy((u8
*)&sta_ptr
->tdls_cap
.ht_capb
, pos
,
926 sizeof(struct ieee80211_ht_cap
));
927 sta_ptr
->is_11n_enabled
= 1;
929 case WLAN_EID_HT_OPERATION
:
930 memcpy(&sta_ptr
->tdls_cap
.ht_oper
, pos
,
931 sizeof(struct ieee80211_ht_operation
));
933 case WLAN_EID_BSS_COEX_2040
:
934 sta_ptr
->tdls_cap
.coex_2040
= pos
[2];
936 case WLAN_EID_EXT_CAPABILITY
:
937 memcpy((u8
*)&sta_ptr
->tdls_cap
.extcap
, pos
,
938 sizeof(struct ieee_types_header
) +
939 min_t(u8
, pos
[1], 8));
942 memcpy((u8
*)&sta_ptr
->tdls_cap
.rsn_ie
, pos
,
943 sizeof(struct ieee_types_header
) +
944 min_t(u8
, pos
[1], IEEE_MAX_IE_SIZE
-
945 sizeof(struct ieee_types_header
)));
947 case WLAN_EID_QOS_CAPA
:
948 sta_ptr
->tdls_cap
.qos_info
= pos
[2];
950 case WLAN_EID_VHT_OPERATION
:
951 if (priv
->adapter
->is_hw_11ac_capable
)
952 memcpy(&sta_ptr
->tdls_cap
.vhtoper
, pos
,
953 sizeof(struct ieee80211_vht_operation
));
955 case WLAN_EID_VHT_CAPABILITY
:
956 if (priv
->adapter
->is_hw_11ac_capable
) {
957 memcpy((u8
*)&sta_ptr
->tdls_cap
.vhtcap
, pos
,
958 sizeof(struct ieee80211_vht_cap
));
959 sta_ptr
->is_11ac_enabled
= 1;
963 if (priv
->adapter
->is_hw_11ac_capable
)
964 sta_ptr
->tdls_cap
.aid
=
965 le16_to_cpu(*(__le16
*)(pos
+ 2));
975 mwifiex_tdls_process_config_link(struct mwifiex_private
*priv
, const u8
*peer
)
977 struct mwifiex_sta_node
*sta_ptr
;
978 struct mwifiex_ds_tdls_oper tdls_oper
;
980 memset(&tdls_oper
, 0, sizeof(struct mwifiex_ds_tdls_oper
));
981 sta_ptr
= mwifiex_get_sta_entry(priv
, peer
);
983 if (!sta_ptr
|| sta_ptr
->tdls_status
== TDLS_SETUP_FAILURE
) {
984 mwifiex_dbg(priv
->adapter
, ERROR
,
985 "link absent for peer %pM; cannot config\n", peer
);
989 memcpy(&tdls_oper
.peer_mac
, peer
, ETH_ALEN
);
990 tdls_oper
.tdls_action
= MWIFIEX_TDLS_CONFIG_LINK
;
991 return mwifiex_send_cmd(priv
, HostCmd_CMD_TDLS_OPER
,
992 HostCmd_ACT_GEN_SET
, 0, &tdls_oper
, true);
996 mwifiex_tdls_process_create_link(struct mwifiex_private
*priv
, const u8
*peer
)
998 struct mwifiex_sta_node
*sta_ptr
;
999 struct mwifiex_ds_tdls_oper tdls_oper
;
1001 memset(&tdls_oper
, 0, sizeof(struct mwifiex_ds_tdls_oper
));
1002 sta_ptr
= mwifiex_get_sta_entry(priv
, peer
);
1004 if (sta_ptr
&& sta_ptr
->tdls_status
== TDLS_SETUP_INPROGRESS
) {
1005 mwifiex_dbg(priv
->adapter
, WARN
,
1006 "Setup already in progress for peer %pM\n", peer
);
1010 sta_ptr
= mwifiex_add_sta_entry(priv
, peer
);
1014 sta_ptr
->tdls_status
= TDLS_SETUP_INPROGRESS
;
1015 mwifiex_hold_tdls_packets(priv
, peer
);
1016 memcpy(&tdls_oper
.peer_mac
, peer
, ETH_ALEN
);
1017 tdls_oper
.tdls_action
= MWIFIEX_TDLS_CREATE_LINK
;
1018 return mwifiex_send_cmd(priv
, HostCmd_CMD_TDLS_OPER
,
1019 HostCmd_ACT_GEN_SET
, 0, &tdls_oper
, true);
1023 mwifiex_tdls_process_disable_link(struct mwifiex_private
*priv
, const u8
*peer
)
1025 struct mwifiex_sta_node
*sta_ptr
;
1026 struct mwifiex_ds_tdls_oper tdls_oper
;
1027 unsigned long flags
;
1029 memset(&tdls_oper
, 0, sizeof(struct mwifiex_ds_tdls_oper
));
1030 sta_ptr
= mwifiex_get_sta_entry(priv
, peer
);
1033 if (sta_ptr
->is_11n_enabled
) {
1034 mwifiex_11n_cleanup_reorder_tbl(priv
);
1035 spin_lock_irqsave(&priv
->wmm
.ra_list_spinlock
,
1037 mwifiex_11n_delete_all_tx_ba_stream_tbl(priv
);
1038 spin_unlock_irqrestore(&priv
->wmm
.ra_list_spinlock
,
1041 mwifiex_del_sta_entry(priv
, peer
);
1044 mwifiex_restore_tdls_packets(priv
, peer
, TDLS_LINK_TEARDOWN
);
1045 mwifiex_auto_tdls_update_peer_status(priv
, peer
, TDLS_NOT_SETUP
);
1046 memcpy(&tdls_oper
.peer_mac
, peer
, ETH_ALEN
);
1047 tdls_oper
.tdls_action
= MWIFIEX_TDLS_DISABLE_LINK
;
1048 return mwifiex_send_cmd(priv
, HostCmd_CMD_TDLS_OPER
,
1049 HostCmd_ACT_GEN_SET
, 0, &tdls_oper
, true);
1053 mwifiex_tdls_process_enable_link(struct mwifiex_private
*priv
, const u8
*peer
)
1055 struct mwifiex_sta_node
*sta_ptr
;
1056 struct ieee80211_mcs_info mcs
;
1057 unsigned long flags
;
1060 sta_ptr
= mwifiex_get_sta_entry(priv
, peer
);
1062 if (sta_ptr
&& (sta_ptr
->tdls_status
!= TDLS_SETUP_FAILURE
)) {
1063 mwifiex_dbg(priv
->adapter
, MSG
,
1064 "tdls: enable link %pM success\n", peer
);
1066 sta_ptr
->tdls_status
= TDLS_SETUP_COMPLETE
;
1068 mcs
= sta_ptr
->tdls_cap
.ht_capb
.mcs
;
1069 if (mcs
.rx_mask
[0] != 0xff)
1070 sta_ptr
->is_11n_enabled
= true;
1071 if (sta_ptr
->is_11n_enabled
) {
1072 if (le16_to_cpu(sta_ptr
->tdls_cap
.ht_capb
.cap_info
) &
1073 IEEE80211_HT_CAP_MAX_AMSDU
)
1074 sta_ptr
->max_amsdu
=
1075 MWIFIEX_TX_DATA_BUF_SIZE_8K
;
1077 sta_ptr
->max_amsdu
=
1078 MWIFIEX_TX_DATA_BUF_SIZE_4K
;
1080 for (i
= 0; i
< MAX_NUM_TID
; i
++)
1081 sta_ptr
->ampdu_sta
[i
] =
1082 priv
->aggr_prio_tbl
[i
].ampdu_user
;
1084 for (i
= 0; i
< MAX_NUM_TID
; i
++)
1085 sta_ptr
->ampdu_sta
[i
] = BA_STREAM_NOT_ALLOWED
;
1087 if (sta_ptr
->tdls_cap
.extcap
.ext_capab
[3] &
1088 WLAN_EXT_CAPA4_TDLS_CHAN_SWITCH
) {
1089 mwifiex_config_tdls_enable(priv
);
1090 mwifiex_config_tdls_cs_params(priv
);
1093 memset(sta_ptr
->rx_seq
, 0xff, sizeof(sta_ptr
->rx_seq
));
1094 mwifiex_restore_tdls_packets(priv
, peer
, TDLS_SETUP_COMPLETE
);
1095 mwifiex_auto_tdls_update_peer_status(priv
, peer
,
1096 TDLS_SETUP_COMPLETE
);
1098 mwifiex_dbg(priv
->adapter
, ERROR
,
1099 "tdls: enable link %pM failed\n", peer
);
1101 mwifiex_11n_cleanup_reorder_tbl(priv
);
1102 spin_lock_irqsave(&priv
->wmm
.ra_list_spinlock
,
1104 mwifiex_11n_delete_all_tx_ba_stream_tbl(priv
);
1105 spin_unlock_irqrestore(&priv
->wmm
.ra_list_spinlock
,
1107 mwifiex_del_sta_entry(priv
, peer
);
1109 mwifiex_restore_tdls_packets(priv
, peer
, TDLS_LINK_TEARDOWN
);
1110 mwifiex_auto_tdls_update_peer_status(priv
, peer
,
1119 int mwifiex_tdls_oper(struct mwifiex_private
*priv
, const u8
*peer
, u8 action
)
1122 case MWIFIEX_TDLS_ENABLE_LINK
:
1123 return mwifiex_tdls_process_enable_link(priv
, peer
);
1124 case MWIFIEX_TDLS_DISABLE_LINK
:
1125 return mwifiex_tdls_process_disable_link(priv
, peer
);
1126 case MWIFIEX_TDLS_CREATE_LINK
:
1127 return mwifiex_tdls_process_create_link(priv
, peer
);
1128 case MWIFIEX_TDLS_CONFIG_LINK
:
1129 return mwifiex_tdls_process_config_link(priv
, peer
);
1134 int mwifiex_get_tdls_link_status(struct mwifiex_private
*priv
, const u8
*mac
)
1136 struct mwifiex_sta_node
*sta_ptr
;
1138 sta_ptr
= mwifiex_get_sta_entry(priv
, mac
);
1140 return sta_ptr
->tdls_status
;
1142 return TDLS_NOT_SETUP
;
1145 int mwifiex_get_tdls_list(struct mwifiex_private
*priv
,
1146 struct tdls_peer_info
*buf
)
1148 struct mwifiex_sta_node
*sta_ptr
;
1149 struct tdls_peer_info
*peer
= buf
;
1151 unsigned long flags
;
1153 if (!ISSUPP_TDLS_ENABLED(priv
->adapter
->fw_cap_info
))
1156 /* make sure we are in station mode and connected */
1157 if (!(priv
->bss_type
== MWIFIEX_BSS_TYPE_STA
&& priv
->media_connected
))
1160 spin_lock_irqsave(&priv
->sta_list_spinlock
, flags
);
1161 list_for_each_entry(sta_ptr
, &priv
->sta_list
, list
) {
1162 if (mwifiex_is_tdls_link_setup(sta_ptr
->tdls_status
)) {
1163 ether_addr_copy(peer
->peer_addr
, sta_ptr
->mac_addr
);
1166 if (count
>= MWIFIEX_MAX_TDLS_PEER_SUPPORTED
)
1170 spin_unlock_irqrestore(&priv
->sta_list_spinlock
, flags
);
1175 void mwifiex_disable_all_tdls_links(struct mwifiex_private
*priv
)
1177 struct mwifiex_sta_node
*sta_ptr
;
1178 struct mwifiex_ds_tdls_oper tdls_oper
;
1179 unsigned long flags
;
1181 if (list_empty(&priv
->sta_list
))
1184 list_for_each_entry(sta_ptr
, &priv
->sta_list
, list
) {
1185 memset(&tdls_oper
, 0, sizeof(struct mwifiex_ds_tdls_oper
));
1187 if (sta_ptr
->is_11n_enabled
) {
1188 mwifiex_11n_cleanup_reorder_tbl(priv
);
1189 spin_lock_irqsave(&priv
->wmm
.ra_list_spinlock
,
1191 mwifiex_11n_delete_all_tx_ba_stream_tbl(priv
);
1192 spin_unlock_irqrestore(&priv
->wmm
.ra_list_spinlock
,
1196 mwifiex_restore_tdls_packets(priv
, sta_ptr
->mac_addr
,
1197 TDLS_LINK_TEARDOWN
);
1198 memcpy(&tdls_oper
.peer_mac
, sta_ptr
->mac_addr
, ETH_ALEN
);
1199 tdls_oper
.tdls_action
= MWIFIEX_TDLS_DISABLE_LINK
;
1200 if (mwifiex_send_cmd(priv
, HostCmd_CMD_TDLS_OPER
,
1201 HostCmd_ACT_GEN_SET
, 0, &tdls_oper
, false))
1202 mwifiex_dbg(priv
->adapter
, ERROR
,
1203 "Disable link failed for TDLS peer %pM",
1207 mwifiex_del_all_sta_list(priv
);
1210 int mwifiex_tdls_check_tx(struct mwifiex_private
*priv
, struct sk_buff
*skb
)
1212 struct mwifiex_auto_tdls_peer
*peer
;
1213 unsigned long flags
;
1216 ether_addr_copy(mac
, skb
->data
);
1218 spin_lock_irqsave(&priv
->auto_tdls_lock
, flags
);
1219 list_for_each_entry(peer
, &priv
->auto_tdls_list
, list
) {
1220 if (!memcmp(mac
, peer
->mac_addr
, ETH_ALEN
)) {
1221 if (peer
->rssi
<= MWIFIEX_TDLS_RSSI_HIGH
&&
1222 peer
->tdls_status
== TDLS_NOT_SETUP
&&
1223 (peer
->failure_count
<
1224 MWIFIEX_TDLS_MAX_FAIL_COUNT
)) {
1225 peer
->tdls_status
= TDLS_SETUP_INPROGRESS
;
1226 mwifiex_dbg(priv
->adapter
, INFO
,
1227 "setup TDLS link, peer=%pM rssi=%d\n",
1228 peer
->mac_addr
, peer
->rssi
);
1230 cfg80211_tdls_oper_request(priv
->netdev
,
1234 peer
->do_setup
= false;
1235 priv
->check_tdls_tx
= false;
1236 } else if (peer
->failure_count
<
1237 MWIFIEX_TDLS_MAX_FAIL_COUNT
&&
1238 peer
->do_discover
) {
1239 mwifiex_send_tdls_data_frame(priv
,
1241 WLAN_TDLS_DISCOVERY_REQUEST
,
1243 peer
->do_discover
= false;
1247 spin_unlock_irqrestore(&priv
->auto_tdls_lock
, flags
);
1252 void mwifiex_flush_auto_tdls_list(struct mwifiex_private
*priv
)
1254 struct mwifiex_auto_tdls_peer
*peer
, *tmp_node
;
1255 unsigned long flags
;
1257 spin_lock_irqsave(&priv
->auto_tdls_lock
, flags
);
1258 list_for_each_entry_safe(peer
, tmp_node
, &priv
->auto_tdls_list
, list
) {
1259 list_del(&peer
->list
);
1263 INIT_LIST_HEAD(&priv
->auto_tdls_list
);
1264 spin_unlock_irqrestore(&priv
->auto_tdls_lock
, flags
);
1265 priv
->check_tdls_tx
= false;
1268 void mwifiex_add_auto_tdls_peer(struct mwifiex_private
*priv
, const u8
*mac
)
1270 struct mwifiex_auto_tdls_peer
*tdls_peer
;
1271 unsigned long flags
;
1273 if (!priv
->adapter
->auto_tdls
)
1276 spin_lock_irqsave(&priv
->auto_tdls_lock
, flags
);
1277 list_for_each_entry(tdls_peer
, &priv
->auto_tdls_list
, list
) {
1278 if (!memcmp(tdls_peer
->mac_addr
, mac
, ETH_ALEN
)) {
1279 tdls_peer
->tdls_status
= TDLS_SETUP_INPROGRESS
;
1280 tdls_peer
->rssi_jiffies
= jiffies
;
1281 spin_unlock_irqrestore(&priv
->auto_tdls_lock
, flags
);
1286 /* create new TDLS peer */
1287 tdls_peer
= kzalloc(sizeof(*tdls_peer
), GFP_ATOMIC
);
1289 ether_addr_copy(tdls_peer
->mac_addr
, mac
);
1290 tdls_peer
->tdls_status
= TDLS_SETUP_INPROGRESS
;
1291 tdls_peer
->rssi_jiffies
= jiffies
;
1292 INIT_LIST_HEAD(&tdls_peer
->list
);
1293 list_add_tail(&tdls_peer
->list
, &priv
->auto_tdls_list
);
1294 mwifiex_dbg(priv
->adapter
, INFO
,
1295 "Add auto TDLS peer= %pM to list\n", mac
);
1298 spin_unlock_irqrestore(&priv
->auto_tdls_lock
, flags
);
1301 void mwifiex_auto_tdls_update_peer_status(struct mwifiex_private
*priv
,
1302 const u8
*mac
, u8 link_status
)
1304 struct mwifiex_auto_tdls_peer
*peer
;
1305 unsigned long flags
;
1307 if (!priv
->adapter
->auto_tdls
)
1310 spin_lock_irqsave(&priv
->auto_tdls_lock
, flags
);
1311 list_for_each_entry(peer
, &priv
->auto_tdls_list
, list
) {
1312 if (!memcmp(peer
->mac_addr
, mac
, ETH_ALEN
)) {
1313 if ((link_status
== TDLS_NOT_SETUP
) &&
1314 (peer
->tdls_status
== TDLS_SETUP_INPROGRESS
))
1315 peer
->failure_count
++;
1316 else if (mwifiex_is_tdls_link_setup(link_status
))
1317 peer
->failure_count
= 0;
1319 peer
->tdls_status
= link_status
;
1323 spin_unlock_irqrestore(&priv
->auto_tdls_lock
, flags
);
1326 void mwifiex_auto_tdls_update_peer_signal(struct mwifiex_private
*priv
,
1327 u8
*mac
, s8 snr
, s8 nflr
)
1329 struct mwifiex_auto_tdls_peer
*peer
;
1330 unsigned long flags
;
1332 if (!priv
->adapter
->auto_tdls
)
1335 spin_lock_irqsave(&priv
->auto_tdls_lock
, flags
);
1336 list_for_each_entry(peer
, &priv
->auto_tdls_list
, list
) {
1337 if (!memcmp(peer
->mac_addr
, mac
, ETH_ALEN
)) {
1338 peer
->rssi
= nflr
- snr
;
1339 peer
->rssi_jiffies
= jiffies
;
1343 spin_unlock_irqrestore(&priv
->auto_tdls_lock
, flags
);
1346 void mwifiex_check_auto_tdls(unsigned long context
)
1348 struct mwifiex_private
*priv
= (struct mwifiex_private
*)context
;
1349 struct mwifiex_auto_tdls_peer
*tdls_peer
;
1350 unsigned long flags
;
1351 u16 reason
= WLAN_REASON_TDLS_TEARDOWN_UNSPECIFIED
;
1353 if (WARN_ON_ONCE(!priv
|| !priv
->adapter
)) {
1354 pr_err("mwifiex: %s: adapter or private structure is NULL\n",
1359 if (unlikely(!priv
->adapter
->auto_tdls
))
1362 if (!priv
->auto_tdls_timer_active
) {
1363 mwifiex_dbg(priv
->adapter
, INFO
,
1364 "auto TDLS timer inactive; return");
1368 priv
->check_tdls_tx
= false;
1370 if (list_empty(&priv
->auto_tdls_list
)) {
1371 mod_timer(&priv
->auto_tdls_timer
,
1373 msecs_to_jiffies(MWIFIEX_TIMER_10S
));
1377 spin_lock_irqsave(&priv
->auto_tdls_lock
, flags
);
1378 list_for_each_entry(tdls_peer
, &priv
->auto_tdls_list
, list
) {
1379 if ((jiffies
- tdls_peer
->rssi_jiffies
) >
1380 (MWIFIEX_AUTO_TDLS_IDLE_TIME
* HZ
)) {
1381 tdls_peer
->rssi
= 0;
1382 tdls_peer
->do_discover
= true;
1383 priv
->check_tdls_tx
= true;
1386 if (((tdls_peer
->rssi
>= MWIFIEX_TDLS_RSSI_LOW
) ||
1387 !tdls_peer
->rssi
) &&
1388 mwifiex_is_tdls_link_setup(tdls_peer
->tdls_status
)) {
1389 tdls_peer
->tdls_status
= TDLS_LINK_TEARDOWN
;
1390 mwifiex_dbg(priv
->adapter
, MSG
,
1391 "teardown TDLS link,peer=%pM rssi=%d\n",
1392 tdls_peer
->mac_addr
, -tdls_peer
->rssi
);
1393 tdls_peer
->do_discover
= true;
1394 priv
->check_tdls_tx
= true;
1395 cfg80211_tdls_oper_request(priv
->netdev
,
1396 tdls_peer
->mac_addr
,
1397 NL80211_TDLS_TEARDOWN
,
1398 reason
, GFP_ATOMIC
);
1399 } else if (tdls_peer
->rssi
&&
1400 tdls_peer
->rssi
<= MWIFIEX_TDLS_RSSI_HIGH
&&
1401 tdls_peer
->tdls_status
== TDLS_NOT_SETUP
&&
1402 tdls_peer
->failure_count
<
1403 MWIFIEX_TDLS_MAX_FAIL_COUNT
) {
1404 priv
->check_tdls_tx
= true;
1405 tdls_peer
->do_setup
= true;
1406 mwifiex_dbg(priv
->adapter
, INFO
,
1407 "check TDLS with peer=%pM\t"
1408 "rssi=%d\n", tdls_peer
->mac_addr
,
1412 spin_unlock_irqrestore(&priv
->auto_tdls_lock
, flags
);
1414 mod_timer(&priv
->auto_tdls_timer
,
1415 jiffies
+ msecs_to_jiffies(MWIFIEX_TIMER_10S
));
1418 void mwifiex_setup_auto_tdls_timer(struct mwifiex_private
*priv
)
1420 setup_timer(&priv
->auto_tdls_timer
, mwifiex_check_auto_tdls
,
1421 (unsigned long)priv
);
1422 priv
->auto_tdls_timer_active
= true;
1423 mod_timer(&priv
->auto_tdls_timer
,
1424 jiffies
+ msecs_to_jiffies(MWIFIEX_TIMER_10S
));
1427 void mwifiex_clean_auto_tdls(struct mwifiex_private
*priv
)
1429 if (ISSUPP_TDLS_ENABLED(priv
->adapter
->fw_cap_info
) &&
1430 priv
->adapter
->auto_tdls
&&
1431 priv
->bss_type
== MWIFIEX_BSS_TYPE_STA
) {
1432 priv
->auto_tdls_timer_active
= false;
1433 del_timer(&priv
->auto_tdls_timer
);
1434 mwifiex_flush_auto_tdls_list(priv
);
1438 static int mwifiex_config_tdls(struct mwifiex_private
*priv
, u8 enable
)
1440 struct mwifiex_tdls_config config
;
1442 config
.enable
= cpu_to_le16(enable
);
1443 return mwifiex_send_cmd(priv
, HostCmd_CMD_TDLS_CONFIG
,
1444 ACT_TDLS_CS_ENABLE_CONFIG
, 0, &config
, true);
1447 int mwifiex_config_tdls_enable(struct mwifiex_private
*priv
)
1449 return mwifiex_config_tdls(priv
, true);
1452 int mwifiex_config_tdls_disable(struct mwifiex_private
*priv
)
1454 return mwifiex_config_tdls(priv
, false);
1457 int mwifiex_config_tdls_cs_params(struct mwifiex_private
*priv
)
1459 struct mwifiex_tdls_config_cs_params config_tdls_cs_params
;
1461 config_tdls_cs_params
.unit_time
= MWIFIEX_DEF_CS_UNIT_TIME
;
1462 config_tdls_cs_params
.thr_otherlink
= MWIFIEX_DEF_CS_THR_OTHERLINK
;
1463 config_tdls_cs_params
.thr_directlink
= MWIFIEX_DEF_THR_DIRECTLINK
;
1465 return mwifiex_send_cmd(priv
, HostCmd_CMD_TDLS_CONFIG
,
1466 ACT_TDLS_CS_PARAMS
, 0,
1467 &config_tdls_cs_params
, true);
1470 int mwifiex_stop_tdls_cs(struct mwifiex_private
*priv
, const u8
*peer_mac
)
1472 struct mwifiex_tdls_stop_cs_params stop_tdls_cs_params
;
1474 ether_addr_copy(stop_tdls_cs_params
.peer_mac
, peer_mac
);
1476 return mwifiex_send_cmd(priv
, HostCmd_CMD_TDLS_CONFIG
,
1477 ACT_TDLS_CS_STOP
, 0,
1478 &stop_tdls_cs_params
, true);
1481 int mwifiex_start_tdls_cs(struct mwifiex_private
*priv
, const u8
*peer_mac
,
1482 u8 primary_chan
, u8 second_chan_offset
, u8 band
)
1484 struct mwifiex_tdls_init_cs_params start_tdls_cs_params
;
1486 ether_addr_copy(start_tdls_cs_params
.peer_mac
, peer_mac
);
1487 start_tdls_cs_params
.primary_chan
= primary_chan
;
1488 start_tdls_cs_params
.second_chan_offset
= second_chan_offset
;
1489 start_tdls_cs_params
.band
= band
;
1491 start_tdls_cs_params
.switch_time
= cpu_to_le16(MWIFIEX_DEF_CS_TIME
);
1492 start_tdls_cs_params
.switch_timeout
=
1493 cpu_to_le16(MWIFIEX_DEF_CS_TIMEOUT
);
1494 start_tdls_cs_params
.reg_class
= MWIFIEX_DEF_CS_REG_CLASS
;
1495 start_tdls_cs_params
.periodicity
= MWIFIEX_DEF_CS_PERIODICITY
;
1497 return mwifiex_send_cmd(priv
, HostCmd_CMD_TDLS_CONFIG
,
1498 ACT_TDLS_CS_INIT
, 0,
1499 &start_tdls_cs_params
, true);