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