phy/rockchip: inno-hdmi: round clock rate down to closest 1000 Hz
[linux-2.6-microblaze.git] / drivers / net / wireless / marvell / mwifiex / tdls.c
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
29 static 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
84 static 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. */
117 static int
118 mwifiex_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
152 static 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
167 static 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
185 static int
186 mwifiex_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
233 static 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
355 static 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
371 static 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
380 static void
381 mwifiex_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
408 static void
409 mwifiex_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
428 static 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
439 static 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
451 static 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
463 static 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
611 static void
612 mwifiex_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
627 int 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
727 static int
728 mwifiex_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
809 int 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  */
890 void 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                         sta_ptr->tdls_cap.rates_len = pos[1];
957                         for (i = 0; i < pos[1]; i++)
958                                 sta_ptr->tdls_cap.rates[i] = pos[i + 2];
959                         break;
960
961                 case WLAN_EID_EXT_SUPP_RATES:
962                         basic = sta_ptr->tdls_cap.rates_len;
963                         for (i = 0; i < pos[1]; i++)
964                                 sta_ptr->tdls_cap.rates[basic + i] = pos[i + 2];
965                         sta_ptr->tdls_cap.rates_len += pos[1];
966                         break;
967                 case WLAN_EID_HT_CAPABILITY:
968                         memcpy((u8 *)&sta_ptr->tdls_cap.ht_capb, pos,
969                                sizeof(struct ieee80211_ht_cap));
970                         sta_ptr->is_11n_enabled = 1;
971                         break;
972                 case WLAN_EID_HT_OPERATION:
973                         memcpy(&sta_ptr->tdls_cap.ht_oper, pos,
974                                sizeof(struct ieee80211_ht_operation));
975                         break;
976                 case WLAN_EID_BSS_COEX_2040:
977                         sta_ptr->tdls_cap.coex_2040 = pos[2];
978                         break;
979                 case WLAN_EID_EXT_CAPABILITY:
980                         memcpy((u8 *)&sta_ptr->tdls_cap.extcap, pos,
981                                sizeof(struct ieee_types_header) +
982                                min_t(u8, pos[1], 8));
983                         break;
984                 case WLAN_EID_RSN:
985                         memcpy((u8 *)&sta_ptr->tdls_cap.rsn_ie, pos,
986                                sizeof(struct ieee_types_header) +
987                                min_t(u8, pos[1], IEEE_MAX_IE_SIZE -
988                                      sizeof(struct ieee_types_header)));
989                         break;
990                 case WLAN_EID_QOS_CAPA:
991                         sta_ptr->tdls_cap.qos_info = pos[2];
992                         break;
993                 case WLAN_EID_VHT_OPERATION:
994                         if (priv->adapter->is_hw_11ac_capable)
995                                 memcpy(&sta_ptr->tdls_cap.vhtoper, pos,
996                                        sizeof(struct ieee80211_vht_operation));
997                         break;
998                 case WLAN_EID_VHT_CAPABILITY:
999                         if (priv->adapter->is_hw_11ac_capable) {
1000                                 memcpy((u8 *)&sta_ptr->tdls_cap.vhtcap, pos,
1001                                        sizeof(struct ieee80211_vht_cap));
1002                                 sta_ptr->is_11ac_enabled = 1;
1003                         }
1004                         break;
1005                 case WLAN_EID_AID:
1006                         if (priv->adapter->is_hw_11ac_capable)
1007                                 sta_ptr->tdls_cap.aid =
1008                                         get_unaligned_le16((pos + 2));
1009                 default:
1010                         break;
1011                 }
1012         }
1013
1014         return;
1015 }
1016
1017 static int
1018 mwifiex_tdls_process_config_link(struct mwifiex_private *priv, const u8 *peer)
1019 {
1020         struct mwifiex_sta_node *sta_ptr;
1021         struct mwifiex_ds_tdls_oper tdls_oper;
1022
1023         memset(&tdls_oper, 0, sizeof(struct mwifiex_ds_tdls_oper));
1024         sta_ptr = mwifiex_get_sta_entry(priv, peer);
1025
1026         if (!sta_ptr || sta_ptr->tdls_status == TDLS_SETUP_FAILURE) {
1027                 mwifiex_dbg(priv->adapter, ERROR,
1028                             "link absent for peer %pM; cannot config\n", peer);
1029                 return -EINVAL;
1030         }
1031
1032         memcpy(&tdls_oper.peer_mac, peer, ETH_ALEN);
1033         tdls_oper.tdls_action = MWIFIEX_TDLS_CONFIG_LINK;
1034         return mwifiex_send_cmd(priv, HostCmd_CMD_TDLS_OPER,
1035                                 HostCmd_ACT_GEN_SET, 0, &tdls_oper, true);
1036 }
1037
1038 static int
1039 mwifiex_tdls_process_create_link(struct mwifiex_private *priv, const u8 *peer)
1040 {
1041         struct mwifiex_sta_node *sta_ptr;
1042         struct mwifiex_ds_tdls_oper tdls_oper;
1043
1044         memset(&tdls_oper, 0, sizeof(struct mwifiex_ds_tdls_oper));
1045         sta_ptr = mwifiex_get_sta_entry(priv, peer);
1046
1047         if (sta_ptr && sta_ptr->tdls_status == TDLS_SETUP_INPROGRESS) {
1048                 mwifiex_dbg(priv->adapter, WARN,
1049                             "Setup already in progress for peer %pM\n", peer);
1050                 return 0;
1051         }
1052
1053         sta_ptr = mwifiex_add_sta_entry(priv, peer);
1054         if (!sta_ptr)
1055                 return -ENOMEM;
1056
1057         sta_ptr->tdls_status = TDLS_SETUP_INPROGRESS;
1058         mwifiex_hold_tdls_packets(priv, peer);
1059         memcpy(&tdls_oper.peer_mac, peer, ETH_ALEN);
1060         tdls_oper.tdls_action = MWIFIEX_TDLS_CREATE_LINK;
1061         return mwifiex_send_cmd(priv, HostCmd_CMD_TDLS_OPER,
1062                                 HostCmd_ACT_GEN_SET, 0, &tdls_oper, true);
1063 }
1064
1065 static int
1066 mwifiex_tdls_process_disable_link(struct mwifiex_private *priv, const u8 *peer)
1067 {
1068         struct mwifiex_sta_node *sta_ptr;
1069         struct mwifiex_ds_tdls_oper tdls_oper;
1070
1071         memset(&tdls_oper, 0, sizeof(struct mwifiex_ds_tdls_oper));
1072         sta_ptr = mwifiex_get_sta_entry(priv, peer);
1073
1074         if (sta_ptr) {
1075                 if (sta_ptr->is_11n_enabled) {
1076                         mwifiex_11n_cleanup_reorder_tbl(priv);
1077                         spin_lock_bh(&priv->wmm.ra_list_spinlock);
1078                         mwifiex_11n_delete_all_tx_ba_stream_tbl(priv);
1079                         spin_unlock_bh(&priv->wmm.ra_list_spinlock);
1080                 }
1081                 mwifiex_del_sta_entry(priv, peer);
1082         }
1083
1084         mwifiex_restore_tdls_packets(priv, peer, TDLS_LINK_TEARDOWN);
1085         mwifiex_auto_tdls_update_peer_status(priv, peer, TDLS_NOT_SETUP);
1086         memcpy(&tdls_oper.peer_mac, peer, ETH_ALEN);
1087         tdls_oper.tdls_action = MWIFIEX_TDLS_DISABLE_LINK;
1088         return mwifiex_send_cmd(priv, HostCmd_CMD_TDLS_OPER,
1089                                 HostCmd_ACT_GEN_SET, 0, &tdls_oper, true);
1090 }
1091
1092 static int
1093 mwifiex_tdls_process_enable_link(struct mwifiex_private *priv, const u8 *peer)
1094 {
1095         struct mwifiex_sta_node *sta_ptr;
1096         struct ieee80211_mcs_info mcs;
1097         int i;
1098
1099         sta_ptr = mwifiex_get_sta_entry(priv, peer);
1100
1101         if (sta_ptr && (sta_ptr->tdls_status != TDLS_SETUP_FAILURE)) {
1102                 mwifiex_dbg(priv->adapter, MSG,
1103                             "tdls: enable link %pM success\n", peer);
1104
1105                 sta_ptr->tdls_status = TDLS_SETUP_COMPLETE;
1106
1107                 mcs = sta_ptr->tdls_cap.ht_capb.mcs;
1108                 if (mcs.rx_mask[0] != 0xff)
1109                         sta_ptr->is_11n_enabled = true;
1110                 if (sta_ptr->is_11n_enabled) {
1111                         if (le16_to_cpu(sta_ptr->tdls_cap.ht_capb.cap_info) &
1112                             IEEE80211_HT_CAP_MAX_AMSDU)
1113                                 sta_ptr->max_amsdu =
1114                                         MWIFIEX_TX_DATA_BUF_SIZE_8K;
1115                         else
1116                                 sta_ptr->max_amsdu =
1117                                         MWIFIEX_TX_DATA_BUF_SIZE_4K;
1118
1119                         for (i = 0; i < MAX_NUM_TID; i++)
1120                                 sta_ptr->ampdu_sta[i] =
1121                                               priv->aggr_prio_tbl[i].ampdu_user;
1122                 } else {
1123                         for (i = 0; i < MAX_NUM_TID; i++)
1124                                 sta_ptr->ampdu_sta[i] = BA_STREAM_NOT_ALLOWED;
1125                 }
1126                 if (sta_ptr->tdls_cap.extcap.ext_capab[3] &
1127                     WLAN_EXT_CAPA4_TDLS_CHAN_SWITCH) {
1128                         mwifiex_config_tdls_enable(priv);
1129                         mwifiex_config_tdls_cs_params(priv);
1130                 }
1131
1132                 memset(sta_ptr->rx_seq, 0xff, sizeof(sta_ptr->rx_seq));
1133                 mwifiex_restore_tdls_packets(priv, peer, TDLS_SETUP_COMPLETE);
1134                 mwifiex_auto_tdls_update_peer_status(priv, peer,
1135                                                      TDLS_SETUP_COMPLETE);
1136         } else {
1137                 mwifiex_dbg(priv->adapter, ERROR,
1138                             "tdls: enable link %pM failed\n", peer);
1139                 if (sta_ptr) {
1140                         mwifiex_11n_cleanup_reorder_tbl(priv);
1141                         spin_lock_bh(&priv->wmm.ra_list_spinlock);
1142                         mwifiex_11n_delete_all_tx_ba_stream_tbl(priv);
1143                         spin_unlock_bh(&priv->wmm.ra_list_spinlock);
1144                         mwifiex_del_sta_entry(priv, peer);
1145                 }
1146                 mwifiex_restore_tdls_packets(priv, peer, TDLS_LINK_TEARDOWN);
1147                 mwifiex_auto_tdls_update_peer_status(priv, peer,
1148                                                      TDLS_NOT_SETUP);
1149
1150                 return -1;
1151         }
1152
1153         return 0;
1154 }
1155
1156 int mwifiex_tdls_oper(struct mwifiex_private *priv, const u8 *peer, u8 action)
1157 {
1158         switch (action) {
1159         case MWIFIEX_TDLS_ENABLE_LINK:
1160                 return mwifiex_tdls_process_enable_link(priv, peer);
1161         case MWIFIEX_TDLS_DISABLE_LINK:
1162                 return mwifiex_tdls_process_disable_link(priv, peer);
1163         case MWIFIEX_TDLS_CREATE_LINK:
1164                 return mwifiex_tdls_process_create_link(priv, peer);
1165         case MWIFIEX_TDLS_CONFIG_LINK:
1166                 return mwifiex_tdls_process_config_link(priv, peer);
1167         }
1168         return 0;
1169 }
1170
1171 int mwifiex_get_tdls_link_status(struct mwifiex_private *priv, const u8 *mac)
1172 {
1173         struct mwifiex_sta_node *sta_ptr;
1174
1175         sta_ptr = mwifiex_get_sta_entry(priv, mac);
1176         if (sta_ptr)
1177                 return sta_ptr->tdls_status;
1178
1179         return TDLS_NOT_SETUP;
1180 }
1181
1182 int mwifiex_get_tdls_list(struct mwifiex_private *priv,
1183                           struct tdls_peer_info *buf)
1184 {
1185         struct mwifiex_sta_node *sta_ptr;
1186         struct tdls_peer_info *peer = buf;
1187         int count = 0;
1188
1189         if (!ISSUPP_TDLS_ENABLED(priv->adapter->fw_cap_info))
1190                 return 0;
1191
1192         /* make sure we are in station mode and connected */
1193         if (!(priv->bss_type == MWIFIEX_BSS_TYPE_STA && priv->media_connected))
1194                 return 0;
1195
1196         spin_lock_bh(&priv->sta_list_spinlock);
1197         list_for_each_entry(sta_ptr, &priv->sta_list, list) {
1198                 if (mwifiex_is_tdls_link_setup(sta_ptr->tdls_status)) {
1199                         ether_addr_copy(peer->peer_addr, sta_ptr->mac_addr);
1200                         peer++;
1201                         count++;
1202                         if (count >= MWIFIEX_MAX_TDLS_PEER_SUPPORTED)
1203                                 break;
1204                 }
1205         }
1206         spin_unlock_bh(&priv->sta_list_spinlock);
1207
1208         return count;
1209 }
1210
1211 void mwifiex_disable_all_tdls_links(struct mwifiex_private *priv)
1212 {
1213         struct mwifiex_sta_node *sta_ptr;
1214         struct mwifiex_ds_tdls_oper tdls_oper;
1215
1216         if (list_empty(&priv->sta_list))
1217                 return;
1218
1219         list_for_each_entry(sta_ptr, &priv->sta_list, list) {
1220                 memset(&tdls_oper, 0, sizeof(struct mwifiex_ds_tdls_oper));
1221
1222                 if (sta_ptr->is_11n_enabled) {
1223                         mwifiex_11n_cleanup_reorder_tbl(priv);
1224                         spin_lock_bh(&priv->wmm.ra_list_spinlock);
1225                         mwifiex_11n_delete_all_tx_ba_stream_tbl(priv);
1226                         spin_unlock_bh(&priv->wmm.ra_list_spinlock);
1227                 }
1228
1229                 mwifiex_restore_tdls_packets(priv, sta_ptr->mac_addr,
1230                                              TDLS_LINK_TEARDOWN);
1231                 memcpy(&tdls_oper.peer_mac, sta_ptr->mac_addr, ETH_ALEN);
1232                 tdls_oper.tdls_action = MWIFIEX_TDLS_DISABLE_LINK;
1233                 if (mwifiex_send_cmd(priv, HostCmd_CMD_TDLS_OPER,
1234                                      HostCmd_ACT_GEN_SET, 0, &tdls_oper, false))
1235                         mwifiex_dbg(priv->adapter, ERROR,
1236                                     "Disable link failed for TDLS peer %pM",
1237                                     sta_ptr->mac_addr);
1238         }
1239
1240         mwifiex_del_all_sta_list(priv);
1241 }
1242
1243 int mwifiex_tdls_check_tx(struct mwifiex_private *priv, struct sk_buff *skb)
1244 {
1245         struct mwifiex_auto_tdls_peer *peer;
1246         u8 mac[ETH_ALEN];
1247
1248         ether_addr_copy(mac, skb->data);
1249
1250         spin_lock_bh(&priv->auto_tdls_lock);
1251         list_for_each_entry(peer, &priv->auto_tdls_list, list) {
1252                 if (!memcmp(mac, peer->mac_addr, ETH_ALEN)) {
1253                         if (peer->rssi <= MWIFIEX_TDLS_RSSI_HIGH &&
1254                             peer->tdls_status == TDLS_NOT_SETUP &&
1255                             (peer->failure_count <
1256                              MWIFIEX_TDLS_MAX_FAIL_COUNT)) {
1257                                 peer->tdls_status = TDLS_SETUP_INPROGRESS;
1258                                 mwifiex_dbg(priv->adapter, INFO,
1259                                             "setup TDLS link, peer=%pM rssi=%d\n",
1260                                             peer->mac_addr, peer->rssi);
1261
1262                                 cfg80211_tdls_oper_request(priv->netdev,
1263                                                            peer->mac_addr,
1264                                                            NL80211_TDLS_SETUP,
1265                                                            0, GFP_ATOMIC);
1266                                 peer->do_setup = false;
1267                                 priv->check_tdls_tx = false;
1268                         } else if (peer->failure_count <
1269                                    MWIFIEX_TDLS_MAX_FAIL_COUNT &&
1270                                    peer->do_discover) {
1271                                 mwifiex_send_tdls_data_frame(priv,
1272                                                              peer->mac_addr,
1273                                                     WLAN_TDLS_DISCOVERY_REQUEST,
1274                                                              1, 0, NULL, 0);
1275                                 peer->do_discover = false;
1276                         }
1277                 }
1278         }
1279         spin_unlock_bh(&priv->auto_tdls_lock);
1280
1281         return 0;
1282 }
1283
1284 void mwifiex_flush_auto_tdls_list(struct mwifiex_private *priv)
1285 {
1286         struct mwifiex_auto_tdls_peer *peer, *tmp_node;
1287
1288         spin_lock_bh(&priv->auto_tdls_lock);
1289         list_for_each_entry_safe(peer, tmp_node, &priv->auto_tdls_list, list) {
1290                 list_del(&peer->list);
1291                 kfree(peer);
1292         }
1293
1294         INIT_LIST_HEAD(&priv->auto_tdls_list);
1295         spin_unlock_bh(&priv->auto_tdls_lock);
1296         priv->check_tdls_tx = false;
1297 }
1298
1299 void mwifiex_add_auto_tdls_peer(struct mwifiex_private *priv, const u8 *mac)
1300 {
1301         struct mwifiex_auto_tdls_peer *tdls_peer;
1302
1303         if (!priv->adapter->auto_tdls)
1304                 return;
1305
1306         spin_lock_bh(&priv->auto_tdls_lock);
1307         list_for_each_entry(tdls_peer, &priv->auto_tdls_list, list) {
1308                 if (!memcmp(tdls_peer->mac_addr, mac, ETH_ALEN)) {
1309                         tdls_peer->tdls_status = TDLS_SETUP_INPROGRESS;
1310                         tdls_peer->rssi_jiffies = jiffies;
1311                         spin_unlock_bh(&priv->auto_tdls_lock);
1312                         return;
1313                 }
1314         }
1315
1316         /* create new TDLS peer */
1317         tdls_peer = kzalloc(sizeof(*tdls_peer), GFP_ATOMIC);
1318         if (tdls_peer) {
1319                 ether_addr_copy(tdls_peer->mac_addr, mac);
1320                 tdls_peer->tdls_status = TDLS_SETUP_INPROGRESS;
1321                 tdls_peer->rssi_jiffies = jiffies;
1322                 INIT_LIST_HEAD(&tdls_peer->list);
1323                 list_add_tail(&tdls_peer->list, &priv->auto_tdls_list);
1324                 mwifiex_dbg(priv->adapter, INFO,
1325                             "Add auto TDLS peer= %pM to list\n", mac);
1326         }
1327
1328         spin_unlock_bh(&priv->auto_tdls_lock);
1329 }
1330
1331 void mwifiex_auto_tdls_update_peer_status(struct mwifiex_private *priv,
1332                                           const u8 *mac, u8 link_status)
1333 {
1334         struct mwifiex_auto_tdls_peer *peer;
1335
1336         if (!priv->adapter->auto_tdls)
1337                 return;
1338
1339         spin_lock_bh(&priv->auto_tdls_lock);
1340         list_for_each_entry(peer, &priv->auto_tdls_list, list) {
1341                 if (!memcmp(peer->mac_addr, mac, ETH_ALEN)) {
1342                         if ((link_status == TDLS_NOT_SETUP) &&
1343                             (peer->tdls_status == TDLS_SETUP_INPROGRESS))
1344                                 peer->failure_count++;
1345                         else if (mwifiex_is_tdls_link_setup(link_status))
1346                                 peer->failure_count = 0;
1347
1348                         peer->tdls_status = link_status;
1349                         break;
1350                 }
1351         }
1352         spin_unlock_bh(&priv->auto_tdls_lock);
1353 }
1354
1355 void mwifiex_auto_tdls_update_peer_signal(struct mwifiex_private *priv,
1356                                           u8 *mac, s8 snr, s8 nflr)
1357 {
1358         struct mwifiex_auto_tdls_peer *peer;
1359
1360         if (!priv->adapter->auto_tdls)
1361                 return;
1362
1363         spin_lock_bh(&priv->auto_tdls_lock);
1364         list_for_each_entry(peer, &priv->auto_tdls_list, list) {
1365                 if (!memcmp(peer->mac_addr, mac, ETH_ALEN)) {
1366                         peer->rssi = nflr - snr;
1367                         peer->rssi_jiffies = jiffies;
1368                         break;
1369                 }
1370         }
1371         spin_unlock_bh(&priv->auto_tdls_lock);
1372 }
1373
1374 void mwifiex_check_auto_tdls(struct timer_list *t)
1375 {
1376         struct mwifiex_private *priv = from_timer(priv, t, auto_tdls_timer);
1377         struct mwifiex_auto_tdls_peer *tdls_peer;
1378         u16 reason = WLAN_REASON_TDLS_TEARDOWN_UNSPECIFIED;
1379
1380         if (WARN_ON_ONCE(!priv || !priv->adapter)) {
1381                 pr_err("mwifiex: %s: adapter or private structure is NULL\n",
1382                        __func__);
1383                 return;
1384         }
1385
1386         if (unlikely(!priv->adapter->auto_tdls))
1387                 return;
1388
1389         if (!priv->auto_tdls_timer_active) {
1390                 mwifiex_dbg(priv->adapter, INFO,
1391                             "auto TDLS timer inactive; return");
1392                 return;
1393         }
1394
1395         priv->check_tdls_tx = false;
1396
1397         spin_lock_bh(&priv->auto_tdls_lock);
1398         list_for_each_entry(tdls_peer, &priv->auto_tdls_list, list) {
1399                 if ((jiffies - tdls_peer->rssi_jiffies) >
1400                     (MWIFIEX_AUTO_TDLS_IDLE_TIME * HZ)) {
1401                         tdls_peer->rssi = 0;
1402                         tdls_peer->do_discover = true;
1403                         priv->check_tdls_tx = true;
1404                 }
1405
1406                 if (((tdls_peer->rssi >= MWIFIEX_TDLS_RSSI_LOW) ||
1407                      !tdls_peer->rssi) &&
1408                     mwifiex_is_tdls_link_setup(tdls_peer->tdls_status)) {
1409                         tdls_peer->tdls_status = TDLS_LINK_TEARDOWN;
1410                         mwifiex_dbg(priv->adapter, MSG,
1411                                     "teardown TDLS link,peer=%pM rssi=%d\n",
1412                                     tdls_peer->mac_addr, -tdls_peer->rssi);
1413                         tdls_peer->do_discover = true;
1414                         priv->check_tdls_tx = true;
1415                         cfg80211_tdls_oper_request(priv->netdev,
1416                                                    tdls_peer->mac_addr,
1417                                                    NL80211_TDLS_TEARDOWN,
1418                                                    reason, GFP_ATOMIC);
1419                 } else if (tdls_peer->rssi &&
1420                            tdls_peer->rssi <= MWIFIEX_TDLS_RSSI_HIGH &&
1421                            tdls_peer->tdls_status == TDLS_NOT_SETUP &&
1422                            tdls_peer->failure_count <
1423                            MWIFIEX_TDLS_MAX_FAIL_COUNT) {
1424                                 priv->check_tdls_tx = true;
1425                                 tdls_peer->do_setup = true;
1426                                 mwifiex_dbg(priv->adapter, INFO,
1427                                             "check TDLS with peer=%pM\t"
1428                                             "rssi=%d\n", tdls_peer->mac_addr,
1429                                             tdls_peer->rssi);
1430                 }
1431         }
1432         spin_unlock_bh(&priv->auto_tdls_lock);
1433
1434         mod_timer(&priv->auto_tdls_timer,
1435                   jiffies + msecs_to_jiffies(MWIFIEX_TIMER_10S));
1436 }
1437
1438 void mwifiex_setup_auto_tdls_timer(struct mwifiex_private *priv)
1439 {
1440         timer_setup(&priv->auto_tdls_timer, mwifiex_check_auto_tdls, 0);
1441         priv->auto_tdls_timer_active = true;
1442         mod_timer(&priv->auto_tdls_timer,
1443                   jiffies + msecs_to_jiffies(MWIFIEX_TIMER_10S));
1444 }
1445
1446 void mwifiex_clean_auto_tdls(struct mwifiex_private *priv)
1447 {
1448         if (ISSUPP_TDLS_ENABLED(priv->adapter->fw_cap_info) &&
1449             priv->adapter->auto_tdls &&
1450             priv->bss_type == MWIFIEX_BSS_TYPE_STA) {
1451                 priv->auto_tdls_timer_active = false;
1452                 del_timer(&priv->auto_tdls_timer);
1453                 mwifiex_flush_auto_tdls_list(priv);
1454         }
1455 }
1456
1457 static int mwifiex_config_tdls(struct mwifiex_private *priv, u8 enable)
1458 {
1459         struct mwifiex_tdls_config config;
1460
1461         config.enable = cpu_to_le16(enable);
1462         return mwifiex_send_cmd(priv, HostCmd_CMD_TDLS_CONFIG,
1463                                 ACT_TDLS_CS_ENABLE_CONFIG, 0, &config, true);
1464 }
1465
1466 int mwifiex_config_tdls_enable(struct mwifiex_private *priv)
1467 {
1468         return mwifiex_config_tdls(priv, true);
1469 }
1470
1471 int mwifiex_config_tdls_disable(struct mwifiex_private *priv)
1472 {
1473         return mwifiex_config_tdls(priv, false);
1474 }
1475
1476 int mwifiex_config_tdls_cs_params(struct mwifiex_private *priv)
1477 {
1478         struct mwifiex_tdls_config_cs_params config_tdls_cs_params;
1479
1480         config_tdls_cs_params.unit_time = MWIFIEX_DEF_CS_UNIT_TIME;
1481         config_tdls_cs_params.thr_otherlink = MWIFIEX_DEF_CS_THR_OTHERLINK;
1482         config_tdls_cs_params.thr_directlink = MWIFIEX_DEF_THR_DIRECTLINK;
1483
1484         return mwifiex_send_cmd(priv, HostCmd_CMD_TDLS_CONFIG,
1485                                 ACT_TDLS_CS_PARAMS, 0,
1486                                 &config_tdls_cs_params, true);
1487 }
1488
1489 int mwifiex_stop_tdls_cs(struct mwifiex_private *priv, const u8 *peer_mac)
1490 {
1491         struct mwifiex_tdls_stop_cs_params stop_tdls_cs_params;
1492
1493         ether_addr_copy(stop_tdls_cs_params.peer_mac, peer_mac);
1494
1495         return mwifiex_send_cmd(priv, HostCmd_CMD_TDLS_CONFIG,
1496                                 ACT_TDLS_CS_STOP, 0,
1497                                 &stop_tdls_cs_params, true);
1498 }
1499
1500 int mwifiex_start_tdls_cs(struct mwifiex_private *priv, const u8 *peer_mac,
1501                           u8 primary_chan, u8 second_chan_offset, u8 band)
1502 {
1503         struct mwifiex_tdls_init_cs_params start_tdls_cs_params;
1504
1505         ether_addr_copy(start_tdls_cs_params.peer_mac, peer_mac);
1506         start_tdls_cs_params.primary_chan = primary_chan;
1507         start_tdls_cs_params.second_chan_offset = second_chan_offset;
1508         start_tdls_cs_params.band = band;
1509
1510         start_tdls_cs_params.switch_time = cpu_to_le16(MWIFIEX_DEF_CS_TIME);
1511         start_tdls_cs_params.switch_timeout =
1512                                         cpu_to_le16(MWIFIEX_DEF_CS_TIMEOUT);
1513         start_tdls_cs_params.reg_class = MWIFIEX_DEF_CS_REG_CLASS;
1514         start_tdls_cs_params.periodicity = MWIFIEX_DEF_CS_PERIODICITY;
1515
1516         return mwifiex_send_cmd(priv, HostCmd_CMD_TDLS_CONFIG,
1517                                 ACT_TDLS_CS_INIT, 0,
1518                                 &start_tdls_cs_params, true);
1519 }