linux/drivers/net/wireless/marvell/mwifiex/tdls.c
<<
>>
Prefs
   1/*
   2 * NXP Wireless LAN device driver: TDLS handling
   3 *
   4 * Copyright 2011-2020 NXP
   5 *
   6 * This software file (the "File") is distributed by NXP
   7 * under the terms of the GNU General Public License Version 2, June 1991
   8 * (the "License").  You may use, redistribute and/or modify this File in
   9 * accordance with the terms and conditions of the License, a copy of which
  10 * is available on the worldwide web at
  11 * 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 THE
  14 * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
  15 * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
  16 * 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      6
  26#define TDLS_RESP_FIX_LEN     8
  27#define TDLS_CONFIRM_FIX_LEN  6
  28#define MWIFIEX_TDLS_WMM_INFO_SIZE 7
  29
  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 int
 119mwifiex_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 int
 187mwifiex_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        else
 282                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                else
 328                        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 void
 382mwifiex_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 void
 410mwifiex_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 void
 613mwifiex_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 frame
 719         * is received by peer
 720        */
 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 int
 729mwifiex_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        u8 radio, *pos;
 739
 740        capab = priv->curr_bss_params.bss_descriptor.cap_info_bitmap;
 741
 742        mgmt = skb_put(skb, offsetof(struct ieee80211_mgmt, u));
 743
 744        memset(mgmt, 0, 24);
 745        memcpy(mgmt->da, peer, ETH_ALEN);
 746        memcpy(mgmt->sa, priv->curr_addr, ETH_ALEN);
 747        memcpy(mgmt->bssid, priv->cfg_bssid, ETH_ALEN);
 748        mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
 749                                          IEEE80211_STYPE_ACTION);
 750
 751        /* add address 4 */
 752        pos = skb_put(skb, ETH_ALEN);
 753
 754        switch (action_code) {
 755        case WLAN_PUB_ACTION_TDLS_DISCOVER_RES:
 756                skb_put(skb, sizeof(mgmt->u.action.u.tdls_discover_resp) + 1);
 757                mgmt->u.action.category = WLAN_CATEGORY_PUBLIC;
 758                mgmt->u.action.u.tdls_discover_resp.action_code =
 759                                              WLAN_PUB_ACTION_TDLS_DISCOVER_RES;
 760                mgmt->u.action.u.tdls_discover_resp.dialog_token =
 761                                                                   dialog_token;
 762                mgmt->u.action.u.tdls_discover_resp.capability =
 763                                                             cpu_to_le16(capab);
 764                /* move back for addr4 */
 765                memmove(pos + ETH_ALEN, &mgmt->u.action.category,
 766                        sizeof(mgmt->u.action.u.tdls_discover_resp));
 767                /* init address 4 */
 768                eth_broadcast_addr(pos);
 769
 770                ret = mwifiex_tdls_append_rates_ie(priv, skb);
 771                if (ret) {
 772                        dev_kfree_skb_any(skb);
 773                        return ret;
 774                }
 775
 776                pos = skb_put(skb, sizeof(struct ieee80211_ht_cap) + 2);
 777                *pos++ = WLAN_EID_HT_CAPABILITY;
 778                *pos++ = sizeof(struct ieee80211_ht_cap);
 779                ht_cap = (void *)pos;
 780                radio = mwifiex_band_to_radio_type(priv->curr_bss_params.band);
 781                ret = mwifiex_fill_cap_info(priv, radio, ht_cap);
 782                if (ret) {
 783                        dev_kfree_skb_any(skb);
 784                        return ret;
 785                }
 786
 787                if (priv->adapter->is_hw_11ac_capable) {
 788                        ret = mwifiex_tdls_add_vht_capab(priv, skb);
 789                        if (ret) {
 790                                dev_kfree_skb_any(skb);
 791                                return ret;
 792                        }
 793                        mwifiex_tdls_add_aid(priv, skb);
 794                }
 795
 796                mwifiex_tdls_add_ext_capab(priv, skb);
 797                mwifiex_tdls_add_bss_co_2040(skb);
 798                mwifiex_tdls_add_supported_chan(skb);
 799                mwifiex_tdls_add_qos_capab(skb);
 800                mwifiex_tdls_add_oper_class(skb);
 801                break;
 802        default:
 803                mwifiex_dbg(priv->adapter, ERROR, "Unknown TDLS action frame type\n");
 804                return -EINVAL;
 805        }
 806
 807        return 0;
 808}
 809
 810int mwifiex_send_tdls_action_frame(struct mwifiex_private *priv, const u8 *peer,
 811                                   u8 action_code, u8 dialog_token,
 812                                   u16 status_code, const u8 *extra_ies,
 813                                   size_t extra_ies_len)
 814{
 815        struct sk_buff *skb;
 816        struct mwifiex_txinfo *tx_info;
 817        u8 *pos;
 818        u32 pkt_type, tx_control;
 819        u16 pkt_len, skb_len;
 820
 821        skb_len = MWIFIEX_MIN_DATA_HEADER_LEN +
 822                  max(sizeof(struct ieee80211_mgmt),
 823                      sizeof(struct ieee80211_tdls_data)) +
 824                  MWIFIEX_MGMT_FRAME_HEADER_SIZE +
 825                  MWIFIEX_SUPPORTED_RATES +
 826                  sizeof(struct ieee_types_extcap) +
 827                  sizeof(struct ieee80211_ht_cap) +
 828                  sizeof(struct ieee_types_bss_co_2040) +
 829                  sizeof(struct ieee80211_ht_operation) +
 830                  sizeof(struct ieee80211_tdls_lnkie) +
 831                  extra_ies_len +
 832                  3 + /* Qos Info */
 833                  ETH_ALEN; /* Address4 */
 834
 835        if (priv->adapter->is_hw_11ac_capable)
 836                skb_len += sizeof(struct ieee_types_vht_cap) +
 837                           sizeof(struct ieee_types_vht_oper) +
 838                           sizeof(struct ieee_types_aid);
 839
 840        skb = dev_alloc_skb(skb_len);
 841        if (!skb) {
 842                mwifiex_dbg(priv->adapter, ERROR,
 843                            "allocate skb failed for management frame\n");
 844                return -ENOMEM;
 845        }
 846
 847        skb_reserve(skb, MWIFIEX_MIN_DATA_HEADER_LEN);
 848
 849        pkt_type = PKT_TYPE_MGMT;
 850        tx_control = 0;
 851        pos = skb_put_zero(skb,
 852                           MWIFIEX_MGMT_FRAME_HEADER_SIZE + sizeof(pkt_len));
 853        memcpy(pos, &pkt_type, sizeof(pkt_type));
 854        memcpy(pos + sizeof(pkt_type), &tx_control, sizeof(tx_control));
 855
 856        if (mwifiex_construct_tdls_action_frame(priv, peer, action_code,
 857                                                dialog_token, status_code,
 858                                                skb)) {
 859                dev_kfree_skb_any(skb);
 860                return -EINVAL;
 861        }
 862
 863        if (extra_ies_len)
 864                skb_put_data(skb, extra_ies, extra_ies_len);
 865
 866        /* the TDLS link IE is always added last we are the responder */
 867
 868        mwifiex_tdls_add_link_ie(skb, peer, priv->curr_addr,
 869                                 priv->cfg_bssid);
 870
 871        skb->priority = MWIFIEX_PRIO_VI;
 872
 873        tx_info = MWIFIEX_SKB_TXCB(skb);
 874        memset(tx_info, 0, sizeof(*tx_info));
 875        tx_info->bss_num = priv->bss_num;
 876        tx_info->bss_type = priv->bss_type;
 877        tx_info->flags |= MWIFIEX_BUF_FLAG_TDLS_PKT;
 878
 879        pkt_len = skb->len - MWIFIEX_MGMT_FRAME_HEADER_SIZE - sizeof(pkt_len);
 880        memcpy(skb->data + MWIFIEX_MGMT_FRAME_HEADER_SIZE, &pkt_len,
 881               sizeof(pkt_len));
 882        __net_timestamp(skb);
 883        mwifiex_queue_tx_pkt(priv, skb);
 884
 885        return 0;
 886}
 887
 888/* This function process tdls action frame from peer.
 889 * Peer capabilities are stored into station node structure.
 890 */
 891void mwifiex_process_tdls_action_frame(struct mwifiex_private *priv,
 892                                       u8 *buf, int len)
 893{
 894        struct mwifiex_sta_node *sta_ptr;
 895        u8 *peer, *pos, *end;
 896        u8 i, action, basic;
 897        u16 cap = 0;
 898        int ies_len = 0;
 899
 900        if (len < (sizeof(struct ethhdr) + 3))
 901                return;
 902        if (*(buf + sizeof(struct ethhdr)) != WLAN_TDLS_SNAP_RFTYPE)
 903                return;
 904        if (*(buf + sizeof(struct ethhdr) + 1) != WLAN_CATEGORY_TDLS)
 905                return;
 906
 907        peer = buf + ETH_ALEN;
 908        action = *(buf + sizeof(struct ethhdr) + 2);
 909        mwifiex_dbg(priv->adapter, DATA,
 910                    "rx:tdls action: peer=%pM, action=%d\n", peer, action);
 911
 912        switch (action) {
 913        case WLAN_TDLS_SETUP_REQUEST:
 914                if (len < (sizeof(struct ethhdr) + TDLS_REQ_FIX_LEN))
 915                        return;
 916
 917                pos = buf + sizeof(struct ethhdr) + 4;
 918                /* payload 1+ category 1 + action 1 + dialog 1 */
 919                cap = get_unaligned_le16(pos);
 920                ies_len = len - sizeof(struct ethhdr) - TDLS_REQ_FIX_LEN;
 921                pos += 2;
 922                break;
 923
 924        case WLAN_TDLS_SETUP_RESPONSE:
 925                if (len < (sizeof(struct ethhdr) + TDLS_RESP_FIX_LEN))
 926                        return;
 927                /* payload 1+ category 1 + action 1 + dialog 1 + status code 2*/
 928                pos = buf + sizeof(struct ethhdr) + 6;
 929                cap = get_unaligned_le16(pos);
 930                ies_len = len - sizeof(struct ethhdr) - TDLS_RESP_FIX_LEN;
 931                pos += 2;
 932                break;
 933
 934        case WLAN_TDLS_SETUP_CONFIRM:
 935                if (len < (sizeof(struct ethhdr) + TDLS_CONFIRM_FIX_LEN))
 936                        return;
 937                pos = buf + sizeof(struct ethhdr) + TDLS_CONFIRM_FIX_LEN;
 938                ies_len = len - sizeof(struct ethhdr) - TDLS_CONFIRM_FIX_LEN;
 939                break;
 940        default:
 941                mwifiex_dbg(priv->adapter, ERROR, "Unknown TDLS frame type.\n");
 942                return;
 943        }
 944
 945        sta_ptr = mwifiex_add_sta_entry(priv, peer);
 946        if (!sta_ptr)
 947                return;
 948
 949        sta_ptr->tdls_cap.capab = cpu_to_le16(cap);
 950
 951        for (end = pos + ies_len; pos + 1 < end; pos += 2 + pos[1]) {
 952                u8 ie_len = pos[1];
 953
 954                if (pos + 2 + ie_len > end)
 955                        break;
 956
 957                switch (*pos) {
 958                case WLAN_EID_SUPP_RATES:
 959                        if (ie_len > sizeof(sta_ptr->tdls_cap.rates))
 960                                return;
 961                        sta_ptr->tdls_cap.rates_len = ie_len;
 962                        for (i = 0; i < ie_len; i++)
 963                                sta_ptr->tdls_cap.rates[i] = pos[i + 2];
 964                        break;
 965
 966                case WLAN_EID_EXT_SUPP_RATES:
 967                        if (ie_len > sizeof(sta_ptr->tdls_cap.rates))
 968                                return;
 969                        basic = sta_ptr->tdls_cap.rates_len;
 970                        if (ie_len > sizeof(sta_ptr->tdls_cap.rates) - basic)
 971                                return;
 972                        for (i = 0; i < ie_len; i++)
 973                                sta_ptr->tdls_cap.rates[basic + i] = pos[i + 2];
 974                        sta_ptr->tdls_cap.rates_len += ie_len;
 975                        break;
 976                case WLAN_EID_HT_CAPABILITY:
 977                        if (ie_len != sizeof(struct ieee80211_ht_cap))
 978                                return;
 979                        /* copy the ie's value into ht_capb*/
 980                        memcpy((u8 *)&sta_ptr->tdls_cap.ht_capb, pos + 2,
 981                               sizeof(struct ieee80211_ht_cap));
 982                        sta_ptr->is_11n_enabled = 1;
 983                        break;
 984                case WLAN_EID_HT_OPERATION:
 985                        if (ie_len != sizeof(struct ieee80211_ht_operation))
 986                                return;
 987                        /* copy the ie's value into ht_oper*/
 988                        memcpy(&sta_ptr->tdls_cap.ht_oper, pos + 2,
 989                               sizeof(struct ieee80211_ht_operation));
 990                        break;
 991                case WLAN_EID_BSS_COEX_2040:
 992                        if (ie_len != sizeof(pos[2]))
 993                                return;
 994                        sta_ptr->tdls_cap.coex_2040 = pos[2];
 995                        break;
 996                case WLAN_EID_EXT_CAPABILITY:
 997                        if (ie_len < sizeof(struct ieee_types_header))
 998                                return;
 999                        if (ie_len > 8)
1000                                return;
1001                        memcpy((u8 *)&sta_ptr->tdls_cap.extcap, pos,
1002                               sizeof(struct ieee_types_header) +
1003                               min_t(u8, ie_len, 8));
1004                        break;
1005                case WLAN_EID_RSN:
1006                        if (ie_len < sizeof(struct ieee_types_header))
1007                                return;
1008                        if (ie_len > IEEE_MAX_IE_SIZE -
1009                            sizeof(struct ieee_types_header))
1010                                return;
1011                        memcpy((u8 *)&sta_ptr->tdls_cap.rsn_ie, pos,
1012                               sizeof(struct ieee_types_header) +
1013                               min_t(u8, ie_len, IEEE_MAX_IE_SIZE -
1014                                     sizeof(struct ieee_types_header)));
1015                        break;
1016                case WLAN_EID_QOS_CAPA:
1017                        if (ie_len != sizeof(pos[2]))
1018                                return;
1019                        sta_ptr->tdls_cap.qos_info = pos[2];
1020                        break;
1021                case WLAN_EID_VHT_OPERATION:
1022                        if (priv->adapter->is_hw_11ac_capable) {
1023                                if (ie_len !=
1024                                    sizeof(struct ieee80211_vht_operation))
1025                                        return;
1026                                /* copy the ie's value into vhtoper*/
1027                                memcpy(&sta_ptr->tdls_cap.vhtoper, pos + 2,
1028                                       sizeof(struct ieee80211_vht_operation));
1029                        }
1030                        break;
1031                case WLAN_EID_VHT_CAPABILITY:
1032                        if (priv->adapter->is_hw_11ac_capable) {
1033                                if (ie_len != sizeof(struct ieee80211_vht_cap))
1034                                        return;
1035                                /* copy the ie's value into vhtcap*/
1036                                memcpy((u8 *)&sta_ptr->tdls_cap.vhtcap, pos + 2,
1037                                       sizeof(struct ieee80211_vht_cap));
1038                                sta_ptr->is_11ac_enabled = 1;
1039                        }
1040                        break;
1041                case WLAN_EID_AID:
1042                        if (priv->adapter->is_hw_11ac_capable) {
1043                                if (ie_len != sizeof(u16))
1044                                        return;
1045                                sta_ptr->tdls_cap.aid =
1046                                        get_unaligned_le16((pos + 2));
1047                        }
1048                        break;
1049                default:
1050                        break;
1051                }
1052        }
1053
1054        return;
1055}
1056
1057static int
1058mwifiex_tdls_process_config_link(struct mwifiex_private *priv, const u8 *peer)
1059{
1060        struct mwifiex_sta_node *sta_ptr;
1061        struct mwifiex_ds_tdls_oper tdls_oper;
1062
1063        memset(&tdls_oper, 0, sizeof(struct mwifiex_ds_tdls_oper));
1064        sta_ptr = mwifiex_get_sta_entry(priv, peer);
1065
1066        if (!sta_ptr || sta_ptr->tdls_status == TDLS_SETUP_FAILURE) {
1067                mwifiex_dbg(priv->adapter, ERROR,
1068                            "link absent for peer %pM; cannot config\n", peer);
1069                return -EINVAL;
1070        }
1071
1072        memcpy(&tdls_oper.peer_mac, peer, ETH_ALEN);
1073        tdls_oper.tdls_action = MWIFIEX_TDLS_CONFIG_LINK;
1074        return mwifiex_send_cmd(priv, HostCmd_CMD_TDLS_OPER,
1075                                HostCmd_ACT_GEN_SET, 0, &tdls_oper, true);
1076}
1077
1078static int
1079mwifiex_tdls_process_create_link(struct mwifiex_private *priv, const u8 *peer)
1080{
1081        struct mwifiex_sta_node *sta_ptr;
1082        struct mwifiex_ds_tdls_oper tdls_oper;
1083
1084        memset(&tdls_oper, 0, sizeof(struct mwifiex_ds_tdls_oper));
1085        sta_ptr = mwifiex_get_sta_entry(priv, peer);
1086
1087        if (sta_ptr && sta_ptr->tdls_status == TDLS_SETUP_INPROGRESS) {
1088                mwifiex_dbg(priv->adapter, WARN,
1089                            "Setup already in progress for peer %pM\n", peer);
1090                return 0;
1091        }
1092
1093        sta_ptr = mwifiex_add_sta_entry(priv, peer);
1094        if (!sta_ptr)
1095                return -ENOMEM;
1096
1097        sta_ptr->tdls_status = TDLS_SETUP_INPROGRESS;
1098        mwifiex_hold_tdls_packets(priv, peer);
1099        memcpy(&tdls_oper.peer_mac, peer, ETH_ALEN);
1100        tdls_oper.tdls_action = MWIFIEX_TDLS_CREATE_LINK;
1101        return mwifiex_send_cmd(priv, HostCmd_CMD_TDLS_OPER,
1102                                HostCmd_ACT_GEN_SET, 0, &tdls_oper, true);
1103}
1104
1105static int
1106mwifiex_tdls_process_disable_link(struct mwifiex_private *priv, const u8 *peer)
1107{
1108        struct mwifiex_sta_node *sta_ptr;
1109        struct mwifiex_ds_tdls_oper tdls_oper;
1110
1111        memset(&tdls_oper, 0, sizeof(struct mwifiex_ds_tdls_oper));
1112        sta_ptr = mwifiex_get_sta_entry(priv, peer);
1113
1114        if (sta_ptr) {
1115                if (sta_ptr->is_11n_enabled) {
1116                        mwifiex_11n_cleanup_reorder_tbl(priv);
1117                        spin_lock_bh(&priv->wmm.ra_list_spinlock);
1118                        mwifiex_11n_delete_all_tx_ba_stream_tbl(priv);
1119                        spin_unlock_bh(&priv->wmm.ra_list_spinlock);
1120                }
1121                mwifiex_del_sta_entry(priv, peer);
1122        }
1123
1124        mwifiex_restore_tdls_packets(priv, peer, TDLS_LINK_TEARDOWN);
1125        mwifiex_auto_tdls_update_peer_status(priv, peer, TDLS_NOT_SETUP);
1126        memcpy(&tdls_oper.peer_mac, peer, ETH_ALEN);
1127        tdls_oper.tdls_action = MWIFIEX_TDLS_DISABLE_LINK;
1128        return mwifiex_send_cmd(priv, HostCmd_CMD_TDLS_OPER,
1129                                HostCmd_ACT_GEN_SET, 0, &tdls_oper, true);
1130}
1131
1132static int
1133mwifiex_tdls_process_enable_link(struct mwifiex_private *priv, const u8 *peer)
1134{
1135        struct mwifiex_sta_node *sta_ptr;
1136        struct ieee80211_mcs_info mcs;
1137        int i;
1138
1139        sta_ptr = mwifiex_get_sta_entry(priv, peer);
1140
1141        if (sta_ptr && (sta_ptr->tdls_status != TDLS_SETUP_FAILURE)) {
1142                mwifiex_dbg(priv->adapter, MSG,
1143                            "tdls: enable link %pM success\n", peer);
1144
1145                sta_ptr->tdls_status = TDLS_SETUP_COMPLETE;
1146
1147                mcs = sta_ptr->tdls_cap.ht_capb.mcs;
1148                if (mcs.rx_mask[0] != 0xff)
1149                        sta_ptr->is_11n_enabled = true;
1150                if (sta_ptr->is_11n_enabled) {
1151                        if (le16_to_cpu(sta_ptr->tdls_cap.ht_capb.cap_info) &
1152                            IEEE80211_HT_CAP_MAX_AMSDU)
1153                                sta_ptr->max_amsdu =
1154                                        MWIFIEX_TX_DATA_BUF_SIZE_8K;
1155                        else
1156                                sta_ptr->max_amsdu =
1157                                        MWIFIEX_TX_DATA_BUF_SIZE_4K;
1158
1159                        for (i = 0; i < MAX_NUM_TID; i++)
1160                                sta_ptr->ampdu_sta[i] =
1161                                              priv->aggr_prio_tbl[i].ampdu_user;
1162                } else {
1163                        for (i = 0; i < MAX_NUM_TID; i++)
1164                                sta_ptr->ampdu_sta[i] = BA_STREAM_NOT_ALLOWED;
1165                }
1166                if (sta_ptr->tdls_cap.extcap.ext_capab[3] &
1167                    WLAN_EXT_CAPA4_TDLS_CHAN_SWITCH) {
1168                        mwifiex_config_tdls_enable(priv);
1169                        mwifiex_config_tdls_cs_params(priv);
1170                }
1171
1172                memset(sta_ptr->rx_seq, 0xff, sizeof(sta_ptr->rx_seq));
1173                mwifiex_restore_tdls_packets(priv, peer, TDLS_SETUP_COMPLETE);
1174                mwifiex_auto_tdls_update_peer_status(priv, peer,
1175                                                     TDLS_SETUP_COMPLETE);
1176        } else {
1177                mwifiex_dbg(priv->adapter, ERROR,
1178                            "tdls: enable link %pM failed\n", peer);
1179                if (sta_ptr) {
1180                        mwifiex_11n_cleanup_reorder_tbl(priv);
1181                        spin_lock_bh(&priv->wmm.ra_list_spinlock);
1182                        mwifiex_11n_delete_all_tx_ba_stream_tbl(priv);
1183                        spin_unlock_bh(&priv->wmm.ra_list_spinlock);
1184                        mwifiex_del_sta_entry(priv, peer);
1185                }
1186                mwifiex_restore_tdls_packets(priv, peer, TDLS_LINK_TEARDOWN);
1187                mwifiex_auto_tdls_update_peer_status(priv, peer,
1188                                                     TDLS_NOT_SETUP);
1189
1190                return -1;
1191        }
1192
1193        return 0;
1194}
1195
1196int mwifiex_tdls_oper(struct mwifiex_private *priv, const u8 *peer, u8 action)
1197{
1198        switch (action) {
1199        case MWIFIEX_TDLS_ENABLE_LINK:
1200                return mwifiex_tdls_process_enable_link(priv, peer);
1201        case MWIFIEX_TDLS_DISABLE_LINK:
1202                return mwifiex_tdls_process_disable_link(priv, peer);
1203        case MWIFIEX_TDLS_CREATE_LINK:
1204                return mwifiex_tdls_process_create_link(priv, peer);
1205        case MWIFIEX_TDLS_CONFIG_LINK:
1206                return mwifiex_tdls_process_config_link(priv, peer);
1207        }
1208        return 0;
1209}
1210
1211int mwifiex_get_tdls_link_status(struct mwifiex_private *priv, const u8 *mac)
1212{
1213        struct mwifiex_sta_node *sta_ptr;
1214
1215        sta_ptr = mwifiex_get_sta_entry(priv, mac);
1216        if (sta_ptr)
1217                return sta_ptr->tdls_status;
1218
1219        return TDLS_NOT_SETUP;
1220}
1221
1222int mwifiex_get_tdls_list(struct mwifiex_private *priv,
1223                          struct tdls_peer_info *buf)
1224{
1225        struct mwifiex_sta_node *sta_ptr;
1226        struct tdls_peer_info *peer = buf;
1227        int count = 0;
1228
1229        if (!ISSUPP_TDLS_ENABLED(priv->adapter->fw_cap_info))
1230                return 0;
1231
1232        /* make sure we are in station mode and connected */
1233        if (!(priv->bss_type == MWIFIEX_BSS_TYPE_STA && priv->media_connected))
1234                return 0;
1235
1236        spin_lock_bh(&priv->sta_list_spinlock);
1237        list_for_each_entry(sta_ptr, &priv->sta_list, list) {
1238                if (mwifiex_is_tdls_link_setup(sta_ptr->tdls_status)) {
1239                        ether_addr_copy(peer->peer_addr, sta_ptr->mac_addr);
1240                        peer++;
1241                        count++;
1242                        if (count >= MWIFIEX_MAX_TDLS_PEER_SUPPORTED)
1243                                break;
1244                }
1245        }
1246        spin_unlock_bh(&priv->sta_list_spinlock);
1247
1248        return count;
1249}
1250
1251void mwifiex_disable_all_tdls_links(struct mwifiex_private *priv)
1252{
1253        struct mwifiex_sta_node *sta_ptr;
1254        struct mwifiex_ds_tdls_oper tdls_oper;
1255
1256        if (list_empty(&priv->sta_list))
1257                return;
1258
1259        list_for_each_entry(sta_ptr, &priv->sta_list, list) {
1260                memset(&tdls_oper, 0, sizeof(struct mwifiex_ds_tdls_oper));
1261
1262                if (sta_ptr->is_11n_enabled) {
1263                        mwifiex_11n_cleanup_reorder_tbl(priv);
1264                        spin_lock_bh(&priv->wmm.ra_list_spinlock);
1265                        mwifiex_11n_delete_all_tx_ba_stream_tbl(priv);
1266                        spin_unlock_bh(&priv->wmm.ra_list_spinlock);
1267                }
1268
1269                mwifiex_restore_tdls_packets(priv, sta_ptr->mac_addr,
1270                                             TDLS_LINK_TEARDOWN);
1271                memcpy(&tdls_oper.peer_mac, sta_ptr->mac_addr, ETH_ALEN);
1272                tdls_oper.tdls_action = MWIFIEX_TDLS_DISABLE_LINK;
1273                if (mwifiex_send_cmd(priv, HostCmd_CMD_TDLS_OPER,
1274                                     HostCmd_ACT_GEN_SET, 0, &tdls_oper, false))
1275                        mwifiex_dbg(priv->adapter, ERROR,
1276                                    "Disable link failed for TDLS peer %pM",
1277                                    sta_ptr->mac_addr);
1278        }
1279
1280        mwifiex_del_all_sta_list(priv);
1281}
1282
1283int mwifiex_tdls_check_tx(struct mwifiex_private *priv, struct sk_buff *skb)
1284{
1285        struct mwifiex_auto_tdls_peer *peer;
1286        u8 mac[ETH_ALEN];
1287
1288        ether_addr_copy(mac, skb->data);
1289
1290        spin_lock_bh(&priv->auto_tdls_lock);
1291        list_for_each_entry(peer, &priv->auto_tdls_list, list) {
1292                if (!memcmp(mac, peer->mac_addr, ETH_ALEN)) {
1293                        if (peer->rssi <= MWIFIEX_TDLS_RSSI_HIGH &&
1294                            peer->tdls_status == TDLS_NOT_SETUP &&
1295                            (peer->failure_count <
1296                             MWIFIEX_TDLS_MAX_FAIL_COUNT)) {
1297                                peer->tdls_status = TDLS_SETUP_INPROGRESS;
1298                                mwifiex_dbg(priv->adapter, INFO,
1299                                            "setup TDLS link, peer=%pM rssi=%d\n",
1300                                            peer->mac_addr, peer->rssi);
1301
1302                                cfg80211_tdls_oper_request(priv->netdev,
1303                                                           peer->mac_addr,
1304                                                           NL80211_TDLS_SETUP,
1305                                                           0, GFP_ATOMIC);
1306                                peer->do_setup = false;
1307                                priv->check_tdls_tx = false;
1308                        } else if (peer->failure_count <
1309                                   MWIFIEX_TDLS_MAX_FAIL_COUNT &&
1310                                   peer->do_discover) {
1311                                mwifiex_send_tdls_data_frame(priv,
1312                                                             peer->mac_addr,
1313                                                    WLAN_TDLS_DISCOVERY_REQUEST,
1314                                                             1, 0, NULL, 0);
1315                                peer->do_discover = false;
1316                        }
1317                }
1318        }
1319        spin_unlock_bh(&priv->auto_tdls_lock);
1320
1321        return 0;
1322}
1323
1324void mwifiex_flush_auto_tdls_list(struct mwifiex_private *priv)
1325{
1326        struct mwifiex_auto_tdls_peer *peer, *tmp_node;
1327
1328        spin_lock_bh(&priv->auto_tdls_lock);
1329        list_for_each_entry_safe(peer, tmp_node, &priv->auto_tdls_list, list) {
1330                list_del(&peer->list);
1331                kfree(peer);
1332        }
1333
1334        INIT_LIST_HEAD(&priv->auto_tdls_list);
1335        spin_unlock_bh(&priv->auto_tdls_lock);
1336        priv->check_tdls_tx = false;
1337}
1338
1339void mwifiex_add_auto_tdls_peer(struct mwifiex_private *priv, const u8 *mac)
1340{
1341        struct mwifiex_auto_tdls_peer *tdls_peer;
1342
1343        if (!priv->adapter->auto_tdls)
1344                return;
1345
1346        spin_lock_bh(&priv->auto_tdls_lock);
1347        list_for_each_entry(tdls_peer, &priv->auto_tdls_list, list) {
1348                if (!memcmp(tdls_peer->mac_addr, mac, ETH_ALEN)) {
1349                        tdls_peer->tdls_status = TDLS_SETUP_INPROGRESS;
1350                        tdls_peer->rssi_jiffies = jiffies;
1351                        spin_unlock_bh(&priv->auto_tdls_lock);
1352                        return;
1353                }
1354        }
1355
1356        /* create new TDLS peer */
1357        tdls_peer = kzalloc(sizeof(*tdls_peer), GFP_ATOMIC);
1358        if (tdls_peer) {
1359                ether_addr_copy(tdls_peer->mac_addr, mac);
1360                tdls_peer->tdls_status = TDLS_SETUP_INPROGRESS;
1361                tdls_peer->rssi_jiffies = jiffies;
1362                INIT_LIST_HEAD(&tdls_peer->list);
1363                list_add_tail(&tdls_peer->list, &priv->auto_tdls_list);
1364                mwifiex_dbg(priv->adapter, INFO,
1365                            "Add auto TDLS peer= %pM to list\n", mac);
1366        }
1367
1368        spin_unlock_bh(&priv->auto_tdls_lock);
1369}
1370
1371void mwifiex_auto_tdls_update_peer_status(struct mwifiex_private *priv,
1372                                          const u8 *mac, u8 link_status)
1373{
1374        struct mwifiex_auto_tdls_peer *peer;
1375
1376        if (!priv->adapter->auto_tdls)
1377                return;
1378
1379        spin_lock_bh(&priv->auto_tdls_lock);
1380        list_for_each_entry(peer, &priv->auto_tdls_list, list) {
1381                if (!memcmp(peer->mac_addr, mac, ETH_ALEN)) {
1382                        if ((link_status == TDLS_NOT_SETUP) &&
1383                            (peer->tdls_status == TDLS_SETUP_INPROGRESS))
1384                                peer->failure_count++;
1385                        else if (mwifiex_is_tdls_link_setup(link_status))
1386                                peer->failure_count = 0;
1387
1388                        peer->tdls_status = link_status;
1389                        break;
1390                }
1391        }
1392        spin_unlock_bh(&priv->auto_tdls_lock);
1393}
1394
1395void mwifiex_auto_tdls_update_peer_signal(struct mwifiex_private *priv,
1396                                          u8 *mac, s8 snr, s8 nflr)
1397{
1398        struct mwifiex_auto_tdls_peer *peer;
1399
1400        if (!priv->adapter->auto_tdls)
1401                return;
1402
1403        spin_lock_bh(&priv->auto_tdls_lock);
1404        list_for_each_entry(peer, &priv->auto_tdls_list, list) {
1405                if (!memcmp(peer->mac_addr, mac, ETH_ALEN)) {
1406                        peer->rssi = nflr - snr;
1407                        peer->rssi_jiffies = jiffies;
1408                        break;
1409                }
1410        }
1411        spin_unlock_bh(&priv->auto_tdls_lock);
1412}
1413
1414void mwifiex_check_auto_tdls(struct timer_list *t)
1415{
1416        struct mwifiex_private *priv = from_timer(priv, t, auto_tdls_timer);
1417        struct mwifiex_auto_tdls_peer *tdls_peer;
1418        u16 reason = WLAN_REASON_TDLS_TEARDOWN_UNSPECIFIED;
1419
1420        if (WARN_ON_ONCE(!priv || !priv->adapter)) {
1421                pr_err("mwifiex: %s: adapter or private structure is NULL\n",
1422                       __func__);
1423                return;
1424        }
1425
1426        if (unlikely(!priv->adapter->auto_tdls))
1427                return;
1428
1429        if (!priv->auto_tdls_timer_active) {
1430                mwifiex_dbg(priv->adapter, INFO,
1431                            "auto TDLS timer inactive; return");
1432                return;
1433        }
1434
1435        priv->check_tdls_tx = false;
1436
1437        spin_lock_bh(&priv->auto_tdls_lock);
1438        list_for_each_entry(tdls_peer, &priv->auto_tdls_list, list) {
1439                if ((jiffies - tdls_peer->rssi_jiffies) >
1440                    (MWIFIEX_AUTO_TDLS_IDLE_TIME * HZ)) {
1441                        tdls_peer->rssi = 0;
1442                        tdls_peer->do_discover = true;
1443                        priv->check_tdls_tx = true;
1444                }
1445
1446                if (((tdls_peer->rssi >= MWIFIEX_TDLS_RSSI_LOW) ||
1447                     !tdls_peer->rssi) &&
1448                    mwifiex_is_tdls_link_setup(tdls_peer->tdls_status)) {
1449                        tdls_peer->tdls_status = TDLS_LINK_TEARDOWN;
1450                        mwifiex_dbg(priv->adapter, MSG,
1451                                    "teardown TDLS link,peer=%pM rssi=%d\n",
1452                                    tdls_peer->mac_addr, -tdls_peer->rssi);
1453                        tdls_peer->do_discover = true;
1454                        priv->check_tdls_tx = true;
1455                        cfg80211_tdls_oper_request(priv->netdev,
1456                                                   tdls_peer->mac_addr,
1457                                                   NL80211_TDLS_TEARDOWN,
1458                                                   reason, GFP_ATOMIC);
1459                } else if (tdls_peer->rssi &&
1460                           tdls_peer->rssi <= MWIFIEX_TDLS_RSSI_HIGH &&
1461                           tdls_peer->tdls_status == TDLS_NOT_SETUP &&
1462                           tdls_peer->failure_count <
1463                           MWIFIEX_TDLS_MAX_FAIL_COUNT) {
1464                                priv->check_tdls_tx = true;
1465                                tdls_peer->do_setup = true;
1466                                mwifiex_dbg(priv->adapter, INFO,
1467                                            "check TDLS with peer=%pM\t"
1468                                            "rssi=%d\n", tdls_peer->mac_addr,
1469                                            tdls_peer->rssi);
1470                }
1471        }
1472        spin_unlock_bh(&priv->auto_tdls_lock);
1473
1474        mod_timer(&priv->auto_tdls_timer,
1475                  jiffies + msecs_to_jiffies(MWIFIEX_TIMER_10S));
1476}
1477
1478void mwifiex_setup_auto_tdls_timer(struct mwifiex_private *priv)
1479{
1480        timer_setup(&priv->auto_tdls_timer, mwifiex_check_auto_tdls, 0);
1481        priv->auto_tdls_timer_active = true;
1482        mod_timer(&priv->auto_tdls_timer,
1483                  jiffies + msecs_to_jiffies(MWIFIEX_TIMER_10S));
1484}
1485
1486void mwifiex_clean_auto_tdls(struct mwifiex_private *priv)
1487{
1488        if (ISSUPP_TDLS_ENABLED(priv->adapter->fw_cap_info) &&
1489            priv->adapter->auto_tdls &&
1490            priv->bss_type == MWIFIEX_BSS_TYPE_STA) {
1491                priv->auto_tdls_timer_active = false;
1492                del_timer(&priv->auto_tdls_timer);
1493                mwifiex_flush_auto_tdls_list(priv);
1494        }
1495}
1496
1497static int mwifiex_config_tdls(struct mwifiex_private *priv, u8 enable)
1498{
1499        struct mwifiex_tdls_config config;
1500
1501        config.enable = cpu_to_le16(enable);
1502        return mwifiex_send_cmd(priv, HostCmd_CMD_TDLS_CONFIG,
1503                                ACT_TDLS_CS_ENABLE_CONFIG, 0, &config, true);
1504}
1505
1506int mwifiex_config_tdls_enable(struct mwifiex_private *priv)
1507{
1508        return mwifiex_config_tdls(priv, true);
1509}
1510
1511int mwifiex_config_tdls_disable(struct mwifiex_private *priv)
1512{
1513        return mwifiex_config_tdls(priv, false);
1514}
1515
1516int mwifiex_config_tdls_cs_params(struct mwifiex_private *priv)
1517{
1518        struct mwifiex_tdls_config_cs_params config_tdls_cs_params;
1519
1520        config_tdls_cs_params.unit_time = MWIFIEX_DEF_CS_UNIT_TIME;
1521        config_tdls_cs_params.thr_otherlink = MWIFIEX_DEF_CS_THR_OTHERLINK;
1522        config_tdls_cs_params.thr_directlink = MWIFIEX_DEF_THR_DIRECTLINK;
1523
1524        return mwifiex_send_cmd(priv, HostCmd_CMD_TDLS_CONFIG,
1525                                ACT_TDLS_CS_PARAMS, 0,
1526                                &config_tdls_cs_params, true);
1527}
1528
1529int mwifiex_stop_tdls_cs(struct mwifiex_private *priv, const u8 *peer_mac)
1530{
1531        struct mwifiex_tdls_stop_cs_params stop_tdls_cs_params;
1532
1533        ether_addr_copy(stop_tdls_cs_params.peer_mac, peer_mac);
1534
1535        return mwifiex_send_cmd(priv, HostCmd_CMD_TDLS_CONFIG,
1536                                ACT_TDLS_CS_STOP, 0,
1537                                &stop_tdls_cs_params, true);
1538}
1539
1540int mwifiex_start_tdls_cs(struct mwifiex_private *priv, const u8 *peer_mac,
1541                          u8 primary_chan, u8 second_chan_offset, u8 band)
1542{
1543        struct mwifiex_tdls_init_cs_params start_tdls_cs_params;
1544
1545        ether_addr_copy(start_tdls_cs_params.peer_mac, peer_mac);
1546        start_tdls_cs_params.primary_chan = primary_chan;
1547        start_tdls_cs_params.second_chan_offset = second_chan_offset;
1548        start_tdls_cs_params.band = band;
1549
1550        start_tdls_cs_params.switch_time = cpu_to_le16(MWIFIEX_DEF_CS_TIME);
1551        start_tdls_cs_params.switch_timeout =
1552                                        cpu_to_le16(MWIFIEX_DEF_CS_TIMEOUT);
1553        start_tdls_cs_params.reg_class = MWIFIEX_DEF_CS_REG_CLASS;
1554        start_tdls_cs_params.periodicity = MWIFIEX_DEF_CS_PERIODICITY;
1555
1556        return mwifiex_send_cmd(priv, HostCmd_CMD_TDLS_CONFIG,
1557                                ACT_TDLS_CS_INIT, 0,
1558                                &start_tdls_cs_params, true);
1559}
1560