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