1563 lines · c
1/*2 * NXP Wireless LAN device driver: TDLS handling3 *4 * Copyright 2011-2020 NXP5 *6 * This software file (the "File") is distributed by NXP7 * under the terms of the GNU General Public License Version 2, June 19918 * (the "License"). You may use, redistribute and/or modify this File in9 * accordance with the terms and conditions of the License, a copy of which10 * is available on the worldwide web at11 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.12 *13 * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE14 * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE15 * ARE EXPRESSLY DISCLAIMED. The License provides additional details about16 * this warranty disclaimer.17 */18 19#include "main.h"20#include "wmm.h"21#include "11n.h"22#include "11n_rxreorder.h"23#include "11ac.h"24 25#define TDLS_REQ_FIX_LEN 626#define TDLS_RESP_FIX_LEN 827#define TDLS_CONFIRM_FIX_LEN 628#define MWIFIEX_TDLS_WMM_INFO_SIZE 729 30static void mwifiex_restore_tdls_packets(struct mwifiex_private *priv,31 const u8 *mac, u8 status)32{33 struct mwifiex_ra_list_tbl *ra_list;34 struct list_head *tid_list;35 struct sk_buff *skb, *tmp;36 struct mwifiex_txinfo *tx_info;37 u32 tid;38 u8 tid_down;39 40 mwifiex_dbg(priv->adapter, DATA, "%s: %pM\n", __func__, mac);41 spin_lock_bh(&priv->wmm.ra_list_spinlock);42 43 skb_queue_walk_safe(&priv->tdls_txq, skb, tmp) {44 if (!ether_addr_equal(mac, skb->data))45 continue;46 47 __skb_unlink(skb, &priv->tdls_txq);48 tx_info = MWIFIEX_SKB_TXCB(skb);49 tid = skb->priority;50 tid_down = mwifiex_wmm_downgrade_tid(priv, tid);51 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;56 } else {57 tid_list = &priv->wmm.tid_tbl_ptr[tid_down].ra_list;58 ra_list = list_first_entry_or_null(tid_list,59 struct mwifiex_ra_list_tbl, list);60 tx_info->flags &= ~MWIFIEX_BUF_FLAG_TDLS_PKT;61 }62 63 if (!ra_list) {64 mwifiex_write_data_complete(priv->adapter, skb, 0, -1);65 continue;66 }67 68 skb_queue_tail(&ra_list->skb_head, skb);69 70 ra_list->ba_pkt_count++;71 ra_list->total_pkt_count++;72 73 if (atomic_read(&priv->wmm.highest_queued_prio) <74 tos_to_tid_inv[tid_down])75 atomic_set(&priv->wmm.highest_queued_prio,76 tos_to_tid_inv[tid_down]);77 78 atomic_inc(&priv->wmm.tx_pkts_queued);79 }80 81 spin_unlock_bh(&priv->wmm.ra_list_spinlock);82 return;83}84 85static void mwifiex_hold_tdls_packets(struct mwifiex_private *priv,86 const u8 *mac)87{88 struct mwifiex_ra_list_tbl *ra_list;89 struct list_head *ra_list_head;90 struct sk_buff *skb, *tmp;91 int i;92 93 mwifiex_dbg(priv->adapter, DATA, "%s: %pM\n", __func__, mac);94 spin_lock_bh(&priv->wmm.ra_list_spinlock);95 96 for (i = 0; i < MAX_NUM_TID; i++) {97 if (!list_empty(&priv->wmm.tid_tbl_ptr[i].ra_list)) {98 ra_list_head = &priv->wmm.tid_tbl_ptr[i].ra_list;99 list_for_each_entry(ra_list, ra_list_head, list) {100 skb_queue_walk_safe(&ra_list->skb_head, skb,101 tmp) {102 if (!ether_addr_equal(mac, skb->data))103 continue;104 __skb_unlink(skb, &ra_list->skb_head);105 atomic_dec(&priv->wmm.tx_pkts_queued);106 ra_list->total_pkt_count--;107 skb_queue_tail(&priv->tdls_txq, skb);108 }109 }110 }111 }112 113 spin_unlock_bh(&priv->wmm.ra_list_spinlock);114 return;115}116 117/* This function appends rate TLV to scan config command. */118static int119mwifiex_tdls_append_rates_ie(struct mwifiex_private *priv,120 struct sk_buff *skb)121{122 u8 rates[MWIFIEX_SUPPORTED_RATES], *pos;123 u16 rates_size, supp_rates_size, ext_rates_size;124 125 memset(rates, 0, sizeof(rates));126 rates_size = mwifiex_get_supported_rates(priv, rates);127 128 supp_rates_size = min_t(u16, rates_size, MWIFIEX_TDLS_SUPPORTED_RATES);129 130 if (skb_tailroom(skb) < rates_size + 4) {131 mwifiex_dbg(priv->adapter, ERROR,132 "Insufficient space while adding rates\n");133 return -ENOMEM;134 }135 136 pos = skb_put(skb, supp_rates_size + 2);137 *pos++ = WLAN_EID_SUPP_RATES;138 *pos++ = supp_rates_size;139 memcpy(pos, rates, supp_rates_size);140 141 if (rates_size > MWIFIEX_TDLS_SUPPORTED_RATES) {142 ext_rates_size = rates_size - MWIFIEX_TDLS_SUPPORTED_RATES;143 pos = skb_put(skb, ext_rates_size + 2);144 *pos++ = WLAN_EID_EXT_SUPP_RATES;145 *pos++ = ext_rates_size;146 memcpy(pos, rates + MWIFIEX_TDLS_SUPPORTED_RATES,147 ext_rates_size);148 }149 150 return 0;151}152 153static void mwifiex_tdls_add_aid(struct mwifiex_private *priv,154 struct sk_buff *skb)155{156 struct ieee_types_assoc_rsp *assoc_rsp;157 u8 *pos;158 159 assoc_rsp = (struct ieee_types_assoc_rsp *)&priv->assoc_rsp_buf;160 pos = skb_put(skb, 4);161 *pos++ = WLAN_EID_AID;162 *pos++ = 2;163 memcpy(pos, &assoc_rsp->a_id, sizeof(assoc_rsp->a_id));164 165 return;166}167 168static int mwifiex_tdls_add_vht_capab(struct mwifiex_private *priv,169 struct sk_buff *skb)170{171 struct ieee80211_vht_cap vht_cap;172 u8 *pos;173 174 pos = skb_put(skb, sizeof(struct ieee80211_vht_cap) + 2);175 *pos++ = WLAN_EID_VHT_CAPABILITY;176 *pos++ = sizeof(struct ieee80211_vht_cap);177 178 memset(&vht_cap, 0, sizeof(struct ieee80211_vht_cap));179 180 mwifiex_fill_vht_cap_tlv(priv, &vht_cap, priv->curr_bss_params.band);181 memcpy(pos, &vht_cap, sizeof(vht_cap));182 183 return 0;184}185 186static int187mwifiex_tdls_add_ht_oper(struct mwifiex_private *priv, const u8 *mac,188 u8 vht_enabled, struct sk_buff *skb)189{190 struct ieee80211_ht_operation *ht_oper;191 struct mwifiex_sta_node *sta_ptr;192 struct mwifiex_bssdescriptor *bss_desc =193 &priv->curr_bss_params.bss_descriptor;194 u8 *pos;195 196 sta_ptr = mwifiex_get_sta_entry(priv, mac);197 if (unlikely(!sta_ptr)) {198 mwifiex_dbg(priv->adapter, ERROR,199 "TDLS peer station not found in list\n");200 return -1;201 }202 203 if (!(le16_to_cpu(sta_ptr->tdls_cap.ht_capb.cap_info))) {204 mwifiex_dbg(priv->adapter, WARN,205 "TDLS peer doesn't support ht capabilities\n");206 return 0;207 }208 209 pos = skb_put(skb, sizeof(struct ieee80211_ht_operation) + 2);210 *pos++ = WLAN_EID_HT_OPERATION;211 *pos++ = sizeof(struct ieee80211_ht_operation);212 ht_oper = (void *)pos;213 214 ht_oper->primary_chan = bss_desc->channel;215 216 /* follow AP's channel bandwidth */217 if (ISSUPP_CHANWIDTH40(priv->adapter->hw_dot_11n_dev_cap) &&218 bss_desc->bcn_ht_cap &&219 ISALLOWED_CHANWIDTH40(bss_desc->bcn_ht_oper->ht_param))220 ht_oper->ht_param = bss_desc->bcn_ht_oper->ht_param;221 222 if (vht_enabled) {223 ht_oper->ht_param =224 mwifiex_get_sec_chan_offset(bss_desc->channel);225 ht_oper->ht_param |= BIT(2);226 }227 228 memcpy(&sta_ptr->tdls_cap.ht_oper, ht_oper,229 sizeof(struct ieee80211_ht_operation));230 231 return 0;232}233 234static int mwifiex_tdls_add_vht_oper(struct mwifiex_private *priv,235 const u8 *mac, struct sk_buff *skb)236{237 struct mwifiex_bssdescriptor *bss_desc;238 struct ieee80211_vht_operation *vht_oper;239 struct ieee80211_vht_cap *vht_cap, *ap_vht_cap = NULL;240 struct mwifiex_sta_node *sta_ptr;241 struct mwifiex_adapter *adapter = priv->adapter;242 u8 supp_chwd_set, peer_supp_chwd_set;243 u8 *pos, ap_supp_chwd_set, chan_bw;244 u16 mcs_map_user, mcs_map_resp, mcs_map_result;245 u16 mcs_user, mcs_resp, nss;246 u32 usr_vht_cap_info;247 248 bss_desc = &priv->curr_bss_params.bss_descriptor;249 250 sta_ptr = mwifiex_get_sta_entry(priv, mac);251 if (unlikely(!sta_ptr)) {252 mwifiex_dbg(adapter, ERROR,253 "TDLS peer station not found in list\n");254 return -1;255 }256 257 if (!(le32_to_cpu(sta_ptr->tdls_cap.vhtcap.vht_cap_info))) {258 mwifiex_dbg(adapter, WARN,259 "TDLS peer doesn't support vht capabilities\n");260 return 0;261 }262 263 if (!mwifiex_is_bss_in_11ac_mode(priv)) {264 if (sta_ptr->tdls_cap.extcap.ext_capab[7] &265 WLAN_EXT_CAPA8_TDLS_WIDE_BW_ENABLED) {266 mwifiex_dbg(adapter, WARN,267 "TDLS peer doesn't support wider bandwidth\n");268 return 0;269 }270 } else {271 ap_vht_cap = bss_desc->bcn_vht_cap;272 }273 274 pos = skb_put(skb, sizeof(struct ieee80211_vht_operation) + 2);275 *pos++ = WLAN_EID_VHT_OPERATION;276 *pos++ = sizeof(struct ieee80211_vht_operation);277 vht_oper = (struct ieee80211_vht_operation *)pos;278 279 if (bss_desc->bss_band & BAND_A)280 usr_vht_cap_info = adapter->usr_dot_11ac_dev_cap_a;281 else282 usr_vht_cap_info = adapter->usr_dot_11ac_dev_cap_bg;283 284 /* find the minimum bandwidth between AP/TDLS peers */285 vht_cap = &sta_ptr->tdls_cap.vhtcap;286 supp_chwd_set = GET_VHTCAP_CHWDSET(usr_vht_cap_info);287 peer_supp_chwd_set =288 GET_VHTCAP_CHWDSET(le32_to_cpu(vht_cap->vht_cap_info));289 supp_chwd_set = min_t(u8, supp_chwd_set, peer_supp_chwd_set);290 291 /* We need check AP's bandwidth when TDLS_WIDER_BANDWIDTH is off */292 293 if (ap_vht_cap && sta_ptr->tdls_cap.extcap.ext_capab[7] &294 WLAN_EXT_CAPA8_TDLS_WIDE_BW_ENABLED) {295 ap_supp_chwd_set =296 GET_VHTCAP_CHWDSET(le32_to_cpu(ap_vht_cap->vht_cap_info));297 supp_chwd_set = min_t(u8, supp_chwd_set, ap_supp_chwd_set);298 }299 300 switch (supp_chwd_set) {301 case IEEE80211_VHT_CHANWIDTH_80MHZ:302 vht_oper->chan_width = IEEE80211_VHT_CHANWIDTH_80MHZ;303 break;304 case IEEE80211_VHT_CHANWIDTH_160MHZ:305 vht_oper->chan_width = IEEE80211_VHT_CHANWIDTH_160MHZ;306 break;307 case IEEE80211_VHT_CHANWIDTH_80P80MHZ:308 vht_oper->chan_width = IEEE80211_VHT_CHANWIDTH_80P80MHZ;309 break;310 default:311 vht_oper->chan_width = IEEE80211_VHT_CHANWIDTH_USE_HT;312 break;313 }314 315 mcs_map_user = GET_DEVRXMCSMAP(adapter->usr_dot_11ac_mcs_support);316 mcs_map_resp = le16_to_cpu(vht_cap->supp_mcs.rx_mcs_map);317 mcs_map_result = 0;318 319 for (nss = 1; nss <= 8; nss++) {320 mcs_user = GET_VHTNSSMCS(mcs_map_user, nss);321 mcs_resp = GET_VHTNSSMCS(mcs_map_resp, nss);322 323 if ((mcs_user == IEEE80211_VHT_MCS_NOT_SUPPORTED) ||324 (mcs_resp == IEEE80211_VHT_MCS_NOT_SUPPORTED))325 SET_VHTNSSMCS(mcs_map_result, nss,326 IEEE80211_VHT_MCS_NOT_SUPPORTED);327 else328 SET_VHTNSSMCS(mcs_map_result, nss,329 min_t(u16, mcs_user, mcs_resp));330 }331 332 vht_oper->basic_mcs_set = cpu_to_le16(mcs_map_result);333 334 switch (vht_oper->chan_width) {335 case IEEE80211_VHT_CHANWIDTH_80MHZ:336 chan_bw = IEEE80211_VHT_CHANWIDTH_80MHZ;337 break;338 case IEEE80211_VHT_CHANWIDTH_160MHZ:339 chan_bw = IEEE80211_VHT_CHANWIDTH_160MHZ;340 break;341 case IEEE80211_VHT_CHANWIDTH_80P80MHZ:342 chan_bw = IEEE80211_VHT_CHANWIDTH_80MHZ;343 break;344 default:345 chan_bw = IEEE80211_VHT_CHANWIDTH_USE_HT;346 break;347 }348 vht_oper->center_freq_seg0_idx =349 mwifiex_get_center_freq_index(priv, BAND_AAC,350 bss_desc->channel,351 chan_bw);352 353 return 0;354}355 356static void mwifiex_tdls_add_ext_capab(struct mwifiex_private *priv,357 struct sk_buff *skb)358{359 struct ieee_types_extcap *extcap;360 361 extcap = skb_put(skb, sizeof(struct ieee_types_extcap));362 extcap->ieee_hdr.element_id = WLAN_EID_EXT_CAPABILITY;363 extcap->ieee_hdr.len = 8;364 memset(extcap->ext_capab, 0, 8);365 extcap->ext_capab[4] |= WLAN_EXT_CAPA5_TDLS_ENABLED;366 extcap->ext_capab[3] |= WLAN_EXT_CAPA4_TDLS_CHAN_SWITCH;367 368 if (priv->adapter->is_hw_11ac_capable)369 extcap->ext_capab[7] |= WLAN_EXT_CAPA8_TDLS_WIDE_BW_ENABLED;370}371 372static void mwifiex_tdls_add_qos_capab(struct sk_buff *skb)373{374 u8 *pos = skb_put(skb, 3);375 376 *pos++ = WLAN_EID_QOS_CAPA;377 *pos++ = 1;378 *pos++ = MWIFIEX_TDLS_DEF_QOS_CAPAB;379}380 381static void382mwifiex_tdls_add_wmm_param_ie(struct mwifiex_private *priv, struct sk_buff *skb)383{384 struct ieee80211_wmm_param_ie *wmm;385 u8 ac_vi[] = {0x42, 0x43, 0x5e, 0x00};386 u8 ac_vo[] = {0x62, 0x32, 0x2f, 0x00};387 u8 ac_be[] = {0x03, 0xa4, 0x00, 0x00};388 u8 ac_bk[] = {0x27, 0xa4, 0x00, 0x00};389 390 wmm = skb_put_zero(skb, sizeof(*wmm));391 392 wmm->element_id = WLAN_EID_VENDOR_SPECIFIC;393 wmm->len = sizeof(*wmm) - 2;394 wmm->oui[0] = 0x00; /* Microsoft OUI 00:50:F2 */395 wmm->oui[1] = 0x50;396 wmm->oui[2] = 0xf2;397 wmm->oui_type = 2; /* WME */398 wmm->oui_subtype = 1; /* WME param */399 wmm->version = 1; /* WME ver */400 wmm->qos_info = 0; /* U-APSD not in use */401 402 /* use default WMM AC parameters for TDLS link*/403 memcpy(&wmm->ac[0], ac_be, sizeof(ac_be));404 memcpy(&wmm->ac[1], ac_bk, sizeof(ac_bk));405 memcpy(&wmm->ac[2], ac_vi, sizeof(ac_vi));406 memcpy(&wmm->ac[3], ac_vo, sizeof(ac_vo));407}408 409static void410mwifiex_add_wmm_info_ie(struct mwifiex_private *priv, struct sk_buff *skb,411 u8 qosinfo)412{413 u8 *buf;414 415 buf = skb_put(skb,416 MWIFIEX_TDLS_WMM_INFO_SIZE + sizeof(struct ieee_types_header));417 418 *buf++ = WLAN_EID_VENDOR_SPECIFIC;419 *buf++ = 7; /* len */420 *buf++ = 0x00; /* Microsoft OUI 00:50:F2 */421 *buf++ = 0x50;422 *buf++ = 0xf2;423 *buf++ = 2; /* WME */424 *buf++ = 0; /* WME info */425 *buf++ = 1; /* WME ver */426 *buf++ = qosinfo; /* U-APSD no in use */427}428 429static void mwifiex_tdls_add_bss_co_2040(struct sk_buff *skb)430{431 struct ieee_types_bss_co_2040 *bssco;432 433 bssco = skb_put(skb, sizeof(struct ieee_types_bss_co_2040));434 bssco->ieee_hdr.element_id = WLAN_EID_BSS_COEX_2040;435 bssco->ieee_hdr.len = sizeof(struct ieee_types_bss_co_2040) -436 sizeof(struct ieee_types_header);437 bssco->bss_2040co = 0x01;438}439 440static void mwifiex_tdls_add_supported_chan(struct sk_buff *skb)441{442 struct ieee_types_generic *supp_chan;443 u8 chan_supp[] = {1, 11};444 445 supp_chan = skb_put(skb,446 (sizeof(struct ieee_types_header) + sizeof(chan_supp)));447 supp_chan->ieee_hdr.element_id = WLAN_EID_SUPPORTED_CHANNELS;448 supp_chan->ieee_hdr.len = sizeof(chan_supp);449 memcpy(supp_chan->data, chan_supp, sizeof(chan_supp));450}451 452static void mwifiex_tdls_add_oper_class(struct sk_buff *skb)453{454 struct ieee_types_generic *reg_class;455 u8 rc_list[] = {1,456 1, 2, 3, 4, 12, 22, 23, 24, 25, 27, 28, 29, 30, 32, 33};457 reg_class = skb_put(skb,458 (sizeof(struct ieee_types_header) + sizeof(rc_list)));459 reg_class->ieee_hdr.element_id = WLAN_EID_SUPPORTED_REGULATORY_CLASSES;460 reg_class->ieee_hdr.len = sizeof(rc_list);461 memcpy(reg_class->data, rc_list, sizeof(rc_list));462}463 464static int mwifiex_prep_tdls_encap_data(struct mwifiex_private *priv,465 const u8 *peer, u8 action_code,466 u8 dialog_token,467 u16 status_code, struct sk_buff *skb)468{469 struct ieee80211_tdls_data *tf;470 int ret;471 u16 capab;472 struct ieee80211_ht_cap *ht_cap;473 u8 radio, *pos;474 475 capab = priv->curr_bss_params.bss_descriptor.cap_info_bitmap;476 477 tf = skb_put(skb, offsetof(struct ieee80211_tdls_data, u));478 memcpy(tf->da, peer, ETH_ALEN);479 memcpy(tf->sa, priv->curr_addr, ETH_ALEN);480 tf->ether_type = cpu_to_be16(ETH_P_TDLS);481 tf->payload_type = WLAN_TDLS_SNAP_RFTYPE;482 483 switch (action_code) {484 case WLAN_TDLS_SETUP_REQUEST:485 tf->category = WLAN_CATEGORY_TDLS;486 tf->action_code = WLAN_TDLS_SETUP_REQUEST;487 skb_put(skb, sizeof(tf->u.setup_req));488 tf->u.setup_req.dialog_token = dialog_token;489 tf->u.setup_req.capability = cpu_to_le16(capab);490 ret = mwifiex_tdls_append_rates_ie(priv, skb);491 if (ret) {492 dev_kfree_skb_any(skb);493 return ret;494 }495 496 pos = skb_put(skb, sizeof(struct ieee80211_ht_cap) + 2);497 *pos++ = WLAN_EID_HT_CAPABILITY;498 *pos++ = sizeof(struct ieee80211_ht_cap);499 ht_cap = (void *)pos;500 radio = mwifiex_band_to_radio_type(priv->curr_bss_params.band);501 ret = mwifiex_fill_cap_info(priv, radio, ht_cap);502 if (ret) {503 dev_kfree_skb_any(skb);504 return ret;505 }506 507 if (priv->adapter->is_hw_11ac_capable) {508 ret = mwifiex_tdls_add_vht_capab(priv, skb);509 if (ret) {510 dev_kfree_skb_any(skb);511 return ret;512 }513 mwifiex_tdls_add_aid(priv, skb);514 }515 516 mwifiex_tdls_add_ext_capab(priv, skb);517 mwifiex_tdls_add_bss_co_2040(skb);518 mwifiex_tdls_add_supported_chan(skb);519 mwifiex_tdls_add_oper_class(skb);520 mwifiex_add_wmm_info_ie(priv, skb, 0);521 break;522 523 case WLAN_TDLS_SETUP_RESPONSE:524 tf->category = WLAN_CATEGORY_TDLS;525 tf->action_code = WLAN_TDLS_SETUP_RESPONSE;526 skb_put(skb, sizeof(tf->u.setup_resp));527 tf->u.setup_resp.status_code = cpu_to_le16(status_code);528 tf->u.setup_resp.dialog_token = dialog_token;529 tf->u.setup_resp.capability = cpu_to_le16(capab);530 ret = mwifiex_tdls_append_rates_ie(priv, skb);531 if (ret) {532 dev_kfree_skb_any(skb);533 return ret;534 }535 536 pos = skb_put(skb, sizeof(struct ieee80211_ht_cap) + 2);537 *pos++ = WLAN_EID_HT_CAPABILITY;538 *pos++ = sizeof(struct ieee80211_ht_cap);539 ht_cap = (void *)pos;540 radio = mwifiex_band_to_radio_type(priv->curr_bss_params.band);541 ret = mwifiex_fill_cap_info(priv, radio, ht_cap);542 if (ret) {543 dev_kfree_skb_any(skb);544 return ret;545 }546 547 if (priv->adapter->is_hw_11ac_capable) {548 ret = mwifiex_tdls_add_vht_capab(priv, skb);549 if (ret) {550 dev_kfree_skb_any(skb);551 return ret;552 }553 mwifiex_tdls_add_aid(priv, skb);554 }555 556 mwifiex_tdls_add_ext_capab(priv, skb);557 mwifiex_tdls_add_bss_co_2040(skb);558 mwifiex_tdls_add_supported_chan(skb);559 mwifiex_tdls_add_oper_class(skb);560 mwifiex_add_wmm_info_ie(priv, skb, 0);561 break;562 563 case WLAN_TDLS_SETUP_CONFIRM:564 tf->category = WLAN_CATEGORY_TDLS;565 tf->action_code = WLAN_TDLS_SETUP_CONFIRM;566 skb_put(skb, sizeof(tf->u.setup_cfm));567 tf->u.setup_cfm.status_code = cpu_to_le16(status_code);568 tf->u.setup_cfm.dialog_token = dialog_token;569 570 mwifiex_tdls_add_wmm_param_ie(priv, skb);571 if (priv->adapter->is_hw_11ac_capable) {572 ret = mwifiex_tdls_add_vht_oper(priv, peer, skb);573 if (ret) {574 dev_kfree_skb_any(skb);575 return ret;576 }577 ret = mwifiex_tdls_add_ht_oper(priv, peer, 1, skb);578 if (ret) {579 dev_kfree_skb_any(skb);580 return ret;581 }582 } else {583 ret = mwifiex_tdls_add_ht_oper(priv, peer, 0, skb);584 if (ret) {585 dev_kfree_skb_any(skb);586 return ret;587 }588 }589 break;590 591 case WLAN_TDLS_TEARDOWN:592 tf->category = WLAN_CATEGORY_TDLS;593 tf->action_code = WLAN_TDLS_TEARDOWN;594 skb_put(skb, sizeof(tf->u.teardown));595 tf->u.teardown.reason_code = cpu_to_le16(status_code);596 break;597 598 case WLAN_TDLS_DISCOVERY_REQUEST:599 tf->category = WLAN_CATEGORY_TDLS;600 tf->action_code = WLAN_TDLS_DISCOVERY_REQUEST;601 skb_put(skb, sizeof(tf->u.discover_req));602 tf->u.discover_req.dialog_token = dialog_token;603 break;604 default:605 mwifiex_dbg(priv->adapter, ERROR, "Unknown TDLS frame type.\n");606 return -EINVAL;607 }608 609 return 0;610}611 612static void613mwifiex_tdls_add_link_ie(struct sk_buff *skb, const u8 *src_addr,614 const u8 *peer, const u8 *bssid)615{616 struct ieee80211_tdls_lnkie *lnkid;617 618 lnkid = skb_put(skb, sizeof(struct ieee80211_tdls_lnkie));619 lnkid->ie_type = WLAN_EID_LINK_ID;620 lnkid->ie_len = sizeof(struct ieee80211_tdls_lnkie) -621 sizeof(struct ieee_types_header);622 623 memcpy(lnkid->bssid, bssid, ETH_ALEN);624 memcpy(lnkid->init_sta, src_addr, ETH_ALEN);625 memcpy(lnkid->resp_sta, peer, ETH_ALEN);626}627 628int mwifiex_send_tdls_data_frame(struct mwifiex_private *priv, const u8 *peer,629 u8 action_code, u8 dialog_token,630 u16 status_code, const u8 *extra_ies,631 size_t extra_ies_len)632{633 struct sk_buff *skb;634 struct mwifiex_txinfo *tx_info;635 int ret;636 u16 skb_len;637 638 skb_len = MWIFIEX_MIN_DATA_HEADER_LEN +639 max(sizeof(struct ieee80211_mgmt),640 sizeof(struct ieee80211_tdls_data)) +641 MWIFIEX_MGMT_FRAME_HEADER_SIZE +642 MWIFIEX_SUPPORTED_RATES +643 3 + /* Qos Info */644 sizeof(struct ieee_types_extcap) +645 sizeof(struct ieee80211_ht_cap) +646 sizeof(struct ieee_types_bss_co_2040) +647 sizeof(struct ieee80211_ht_operation) +648 sizeof(struct ieee80211_tdls_lnkie) +649 (2 * (sizeof(struct ieee_types_header))) +650 MWIFIEX_SUPPORTED_CHANNELS +651 MWIFIEX_OPERATING_CLASSES +652 sizeof(struct ieee80211_wmm_param_ie) +653 extra_ies_len;654 655 if (priv->adapter->is_hw_11ac_capable)656 skb_len += sizeof(struct ieee_types_vht_cap) +657 sizeof(struct ieee_types_vht_oper) +658 sizeof(struct ieee_types_aid);659 660 skb = dev_alloc_skb(skb_len);661 if (!skb) {662 mwifiex_dbg(priv->adapter, ERROR,663 "allocate skb failed for management frame\n");664 return -ENOMEM;665 }666 skb_reserve(skb, MWIFIEX_MIN_DATA_HEADER_LEN);667 668 switch (action_code) {669 case WLAN_TDLS_SETUP_REQUEST:670 case WLAN_TDLS_SETUP_CONFIRM:671 case WLAN_TDLS_TEARDOWN:672 case WLAN_TDLS_DISCOVERY_REQUEST:673 ret = mwifiex_prep_tdls_encap_data(priv, peer, action_code,674 dialog_token, status_code,675 skb);676 if (ret) {677 dev_kfree_skb_any(skb);678 return ret;679 }680 if (extra_ies_len)681 skb_put_data(skb, extra_ies, extra_ies_len);682 mwifiex_tdls_add_link_ie(skb, priv->curr_addr, peer,683 priv->cfg_bssid);684 break;685 case WLAN_TDLS_SETUP_RESPONSE:686 ret = mwifiex_prep_tdls_encap_data(priv, peer, action_code,687 dialog_token, status_code,688 skb);689 if (ret) {690 dev_kfree_skb_any(skb);691 return ret;692 }693 if (extra_ies_len)694 skb_put_data(skb, extra_ies, extra_ies_len);695 mwifiex_tdls_add_link_ie(skb, peer, priv->curr_addr,696 priv->cfg_bssid);697 break;698 }699 700 switch (action_code) {701 case WLAN_TDLS_SETUP_REQUEST:702 case WLAN_TDLS_SETUP_RESPONSE:703 skb->priority = MWIFIEX_PRIO_BK;704 break;705 default:706 skb->priority = MWIFIEX_PRIO_VI;707 break;708 }709 710 tx_info = MWIFIEX_SKB_TXCB(skb);711 memset(tx_info, 0, sizeof(*tx_info));712 tx_info->bss_num = priv->bss_num;713 tx_info->bss_type = priv->bss_type;714 715 __net_timestamp(skb);716 mwifiex_queue_tx_pkt(priv, skb);717 718 /* Delay 10ms to make sure tdls setup confirm/teardown frame719 * is received by peer720 */721 if (action_code == WLAN_TDLS_SETUP_CONFIRM ||722 action_code == WLAN_TDLS_TEARDOWN)723 msleep_interruptible(10);724 725 return 0;726}727 728static int729mwifiex_construct_tdls_action_frame(struct mwifiex_private *priv,730 const u8 *peer,731 u8 action_code, u8 dialog_token,732 u16 status_code, struct sk_buff *skb)733{734 struct ieee80211_mgmt *mgmt;735 int ret;736 u16 capab;737 struct ieee80211_ht_cap *ht_cap;738 unsigned int extra;739 u8 radio, *pos;740 741 capab = priv->curr_bss_params.bss_descriptor.cap_info_bitmap;742 743 mgmt = skb_put(skb, offsetof(struct ieee80211_mgmt, u));744 745 memset(mgmt, 0, 24);746 memcpy(mgmt->da, peer, ETH_ALEN);747 memcpy(mgmt->sa, priv->curr_addr, ETH_ALEN);748 memcpy(mgmt->bssid, priv->cfg_bssid, ETH_ALEN);749 mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |750 IEEE80211_STYPE_ACTION);751 752 /* add address 4 */753 pos = skb_put(skb, ETH_ALEN);754 755 switch (action_code) {756 case WLAN_PUB_ACTION_TDLS_DISCOVER_RES:757 /* See the layout of 'struct ieee80211_mgmt'. */758 extra = sizeof(mgmt->u.action.u.tdls_discover_resp) +759 sizeof(mgmt->u.action.category);760 skb_put(skb, extra);761 mgmt->u.action.category = WLAN_CATEGORY_PUBLIC;762 mgmt->u.action.u.tdls_discover_resp.action_code =763 WLAN_PUB_ACTION_TDLS_DISCOVER_RES;764 mgmt->u.action.u.tdls_discover_resp.dialog_token =765 dialog_token;766 mgmt->u.action.u.tdls_discover_resp.capability =767 cpu_to_le16(capab);768 /* move back for addr4 */769 memmove(pos + ETH_ALEN, &mgmt->u.action, extra);770 /* init address 4 */771 eth_broadcast_addr(pos);772 773 ret = mwifiex_tdls_append_rates_ie(priv, skb);774 if (ret) {775 dev_kfree_skb_any(skb);776 return ret;777 }778 779 pos = skb_put(skb, sizeof(struct ieee80211_ht_cap) + 2);780 *pos++ = WLAN_EID_HT_CAPABILITY;781 *pos++ = sizeof(struct ieee80211_ht_cap);782 ht_cap = (void *)pos;783 radio = mwifiex_band_to_radio_type(priv->curr_bss_params.band);784 ret = mwifiex_fill_cap_info(priv, radio, ht_cap);785 if (ret) {786 dev_kfree_skb_any(skb);787 return ret;788 }789 790 if (priv->adapter->is_hw_11ac_capable) {791 ret = mwifiex_tdls_add_vht_capab(priv, skb);792 if (ret) {793 dev_kfree_skb_any(skb);794 return ret;795 }796 mwifiex_tdls_add_aid(priv, skb);797 }798 799 mwifiex_tdls_add_ext_capab(priv, skb);800 mwifiex_tdls_add_bss_co_2040(skb);801 mwifiex_tdls_add_supported_chan(skb);802 mwifiex_tdls_add_qos_capab(skb);803 mwifiex_tdls_add_oper_class(skb);804 break;805 default:806 mwifiex_dbg(priv->adapter, ERROR, "Unknown TDLS action frame type\n");807 return -EINVAL;808 }809 810 return 0;811}812 813int mwifiex_send_tdls_action_frame(struct mwifiex_private *priv, const u8 *peer,814 u8 action_code, u8 dialog_token,815 u16 status_code, const u8 *extra_ies,816 size_t extra_ies_len)817{818 struct sk_buff *skb;819 struct mwifiex_txinfo *tx_info;820 u8 *pos;821 u32 pkt_type, tx_control;822 u16 pkt_len, skb_len;823 824 skb_len = MWIFIEX_MIN_DATA_HEADER_LEN +825 max(sizeof(struct ieee80211_mgmt),826 sizeof(struct ieee80211_tdls_data)) +827 MWIFIEX_MGMT_FRAME_HEADER_SIZE +828 MWIFIEX_SUPPORTED_RATES +829 sizeof(struct ieee_types_extcap) +830 sizeof(struct ieee80211_ht_cap) +831 sizeof(struct ieee_types_bss_co_2040) +832 sizeof(struct ieee80211_ht_operation) +833 sizeof(struct ieee80211_tdls_lnkie) +834 extra_ies_len +835 3 + /* Qos Info */836 ETH_ALEN; /* Address4 */837 838 if (priv->adapter->is_hw_11ac_capable)839 skb_len += sizeof(struct ieee_types_vht_cap) +840 sizeof(struct ieee_types_vht_oper) +841 sizeof(struct ieee_types_aid);842 843 skb = dev_alloc_skb(skb_len);844 if (!skb) {845 mwifiex_dbg(priv->adapter, ERROR,846 "allocate skb failed for management frame\n");847 return -ENOMEM;848 }849 850 skb_reserve(skb, MWIFIEX_MIN_DATA_HEADER_LEN);851 852 pkt_type = PKT_TYPE_MGMT;853 tx_control = 0;854 pos = skb_put_zero(skb,855 MWIFIEX_MGMT_FRAME_HEADER_SIZE + sizeof(pkt_len));856 memcpy(pos, &pkt_type, sizeof(pkt_type));857 memcpy(pos + sizeof(pkt_type), &tx_control, sizeof(tx_control));858 859 if (mwifiex_construct_tdls_action_frame(priv, peer, action_code,860 dialog_token, status_code,861 skb)) {862 dev_kfree_skb_any(skb);863 return -EINVAL;864 }865 866 if (extra_ies_len)867 skb_put_data(skb, extra_ies, extra_ies_len);868 869 /* the TDLS link IE is always added last we are the responder */870 871 mwifiex_tdls_add_link_ie(skb, peer, priv->curr_addr,872 priv->cfg_bssid);873 874 skb->priority = MWIFIEX_PRIO_VI;875 876 tx_info = MWIFIEX_SKB_TXCB(skb);877 memset(tx_info, 0, sizeof(*tx_info));878 tx_info->bss_num = priv->bss_num;879 tx_info->bss_type = priv->bss_type;880 tx_info->flags |= MWIFIEX_BUF_FLAG_TDLS_PKT;881 882 pkt_len = skb->len - MWIFIEX_MGMT_FRAME_HEADER_SIZE - sizeof(pkt_len);883 memcpy(skb->data + MWIFIEX_MGMT_FRAME_HEADER_SIZE, &pkt_len,884 sizeof(pkt_len));885 __net_timestamp(skb);886 mwifiex_queue_tx_pkt(priv, skb);887 888 return 0;889}890 891/* This function process tdls action frame from peer.892 * Peer capabilities are stored into station node structure.893 */894void mwifiex_process_tdls_action_frame(struct mwifiex_private *priv,895 u8 *buf, int len)896{897 struct mwifiex_sta_node *sta_ptr;898 u8 *peer, *pos, *end;899 u8 i, action, basic;900 u16 cap = 0;901 int ies_len = 0;902 903 if (len < (sizeof(struct ethhdr) + 3))904 return;905 if (*(buf + sizeof(struct ethhdr)) != WLAN_TDLS_SNAP_RFTYPE)906 return;907 if (*(buf + sizeof(struct ethhdr) + 1) != WLAN_CATEGORY_TDLS)908 return;909 910 peer = buf + ETH_ALEN;911 action = *(buf + sizeof(struct ethhdr) + 2);912 mwifiex_dbg(priv->adapter, DATA,913 "rx:tdls action: peer=%pM, action=%d\n", peer, action);914 915 switch (action) {916 case WLAN_TDLS_SETUP_REQUEST:917 if (len < (sizeof(struct ethhdr) + TDLS_REQ_FIX_LEN))918 return;919 920 pos = buf + sizeof(struct ethhdr) + 4;921 /* payload 1+ category 1 + action 1 + dialog 1 */922 cap = get_unaligned_le16(pos);923 ies_len = len - sizeof(struct ethhdr) - TDLS_REQ_FIX_LEN;924 pos += 2;925 break;926 927 case WLAN_TDLS_SETUP_RESPONSE:928 if (len < (sizeof(struct ethhdr) + TDLS_RESP_FIX_LEN))929 return;930 /* payload 1+ category 1 + action 1 + dialog 1 + status code 2*/931 pos = buf + sizeof(struct ethhdr) + 6;932 cap = get_unaligned_le16(pos);933 ies_len = len - sizeof(struct ethhdr) - TDLS_RESP_FIX_LEN;934 pos += 2;935 break;936 937 case WLAN_TDLS_SETUP_CONFIRM:938 if (len < (sizeof(struct ethhdr) + TDLS_CONFIRM_FIX_LEN))939 return;940 pos = buf + sizeof(struct ethhdr) + TDLS_CONFIRM_FIX_LEN;941 ies_len = len - sizeof(struct ethhdr) - TDLS_CONFIRM_FIX_LEN;942 break;943 default:944 mwifiex_dbg(priv->adapter, ERROR, "Unknown TDLS frame type.\n");945 return;946 }947 948 sta_ptr = mwifiex_add_sta_entry(priv, peer);949 if (!sta_ptr)950 return;951 952 sta_ptr->tdls_cap.capab = cpu_to_le16(cap);953 954 for (end = pos + ies_len; pos + 1 < end; pos += 2 + pos[1]) {955 u8 ie_len = pos[1];956 957 if (pos + 2 + ie_len > end)958 break;959 960 switch (*pos) {961 case WLAN_EID_SUPP_RATES:962 if (ie_len > sizeof(sta_ptr->tdls_cap.rates))963 return;964 sta_ptr->tdls_cap.rates_len = ie_len;965 for (i = 0; i < ie_len; i++)966 sta_ptr->tdls_cap.rates[i] = pos[i + 2];967 break;968 969 case WLAN_EID_EXT_SUPP_RATES:970 if (ie_len > sizeof(sta_ptr->tdls_cap.rates))971 return;972 basic = sta_ptr->tdls_cap.rates_len;973 if (ie_len > sizeof(sta_ptr->tdls_cap.rates) - basic)974 return;975 for (i = 0; i < ie_len; i++)976 sta_ptr->tdls_cap.rates[basic + i] = pos[i + 2];977 sta_ptr->tdls_cap.rates_len += ie_len;978 break;979 case WLAN_EID_HT_CAPABILITY:980 if (ie_len != sizeof(struct ieee80211_ht_cap))981 return;982 /* copy the ie's value into ht_capb*/983 memcpy((u8 *)&sta_ptr->tdls_cap.ht_capb, pos + 2,984 sizeof(struct ieee80211_ht_cap));985 sta_ptr->is_11n_enabled = 1;986 break;987 case WLAN_EID_HT_OPERATION:988 if (ie_len != sizeof(struct ieee80211_ht_operation))989 return;990 /* copy the ie's value into ht_oper*/991 memcpy(&sta_ptr->tdls_cap.ht_oper, pos + 2,992 sizeof(struct ieee80211_ht_operation));993 break;994 case WLAN_EID_BSS_COEX_2040:995 if (ie_len != sizeof(pos[2]))996 return;997 sta_ptr->tdls_cap.coex_2040 = pos[2];998 break;999 case WLAN_EID_EXT_CAPABILITY:1000 if (ie_len < sizeof(struct ieee_types_header))1001 return;1002 if (ie_len > 8)1003 return;1004 memcpy((u8 *)&sta_ptr->tdls_cap.extcap, pos,1005 sizeof(struct ieee_types_header) +1006 min_t(u8, ie_len, 8));1007 break;1008 case WLAN_EID_RSN:1009 if (ie_len < sizeof(struct ieee_types_header))1010 return;1011 if (ie_len > IEEE_MAX_IE_SIZE -1012 sizeof(struct ieee_types_header))1013 return;1014 memcpy((u8 *)&sta_ptr->tdls_cap.rsn_ie, pos,1015 sizeof(struct ieee_types_header) +1016 min_t(u8, ie_len, IEEE_MAX_IE_SIZE -1017 sizeof(struct ieee_types_header)));1018 break;1019 case WLAN_EID_QOS_CAPA:1020 if (ie_len != sizeof(pos[2]))1021 return;1022 sta_ptr->tdls_cap.qos_info = pos[2];1023 break;1024 case WLAN_EID_VHT_OPERATION:1025 if (priv->adapter->is_hw_11ac_capable) {1026 if (ie_len !=1027 sizeof(struct ieee80211_vht_operation))1028 return;1029 /* copy the ie's value into vhtoper*/1030 memcpy(&sta_ptr->tdls_cap.vhtoper, pos + 2,1031 sizeof(struct ieee80211_vht_operation));1032 }1033 break;1034 case WLAN_EID_VHT_CAPABILITY:1035 if (priv->adapter->is_hw_11ac_capable) {1036 if (ie_len != sizeof(struct ieee80211_vht_cap))1037 return;1038 /* copy the ie's value into vhtcap*/1039 memcpy((u8 *)&sta_ptr->tdls_cap.vhtcap, pos + 2,1040 sizeof(struct ieee80211_vht_cap));1041 sta_ptr->is_11ac_enabled = 1;1042 }1043 break;1044 case WLAN_EID_AID:1045 if (priv->adapter->is_hw_11ac_capable) {1046 if (ie_len != sizeof(u16))1047 return;1048 sta_ptr->tdls_cap.aid =1049 get_unaligned_le16((pos + 2));1050 }1051 break;1052 default:1053 break;1054 }1055 }1056 1057 return;1058}1059 1060static int1061mwifiex_tdls_process_config_link(struct mwifiex_private *priv, const u8 *peer)1062{1063 struct mwifiex_sta_node *sta_ptr;1064 struct mwifiex_ds_tdls_oper tdls_oper;1065 1066 memset(&tdls_oper, 0, sizeof(struct mwifiex_ds_tdls_oper));1067 sta_ptr = mwifiex_get_sta_entry(priv, peer);1068 1069 if (!sta_ptr || sta_ptr->tdls_status == TDLS_SETUP_FAILURE) {1070 mwifiex_dbg(priv->adapter, ERROR,1071 "link absent for peer %pM; cannot config\n", peer);1072 return -EINVAL;1073 }1074 1075 memcpy(&tdls_oper.peer_mac, peer, ETH_ALEN);1076 tdls_oper.tdls_action = MWIFIEX_TDLS_CONFIG_LINK;1077 return mwifiex_send_cmd(priv, HostCmd_CMD_TDLS_OPER,1078 HostCmd_ACT_GEN_SET, 0, &tdls_oper, true);1079}1080 1081static int1082mwifiex_tdls_process_create_link(struct mwifiex_private *priv, const u8 *peer)1083{1084 struct mwifiex_sta_node *sta_ptr;1085 struct mwifiex_ds_tdls_oper tdls_oper;1086 1087 memset(&tdls_oper, 0, sizeof(struct mwifiex_ds_tdls_oper));1088 sta_ptr = mwifiex_get_sta_entry(priv, peer);1089 1090 if (sta_ptr && sta_ptr->tdls_status == TDLS_SETUP_INPROGRESS) {1091 mwifiex_dbg(priv->adapter, WARN,1092 "Setup already in progress for peer %pM\n", peer);1093 return 0;1094 }1095 1096 sta_ptr = mwifiex_add_sta_entry(priv, peer);1097 if (!sta_ptr)1098 return -ENOMEM;1099 1100 sta_ptr->tdls_status = TDLS_SETUP_INPROGRESS;1101 mwifiex_hold_tdls_packets(priv, peer);1102 memcpy(&tdls_oper.peer_mac, peer, ETH_ALEN);1103 tdls_oper.tdls_action = MWIFIEX_TDLS_CREATE_LINK;1104 return mwifiex_send_cmd(priv, HostCmd_CMD_TDLS_OPER,1105 HostCmd_ACT_GEN_SET, 0, &tdls_oper, true);1106}1107 1108static int1109mwifiex_tdls_process_disable_link(struct mwifiex_private *priv, const u8 *peer)1110{1111 struct mwifiex_sta_node *sta_ptr;1112 struct mwifiex_ds_tdls_oper tdls_oper;1113 1114 memset(&tdls_oper, 0, sizeof(struct mwifiex_ds_tdls_oper));1115 sta_ptr = mwifiex_get_sta_entry(priv, peer);1116 1117 if (sta_ptr) {1118 if (sta_ptr->is_11n_enabled) {1119 mwifiex_11n_cleanup_reorder_tbl(priv);1120 spin_lock_bh(&priv->wmm.ra_list_spinlock);1121 mwifiex_11n_delete_all_tx_ba_stream_tbl(priv);1122 spin_unlock_bh(&priv->wmm.ra_list_spinlock);1123 }1124 mwifiex_del_sta_entry(priv, peer);1125 }1126 1127 mwifiex_restore_tdls_packets(priv, peer, TDLS_LINK_TEARDOWN);1128 mwifiex_auto_tdls_update_peer_status(priv, peer, TDLS_NOT_SETUP);1129 memcpy(&tdls_oper.peer_mac, peer, ETH_ALEN);1130 tdls_oper.tdls_action = MWIFIEX_TDLS_DISABLE_LINK;1131 return mwifiex_send_cmd(priv, HostCmd_CMD_TDLS_OPER,1132 HostCmd_ACT_GEN_SET, 0, &tdls_oper, true);1133}1134 1135static int1136mwifiex_tdls_process_enable_link(struct mwifiex_private *priv, const u8 *peer)1137{1138 struct mwifiex_sta_node *sta_ptr;1139 struct ieee80211_mcs_info mcs;1140 int i;1141 1142 sta_ptr = mwifiex_get_sta_entry(priv, peer);1143 1144 if (sta_ptr && (sta_ptr->tdls_status != TDLS_SETUP_FAILURE)) {1145 mwifiex_dbg(priv->adapter, MSG,1146 "tdls: enable link %pM success\n", peer);1147 1148 sta_ptr->tdls_status = TDLS_SETUP_COMPLETE;1149 1150 mcs = sta_ptr->tdls_cap.ht_capb.mcs;1151 if (mcs.rx_mask[0] != 0xff)1152 sta_ptr->is_11n_enabled = true;1153 if (sta_ptr->is_11n_enabled) {1154 if (le16_to_cpu(sta_ptr->tdls_cap.ht_capb.cap_info) &1155 IEEE80211_HT_CAP_MAX_AMSDU)1156 sta_ptr->max_amsdu =1157 MWIFIEX_TX_DATA_BUF_SIZE_8K;1158 else1159 sta_ptr->max_amsdu =1160 MWIFIEX_TX_DATA_BUF_SIZE_4K;1161 1162 for (i = 0; i < MAX_NUM_TID; i++)1163 sta_ptr->ampdu_sta[i] =1164 priv->aggr_prio_tbl[i].ampdu_user;1165 } else {1166 for (i = 0; i < MAX_NUM_TID; i++)1167 sta_ptr->ampdu_sta[i] = BA_STREAM_NOT_ALLOWED;1168 }1169 if (sta_ptr->tdls_cap.extcap.ext_capab[3] &1170 WLAN_EXT_CAPA4_TDLS_CHAN_SWITCH) {1171 mwifiex_config_tdls_enable(priv);1172 mwifiex_config_tdls_cs_params(priv);1173 }1174 1175 memset(sta_ptr->rx_seq, 0xff, sizeof(sta_ptr->rx_seq));1176 mwifiex_restore_tdls_packets(priv, peer, TDLS_SETUP_COMPLETE);1177 mwifiex_auto_tdls_update_peer_status(priv, peer,1178 TDLS_SETUP_COMPLETE);1179 } else {1180 mwifiex_dbg(priv->adapter, ERROR,1181 "tdls: enable link %pM failed\n", peer);1182 if (sta_ptr) {1183 mwifiex_11n_cleanup_reorder_tbl(priv);1184 spin_lock_bh(&priv->wmm.ra_list_spinlock);1185 mwifiex_11n_delete_all_tx_ba_stream_tbl(priv);1186 spin_unlock_bh(&priv->wmm.ra_list_spinlock);1187 mwifiex_del_sta_entry(priv, peer);1188 }1189 mwifiex_restore_tdls_packets(priv, peer, TDLS_LINK_TEARDOWN);1190 mwifiex_auto_tdls_update_peer_status(priv, peer,1191 TDLS_NOT_SETUP);1192 1193 return -1;1194 }1195 1196 return 0;1197}1198 1199int mwifiex_tdls_oper(struct mwifiex_private *priv, const u8 *peer, u8 action)1200{1201 switch (action) {1202 case MWIFIEX_TDLS_ENABLE_LINK:1203 return mwifiex_tdls_process_enable_link(priv, peer);1204 case MWIFIEX_TDLS_DISABLE_LINK:1205 return mwifiex_tdls_process_disable_link(priv, peer);1206 case MWIFIEX_TDLS_CREATE_LINK:1207 return mwifiex_tdls_process_create_link(priv, peer);1208 case MWIFIEX_TDLS_CONFIG_LINK:1209 return mwifiex_tdls_process_config_link(priv, peer);1210 }1211 return 0;1212}1213 1214int mwifiex_get_tdls_link_status(struct mwifiex_private *priv, const u8 *mac)1215{1216 struct mwifiex_sta_node *sta_ptr;1217 1218 sta_ptr = mwifiex_get_sta_entry(priv, mac);1219 if (sta_ptr)1220 return sta_ptr->tdls_status;1221 1222 return TDLS_NOT_SETUP;1223}1224 1225int mwifiex_get_tdls_list(struct mwifiex_private *priv,1226 struct tdls_peer_info *buf)1227{1228 struct mwifiex_sta_node *sta_ptr;1229 struct tdls_peer_info *peer = buf;1230 int count = 0;1231 1232 if (!ISSUPP_TDLS_ENABLED(priv->adapter->fw_cap_info))1233 return 0;1234 1235 /* make sure we are in station mode and connected */1236 if (!(priv->bss_type == MWIFIEX_BSS_TYPE_STA && priv->media_connected))1237 return 0;1238 1239 spin_lock_bh(&priv->sta_list_spinlock);1240 list_for_each_entry(sta_ptr, &priv->sta_list, list) {1241 if (mwifiex_is_tdls_link_setup(sta_ptr->tdls_status)) {1242 ether_addr_copy(peer->peer_addr, sta_ptr->mac_addr);1243 peer++;1244 count++;1245 if (count >= MWIFIEX_MAX_TDLS_PEER_SUPPORTED)1246 break;1247 }1248 }1249 spin_unlock_bh(&priv->sta_list_spinlock);1250 1251 return count;1252}1253 1254void mwifiex_disable_all_tdls_links(struct mwifiex_private *priv)1255{1256 struct mwifiex_sta_node *sta_ptr;1257 struct mwifiex_ds_tdls_oper tdls_oper;1258 1259 if (list_empty(&priv->sta_list))1260 return;1261 1262 list_for_each_entry(sta_ptr, &priv->sta_list, list) {1263 memset(&tdls_oper, 0, sizeof(struct mwifiex_ds_tdls_oper));1264 1265 if (sta_ptr->is_11n_enabled) {1266 mwifiex_11n_cleanup_reorder_tbl(priv);1267 spin_lock_bh(&priv->wmm.ra_list_spinlock);1268 mwifiex_11n_delete_all_tx_ba_stream_tbl(priv);1269 spin_unlock_bh(&priv->wmm.ra_list_spinlock);1270 }1271 1272 mwifiex_restore_tdls_packets(priv, sta_ptr->mac_addr,1273 TDLS_LINK_TEARDOWN);1274 memcpy(&tdls_oper.peer_mac, sta_ptr->mac_addr, ETH_ALEN);1275 tdls_oper.tdls_action = MWIFIEX_TDLS_DISABLE_LINK;1276 if (mwifiex_send_cmd(priv, HostCmd_CMD_TDLS_OPER,1277 HostCmd_ACT_GEN_SET, 0, &tdls_oper, false))1278 mwifiex_dbg(priv->adapter, ERROR,1279 "Disable link failed for TDLS peer %pM",1280 sta_ptr->mac_addr);1281 }1282 1283 mwifiex_del_all_sta_list(priv);1284}1285 1286int mwifiex_tdls_check_tx(struct mwifiex_private *priv, struct sk_buff *skb)1287{1288 struct mwifiex_auto_tdls_peer *peer;1289 u8 mac[ETH_ALEN];1290 1291 ether_addr_copy(mac, skb->data);1292 1293 spin_lock_bh(&priv->auto_tdls_lock);1294 list_for_each_entry(peer, &priv->auto_tdls_list, list) {1295 if (!memcmp(mac, peer->mac_addr, ETH_ALEN)) {1296 if (peer->rssi <= MWIFIEX_TDLS_RSSI_HIGH &&1297 peer->tdls_status == TDLS_NOT_SETUP &&1298 (peer->failure_count <1299 MWIFIEX_TDLS_MAX_FAIL_COUNT)) {1300 peer->tdls_status = TDLS_SETUP_INPROGRESS;1301 mwifiex_dbg(priv->adapter, INFO,1302 "setup TDLS link, peer=%pM rssi=%d\n",1303 peer->mac_addr, peer->rssi);1304 1305 cfg80211_tdls_oper_request(priv->netdev,1306 peer->mac_addr,1307 NL80211_TDLS_SETUP,1308 0, GFP_ATOMIC);1309 peer->do_setup = false;1310 priv->check_tdls_tx = false;1311 } else if (peer->failure_count <1312 MWIFIEX_TDLS_MAX_FAIL_COUNT &&1313 peer->do_discover) {1314 mwifiex_send_tdls_data_frame(priv,1315 peer->mac_addr,1316 WLAN_TDLS_DISCOVERY_REQUEST,1317 1, 0, NULL, 0);1318 peer->do_discover = false;1319 }1320 }1321 }1322 spin_unlock_bh(&priv->auto_tdls_lock);1323 1324 return 0;1325}1326 1327void mwifiex_flush_auto_tdls_list(struct mwifiex_private *priv)1328{1329 struct mwifiex_auto_tdls_peer *peer, *tmp_node;1330 1331 spin_lock_bh(&priv->auto_tdls_lock);1332 list_for_each_entry_safe(peer, tmp_node, &priv->auto_tdls_list, list) {1333 list_del(&peer->list);1334 kfree(peer);1335 }1336 1337 INIT_LIST_HEAD(&priv->auto_tdls_list);1338 spin_unlock_bh(&priv->auto_tdls_lock);1339 priv->check_tdls_tx = false;1340}1341 1342void mwifiex_add_auto_tdls_peer(struct mwifiex_private *priv, const u8 *mac)1343{1344 struct mwifiex_auto_tdls_peer *tdls_peer;1345 1346 if (!priv->adapter->auto_tdls)1347 return;1348 1349 spin_lock_bh(&priv->auto_tdls_lock);1350 list_for_each_entry(tdls_peer, &priv->auto_tdls_list, list) {1351 if (!memcmp(tdls_peer->mac_addr, mac, ETH_ALEN)) {1352 tdls_peer->tdls_status = TDLS_SETUP_INPROGRESS;1353 tdls_peer->rssi_jiffies = jiffies;1354 spin_unlock_bh(&priv->auto_tdls_lock);1355 return;1356 }1357 }1358 1359 /* create new TDLS peer */1360 tdls_peer = kzalloc(sizeof(*tdls_peer), GFP_ATOMIC);1361 if (tdls_peer) {1362 ether_addr_copy(tdls_peer->mac_addr, mac);1363 tdls_peer->tdls_status = TDLS_SETUP_INPROGRESS;1364 tdls_peer->rssi_jiffies = jiffies;1365 INIT_LIST_HEAD(&tdls_peer->list);1366 list_add_tail(&tdls_peer->list, &priv->auto_tdls_list);1367 mwifiex_dbg(priv->adapter, INFO,1368 "Add auto TDLS peer= %pM to list\n", mac);1369 }1370 1371 spin_unlock_bh(&priv->auto_tdls_lock);1372}1373 1374void mwifiex_auto_tdls_update_peer_status(struct mwifiex_private *priv,1375 const u8 *mac, u8 link_status)1376{1377 struct mwifiex_auto_tdls_peer *peer;1378 1379 if (!priv->adapter->auto_tdls)1380 return;1381 1382 spin_lock_bh(&priv->auto_tdls_lock);1383 list_for_each_entry(peer, &priv->auto_tdls_list, list) {1384 if (!memcmp(peer->mac_addr, mac, ETH_ALEN)) {1385 if ((link_status == TDLS_NOT_SETUP) &&1386 (peer->tdls_status == TDLS_SETUP_INPROGRESS))1387 peer->failure_count++;1388 else if (mwifiex_is_tdls_link_setup(link_status))1389 peer->failure_count = 0;1390 1391 peer->tdls_status = link_status;1392 break;1393 }1394 }1395 spin_unlock_bh(&priv->auto_tdls_lock);1396}1397 1398void mwifiex_auto_tdls_update_peer_signal(struct mwifiex_private *priv,1399 u8 *mac, s8 snr, s8 nflr)1400{1401 struct mwifiex_auto_tdls_peer *peer;1402 1403 if (!priv->adapter->auto_tdls)1404 return;1405 1406 spin_lock_bh(&priv->auto_tdls_lock);1407 list_for_each_entry(peer, &priv->auto_tdls_list, list) {1408 if (!memcmp(peer->mac_addr, mac, ETH_ALEN)) {1409 peer->rssi = nflr - snr;1410 peer->rssi_jiffies = jiffies;1411 break;1412 }1413 }1414 spin_unlock_bh(&priv->auto_tdls_lock);1415}1416 1417void mwifiex_check_auto_tdls(struct timer_list *t)1418{1419 struct mwifiex_private *priv = from_timer(priv, t, auto_tdls_timer);1420 struct mwifiex_auto_tdls_peer *tdls_peer;1421 u16 reason = WLAN_REASON_TDLS_TEARDOWN_UNSPECIFIED;1422 1423 if (WARN_ON_ONCE(!priv || !priv->adapter)) {1424 pr_err("mwifiex: %s: adapter or private structure is NULL\n",1425 __func__);1426 return;1427 }1428 1429 if (unlikely(!priv->adapter->auto_tdls))1430 return;1431 1432 if (!priv->auto_tdls_timer_active) {1433 mwifiex_dbg(priv->adapter, INFO,1434 "auto TDLS timer inactive; return");1435 return;1436 }1437 1438 priv->check_tdls_tx = false;1439 1440 spin_lock_bh(&priv->auto_tdls_lock);1441 list_for_each_entry(tdls_peer, &priv->auto_tdls_list, list) {1442 if (time_after(jiffies, tdls_peer->rssi_jiffies +1443 MWIFIEX_AUTO_TDLS_IDLE_TIME * HZ)) {1444 tdls_peer->rssi = 0;1445 tdls_peer->do_discover = true;1446 priv->check_tdls_tx = true;1447 }1448 1449 if (((tdls_peer->rssi >= MWIFIEX_TDLS_RSSI_LOW) ||1450 !tdls_peer->rssi) &&1451 mwifiex_is_tdls_link_setup(tdls_peer->tdls_status)) {1452 tdls_peer->tdls_status = TDLS_LINK_TEARDOWN;1453 mwifiex_dbg(priv->adapter, MSG,1454 "teardown TDLS link,peer=%pM rssi=%d\n",1455 tdls_peer->mac_addr, -tdls_peer->rssi);1456 tdls_peer->do_discover = true;1457 priv->check_tdls_tx = true;1458 cfg80211_tdls_oper_request(priv->netdev,1459 tdls_peer->mac_addr,1460 NL80211_TDLS_TEARDOWN,1461 reason, GFP_ATOMIC);1462 } else if (tdls_peer->rssi &&1463 tdls_peer->rssi <= MWIFIEX_TDLS_RSSI_HIGH &&1464 tdls_peer->tdls_status == TDLS_NOT_SETUP &&1465 tdls_peer->failure_count <1466 MWIFIEX_TDLS_MAX_FAIL_COUNT) {1467 priv->check_tdls_tx = true;1468 tdls_peer->do_setup = true;1469 mwifiex_dbg(priv->adapter, INFO,1470 "check TDLS with peer=%pM\t"1471 "rssi=%d\n", tdls_peer->mac_addr,1472 tdls_peer->rssi);1473 }1474 }1475 spin_unlock_bh(&priv->auto_tdls_lock);1476 1477 mod_timer(&priv->auto_tdls_timer,1478 jiffies + msecs_to_jiffies(MWIFIEX_TIMER_10S));1479}1480 1481void mwifiex_setup_auto_tdls_timer(struct mwifiex_private *priv)1482{1483 timer_setup(&priv->auto_tdls_timer, mwifiex_check_auto_tdls, 0);1484 priv->auto_tdls_timer_active = true;1485 mod_timer(&priv->auto_tdls_timer,1486 jiffies + msecs_to_jiffies(MWIFIEX_TIMER_10S));1487}1488 1489void mwifiex_clean_auto_tdls(struct mwifiex_private *priv)1490{1491 if (ISSUPP_TDLS_ENABLED(priv->adapter->fw_cap_info) &&1492 priv->adapter->auto_tdls &&1493 priv->bss_type == MWIFIEX_BSS_TYPE_STA) {1494 priv->auto_tdls_timer_active = false;1495 del_timer(&priv->auto_tdls_timer);1496 mwifiex_flush_auto_tdls_list(priv);1497 }1498}1499 1500static int mwifiex_config_tdls(struct mwifiex_private *priv, u8 enable)1501{1502 struct mwifiex_tdls_config config;1503 1504 config.enable = cpu_to_le16(enable);1505 return mwifiex_send_cmd(priv, HostCmd_CMD_TDLS_CONFIG,1506 ACT_TDLS_CS_ENABLE_CONFIG, 0, &config, true);1507}1508 1509int mwifiex_config_tdls_enable(struct mwifiex_private *priv)1510{1511 return mwifiex_config_tdls(priv, true);1512}1513 1514int mwifiex_config_tdls_disable(struct mwifiex_private *priv)1515{1516 return mwifiex_config_tdls(priv, false);1517}1518 1519int mwifiex_config_tdls_cs_params(struct mwifiex_private *priv)1520{1521 struct mwifiex_tdls_config_cs_params config_tdls_cs_params;1522 1523 config_tdls_cs_params.unit_time = MWIFIEX_DEF_CS_UNIT_TIME;1524 config_tdls_cs_params.thr_otherlink = MWIFIEX_DEF_CS_THR_OTHERLINK;1525 config_tdls_cs_params.thr_directlink = MWIFIEX_DEF_THR_DIRECTLINK;1526 1527 return mwifiex_send_cmd(priv, HostCmd_CMD_TDLS_CONFIG,1528 ACT_TDLS_CS_PARAMS, 0,1529 &config_tdls_cs_params, true);1530}1531 1532int mwifiex_stop_tdls_cs(struct mwifiex_private *priv, const u8 *peer_mac)1533{1534 struct mwifiex_tdls_stop_cs_params stop_tdls_cs_params;1535 1536 ether_addr_copy(stop_tdls_cs_params.peer_mac, peer_mac);1537 1538 return mwifiex_send_cmd(priv, HostCmd_CMD_TDLS_CONFIG,1539 ACT_TDLS_CS_STOP, 0,1540 &stop_tdls_cs_params, true);1541}1542 1543int mwifiex_start_tdls_cs(struct mwifiex_private *priv, const u8 *peer_mac,1544 u8 primary_chan, u8 second_chan_offset, u8 band)1545{1546 struct mwifiex_tdls_init_cs_params start_tdls_cs_params;1547 1548 ether_addr_copy(start_tdls_cs_params.peer_mac, peer_mac);1549 start_tdls_cs_params.primary_chan = primary_chan;1550 start_tdls_cs_params.second_chan_offset = second_chan_offset;1551 start_tdls_cs_params.band = band;1552 1553 start_tdls_cs_params.switch_time = cpu_to_le16(MWIFIEX_DEF_CS_TIME);1554 start_tdls_cs_params.switch_timeout =1555 cpu_to_le16(MWIFIEX_DEF_CS_TIMEOUT);1556 start_tdls_cs_params.reg_class = MWIFIEX_DEF_CS_REG_CLASS;1557 start_tdls_cs_params.periodicity = MWIFIEX_DEF_CS_PERIODICITY;1558 1559 return mwifiex_send_cmd(priv, HostCmd_CMD_TDLS_CONFIG,1560 ACT_TDLS_CS_INIT, 0,1561 &start_tdls_cs_params, true);1562}1563