mwifiex: restart rxreorder timer correctly
[firefly-linux-kernel-4.4.55.git] / drivers / net / wireless / 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
28 static void mwifiex_restore_tdls_packets(struct mwifiex_private *priv,
29                                          const u8 *mac, u8 status)
30 {
31         struct mwifiex_ra_list_tbl *ra_list;
32         struct list_head *tid_list;
33         struct sk_buff *skb, *tmp;
34         struct mwifiex_txinfo *tx_info;
35         unsigned long flags;
36         u32 tid;
37         u8 tid_down;
38
39         dev_dbg(priv->adapter->dev, "%s: %pM\n", __func__, mac);
40         spin_lock_irqsave(&priv->wmm.ra_list_spinlock, flags);
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 (status == TDLS_SETUP_COMPLETE) {
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                         if (!list_empty(tid_list))
58                                 ra_list = list_first_entry(tid_list,
59                                               struct mwifiex_ra_list_tbl, list);
60                         else
61                                 ra_list = NULL;
62                         tx_info->flags &= ~MWIFIEX_BUF_FLAG_TDLS_PKT;
63                 }
64
65                 if (!ra_list) {
66                         mwifiex_write_data_complete(priv->adapter, skb, 0, -1);
67                         continue;
68                 }
69
70                 skb_queue_tail(&ra_list->skb_head, skb);
71
72                 ra_list->ba_pkt_count++;
73                 ra_list->total_pkt_count++;
74
75                 if (atomic_read(&priv->wmm.highest_queued_prio) <
76                                                        tos_to_tid_inv[tid_down])
77                         atomic_set(&priv->wmm.highest_queued_prio,
78                                    tos_to_tid_inv[tid_down]);
79
80                 atomic_inc(&priv->wmm.tx_pkts_queued);
81         }
82
83         spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, flags);
84         return;
85 }
86
87 static void mwifiex_hold_tdls_packets(struct mwifiex_private *priv,
88                                       const u8 *mac)
89 {
90         struct mwifiex_ra_list_tbl *ra_list;
91         struct list_head *ra_list_head;
92         struct sk_buff *skb, *tmp;
93         unsigned long flags;
94         int i;
95
96         dev_dbg(priv->adapter->dev, "%s: %pM\n", __func__, mac);
97         spin_lock_irqsave(&priv->wmm.ra_list_spinlock, flags);
98
99         for (i = 0; i < MAX_NUM_TID; i++) {
100                 if (!list_empty(&priv->wmm.tid_tbl_ptr[i].ra_list)) {
101                         ra_list_head = &priv->wmm.tid_tbl_ptr[i].ra_list;
102                         list_for_each_entry(ra_list, ra_list_head, list) {
103                                 skb_queue_walk_safe(&ra_list->skb_head, skb,
104                                                     tmp) {
105                                         if (!ether_addr_equal(mac, skb->data))
106                                                 continue;
107                                         __skb_unlink(skb, &ra_list->skb_head);
108                                         atomic_dec(&priv->wmm.tx_pkts_queued);
109                                         ra_list->total_pkt_count--;
110                                         skb_queue_tail(&priv->tdls_txq, skb);
111                                 }
112                         }
113                 }
114         }
115
116         spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, flags);
117         return;
118 }
119
120 /* This function appends rate TLV to scan config command. */
121 static int
122 mwifiex_tdls_append_rates_ie(struct mwifiex_private *priv,
123                              struct sk_buff *skb)
124 {
125         u8 rates[MWIFIEX_SUPPORTED_RATES], *pos;
126         u16 rates_size, supp_rates_size, ext_rates_size;
127
128         memset(rates, 0, sizeof(rates));
129         rates_size = mwifiex_get_supported_rates(priv, rates);
130
131         supp_rates_size = min_t(u16, rates_size, MWIFIEX_TDLS_SUPPORTED_RATES);
132
133         if (skb_tailroom(skb) < rates_size + 4) {
134                 dev_err(priv->adapter->dev,
135                         "Insuffient space while adding rates\n");
136                 return -ENOMEM;
137         }
138
139         pos = skb_put(skb, supp_rates_size + 2);
140         *pos++ = WLAN_EID_SUPP_RATES;
141         *pos++ = supp_rates_size;
142         memcpy(pos, rates, supp_rates_size);
143
144         if (rates_size > MWIFIEX_TDLS_SUPPORTED_RATES) {
145                 ext_rates_size = rates_size - MWIFIEX_TDLS_SUPPORTED_RATES;
146                 pos = skb_put(skb, ext_rates_size + 2);
147                 *pos++ = WLAN_EID_EXT_SUPP_RATES;
148                 *pos++ = ext_rates_size;
149                 memcpy(pos, rates + MWIFIEX_TDLS_SUPPORTED_RATES,
150                        ext_rates_size);
151         }
152
153         return 0;
154 }
155
156 static void mwifiex_tdls_add_aid(struct mwifiex_private *priv,
157                                 struct sk_buff *skb)
158 {
159         struct ieee_types_assoc_rsp *assoc_rsp;
160         u8 *pos;
161
162         assoc_rsp = (struct ieee_types_assoc_rsp *)&priv->assoc_rsp_buf;
163         pos = (void *)skb_put(skb, 4);
164         *pos++ = WLAN_EID_AID;
165         *pos++ = 2;
166         *pos++ = le16_to_cpu(assoc_rsp->a_id);
167
168         return;
169 }
170
171 static int mwifiex_tdls_add_vht_capab(struct mwifiex_private *priv,
172                                       struct sk_buff *skb)
173 {
174         struct ieee80211_vht_cap vht_cap;
175         u8 *pos;
176
177         pos = (void *)skb_put(skb, sizeof(struct ieee80211_vht_cap) + 2);
178         *pos++ = WLAN_EID_VHT_CAPABILITY;
179         *pos++ = sizeof(struct ieee80211_vht_cap);
180
181         memset(&vht_cap, 0, sizeof(struct ieee80211_vht_cap));
182
183         mwifiex_fill_vht_cap_tlv(priv, &vht_cap, priv->curr_bss_params.band);
184         memcpy(pos, &vht_cap, sizeof(vht_cap));
185
186         return 0;
187 }
188
189 static int
190 mwifiex_tdls_add_ht_oper(struct mwifiex_private *priv, const u8 *mac,
191                          u8 vht_enabled, struct sk_buff *skb)
192 {
193         struct ieee80211_ht_operation *ht_oper;
194         struct mwifiex_sta_node *sta_ptr;
195         struct mwifiex_bssdescriptor *bss_desc =
196                                         &priv->curr_bss_params.bss_descriptor;
197         u8 *pos;
198
199         sta_ptr = mwifiex_get_sta_entry(priv, mac);
200         if (unlikely(!sta_ptr)) {
201                 dev_warn(priv->adapter->dev,
202                          "TDLS peer station not found in list\n");
203                 return -1;
204         }
205
206         pos = (void *)skb_put(skb, sizeof(struct ieee80211_ht_operation) + 2);
207         *pos++ = WLAN_EID_HT_OPERATION;
208         *pos++ = sizeof(struct ieee80211_ht_operation);
209         ht_oper = (void *)pos;
210
211         ht_oper->primary_chan = bss_desc->channel;
212
213         /* follow AP's channel bandwidth */
214         if (ISSUPP_CHANWIDTH40(priv->adapter->hw_dot_11n_dev_cap) &&
215             bss_desc->bcn_ht_cap &&
216             ISALLOWED_CHANWIDTH40(bss_desc->bcn_ht_oper->ht_param))
217                 ht_oper->ht_param = bss_desc->bcn_ht_oper->ht_param;
218
219         if (vht_enabled) {
220                 ht_oper->ht_param =
221                           mwifiex_get_sec_chan_offset(bss_desc->channel);
222                 ht_oper->ht_param |= BIT(2);
223         }
224
225         memcpy(&sta_ptr->tdls_cap.ht_oper, ht_oper,
226                sizeof(struct ieee80211_ht_operation));
227
228         return 0;
229 }
230
231 static int mwifiex_tdls_add_vht_oper(struct mwifiex_private *priv,
232                                      const u8 *mac, struct sk_buff *skb)
233 {
234         struct mwifiex_bssdescriptor *bss_desc;
235         struct ieee80211_vht_operation *vht_oper;
236         struct ieee80211_vht_cap *vht_cap, *ap_vht_cap = NULL;
237         struct mwifiex_sta_node *sta_ptr;
238         struct mwifiex_adapter *adapter = priv->adapter;
239         u8 supp_chwd_set, peer_supp_chwd_set;
240         u8 *pos, ap_supp_chwd_set, chan_bw;
241         u16 mcs_map_user, mcs_map_resp, mcs_map_result;
242         u16 mcs_user, mcs_resp, nss;
243         u32 usr_vht_cap_info;
244
245         bss_desc = &priv->curr_bss_params.bss_descriptor;
246
247         sta_ptr = mwifiex_get_sta_entry(priv, mac);
248         if (unlikely(!sta_ptr)) {
249                 dev_warn(adapter->dev, "TDLS peer station not found in list\n");
250                 return -1;
251         }
252
253         if (!mwifiex_is_bss_in_11ac_mode(priv)) {
254                 if (sta_ptr->tdls_cap.extcap.ext_capab[7] &
255                    WLAN_EXT_CAPA8_TDLS_WIDE_BW_ENABLED) {
256                         dev_dbg(adapter->dev,
257                                 "TDLS peer doesn't support wider bandwitdh\n");
258                         return 0;
259                 }
260         } else {
261                 ap_vht_cap = bss_desc->bcn_vht_cap;
262         }
263
264         pos = (void *)skb_put(skb, sizeof(struct ieee80211_vht_operation) + 2);
265         *pos++ = WLAN_EID_VHT_OPERATION;
266         *pos++ = sizeof(struct ieee80211_vht_operation);
267         vht_oper = (struct ieee80211_vht_operation *)pos;
268
269         if (bss_desc->bss_band & BAND_A)
270                 usr_vht_cap_info = adapter->usr_dot_11ac_dev_cap_a;
271         else
272                 usr_vht_cap_info = adapter->usr_dot_11ac_dev_cap_bg;
273
274         /* find the minmum bandwith between AP/TDLS peers */
275         vht_cap = &sta_ptr->tdls_cap.vhtcap;
276         supp_chwd_set = GET_VHTCAP_CHWDSET(usr_vht_cap_info);
277         peer_supp_chwd_set =
278                          GET_VHTCAP_CHWDSET(le32_to_cpu(vht_cap->vht_cap_info));
279         supp_chwd_set = min_t(u8, supp_chwd_set, peer_supp_chwd_set);
280
281         /* We need check AP's bandwidth when TDLS_WIDER_BANDWIDTH is off */
282
283         if (ap_vht_cap && sta_ptr->tdls_cap.extcap.ext_capab[7] &
284             WLAN_EXT_CAPA8_TDLS_WIDE_BW_ENABLED) {
285                 ap_supp_chwd_set =
286                       GET_VHTCAP_CHWDSET(le32_to_cpu(ap_vht_cap->vht_cap_info));
287                 supp_chwd_set = min_t(u8, supp_chwd_set, ap_supp_chwd_set);
288         }
289
290         switch (supp_chwd_set) {
291         case IEEE80211_VHT_CHANWIDTH_80MHZ:
292                 vht_oper->chan_width = IEEE80211_VHT_CHANWIDTH_80MHZ;
293                 break;
294         case IEEE80211_VHT_CHANWIDTH_160MHZ:
295                 vht_oper->chan_width = IEEE80211_VHT_CHANWIDTH_160MHZ;
296                 break;
297         case IEEE80211_VHT_CHANWIDTH_80P80MHZ:
298                 vht_oper->chan_width = IEEE80211_VHT_CHANWIDTH_80P80MHZ;
299                 break;
300         default:
301                 vht_oper->chan_width = IEEE80211_VHT_CHANWIDTH_USE_HT;
302                 break;
303         }
304
305         mcs_map_user = GET_DEVRXMCSMAP(adapter->usr_dot_11ac_mcs_support);
306         mcs_map_resp = le16_to_cpu(vht_cap->supp_mcs.rx_mcs_map);
307         mcs_map_result = 0;
308
309         for (nss = 1; nss <= 8; nss++) {
310                 mcs_user = GET_VHTNSSMCS(mcs_map_user, nss);
311                 mcs_resp = GET_VHTNSSMCS(mcs_map_resp, nss);
312
313                 if ((mcs_user == IEEE80211_VHT_MCS_NOT_SUPPORTED) ||
314                     (mcs_resp == IEEE80211_VHT_MCS_NOT_SUPPORTED))
315                         SET_VHTNSSMCS(mcs_map_result, nss,
316                                       IEEE80211_VHT_MCS_NOT_SUPPORTED);
317                 else
318                         SET_VHTNSSMCS(mcs_map_result, nss,
319                                       min_t(u16, mcs_user, mcs_resp));
320         }
321
322         vht_oper->basic_mcs_set = cpu_to_le16(mcs_map_result);
323
324         switch (vht_oper->chan_width) {
325         case IEEE80211_VHT_CHANWIDTH_80MHZ:
326                 chan_bw = IEEE80211_VHT_CHANWIDTH_80MHZ;
327                 break;
328         case IEEE80211_VHT_CHANWIDTH_160MHZ:
329                 chan_bw = IEEE80211_VHT_CHANWIDTH_160MHZ;
330                 break;
331         case IEEE80211_VHT_CHANWIDTH_80P80MHZ:
332                 chan_bw = IEEE80211_VHT_CHANWIDTH_80MHZ;
333                 break;
334         default:
335                 chan_bw = IEEE80211_VHT_CHANWIDTH_USE_HT;
336                 break;
337         }
338         vht_oper->center_freq_seg1_idx =
339                         mwifiex_get_center_freq_index(priv, BAND_AAC,
340                                                       bss_desc->channel,
341                                                       chan_bw);
342
343         return 0;
344 }
345
346 static void mwifiex_tdls_add_ext_capab(struct mwifiex_private *priv,
347                                        struct sk_buff *skb)
348 {
349         struct ieee_types_extcap *extcap;
350
351         extcap = (void *)skb_put(skb, sizeof(struct ieee_types_extcap));
352         extcap->ieee_hdr.element_id = WLAN_EID_EXT_CAPABILITY;
353         extcap->ieee_hdr.len = 8;
354         memset(extcap->ext_capab, 0, 8);
355         extcap->ext_capab[4] |= WLAN_EXT_CAPA5_TDLS_ENABLED;
356
357         if (priv->adapter->is_hw_11ac_capable)
358                 extcap->ext_capab[7] |= WLAN_EXT_CAPA8_TDLS_WIDE_BW_ENABLED;
359 }
360
361 static void mwifiex_tdls_add_qos_capab(struct sk_buff *skb)
362 {
363         u8 *pos = (void *)skb_put(skb, 3);
364
365         *pos++ = WLAN_EID_QOS_CAPA;
366         *pos++ = 1;
367         *pos++ = MWIFIEX_TDLS_DEF_QOS_CAPAB;
368 }
369
370 static int mwifiex_prep_tdls_encap_data(struct mwifiex_private *priv,
371                                         const u8 *peer, u8 action_code,
372                                         u8 dialog_token,
373                                         u16 status_code, struct sk_buff *skb)
374 {
375         struct ieee80211_tdls_data *tf;
376         int ret;
377         u16 capab;
378         struct ieee80211_ht_cap *ht_cap;
379         u8 radio, *pos;
380
381         capab = priv->curr_bss_params.bss_descriptor.cap_info_bitmap;
382
383         tf = (void *)skb_put(skb, offsetof(struct ieee80211_tdls_data, u));
384         memcpy(tf->da, peer, ETH_ALEN);
385         memcpy(tf->sa, priv->curr_addr, ETH_ALEN);
386         tf->ether_type = cpu_to_be16(ETH_P_TDLS);
387         tf->payload_type = WLAN_TDLS_SNAP_RFTYPE;
388
389         switch (action_code) {
390         case WLAN_TDLS_SETUP_REQUEST:
391                 tf->category = WLAN_CATEGORY_TDLS;
392                 tf->action_code = WLAN_TDLS_SETUP_REQUEST;
393                 skb_put(skb, sizeof(tf->u.setup_req));
394                 tf->u.setup_req.dialog_token = dialog_token;
395                 tf->u.setup_req.capability = cpu_to_le16(capab);
396                 ret = mwifiex_tdls_append_rates_ie(priv, skb);
397                 if (ret) {
398                         dev_kfree_skb_any(skb);
399                         return ret;
400                 }
401
402                 pos = (void *)skb_put(skb, sizeof(struct ieee80211_ht_cap) + 2);
403                 *pos++ = WLAN_EID_HT_CAPABILITY;
404                 *pos++ = sizeof(struct ieee80211_ht_cap);
405                 ht_cap = (void *)pos;
406                 radio = mwifiex_band_to_radio_type(priv->curr_bss_params.band);
407                 ret = mwifiex_fill_cap_info(priv, radio, ht_cap);
408                 if (ret) {
409                         dev_kfree_skb_any(skb);
410                         return ret;
411                 }
412
413                 if (priv->adapter->is_hw_11ac_capable) {
414                         ret = mwifiex_tdls_add_vht_capab(priv, skb);
415                         if (ret) {
416                                 dev_kfree_skb_any(skb);
417                                 return ret;
418                         }
419                         mwifiex_tdls_add_aid(priv, skb);
420                 }
421
422                 mwifiex_tdls_add_ext_capab(priv, skb);
423                 mwifiex_tdls_add_qos_capab(skb);
424                 break;
425
426         case WLAN_TDLS_SETUP_RESPONSE:
427                 tf->category = WLAN_CATEGORY_TDLS;
428                 tf->action_code = WLAN_TDLS_SETUP_RESPONSE;
429                 skb_put(skb, sizeof(tf->u.setup_resp));
430                 tf->u.setup_resp.status_code = cpu_to_le16(status_code);
431                 tf->u.setup_resp.dialog_token = dialog_token;
432                 tf->u.setup_resp.capability = cpu_to_le16(capab);
433                 ret = mwifiex_tdls_append_rates_ie(priv, skb);
434                 if (ret) {
435                         dev_kfree_skb_any(skb);
436                         return ret;
437                 }
438
439                 pos = (void *)skb_put(skb, sizeof(struct ieee80211_ht_cap) + 2);
440                 *pos++ = WLAN_EID_HT_CAPABILITY;
441                 *pos++ = sizeof(struct ieee80211_ht_cap);
442                 ht_cap = (void *)pos;
443                 radio = mwifiex_band_to_radio_type(priv->curr_bss_params.band);
444                 ret = mwifiex_fill_cap_info(priv, radio, ht_cap);
445                 if (ret) {
446                         dev_kfree_skb_any(skb);
447                         return ret;
448                 }
449
450                 if (priv->adapter->is_hw_11ac_capable) {
451                         ret = mwifiex_tdls_add_vht_capab(priv, skb);
452                         if (ret) {
453                                 dev_kfree_skb_any(skb);
454                                 return ret;
455                         }
456                         mwifiex_tdls_add_aid(priv, skb);
457                 }
458
459                 mwifiex_tdls_add_ext_capab(priv, skb);
460                 mwifiex_tdls_add_qos_capab(skb);
461                 break;
462
463         case WLAN_TDLS_SETUP_CONFIRM:
464                 tf->category = WLAN_CATEGORY_TDLS;
465                 tf->action_code = WLAN_TDLS_SETUP_CONFIRM;
466                 skb_put(skb, sizeof(tf->u.setup_cfm));
467                 tf->u.setup_cfm.status_code = cpu_to_le16(status_code);
468                 tf->u.setup_cfm.dialog_token = dialog_token;
469                 if (priv->adapter->is_hw_11ac_capable) {
470                         ret = mwifiex_tdls_add_vht_oper(priv, peer, skb);
471                         if (ret) {
472                                 dev_kfree_skb_any(skb);
473                                 return ret;
474                         }
475                         ret = mwifiex_tdls_add_ht_oper(priv, peer, 1, skb);
476                         if (ret) {
477                                 dev_kfree_skb_any(skb);
478                                 return ret;
479                         }
480                 } else {
481                         ret = mwifiex_tdls_add_ht_oper(priv, peer, 0, skb);
482                         if (ret) {
483                                 dev_kfree_skb_any(skb);
484                                 return ret;
485                         }
486                 }
487                 break;
488
489         case WLAN_TDLS_TEARDOWN:
490                 tf->category = WLAN_CATEGORY_TDLS;
491                 tf->action_code = WLAN_TDLS_TEARDOWN;
492                 skb_put(skb, sizeof(tf->u.teardown));
493                 tf->u.teardown.reason_code = cpu_to_le16(status_code);
494                 break;
495
496         case WLAN_TDLS_DISCOVERY_REQUEST:
497                 tf->category = WLAN_CATEGORY_TDLS;
498                 tf->action_code = WLAN_TDLS_DISCOVERY_REQUEST;
499                 skb_put(skb, sizeof(tf->u.discover_req));
500                 tf->u.discover_req.dialog_token = dialog_token;
501                 break;
502         default:
503                 dev_err(priv->adapter->dev, "Unknown TDLS frame type.\n");
504                 return -EINVAL;
505         }
506
507         return 0;
508 }
509
510 static void
511 mwifiex_tdls_add_link_ie(struct sk_buff *skb, const u8 *src_addr,
512                          const u8 *peer, const u8 *bssid)
513 {
514         struct ieee80211_tdls_lnkie *lnkid;
515
516         lnkid = (void *)skb_put(skb, sizeof(struct ieee80211_tdls_lnkie));
517         lnkid->ie_type = WLAN_EID_LINK_ID;
518         lnkid->ie_len = sizeof(struct ieee80211_tdls_lnkie) -
519                         sizeof(struct ieee_types_header);
520
521         memcpy(lnkid->bssid, bssid, ETH_ALEN);
522         memcpy(lnkid->init_sta, src_addr, ETH_ALEN);
523         memcpy(lnkid->resp_sta, peer, ETH_ALEN);
524 }
525
526 int mwifiex_send_tdls_data_frame(struct mwifiex_private *priv, const u8 *peer,
527                                  u8 action_code, u8 dialog_token,
528                                  u16 status_code, const u8 *extra_ies,
529                                  size_t extra_ies_len)
530 {
531         struct sk_buff *skb;
532         struct mwifiex_txinfo *tx_info;
533         int ret;
534         u16 skb_len;
535
536         skb_len = MWIFIEX_MIN_DATA_HEADER_LEN +
537                   max(sizeof(struct ieee80211_mgmt),
538                       sizeof(struct ieee80211_tdls_data)) +
539                   MWIFIEX_MGMT_FRAME_HEADER_SIZE +
540                   MWIFIEX_SUPPORTED_RATES +
541                   3 + /* Qos Info */
542                   sizeof(struct ieee_types_extcap) +
543                   sizeof(struct ieee80211_ht_cap) +
544                   sizeof(struct ieee_types_bss_co_2040) +
545                   sizeof(struct ieee80211_ht_operation) +
546                   sizeof(struct ieee80211_tdls_lnkie) +
547                   extra_ies_len;
548
549         if (priv->adapter->is_hw_11ac_capable)
550                 skb_len += sizeof(struct ieee_types_vht_cap) +
551                            sizeof(struct ieee_types_vht_oper) +
552                            sizeof(struct ieee_types_aid);
553
554         skb = dev_alloc_skb(skb_len);
555         if (!skb) {
556                 dev_err(priv->adapter->dev,
557                         "allocate skb failed for management frame\n");
558                 return -ENOMEM;
559         }
560         skb_reserve(skb, MWIFIEX_MIN_DATA_HEADER_LEN);
561
562         switch (action_code) {
563         case WLAN_TDLS_SETUP_REQUEST:
564         case WLAN_TDLS_SETUP_CONFIRM:
565         case WLAN_TDLS_TEARDOWN:
566         case WLAN_TDLS_DISCOVERY_REQUEST:
567                 ret = mwifiex_prep_tdls_encap_data(priv, peer, action_code,
568                                                    dialog_token, status_code,
569                                                    skb);
570                 if (ret) {
571                         dev_kfree_skb_any(skb);
572                         return ret;
573                 }
574                 if (extra_ies_len)
575                         memcpy(skb_put(skb, extra_ies_len), extra_ies,
576                                extra_ies_len);
577                 mwifiex_tdls_add_link_ie(skb, priv->curr_addr, peer,
578                                          priv->cfg_bssid);
579                 break;
580         case WLAN_TDLS_SETUP_RESPONSE:
581                 ret = mwifiex_prep_tdls_encap_data(priv, peer, action_code,
582                                                    dialog_token, status_code,
583                                                    skb);
584                 if (ret) {
585                         dev_kfree_skb_any(skb);
586                         return ret;
587                 }
588                 if (extra_ies_len)
589                         memcpy(skb_put(skb, extra_ies_len), extra_ies,
590                                extra_ies_len);
591                 mwifiex_tdls_add_link_ie(skb, peer, priv->curr_addr,
592                                          priv->cfg_bssid);
593                 break;
594         }
595
596         switch (action_code) {
597         case WLAN_TDLS_SETUP_REQUEST:
598         case WLAN_TDLS_SETUP_RESPONSE:
599                 skb->priority = MWIFIEX_PRIO_BK;
600                 break;
601         default:
602                 skb->priority = MWIFIEX_PRIO_VI;
603                 break;
604         }
605
606         tx_info = MWIFIEX_SKB_TXCB(skb);
607         memset(tx_info, 0, sizeof(*tx_info));
608         tx_info->bss_num = priv->bss_num;
609         tx_info->bss_type = priv->bss_type;
610
611         __net_timestamp(skb);
612         mwifiex_queue_tx_pkt(priv, skb);
613
614         return 0;
615 }
616
617 static int
618 mwifiex_construct_tdls_action_frame(struct mwifiex_private *priv,
619                                     const u8 *peer,
620                                     u8 action_code, u8 dialog_token,
621                                     u16 status_code, struct sk_buff *skb)
622 {
623         struct ieee80211_mgmt *mgmt;
624         u8 bc_addr[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
625         int ret;
626         u16 capab;
627         struct ieee80211_ht_cap *ht_cap;
628         u8 radio, *pos;
629
630         capab = priv->curr_bss_params.bss_descriptor.cap_info_bitmap;
631
632         mgmt = (void *)skb_put(skb, offsetof(struct ieee80211_mgmt, u));
633
634         memset(mgmt, 0, 24);
635         memcpy(mgmt->da, peer, ETH_ALEN);
636         memcpy(mgmt->sa, priv->curr_addr, ETH_ALEN);
637         memcpy(mgmt->bssid, priv->cfg_bssid, ETH_ALEN);
638         mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
639                                           IEEE80211_STYPE_ACTION);
640
641         /* add address 4 */
642         pos = skb_put(skb, ETH_ALEN);
643
644         switch (action_code) {
645         case WLAN_PUB_ACTION_TDLS_DISCOVER_RES:
646                 skb_put(skb, sizeof(mgmt->u.action.u.tdls_discover_resp) + 1);
647                 mgmt->u.action.category = WLAN_CATEGORY_PUBLIC;
648                 mgmt->u.action.u.tdls_discover_resp.action_code =
649                                               WLAN_PUB_ACTION_TDLS_DISCOVER_RES;
650                 mgmt->u.action.u.tdls_discover_resp.dialog_token =
651                                                                    dialog_token;
652                 mgmt->u.action.u.tdls_discover_resp.capability =
653                                                              cpu_to_le16(capab);
654                 /* move back for addr4 */
655                 memmove(pos + ETH_ALEN, &mgmt->u.action.category,
656                         sizeof(mgmt->u.action.u.tdls_discover_resp));
657                 /* init address 4 */
658                 memcpy(pos, bc_addr, ETH_ALEN);
659
660                 ret = mwifiex_tdls_append_rates_ie(priv, skb);
661                 if (ret) {
662                         dev_kfree_skb_any(skb);
663                         return ret;
664                 }
665
666                 pos = (void *)skb_put(skb, sizeof(struct ieee80211_ht_cap) + 2);
667                 *pos++ = WLAN_EID_HT_CAPABILITY;
668                 *pos++ = sizeof(struct ieee80211_ht_cap);
669                 ht_cap = (void *)pos;
670                 radio = mwifiex_band_to_radio_type(priv->curr_bss_params.band);
671                 ret = mwifiex_fill_cap_info(priv, radio, ht_cap);
672                 if (ret) {
673                         dev_kfree_skb_any(skb);
674                         return ret;
675                 }
676
677                 if (priv->adapter->is_hw_11ac_capable) {
678                         ret = mwifiex_tdls_add_vht_capab(priv, skb);
679                         if (ret) {
680                                 dev_kfree_skb_any(skb);
681                                 return ret;
682                         }
683                         mwifiex_tdls_add_aid(priv, skb);
684                 }
685
686                 mwifiex_tdls_add_ext_capab(priv, skb);
687                 mwifiex_tdls_add_qos_capab(skb);
688                 break;
689         default:
690                 dev_err(priv->adapter->dev, "Unknown TDLS action frame type\n");
691                 return -EINVAL;
692         }
693
694         return 0;
695 }
696
697 int mwifiex_send_tdls_action_frame(struct mwifiex_private *priv, const u8 *peer,
698                                    u8 action_code, u8 dialog_token,
699                                    u16 status_code, const u8 *extra_ies,
700                                    size_t extra_ies_len)
701 {
702         struct sk_buff *skb;
703         struct mwifiex_txinfo *tx_info;
704         u8 *pos;
705         u32 pkt_type, tx_control;
706         u16 pkt_len, skb_len;
707
708         skb_len = MWIFIEX_MIN_DATA_HEADER_LEN +
709                   max(sizeof(struct ieee80211_mgmt),
710                       sizeof(struct ieee80211_tdls_data)) +
711                   MWIFIEX_MGMT_FRAME_HEADER_SIZE +
712                   MWIFIEX_SUPPORTED_RATES +
713                   sizeof(struct ieee_types_extcap) +
714                   sizeof(struct ieee80211_ht_cap) +
715                   sizeof(struct ieee_types_bss_co_2040) +
716                   sizeof(struct ieee80211_ht_operation) +
717                   sizeof(struct ieee80211_tdls_lnkie) +
718                   extra_ies_len +
719                   3 + /* Qos Info */
720                   ETH_ALEN; /* Address4 */
721
722         if (priv->adapter->is_hw_11ac_capable)
723                 skb_len += sizeof(struct ieee_types_vht_cap) +
724                            sizeof(struct ieee_types_vht_oper) +
725                            sizeof(struct ieee_types_aid);
726
727         skb = dev_alloc_skb(skb_len);
728         if (!skb) {
729                 dev_err(priv->adapter->dev,
730                         "allocate skb failed for management frame\n");
731                 return -ENOMEM;
732         }
733
734         skb_reserve(skb, MWIFIEX_MIN_DATA_HEADER_LEN);
735
736         pkt_type = PKT_TYPE_MGMT;
737         tx_control = 0;
738         pos = skb_put(skb, MWIFIEX_MGMT_FRAME_HEADER_SIZE + sizeof(pkt_len));
739         memset(pos, 0, MWIFIEX_MGMT_FRAME_HEADER_SIZE + sizeof(pkt_len));
740         memcpy(pos, &pkt_type, sizeof(pkt_type));
741         memcpy(pos + sizeof(pkt_type), &tx_control, sizeof(tx_control));
742
743         if (mwifiex_construct_tdls_action_frame(priv, peer, action_code,
744                                                 dialog_token, status_code,
745                                                 skb)) {
746                 dev_kfree_skb_any(skb);
747                 return -EINVAL;
748         }
749
750         if (extra_ies_len)
751                 memcpy(skb_put(skb, extra_ies_len), extra_ies, extra_ies_len);
752
753         /* the TDLS link IE is always added last we are the responder */
754
755         mwifiex_tdls_add_link_ie(skb, peer, priv->curr_addr,
756                                  priv->cfg_bssid);
757
758         skb->priority = MWIFIEX_PRIO_VI;
759
760         tx_info = MWIFIEX_SKB_TXCB(skb);
761         memset(tx_info, 0, sizeof(*tx_info));
762         tx_info->bss_num = priv->bss_num;
763         tx_info->bss_type = priv->bss_type;
764         tx_info->flags |= MWIFIEX_BUF_FLAG_TDLS_PKT;
765
766         pkt_len = skb->len - MWIFIEX_MGMT_FRAME_HEADER_SIZE - sizeof(pkt_len);
767         memcpy(skb->data + MWIFIEX_MGMT_FRAME_HEADER_SIZE, &pkt_len,
768                sizeof(pkt_len));
769         __net_timestamp(skb);
770         mwifiex_queue_tx_pkt(priv, skb);
771
772         return 0;
773 }
774
775 /* This function process tdls action frame from peer.
776  * Peer capabilities are stored into station node structure.
777  */
778 void mwifiex_process_tdls_action_frame(struct mwifiex_private *priv,
779                                        u8 *buf, int len)
780 {
781         struct mwifiex_sta_node *sta_ptr;
782         u8 *peer, *pos, *end;
783         u8 i, action, basic;
784         __le16 cap = 0;
785         int ie_len = 0;
786
787         if (len < (sizeof(struct ethhdr) + 3))
788                 return;
789         if (*(buf + sizeof(struct ethhdr)) != WLAN_TDLS_SNAP_RFTYPE)
790                 return;
791         if (*(buf + sizeof(struct ethhdr) + 1) != WLAN_CATEGORY_TDLS)
792                 return;
793
794         peer = buf + ETH_ALEN;
795         action = *(buf + sizeof(struct ethhdr) + 2);
796         dev_dbg(priv->adapter->dev,
797                 "rx:tdls action: peer=%pM, action=%d\n", peer, action);
798
799         switch (action) {
800         case WLAN_TDLS_SETUP_REQUEST:
801                 if (len < (sizeof(struct ethhdr) + TDLS_REQ_FIX_LEN))
802                         return;
803
804                 pos = buf + sizeof(struct ethhdr) + 4;
805                 /* payload 1+ category 1 + action 1 + dialog 1 */
806                 cap = cpu_to_le16(*(u16 *)pos);
807                 ie_len = len - sizeof(struct ethhdr) - TDLS_REQ_FIX_LEN;
808                 pos += 2;
809                 break;
810
811         case WLAN_TDLS_SETUP_RESPONSE:
812                 if (len < (sizeof(struct ethhdr) + TDLS_RESP_FIX_LEN))
813                         return;
814                 /* payload 1+ category 1 + action 1 + dialog 1 + status code 2*/
815                 pos = buf + sizeof(struct ethhdr) + 6;
816                 cap = cpu_to_le16(*(u16 *)pos);
817                 ie_len = len - sizeof(struct ethhdr) - TDLS_RESP_FIX_LEN;
818                 pos += 2;
819                 break;
820
821         case WLAN_TDLS_SETUP_CONFIRM:
822                 if (len < (sizeof(struct ethhdr) + TDLS_CONFIRM_FIX_LEN))
823                         return;
824                 pos = buf + sizeof(struct ethhdr) + TDLS_CONFIRM_FIX_LEN;
825                 ie_len = len - sizeof(struct ethhdr) - TDLS_CONFIRM_FIX_LEN;
826                 break;
827         default:
828                 dev_dbg(priv->adapter->dev, "Unknown TDLS frame type.\n");
829                 return;
830         }
831
832         sta_ptr = mwifiex_add_sta_entry(priv, peer);
833         if (!sta_ptr)
834                 return;
835
836         sta_ptr->tdls_cap.capab = cap;
837
838         for (end = pos + ie_len; pos + 1 < end; pos += 2 + pos[1]) {
839                 if (pos + 2 + pos[1] > end)
840                         break;
841
842                 switch (*pos) {
843                 case WLAN_EID_SUPP_RATES:
844                         sta_ptr->tdls_cap.rates_len = pos[1];
845                         for (i = 0; i < pos[1]; i++)
846                                 sta_ptr->tdls_cap.rates[i] = pos[i + 2];
847                         break;
848
849                 case WLAN_EID_EXT_SUPP_RATES:
850                         basic = sta_ptr->tdls_cap.rates_len;
851                         for (i = 0; i < pos[1]; i++)
852                                 sta_ptr->tdls_cap.rates[basic + i] = pos[i + 2];
853                         sta_ptr->tdls_cap.rates_len += pos[1];
854                         break;
855                 case WLAN_EID_HT_CAPABILITY:
856                         memcpy((u8 *)&sta_ptr->tdls_cap.ht_capb, pos,
857                                sizeof(struct ieee80211_ht_cap));
858                         sta_ptr->is_11n_enabled = 1;
859                         break;
860                 case WLAN_EID_HT_OPERATION:
861                         memcpy(&sta_ptr->tdls_cap.ht_oper, pos,
862                                sizeof(struct ieee80211_ht_operation));
863                         break;
864                 case WLAN_EID_BSS_COEX_2040:
865                         sta_ptr->tdls_cap.coex_2040 = pos[2];
866                         break;
867                 case WLAN_EID_EXT_CAPABILITY:
868                         memcpy((u8 *)&sta_ptr->tdls_cap.extcap, pos,
869                                sizeof(struct ieee_types_header) +
870                                min_t(u8, pos[1], 8));
871                         break;
872                 case WLAN_EID_RSN:
873                         memcpy((u8 *)&sta_ptr->tdls_cap.rsn_ie, pos,
874                                sizeof(struct ieee_types_header) +
875                                min_t(u8, pos[1], IEEE_MAX_IE_SIZE -
876                                      sizeof(struct ieee_types_header)));
877                         break;
878                 case WLAN_EID_QOS_CAPA:
879                         sta_ptr->tdls_cap.qos_info = pos[2];
880                         break;
881                 case WLAN_EID_VHT_OPERATION:
882                         if (priv->adapter->is_hw_11ac_capable)
883                                 memcpy(&sta_ptr->tdls_cap.vhtoper, pos,
884                                        sizeof(struct ieee80211_vht_operation));
885                         break;
886                 case WLAN_EID_VHT_CAPABILITY:
887                         if (priv->adapter->is_hw_11ac_capable) {
888                                 memcpy((u8 *)&sta_ptr->tdls_cap.vhtcap, pos,
889                                        sizeof(struct ieee80211_vht_cap));
890                                 sta_ptr->is_11ac_enabled = 1;
891                         }
892                         break;
893                 case WLAN_EID_AID:
894                         if (priv->adapter->is_hw_11ac_capable)
895                                 sta_ptr->tdls_cap.aid =
896                                               le16_to_cpu(*(__le16 *)(pos + 2));
897                 default:
898                         break;
899                 }
900         }
901
902         return;
903 }
904
905 static int
906 mwifiex_tdls_process_config_link(struct mwifiex_private *priv, const u8 *peer)
907 {
908         struct mwifiex_sta_node *sta_ptr;
909         struct mwifiex_ds_tdls_oper tdls_oper;
910
911         memset(&tdls_oper, 0, sizeof(struct mwifiex_ds_tdls_oper));
912         sta_ptr = mwifiex_get_sta_entry(priv, peer);
913
914         if (!sta_ptr || sta_ptr->tdls_status == TDLS_SETUP_FAILURE) {
915                 dev_err(priv->adapter->dev,
916                         "link absent for peer %pM; cannot config\n", peer);
917                 return -EINVAL;
918         }
919
920         memcpy(&tdls_oper.peer_mac, peer, ETH_ALEN);
921         tdls_oper.tdls_action = MWIFIEX_TDLS_CONFIG_LINK;
922         return mwifiex_send_cmd(priv, HostCmd_CMD_TDLS_OPER,
923                                 HostCmd_ACT_GEN_SET, 0, &tdls_oper, true);
924 }
925
926 static int
927 mwifiex_tdls_process_create_link(struct mwifiex_private *priv, const u8 *peer)
928 {
929         struct mwifiex_sta_node *sta_ptr;
930         struct mwifiex_ds_tdls_oper tdls_oper;
931
932         memset(&tdls_oper, 0, sizeof(struct mwifiex_ds_tdls_oper));
933         sta_ptr = mwifiex_get_sta_entry(priv, peer);
934
935         if (sta_ptr && sta_ptr->tdls_status == TDLS_SETUP_INPROGRESS) {
936                 dev_dbg(priv->adapter->dev,
937                         "Setup already in progress for peer %pM\n", peer);
938                 return 0;
939         }
940
941         sta_ptr = mwifiex_add_sta_entry(priv, peer);
942         if (!sta_ptr)
943                 return -ENOMEM;
944
945         sta_ptr->tdls_status = TDLS_SETUP_INPROGRESS;
946         mwifiex_hold_tdls_packets(priv, peer);
947         memcpy(&tdls_oper.peer_mac, peer, ETH_ALEN);
948         tdls_oper.tdls_action = MWIFIEX_TDLS_CREATE_LINK;
949         return mwifiex_send_cmd(priv, HostCmd_CMD_TDLS_OPER,
950                                 HostCmd_ACT_GEN_SET, 0, &tdls_oper, true);
951 }
952
953 static int
954 mwifiex_tdls_process_disable_link(struct mwifiex_private *priv, const u8 *peer)
955 {
956         struct mwifiex_sta_node *sta_ptr;
957         struct mwifiex_ds_tdls_oper tdls_oper;
958         unsigned long flags;
959
960         memset(&tdls_oper, 0, sizeof(struct mwifiex_ds_tdls_oper));
961         sta_ptr = mwifiex_get_sta_entry(priv, peer);
962
963         if (sta_ptr) {
964                 if (sta_ptr->is_11n_enabled) {
965                         mwifiex_11n_cleanup_reorder_tbl(priv);
966                         spin_lock_irqsave(&priv->wmm.ra_list_spinlock,
967                                           flags);
968                         mwifiex_11n_delete_all_tx_ba_stream_tbl(priv);
969                         spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock,
970                                                flags);
971                 }
972                 mwifiex_del_sta_entry(priv, peer);
973         }
974
975         mwifiex_restore_tdls_packets(priv, peer, TDLS_LINK_TEARDOWN);
976         memcpy(&tdls_oper.peer_mac, peer, ETH_ALEN);
977         tdls_oper.tdls_action = MWIFIEX_TDLS_DISABLE_LINK;
978         return mwifiex_send_cmd(priv, HostCmd_CMD_TDLS_OPER,
979                                 HostCmd_ACT_GEN_SET, 0, &tdls_oper, true);
980 }
981
982 static int
983 mwifiex_tdls_process_enable_link(struct mwifiex_private *priv, const u8 *peer)
984 {
985         struct mwifiex_sta_node *sta_ptr;
986         struct ieee80211_mcs_info mcs;
987         unsigned long flags;
988         int i;
989
990         sta_ptr = mwifiex_get_sta_entry(priv, peer);
991
992         if (sta_ptr && (sta_ptr->tdls_status != TDLS_SETUP_FAILURE)) {
993                 dev_dbg(priv->adapter->dev,
994                         "tdls: enable link %pM success\n", peer);
995
996                 sta_ptr->tdls_status = TDLS_SETUP_COMPLETE;
997
998                 mcs = sta_ptr->tdls_cap.ht_capb.mcs;
999                 if (mcs.rx_mask[0] != 0xff)
1000                         sta_ptr->is_11n_enabled = true;
1001                 if (sta_ptr->is_11n_enabled) {
1002                         if (le16_to_cpu(sta_ptr->tdls_cap.ht_capb.cap_info) &
1003                             IEEE80211_HT_CAP_MAX_AMSDU)
1004                                 sta_ptr->max_amsdu =
1005                                         MWIFIEX_TX_DATA_BUF_SIZE_8K;
1006                         else
1007                                 sta_ptr->max_amsdu =
1008                                         MWIFIEX_TX_DATA_BUF_SIZE_4K;
1009
1010                         for (i = 0; i < MAX_NUM_TID; i++)
1011                                 sta_ptr->ampdu_sta[i] =
1012                                               priv->aggr_prio_tbl[i].ampdu_user;
1013                 } else {
1014                         for (i = 0; i < MAX_NUM_TID; i++)
1015                                 sta_ptr->ampdu_sta[i] = BA_STREAM_NOT_ALLOWED;
1016                 }
1017
1018                 memset(sta_ptr->rx_seq, 0xff, sizeof(sta_ptr->rx_seq));
1019                 mwifiex_restore_tdls_packets(priv, peer, TDLS_SETUP_COMPLETE);
1020         } else {
1021                 dev_dbg(priv->adapter->dev,
1022                         "tdls: enable link %pM failed\n", peer);
1023                 if (sta_ptr) {
1024                         mwifiex_11n_cleanup_reorder_tbl(priv);
1025                         spin_lock_irqsave(&priv->wmm.ra_list_spinlock,
1026                                           flags);
1027                         mwifiex_11n_delete_all_tx_ba_stream_tbl(priv);
1028                         spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock,
1029                                                flags);
1030                         mwifiex_del_sta_entry(priv, peer);
1031                 }
1032                 mwifiex_restore_tdls_packets(priv, peer, TDLS_LINK_TEARDOWN);
1033
1034                 return -1;
1035         }
1036
1037         return 0;
1038 }
1039
1040 int mwifiex_tdls_oper(struct mwifiex_private *priv, const u8 *peer, u8 action)
1041 {
1042         switch (action) {
1043         case MWIFIEX_TDLS_ENABLE_LINK:
1044                 return mwifiex_tdls_process_enable_link(priv, peer);
1045         case MWIFIEX_TDLS_DISABLE_LINK:
1046                 return mwifiex_tdls_process_disable_link(priv, peer);
1047         case MWIFIEX_TDLS_CREATE_LINK:
1048                 return mwifiex_tdls_process_create_link(priv, peer);
1049         case MWIFIEX_TDLS_CONFIG_LINK:
1050                 return mwifiex_tdls_process_config_link(priv, peer);
1051         }
1052         return 0;
1053 }
1054
1055 int mwifiex_get_tdls_link_status(struct mwifiex_private *priv, const u8 *mac)
1056 {
1057         struct mwifiex_sta_node *sta_ptr;
1058
1059         sta_ptr = mwifiex_get_sta_entry(priv, mac);
1060         if (sta_ptr)
1061                 return sta_ptr->tdls_status;
1062
1063         return TDLS_NOT_SETUP;
1064 }
1065
1066 void mwifiex_disable_all_tdls_links(struct mwifiex_private *priv)
1067 {
1068         struct mwifiex_sta_node *sta_ptr;
1069         struct mwifiex_ds_tdls_oper tdls_oper;
1070         unsigned long flags;
1071
1072         if (list_empty(&priv->sta_list))
1073                 return;
1074
1075         list_for_each_entry(sta_ptr, &priv->sta_list, list) {
1076                 memset(&tdls_oper, 0, sizeof(struct mwifiex_ds_tdls_oper));
1077
1078                 if (sta_ptr->is_11n_enabled) {
1079                         mwifiex_11n_cleanup_reorder_tbl(priv);
1080                         spin_lock_irqsave(&priv->wmm.ra_list_spinlock,
1081                                           flags);
1082                         mwifiex_11n_delete_all_tx_ba_stream_tbl(priv);
1083                         spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock,
1084                                                flags);
1085                 }
1086
1087                 mwifiex_restore_tdls_packets(priv, sta_ptr->mac_addr,
1088                                              TDLS_LINK_TEARDOWN);
1089                 memcpy(&tdls_oper.peer_mac, sta_ptr->mac_addr, ETH_ALEN);
1090                 tdls_oper.tdls_action = MWIFIEX_TDLS_DISABLE_LINK;
1091                 if (mwifiex_send_cmd(priv, HostCmd_CMD_TDLS_OPER,
1092                                      HostCmd_ACT_GEN_SET, 0, &tdls_oper, false))
1093                         dev_warn(priv->adapter->dev,
1094                                  "Disable link failed for TDLS peer %pM",
1095                                  sta_ptr->mac_addr);
1096         }
1097
1098         mwifiex_del_all_sta_list(priv);
1099 }