Merge tag 'stable/for-linus-3.16-rc7-tag' of git://git.kernel.org/pub/scm/linux/kerne...
[cascardo/linux.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         struct timeval tv;
534         int ret;
535         u16 skb_len;
536
537         skb_len = MWIFIEX_MIN_DATA_HEADER_LEN +
538                   max(sizeof(struct ieee80211_mgmt),
539                       sizeof(struct ieee80211_tdls_data)) +
540                   MWIFIEX_MGMT_FRAME_HEADER_SIZE +
541                   MWIFIEX_SUPPORTED_RATES +
542                   3 + /* Qos Info */
543                   sizeof(struct ieee_types_extcap) +
544                   sizeof(struct ieee80211_ht_cap) +
545                   sizeof(struct ieee_types_bss_co_2040) +
546                   sizeof(struct ieee80211_ht_operation) +
547                   sizeof(struct ieee80211_tdls_lnkie) +
548                   extra_ies_len;
549
550         if (priv->adapter->is_hw_11ac_capable)
551                 skb_len += sizeof(struct ieee_types_vht_cap) +
552                            sizeof(struct ieee_types_vht_oper) +
553                            sizeof(struct ieee_types_aid);
554
555         skb = dev_alloc_skb(skb_len);
556         if (!skb) {
557                 dev_err(priv->adapter->dev,
558                         "allocate skb failed for management frame\n");
559                 return -ENOMEM;
560         }
561         skb_reserve(skb, MWIFIEX_MIN_DATA_HEADER_LEN);
562
563         switch (action_code) {
564         case WLAN_TDLS_SETUP_REQUEST:
565         case WLAN_TDLS_SETUP_CONFIRM:
566         case WLAN_TDLS_TEARDOWN:
567         case WLAN_TDLS_DISCOVERY_REQUEST:
568                 ret = mwifiex_prep_tdls_encap_data(priv, peer, action_code,
569                                                    dialog_token, status_code,
570                                                    skb);
571                 if (ret) {
572                         dev_kfree_skb_any(skb);
573                         return ret;
574                 }
575                 if (extra_ies_len)
576                         memcpy(skb_put(skb, extra_ies_len), extra_ies,
577                                extra_ies_len);
578                 mwifiex_tdls_add_link_ie(skb, priv->curr_addr, peer,
579                                          priv->cfg_bssid);
580                 break;
581         case WLAN_TDLS_SETUP_RESPONSE:
582                 ret = mwifiex_prep_tdls_encap_data(priv, peer, action_code,
583                                                    dialog_token, status_code,
584                                                    skb);
585                 if (ret) {
586                         dev_kfree_skb_any(skb);
587                         return ret;
588                 }
589                 if (extra_ies_len)
590                         memcpy(skb_put(skb, extra_ies_len), extra_ies,
591                                extra_ies_len);
592                 mwifiex_tdls_add_link_ie(skb, peer, priv->curr_addr,
593                                          priv->cfg_bssid);
594                 break;
595         }
596
597         switch (action_code) {
598         case WLAN_TDLS_SETUP_REQUEST:
599         case WLAN_TDLS_SETUP_RESPONSE:
600                 skb->priority = MWIFIEX_PRIO_BK;
601                 break;
602         default:
603                 skb->priority = MWIFIEX_PRIO_VI;
604                 break;
605         }
606
607         tx_info = MWIFIEX_SKB_TXCB(skb);
608         memset(tx_info, 0, sizeof(*tx_info));
609         tx_info->bss_num = priv->bss_num;
610         tx_info->bss_type = priv->bss_type;
611
612         do_gettimeofday(&tv);
613         skb->tstamp = timeval_to_ktime(tv);
614         mwifiex_queue_tx_pkt(priv, skb);
615
616         return 0;
617 }
618
619 static int
620 mwifiex_construct_tdls_action_frame(struct mwifiex_private *priv,
621                                     const u8 *peer,
622                                     u8 action_code, u8 dialog_token,
623                                     u16 status_code, struct sk_buff *skb)
624 {
625         struct ieee80211_mgmt *mgmt;
626         u8 bc_addr[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
627         int ret;
628         u16 capab;
629         struct ieee80211_ht_cap *ht_cap;
630         u8 radio, *pos;
631
632         capab = priv->curr_bss_params.bss_descriptor.cap_info_bitmap;
633
634         mgmt = (void *)skb_put(skb, offsetof(struct ieee80211_mgmt, u));
635
636         memset(mgmt, 0, 24);
637         memcpy(mgmt->da, peer, ETH_ALEN);
638         memcpy(mgmt->sa, priv->curr_addr, ETH_ALEN);
639         memcpy(mgmt->bssid, priv->cfg_bssid, ETH_ALEN);
640         mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
641                                           IEEE80211_STYPE_ACTION);
642
643         /* add address 4 */
644         pos = skb_put(skb, ETH_ALEN);
645
646         switch (action_code) {
647         case WLAN_PUB_ACTION_TDLS_DISCOVER_RES:
648                 skb_put(skb, sizeof(mgmt->u.action.u.tdls_discover_resp) + 1);
649                 mgmt->u.action.category = WLAN_CATEGORY_PUBLIC;
650                 mgmt->u.action.u.tdls_discover_resp.action_code =
651                                               WLAN_PUB_ACTION_TDLS_DISCOVER_RES;
652                 mgmt->u.action.u.tdls_discover_resp.dialog_token =
653                                                                    dialog_token;
654                 mgmt->u.action.u.tdls_discover_resp.capability =
655                                                              cpu_to_le16(capab);
656                 /* move back for addr4 */
657                 memmove(pos + ETH_ALEN, &mgmt->u.action.category,
658                         sizeof(mgmt->u.action.u.tdls_discover_resp));
659                 /* init address 4 */
660                 memcpy(pos, bc_addr, ETH_ALEN);
661
662                 ret = mwifiex_tdls_append_rates_ie(priv, skb);
663                 if (ret) {
664                         dev_kfree_skb_any(skb);
665                         return ret;
666                 }
667
668                 pos = (void *)skb_put(skb, sizeof(struct ieee80211_ht_cap) + 2);
669                 *pos++ = WLAN_EID_HT_CAPABILITY;
670                 *pos++ = sizeof(struct ieee80211_ht_cap);
671                 ht_cap = (void *)pos;
672                 radio = mwifiex_band_to_radio_type(priv->curr_bss_params.band);
673                 ret = mwifiex_fill_cap_info(priv, radio, ht_cap);
674                 if (ret) {
675                         dev_kfree_skb_any(skb);
676                         return ret;
677                 }
678
679                 if (priv->adapter->is_hw_11ac_capable) {
680                         ret = mwifiex_tdls_add_vht_capab(priv, skb);
681                         if (ret) {
682                                 dev_kfree_skb_any(skb);
683                                 return ret;
684                         }
685                         mwifiex_tdls_add_aid(priv, skb);
686                 }
687
688                 mwifiex_tdls_add_ext_capab(priv, skb);
689                 mwifiex_tdls_add_qos_capab(skb);
690                 break;
691         default:
692                 dev_err(priv->adapter->dev, "Unknown TDLS action frame type\n");
693                 return -EINVAL;
694         }
695
696         return 0;
697 }
698
699 int mwifiex_send_tdls_action_frame(struct mwifiex_private *priv, const u8 *peer,
700                                    u8 action_code, u8 dialog_token,
701                                    u16 status_code, const u8 *extra_ies,
702                                    size_t extra_ies_len)
703 {
704         struct sk_buff *skb;
705         struct mwifiex_txinfo *tx_info;
706         struct timeval tv;
707         u8 *pos;
708         u32 pkt_type, tx_control;
709         u16 pkt_len, skb_len;
710
711         skb_len = MWIFIEX_MIN_DATA_HEADER_LEN +
712                   max(sizeof(struct ieee80211_mgmt),
713                       sizeof(struct ieee80211_tdls_data)) +
714                   MWIFIEX_MGMT_FRAME_HEADER_SIZE +
715                   MWIFIEX_SUPPORTED_RATES +
716                   sizeof(struct ieee_types_extcap) +
717                   sizeof(struct ieee80211_ht_cap) +
718                   sizeof(struct ieee_types_bss_co_2040) +
719                   sizeof(struct ieee80211_ht_operation) +
720                   sizeof(struct ieee80211_tdls_lnkie) +
721                   extra_ies_len +
722                   3 + /* Qos Info */
723                   ETH_ALEN; /* Address4 */
724
725         if (priv->adapter->is_hw_11ac_capable)
726                 skb_len += sizeof(struct ieee_types_vht_cap) +
727                            sizeof(struct ieee_types_vht_oper) +
728                            sizeof(struct ieee_types_aid);
729
730         skb = dev_alloc_skb(skb_len);
731         if (!skb) {
732                 dev_err(priv->adapter->dev,
733                         "allocate skb failed for management frame\n");
734                 return -ENOMEM;
735         }
736
737         skb_reserve(skb, MWIFIEX_MIN_DATA_HEADER_LEN);
738
739         pkt_type = PKT_TYPE_MGMT;
740         tx_control = 0;
741         pos = skb_put(skb, MWIFIEX_MGMT_FRAME_HEADER_SIZE + sizeof(pkt_len));
742         memset(pos, 0, MWIFIEX_MGMT_FRAME_HEADER_SIZE + sizeof(pkt_len));
743         memcpy(pos, &pkt_type, sizeof(pkt_type));
744         memcpy(pos + sizeof(pkt_type), &tx_control, sizeof(tx_control));
745
746         if (mwifiex_construct_tdls_action_frame(priv, peer, action_code,
747                                                 dialog_token, status_code,
748                                                 skb)) {
749                 dev_kfree_skb_any(skb);
750                 return -EINVAL;
751         }
752
753         if (extra_ies_len)
754                 memcpy(skb_put(skb, extra_ies_len), extra_ies, extra_ies_len);
755
756         /* the TDLS link IE is always added last we are the responder */
757
758         mwifiex_tdls_add_link_ie(skb, peer, priv->curr_addr,
759                                  priv->cfg_bssid);
760
761         skb->priority = MWIFIEX_PRIO_VI;
762
763         tx_info = MWIFIEX_SKB_TXCB(skb);
764         memset(tx_info, 0, sizeof(*tx_info));
765         tx_info->bss_num = priv->bss_num;
766         tx_info->bss_type = priv->bss_type;
767         tx_info->flags |= MWIFIEX_BUF_FLAG_TDLS_PKT;
768
769         pkt_len = skb->len - MWIFIEX_MGMT_FRAME_HEADER_SIZE - sizeof(pkt_len);
770         memcpy(skb->data + MWIFIEX_MGMT_FRAME_HEADER_SIZE, &pkt_len,
771                sizeof(pkt_len));
772         do_gettimeofday(&tv);
773         skb->tstamp = timeval_to_ktime(tv);
774         mwifiex_queue_tx_pkt(priv, skb);
775
776         return 0;
777 }
778
779 /* This function process tdls action frame from peer.
780  * Peer capabilities are stored into station node structure.
781  */
782 void mwifiex_process_tdls_action_frame(struct mwifiex_private *priv,
783                                        u8 *buf, int len)
784 {
785         struct mwifiex_sta_node *sta_ptr;
786         u8 *peer, *pos, *end;
787         u8 i, action, basic;
788         int ie_len = 0;
789
790         if (len < (sizeof(struct ethhdr) + 3))
791                 return;
792         if (*(buf + sizeof(struct ethhdr)) != WLAN_TDLS_SNAP_RFTYPE)
793                 return;
794         if (*(buf + sizeof(struct ethhdr) + 1) != WLAN_CATEGORY_TDLS)
795                 return;
796
797         peer = buf + ETH_ALEN;
798         action = *(buf + sizeof(struct ethhdr) + 2);
799
800         /* just handle TDLS setup request/response/confirm */
801         if (action > WLAN_TDLS_SETUP_CONFIRM)
802                 return;
803
804         dev_dbg(priv->adapter->dev,
805                 "rx:tdls action: peer=%pM, action=%d\n", peer, action);
806
807         sta_ptr = mwifiex_add_sta_entry(priv, peer);
808         if (!sta_ptr)
809                 return;
810
811         switch (action) {
812         case WLAN_TDLS_SETUP_REQUEST:
813                 if (len < (sizeof(struct ethhdr) + TDLS_REQ_FIX_LEN))
814                         return;
815
816                 pos = buf + sizeof(struct ethhdr) + 4;
817                 /* payload 1+ category 1 + action 1 + dialog 1 */
818                 sta_ptr->tdls_cap.capab = cpu_to_le16(*(u16 *)pos);
819                 ie_len = len - sizeof(struct ethhdr) - TDLS_REQ_FIX_LEN;
820                 pos += 2;
821                 break;
822
823         case WLAN_TDLS_SETUP_RESPONSE:
824                 if (len < (sizeof(struct ethhdr) + TDLS_RESP_FIX_LEN))
825                         return;
826                 /* payload 1+ category 1 + action 1 + dialog 1 + status code 2*/
827                 pos = buf + sizeof(struct ethhdr) + 6;
828                 sta_ptr->tdls_cap.capab = cpu_to_le16(*(u16 *)pos);
829                 ie_len = len - sizeof(struct ethhdr) - TDLS_RESP_FIX_LEN;
830                 pos += 2;
831                 break;
832
833         case WLAN_TDLS_SETUP_CONFIRM:
834                 if (len < (sizeof(struct ethhdr) + TDLS_CONFIRM_FIX_LEN))
835                         return;
836                 pos = buf + sizeof(struct ethhdr) + TDLS_CONFIRM_FIX_LEN;
837                 ie_len = len - sizeof(struct ethhdr) - TDLS_CONFIRM_FIX_LEN;
838                 break;
839         default:
840                 dev_warn(priv->adapter->dev, "Unknown TDLS frame type.\n");
841                 return;
842         }
843
844         for (end = pos + ie_len; pos + 1 < end; pos += 2 + pos[1]) {
845                 if (pos + 2 + pos[1] > end)
846                         break;
847
848                 switch (*pos) {
849                 case WLAN_EID_SUPP_RATES:
850                         sta_ptr->tdls_cap.rates_len = pos[1];
851                         for (i = 0; i < pos[1]; i++)
852                                 sta_ptr->tdls_cap.rates[i] = pos[i + 2];
853                         break;
854
855                 case WLAN_EID_EXT_SUPP_RATES:
856                         basic = sta_ptr->tdls_cap.rates_len;
857                         for (i = 0; i < pos[1]; i++)
858                                 sta_ptr->tdls_cap.rates[basic + i] = pos[i + 2];
859                         sta_ptr->tdls_cap.rates_len += pos[1];
860                         break;
861                 case WLAN_EID_HT_CAPABILITY:
862                         memcpy((u8 *)&sta_ptr->tdls_cap.ht_capb, pos,
863                                sizeof(struct ieee80211_ht_cap));
864                         sta_ptr->is_11n_enabled = 1;
865                         break;
866                 case WLAN_EID_HT_OPERATION:
867                         memcpy(&sta_ptr->tdls_cap.ht_oper, pos,
868                                sizeof(struct ieee80211_ht_operation));
869                         break;
870                 case WLAN_EID_BSS_COEX_2040:
871                         sta_ptr->tdls_cap.coex_2040 = pos[2];
872                         break;
873                 case WLAN_EID_EXT_CAPABILITY:
874                         memcpy((u8 *)&sta_ptr->tdls_cap.extcap, pos,
875                                sizeof(struct ieee_types_header) +
876                                min_t(u8, pos[1], 8));
877                         break;
878                 case WLAN_EID_RSN:
879                         memcpy((u8 *)&sta_ptr->tdls_cap.rsn_ie, pos,
880                                sizeof(struct ieee_types_header) + pos[1]);
881                         break;
882                 case WLAN_EID_QOS_CAPA:
883                         sta_ptr->tdls_cap.qos_info = pos[2];
884                         break;
885                 case WLAN_EID_VHT_OPERATION:
886                         if (priv->adapter->is_hw_11ac_capable)
887                                 memcpy(&sta_ptr->tdls_cap.vhtoper, pos,
888                                        sizeof(struct ieee80211_vht_operation));
889                         break;
890                 case WLAN_EID_VHT_CAPABILITY:
891                         if (priv->adapter->is_hw_11ac_capable) {
892                                 memcpy((u8 *)&sta_ptr->tdls_cap.vhtcap, pos,
893                                        sizeof(struct ieee80211_vht_cap));
894                                 sta_ptr->is_11ac_enabled = 1;
895                         }
896                         break;
897                 case WLAN_EID_AID:
898                         if (priv->adapter->is_hw_11ac_capable)
899                                 sta_ptr->tdls_cap.aid =
900                                               le16_to_cpu(*(__le16 *)(pos + 2));
901                 default:
902                         break;
903                 }
904         }
905
906         return;
907 }
908
909 static int
910 mwifiex_tdls_process_config_link(struct mwifiex_private *priv, const u8 *peer)
911 {
912         struct mwifiex_sta_node *sta_ptr;
913         struct mwifiex_ds_tdls_oper tdls_oper;
914
915         memset(&tdls_oper, 0, sizeof(struct mwifiex_ds_tdls_oper));
916         sta_ptr = mwifiex_get_sta_entry(priv, peer);
917
918         if (!sta_ptr || sta_ptr->tdls_status == TDLS_SETUP_FAILURE) {
919                 dev_err(priv->adapter->dev,
920                         "link absent for peer %pM; cannot config\n", peer);
921                 return -EINVAL;
922         }
923
924         memcpy(&tdls_oper.peer_mac, peer, ETH_ALEN);
925         tdls_oper.tdls_action = MWIFIEX_TDLS_CONFIG_LINK;
926         return mwifiex_send_cmd(priv, HostCmd_CMD_TDLS_OPER,
927                                 HostCmd_ACT_GEN_SET, 0, &tdls_oper, true);
928 }
929
930 static int
931 mwifiex_tdls_process_create_link(struct mwifiex_private *priv, const u8 *peer)
932 {
933         struct mwifiex_sta_node *sta_ptr;
934         struct mwifiex_ds_tdls_oper tdls_oper;
935
936         memset(&tdls_oper, 0, sizeof(struct mwifiex_ds_tdls_oper));
937         sta_ptr = mwifiex_get_sta_entry(priv, peer);
938
939         if (sta_ptr && sta_ptr->tdls_status == TDLS_SETUP_INPROGRESS) {
940                 dev_dbg(priv->adapter->dev,
941                         "Setup already in progress for peer %pM\n", peer);
942                 return 0;
943         }
944
945         sta_ptr = mwifiex_add_sta_entry(priv, peer);
946         if (!sta_ptr)
947                 return -ENOMEM;
948
949         sta_ptr->tdls_status = TDLS_SETUP_INPROGRESS;
950         mwifiex_hold_tdls_packets(priv, peer);
951         memcpy(&tdls_oper.peer_mac, peer, ETH_ALEN);
952         tdls_oper.tdls_action = MWIFIEX_TDLS_CREATE_LINK;
953         return mwifiex_send_cmd(priv, HostCmd_CMD_TDLS_OPER,
954                                 HostCmd_ACT_GEN_SET, 0, &tdls_oper, true);
955 }
956
957 static int
958 mwifiex_tdls_process_disable_link(struct mwifiex_private *priv, const u8 *peer)
959 {
960         struct mwifiex_sta_node *sta_ptr;
961         struct mwifiex_ds_tdls_oper tdls_oper;
962         unsigned long flags;
963
964         memset(&tdls_oper, 0, sizeof(struct mwifiex_ds_tdls_oper));
965         sta_ptr = mwifiex_get_sta_entry(priv, peer);
966
967         if (sta_ptr) {
968                 if (sta_ptr->is_11n_enabled) {
969                         mwifiex_11n_cleanup_reorder_tbl(priv);
970                         spin_lock_irqsave(&priv->wmm.ra_list_spinlock,
971                                           flags);
972                         mwifiex_11n_delete_all_tx_ba_stream_tbl(priv);
973                         spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock,
974                                                flags);
975                 }
976                 mwifiex_del_sta_entry(priv, peer);
977         }
978
979         mwifiex_restore_tdls_packets(priv, peer, TDLS_LINK_TEARDOWN);
980         memcpy(&tdls_oper.peer_mac, peer, ETH_ALEN);
981         tdls_oper.tdls_action = MWIFIEX_TDLS_DISABLE_LINK;
982         return mwifiex_send_cmd(priv, HostCmd_CMD_TDLS_OPER,
983                                 HostCmd_ACT_GEN_SET, 0, &tdls_oper, true);
984 }
985
986 static int
987 mwifiex_tdls_process_enable_link(struct mwifiex_private *priv, const u8 *peer)
988 {
989         struct mwifiex_sta_node *sta_ptr;
990         struct ieee80211_mcs_info mcs;
991         unsigned long flags;
992         int i;
993
994         sta_ptr = mwifiex_get_sta_entry(priv, peer);
995
996         if (sta_ptr && (sta_ptr->tdls_status != TDLS_SETUP_FAILURE)) {
997                 dev_dbg(priv->adapter->dev,
998                         "tdls: enable link %pM success\n", peer);
999
1000                 sta_ptr->tdls_status = TDLS_SETUP_COMPLETE;
1001
1002                 mcs = sta_ptr->tdls_cap.ht_capb.mcs;
1003                 if (mcs.rx_mask[0] != 0xff)
1004                         sta_ptr->is_11n_enabled = true;
1005                 if (sta_ptr->is_11n_enabled) {
1006                         if (le16_to_cpu(sta_ptr->tdls_cap.ht_capb.cap_info) &
1007                             IEEE80211_HT_CAP_MAX_AMSDU)
1008                                 sta_ptr->max_amsdu =
1009                                         MWIFIEX_TX_DATA_BUF_SIZE_8K;
1010                         else
1011                                 sta_ptr->max_amsdu =
1012                                         MWIFIEX_TX_DATA_BUF_SIZE_4K;
1013
1014                         for (i = 0; i < MAX_NUM_TID; i++)
1015                                 sta_ptr->ampdu_sta[i] =
1016                                               priv->aggr_prio_tbl[i].ampdu_user;
1017                 } else {
1018                         for (i = 0; i < MAX_NUM_TID; i++)
1019                                 sta_ptr->ampdu_sta[i] = BA_STREAM_NOT_ALLOWED;
1020                 }
1021
1022                 memset(sta_ptr->rx_seq, 0xff, sizeof(sta_ptr->rx_seq));
1023                 mwifiex_restore_tdls_packets(priv, peer, TDLS_SETUP_COMPLETE);
1024         } else {
1025                 dev_dbg(priv->adapter->dev,
1026                         "tdls: enable link %pM failed\n", peer);
1027                 if (sta_ptr) {
1028                         mwifiex_11n_cleanup_reorder_tbl(priv);
1029                         spin_lock_irqsave(&priv->wmm.ra_list_spinlock,
1030                                           flags);
1031                         mwifiex_11n_delete_all_tx_ba_stream_tbl(priv);
1032                         spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock,
1033                                                flags);
1034                         mwifiex_del_sta_entry(priv, peer);
1035                 }
1036                 mwifiex_restore_tdls_packets(priv, peer, TDLS_LINK_TEARDOWN);
1037
1038                 return -1;
1039         }
1040
1041         return 0;
1042 }
1043
1044 int mwifiex_tdls_oper(struct mwifiex_private *priv, const u8 *peer, u8 action)
1045 {
1046         switch (action) {
1047         case MWIFIEX_TDLS_ENABLE_LINK:
1048                 return mwifiex_tdls_process_enable_link(priv, peer);
1049         case MWIFIEX_TDLS_DISABLE_LINK:
1050                 return mwifiex_tdls_process_disable_link(priv, peer);
1051         case MWIFIEX_TDLS_CREATE_LINK:
1052                 return mwifiex_tdls_process_create_link(priv, peer);
1053         case MWIFIEX_TDLS_CONFIG_LINK:
1054                 return mwifiex_tdls_process_config_link(priv, peer);
1055         }
1056         return 0;
1057 }
1058
1059 int mwifiex_get_tdls_link_status(struct mwifiex_private *priv, const u8 *mac)
1060 {
1061         struct mwifiex_sta_node *sta_ptr;
1062
1063         sta_ptr = mwifiex_get_sta_entry(priv, mac);
1064         if (sta_ptr)
1065                 return sta_ptr->tdls_status;
1066
1067         return TDLS_NOT_SETUP;
1068 }
1069
1070 void mwifiex_disable_all_tdls_links(struct mwifiex_private *priv)
1071 {
1072         struct mwifiex_sta_node *sta_ptr;
1073         struct mwifiex_ds_tdls_oper tdls_oper;
1074         unsigned long flags;
1075
1076         if (list_empty(&priv->sta_list))
1077                 return;
1078
1079         list_for_each_entry(sta_ptr, &priv->sta_list, list) {
1080                 memset(&tdls_oper, 0, sizeof(struct mwifiex_ds_tdls_oper));
1081
1082                 if (sta_ptr->is_11n_enabled) {
1083                         mwifiex_11n_cleanup_reorder_tbl(priv);
1084                         spin_lock_irqsave(&priv->wmm.ra_list_spinlock,
1085                                           flags);
1086                         mwifiex_11n_delete_all_tx_ba_stream_tbl(priv);
1087                         spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock,
1088                                                flags);
1089                 }
1090
1091                 mwifiex_restore_tdls_packets(priv, sta_ptr->mac_addr,
1092                                              TDLS_LINK_TEARDOWN);
1093                 memcpy(&tdls_oper.peer_mac, sta_ptr->mac_addr, ETH_ALEN);
1094                 tdls_oper.tdls_action = MWIFIEX_TDLS_DISABLE_LINK;
1095                 if (mwifiex_send_cmd(priv, HostCmd_CMD_TDLS_OPER,
1096                                      HostCmd_ACT_GEN_SET, 0, &tdls_oper, false))
1097                         dev_warn(priv->adapter->dev,
1098                                  "Disable link failed for TDLS peer %pM",
1099                                  sta_ptr->mac_addr);
1100         }
1101
1102         mwifiex_del_all_sta_list(priv);
1103 }