1/* Marvell Wireless LAN device driver: TDLS handling
2 *
3 * Copyright (C) 2014, Marvell International Ltd.
4 *
5 * This software file (the "File") is distributed by Marvell International
6 * Ltd. under the terms of the GNU General Public License Version 2, June 1991
7 * (the "License").  You may use, redistribute and/or modify this File in
8 * accordance with the terms and conditions of the License, a copy of which
9 * is available on the worldwide web at
10 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
11 *
12 * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
13 * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
14 * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
15 * this warranty disclaimer.
16 */
17
18#include "main.h"
19#include "wmm.h"
20#include "11n.h"
21#include "11n_rxreorder.h"
22#include "11ac.h"
23
24#define TDLS_REQ_FIX_LEN      6
25#define TDLS_RESP_FIX_LEN     8
26#define TDLS_CONFIRM_FIX_LEN  6
27#define MWIFIEX_TDLS_WMM_INFO_SIZE 7
28
29static void mwifiex_restore_tdls_packets(struct mwifiex_private *priv,
30					 const u8 *mac, u8 status)
31{
32	struct mwifiex_ra_list_tbl *ra_list;
33	struct list_head *tid_list;
34	struct sk_buff *skb, *tmp;
35	struct mwifiex_txinfo *tx_info;
36	unsigned long flags;
37	u32 tid;
38	u8 tid_down;
39
40	dev_dbg(priv->adapter->dev, "%s: %pM\n", __func__, mac);
41	spin_lock_irqsave(&priv->wmm.ra_list_spinlock, flags);
42
43	skb_queue_walk_safe(&priv->tdls_txq, skb, tmp) {
44		if (!ether_addr_equal(mac, skb->data))
45			continue;
46
47		__skb_unlink(skb, &priv->tdls_txq);
48		tx_info = MWIFIEX_SKB_TXCB(skb);
49		tid = skb->priority;
50		tid_down = mwifiex_wmm_downgrade_tid(priv, tid);
51
52		if (status == TDLS_SETUP_COMPLETE) {
53			ra_list = mwifiex_wmm_get_queue_raptr(priv, tid, mac);
54			ra_list->tdls_link = true;
55			tx_info->flags |= MWIFIEX_BUF_FLAG_TDLS_PKT;
56		} else {
57			tid_list = &priv->wmm.tid_tbl_ptr[tid_down].ra_list;
58			if (!list_empty(tid_list))
59				ra_list = list_first_entry(tid_list,
60					      struct mwifiex_ra_list_tbl, list);
61			else
62				ra_list = NULL;
63			tx_info->flags &= ~MWIFIEX_BUF_FLAG_TDLS_PKT;
64		}
65
66		if (!ra_list) {
67			mwifiex_write_data_complete(priv->adapter, skb, 0, -1);
68			continue;
69		}
70
71		skb_queue_tail(&ra_list->skb_head, skb);
72
73		ra_list->ba_pkt_count++;
74		ra_list->total_pkt_count++;
75
76		if (atomic_read(&priv->wmm.highest_queued_prio) <
77						       tos_to_tid_inv[tid_down])
78			atomic_set(&priv->wmm.highest_queued_prio,
79				   tos_to_tid_inv[tid_down]);
80
81		atomic_inc(&priv->wmm.tx_pkts_queued);
82	}
83
84	spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, flags);
85	return;
86}
87
88static void mwifiex_hold_tdls_packets(struct mwifiex_private *priv,
89				      const u8 *mac)
90{
91	struct mwifiex_ra_list_tbl *ra_list;
92	struct list_head *ra_list_head;
93	struct sk_buff *skb, *tmp;
94	unsigned long flags;
95	int i;
96
97	dev_dbg(priv->adapter->dev, "%s: %pM\n", __func__, mac);
98	spin_lock_irqsave(&priv->wmm.ra_list_spinlock, flags);
99
100	for (i = 0; i < MAX_NUM_TID; i++) {
101		if (!list_empty(&priv->wmm.tid_tbl_ptr[i].ra_list)) {
102			ra_list_head = &priv->wmm.tid_tbl_ptr[i].ra_list;
103			list_for_each_entry(ra_list, ra_list_head, list) {
104				skb_queue_walk_safe(&ra_list->skb_head, skb,
105						    tmp) {
106					if (!ether_addr_equal(mac, skb->data))
107						continue;
108					__skb_unlink(skb, &ra_list->skb_head);
109					atomic_dec(&priv->wmm.tx_pkts_queued);
110					ra_list->total_pkt_count--;
111					skb_queue_tail(&priv->tdls_txq, skb);
112				}
113			}
114		}
115	}
116
117	spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, flags);
118	return;
119}
120
121/* This function appends rate TLV to scan config command. */
122static int
123mwifiex_tdls_append_rates_ie(struct mwifiex_private *priv,
124			     struct sk_buff *skb)
125{
126	u8 rates[MWIFIEX_SUPPORTED_RATES], *pos;
127	u16 rates_size, supp_rates_size, ext_rates_size;
128
129	memset(rates, 0, sizeof(rates));
130	rates_size = mwifiex_get_supported_rates(priv, rates);
131
132	supp_rates_size = min_t(u16, rates_size, MWIFIEX_TDLS_SUPPORTED_RATES);
133
134	if (skb_tailroom(skb) < rates_size + 4) {
135		dev_err(priv->adapter->dev,
136			"Insuffient space while adding rates\n");
137		return -ENOMEM;
138	}
139
140	pos = skb_put(skb, supp_rates_size + 2);
141	*pos++ = WLAN_EID_SUPP_RATES;
142	*pos++ = supp_rates_size;
143	memcpy(pos, rates, supp_rates_size);
144
145	if (rates_size > MWIFIEX_TDLS_SUPPORTED_RATES) {
146		ext_rates_size = rates_size - MWIFIEX_TDLS_SUPPORTED_RATES;
147		pos = skb_put(skb, ext_rates_size + 2);
148		*pos++ = WLAN_EID_EXT_SUPP_RATES;
149		*pos++ = ext_rates_size;
150		memcpy(pos, rates + MWIFIEX_TDLS_SUPPORTED_RATES,
151		       ext_rates_size);
152	}
153
154	return 0;
155}
156
157static void mwifiex_tdls_add_aid(struct mwifiex_private *priv,
158				struct sk_buff *skb)
159{
160	struct ieee_types_assoc_rsp *assoc_rsp;
161	u8 *pos;
162
163	assoc_rsp = (struct ieee_types_assoc_rsp *)&priv->assoc_rsp_buf;
164	pos = (void *)skb_put(skb, 4);
165	*pos++ = WLAN_EID_AID;
166	*pos++ = 2;
167	*pos++ = le16_to_cpu(assoc_rsp->a_id);
168
169	return;
170}
171
172static int mwifiex_tdls_add_vht_capab(struct mwifiex_private *priv,
173				      struct sk_buff *skb)
174{
175	struct ieee80211_vht_cap vht_cap;
176	u8 *pos;
177
178	pos = (void *)skb_put(skb, sizeof(struct ieee80211_vht_cap) + 2);
179	*pos++ = WLAN_EID_VHT_CAPABILITY;
180	*pos++ = sizeof(struct ieee80211_vht_cap);
181
182	memset(&vht_cap, 0, sizeof(struct ieee80211_vht_cap));
183
184	mwifiex_fill_vht_cap_tlv(priv, &vht_cap, priv->curr_bss_params.band);
185	memcpy(pos, &vht_cap, sizeof(vht_cap));
186
187	return 0;
188}
189
190static int
191mwifiex_tdls_add_ht_oper(struct mwifiex_private *priv, const u8 *mac,
192			 u8 vht_enabled, struct sk_buff *skb)
193{
194	struct ieee80211_ht_operation *ht_oper;
195	struct mwifiex_sta_node *sta_ptr;
196	struct mwifiex_bssdescriptor *bss_desc =
197					&priv->curr_bss_params.bss_descriptor;
198	u8 *pos;
199
200	sta_ptr = mwifiex_get_sta_entry(priv, mac);
201	if (unlikely(!sta_ptr)) {
202		dev_warn(priv->adapter->dev,
203			 "TDLS peer station not found in list\n");
204		return -1;
205	}
206
207	pos = (void *)skb_put(skb, sizeof(struct ieee80211_ht_operation) + 2);
208	*pos++ = WLAN_EID_HT_OPERATION;
209	*pos++ = sizeof(struct ieee80211_ht_operation);
210	ht_oper = (void *)pos;
211
212	ht_oper->primary_chan = bss_desc->channel;
213
214	/* follow AP's channel bandwidth */
215	if (ISSUPP_CHANWIDTH40(priv->adapter->hw_dot_11n_dev_cap) &&
216	    bss_desc->bcn_ht_cap &&
217	    ISALLOWED_CHANWIDTH40(bss_desc->bcn_ht_oper->ht_param))
218		ht_oper->ht_param = bss_desc->bcn_ht_oper->ht_param;
219
220	if (vht_enabled) {
221		ht_oper->ht_param =
222			  mwifiex_get_sec_chan_offset(bss_desc->channel);
223		ht_oper->ht_param |= BIT(2);
224	}
225
226	memcpy(&sta_ptr->tdls_cap.ht_oper, ht_oper,
227	       sizeof(struct ieee80211_ht_operation));
228
229	return 0;
230}
231
232static int mwifiex_tdls_add_vht_oper(struct mwifiex_private *priv,
233				     const u8 *mac, struct sk_buff *skb)
234{
235	struct mwifiex_bssdescriptor *bss_desc;
236	struct ieee80211_vht_operation *vht_oper;
237	struct ieee80211_vht_cap *vht_cap, *ap_vht_cap = NULL;
238	struct mwifiex_sta_node *sta_ptr;
239	struct mwifiex_adapter *adapter = priv->adapter;
240	u8 supp_chwd_set, peer_supp_chwd_set;
241	u8 *pos, ap_supp_chwd_set, chan_bw;
242	u16 mcs_map_user, mcs_map_resp, mcs_map_result;
243	u16 mcs_user, mcs_resp, nss;
244	u32 usr_vht_cap_info;
245
246	bss_desc = &priv->curr_bss_params.bss_descriptor;
247
248	sta_ptr = mwifiex_get_sta_entry(priv, mac);
249	if (unlikely(!sta_ptr)) {
250		dev_warn(adapter->dev, "TDLS peer station not found in list\n");
251		return -1;
252	}
253
254	if (!mwifiex_is_bss_in_11ac_mode(priv)) {
255		if (sta_ptr->tdls_cap.extcap.ext_capab[7] &
256		   WLAN_EXT_CAPA8_TDLS_WIDE_BW_ENABLED) {
257			dev_dbg(adapter->dev,
258				"TDLS peer doesn't support wider bandwitdh\n");
259			return 0;
260		}
261	} else {
262		ap_vht_cap = bss_desc->bcn_vht_cap;
263	}
264
265	pos = (void *)skb_put(skb, sizeof(struct ieee80211_vht_operation) + 2);
266	*pos++ = WLAN_EID_VHT_OPERATION;
267	*pos++ = sizeof(struct ieee80211_vht_operation);
268	vht_oper = (struct ieee80211_vht_operation *)pos;
269
270	if (bss_desc->bss_band & BAND_A)
271		usr_vht_cap_info = adapter->usr_dot_11ac_dev_cap_a;
272	else
273		usr_vht_cap_info = adapter->usr_dot_11ac_dev_cap_bg;
274
275	/* find the minmum bandwith between AP/TDLS peers */
276	vht_cap = &sta_ptr->tdls_cap.vhtcap;
277	supp_chwd_set = GET_VHTCAP_CHWDSET(usr_vht_cap_info);
278	peer_supp_chwd_set =
279			 GET_VHTCAP_CHWDSET(le32_to_cpu(vht_cap->vht_cap_info));
280	supp_chwd_set = min_t(u8, supp_chwd_set, peer_supp_chwd_set);
281
282	/* We need check AP's bandwidth when TDLS_WIDER_BANDWIDTH is off */
283
284	if (ap_vht_cap && sta_ptr->tdls_cap.extcap.ext_capab[7] &
285	    WLAN_EXT_CAPA8_TDLS_WIDE_BW_ENABLED) {
286		ap_supp_chwd_set =
287		      GET_VHTCAP_CHWDSET(le32_to_cpu(ap_vht_cap->vht_cap_info));
288		supp_chwd_set = min_t(u8, supp_chwd_set, ap_supp_chwd_set);
289	}
290
291	switch (supp_chwd_set) {
292	case IEEE80211_VHT_CHANWIDTH_80MHZ:
293		vht_oper->chan_width = IEEE80211_VHT_CHANWIDTH_80MHZ;
294		break;
295	case IEEE80211_VHT_CHANWIDTH_160MHZ:
296		vht_oper->chan_width = IEEE80211_VHT_CHANWIDTH_160MHZ;
297		break;
298	case IEEE80211_VHT_CHANWIDTH_80P80MHZ:
299		vht_oper->chan_width = IEEE80211_VHT_CHANWIDTH_80P80MHZ;
300		break;
301	default:
302		vht_oper->chan_width = IEEE80211_VHT_CHANWIDTH_USE_HT;
303		break;
304	}
305
306	mcs_map_user = GET_DEVRXMCSMAP(adapter->usr_dot_11ac_mcs_support);
307	mcs_map_resp = le16_to_cpu(vht_cap->supp_mcs.rx_mcs_map);
308	mcs_map_result = 0;
309
310	for (nss = 1; nss <= 8; nss++) {
311		mcs_user = GET_VHTNSSMCS(mcs_map_user, nss);
312		mcs_resp = GET_VHTNSSMCS(mcs_map_resp, nss);
313
314		if ((mcs_user == IEEE80211_VHT_MCS_NOT_SUPPORTED) ||
315		    (mcs_resp == IEEE80211_VHT_MCS_NOT_SUPPORTED))
316			SET_VHTNSSMCS(mcs_map_result, nss,
317				      IEEE80211_VHT_MCS_NOT_SUPPORTED);
318		else
319			SET_VHTNSSMCS(mcs_map_result, nss,
320				      min_t(u16, mcs_user, mcs_resp));
321	}
322
323	vht_oper->basic_mcs_set = cpu_to_le16(mcs_map_result);
324
325	switch (vht_oper->chan_width) {
326	case IEEE80211_VHT_CHANWIDTH_80MHZ:
327		chan_bw = IEEE80211_VHT_CHANWIDTH_80MHZ;
328		break;
329	case IEEE80211_VHT_CHANWIDTH_160MHZ:
330		chan_bw = IEEE80211_VHT_CHANWIDTH_160MHZ;
331		break;
332	case IEEE80211_VHT_CHANWIDTH_80P80MHZ:
333		chan_bw = IEEE80211_VHT_CHANWIDTH_80MHZ;
334		break;
335	default:
336		chan_bw = IEEE80211_VHT_CHANWIDTH_USE_HT;
337		break;
338	}
339	vht_oper->center_freq_seg1_idx =
340			mwifiex_get_center_freq_index(priv, BAND_AAC,
341						      bss_desc->channel,
342						      chan_bw);
343
344	return 0;
345}
346
347static void mwifiex_tdls_add_ext_capab(struct mwifiex_private *priv,
348				       struct sk_buff *skb)
349{
350	struct ieee_types_extcap *extcap;
351
352	extcap = (void *)skb_put(skb, sizeof(struct ieee_types_extcap));
353	extcap->ieee_hdr.element_id = WLAN_EID_EXT_CAPABILITY;
354	extcap->ieee_hdr.len = 8;
355	memset(extcap->ext_capab, 0, 8);
356	extcap->ext_capab[4] |= WLAN_EXT_CAPA5_TDLS_ENABLED;
357
358	if (priv->adapter->is_hw_11ac_capable)
359		extcap->ext_capab[7] |= WLAN_EXT_CAPA8_TDLS_WIDE_BW_ENABLED;
360}
361
362static void mwifiex_tdls_add_qos_capab(struct sk_buff *skb)
363{
364	u8 *pos = (void *)skb_put(skb, 3);
365
366	*pos++ = WLAN_EID_QOS_CAPA;
367	*pos++ = 1;
368	*pos++ = MWIFIEX_TDLS_DEF_QOS_CAPAB;
369}
370
371static void
372mwifiex_tdls_add_wmm_param_ie(struct mwifiex_private *priv, struct sk_buff *skb)
373{
374	struct ieee80211_wmm_param_ie *wmm;
375	u8 ac_vi[] = {0x42, 0x43, 0x5e, 0x00};
376	u8 ac_vo[] = {0x62, 0x32, 0x2f, 0x00};
377	u8 ac_be[] = {0x03, 0xa4, 0x00, 0x00};
378	u8 ac_bk[] = {0x27, 0xa4, 0x00, 0x00};
379
380	wmm = (void *)skb_put(skb, sizeof(*wmm));
381	memset(wmm, 0, sizeof(*wmm));
382
383	wmm->element_id = WLAN_EID_VENDOR_SPECIFIC;
384	wmm->len = sizeof(*wmm) - 2;
385	wmm->oui[0] = 0x00; /* Microsoft OUI 00:50:F2 */
386	wmm->oui[1] = 0x50;
387	wmm->oui[2] = 0xf2;
388	wmm->oui_type = 2; /* WME */
389	wmm->oui_subtype = 1; /* WME param */
390	wmm->version = 1; /* WME ver */
391	wmm->qos_info = 0; /* U-APSD not in use */
392
393	/* use default WMM AC parameters for TDLS link*/
394	memcpy(&wmm->ac[0], ac_be, sizeof(ac_be));
395	memcpy(&wmm->ac[1], ac_bk, sizeof(ac_bk));
396	memcpy(&wmm->ac[2], ac_vi, sizeof(ac_vi));
397	memcpy(&wmm->ac[3], ac_vo, sizeof(ac_vo));
398}
399
400static void
401mwifiex_add_wmm_info_ie(struct mwifiex_private *priv, struct sk_buff *skb,
402			u8 qosinfo)
403{
404	u8 *buf;
405
406	buf = (void *)skb_put(skb, MWIFIEX_TDLS_WMM_INFO_SIZE +
407			      sizeof(struct ieee_types_header));
408
409	*buf++ = WLAN_EID_VENDOR_SPECIFIC;
410	*buf++ = 7; /* len */
411	*buf++ = 0x00; /* Microsoft OUI 00:50:F2 */
412	*buf++ = 0x50;
413	*buf++ = 0xf2;
414	*buf++ = 2; /* WME */
415	*buf++ = 0; /* WME info */
416	*buf++ = 1; /* WME ver */
417	*buf++ = qosinfo; /* U-APSD no in use */
418}
419
420static int mwifiex_prep_tdls_encap_data(struct mwifiex_private *priv,
421					const u8 *peer, u8 action_code,
422					u8 dialog_token,
423					u16 status_code, struct sk_buff *skb)
424{
425	struct ieee80211_tdls_data *tf;
426	int ret;
427	u16 capab;
428	struct ieee80211_ht_cap *ht_cap;
429	u8 radio, *pos;
430
431	capab = priv->curr_bss_params.bss_descriptor.cap_info_bitmap;
432
433	tf = (void *)skb_put(skb, offsetof(struct ieee80211_tdls_data, u));
434	memcpy(tf->da, peer, ETH_ALEN);
435	memcpy(tf->sa, priv->curr_addr, ETH_ALEN);
436	tf->ether_type = cpu_to_be16(ETH_P_TDLS);
437	tf->payload_type = WLAN_TDLS_SNAP_RFTYPE;
438
439	switch (action_code) {
440	case WLAN_TDLS_SETUP_REQUEST:
441		tf->category = WLAN_CATEGORY_TDLS;
442		tf->action_code = WLAN_TDLS_SETUP_REQUEST;
443		skb_put(skb, sizeof(tf->u.setup_req));
444		tf->u.setup_req.dialog_token = dialog_token;
445		tf->u.setup_req.capability = cpu_to_le16(capab);
446		ret = mwifiex_tdls_append_rates_ie(priv, skb);
447		if (ret) {
448			dev_kfree_skb_any(skb);
449			return ret;
450		}
451
452		pos = (void *)skb_put(skb, sizeof(struct ieee80211_ht_cap) + 2);
453		*pos++ = WLAN_EID_HT_CAPABILITY;
454		*pos++ = sizeof(struct ieee80211_ht_cap);
455		ht_cap = (void *)pos;
456		radio = mwifiex_band_to_radio_type(priv->curr_bss_params.band);
457		ret = mwifiex_fill_cap_info(priv, radio, ht_cap);
458		if (ret) {
459			dev_kfree_skb_any(skb);
460			return ret;
461		}
462
463		if (priv->adapter->is_hw_11ac_capable) {
464			ret = mwifiex_tdls_add_vht_capab(priv, skb);
465			if (ret) {
466				dev_kfree_skb_any(skb);
467				return ret;
468			}
469			mwifiex_tdls_add_aid(priv, skb);
470		}
471
472		mwifiex_tdls_add_ext_capab(priv, skb);
473		mwifiex_tdls_add_qos_capab(skb);
474		mwifiex_add_wmm_info_ie(priv, skb, 0);
475		break;
476
477	case WLAN_TDLS_SETUP_RESPONSE:
478		tf->category = WLAN_CATEGORY_TDLS;
479		tf->action_code = WLAN_TDLS_SETUP_RESPONSE;
480		skb_put(skb, sizeof(tf->u.setup_resp));
481		tf->u.setup_resp.status_code = cpu_to_le16(status_code);
482		tf->u.setup_resp.dialog_token = dialog_token;
483		tf->u.setup_resp.capability = cpu_to_le16(capab);
484		ret = mwifiex_tdls_append_rates_ie(priv, skb);
485		if (ret) {
486			dev_kfree_skb_any(skb);
487			return ret;
488		}
489
490		pos = (void *)skb_put(skb, sizeof(struct ieee80211_ht_cap) + 2);
491		*pos++ = WLAN_EID_HT_CAPABILITY;
492		*pos++ = sizeof(struct ieee80211_ht_cap);
493		ht_cap = (void *)pos;
494		radio = mwifiex_band_to_radio_type(priv->curr_bss_params.band);
495		ret = mwifiex_fill_cap_info(priv, radio, ht_cap);
496		if (ret) {
497			dev_kfree_skb_any(skb);
498			return ret;
499		}
500
501		if (priv->adapter->is_hw_11ac_capable) {
502			ret = mwifiex_tdls_add_vht_capab(priv, skb);
503			if (ret) {
504				dev_kfree_skb_any(skb);
505				return ret;
506			}
507			mwifiex_tdls_add_aid(priv, skb);
508		}
509
510		mwifiex_tdls_add_ext_capab(priv, skb);
511		mwifiex_tdls_add_qos_capab(skb);
512		mwifiex_add_wmm_info_ie(priv, skb, 0);
513		break;
514
515	case WLAN_TDLS_SETUP_CONFIRM:
516		tf->category = WLAN_CATEGORY_TDLS;
517		tf->action_code = WLAN_TDLS_SETUP_CONFIRM;
518		skb_put(skb, sizeof(tf->u.setup_cfm));
519		tf->u.setup_cfm.status_code = cpu_to_le16(status_code);
520		tf->u.setup_cfm.dialog_token = dialog_token;
521
522		mwifiex_tdls_add_wmm_param_ie(priv, skb);
523		if (priv->adapter->is_hw_11ac_capable) {
524			ret = mwifiex_tdls_add_vht_oper(priv, peer, skb);
525			if (ret) {
526				dev_kfree_skb_any(skb);
527				return ret;
528			}
529			ret = mwifiex_tdls_add_ht_oper(priv, peer, 1, skb);
530			if (ret) {
531				dev_kfree_skb_any(skb);
532				return ret;
533			}
534		} else {
535			ret = mwifiex_tdls_add_ht_oper(priv, peer, 0, skb);
536			if (ret) {
537				dev_kfree_skb_any(skb);
538				return ret;
539			}
540		}
541		break;
542
543	case WLAN_TDLS_TEARDOWN:
544		tf->category = WLAN_CATEGORY_TDLS;
545		tf->action_code = WLAN_TDLS_TEARDOWN;
546		skb_put(skb, sizeof(tf->u.teardown));
547		tf->u.teardown.reason_code = cpu_to_le16(status_code);
548		break;
549
550	case WLAN_TDLS_DISCOVERY_REQUEST:
551		tf->category = WLAN_CATEGORY_TDLS;
552		tf->action_code = WLAN_TDLS_DISCOVERY_REQUEST;
553		skb_put(skb, sizeof(tf->u.discover_req));
554		tf->u.discover_req.dialog_token = dialog_token;
555		break;
556	default:
557		dev_err(priv->adapter->dev, "Unknown TDLS frame type.\n");
558		return -EINVAL;
559	}
560
561	return 0;
562}
563
564static void
565mwifiex_tdls_add_link_ie(struct sk_buff *skb, const u8 *src_addr,
566			 const u8 *peer, const u8 *bssid)
567{
568	struct ieee80211_tdls_lnkie *lnkid;
569
570	lnkid = (void *)skb_put(skb, sizeof(struct ieee80211_tdls_lnkie));
571	lnkid->ie_type = WLAN_EID_LINK_ID;
572	lnkid->ie_len = sizeof(struct ieee80211_tdls_lnkie) -
573			sizeof(struct ieee_types_header);
574
575	memcpy(lnkid->bssid, bssid, ETH_ALEN);
576	memcpy(lnkid->init_sta, src_addr, ETH_ALEN);
577	memcpy(lnkid->resp_sta, peer, ETH_ALEN);
578}
579
580int mwifiex_send_tdls_data_frame(struct mwifiex_private *priv, const u8 *peer,
581				 u8 action_code, u8 dialog_token,
582				 u16 status_code, const u8 *extra_ies,
583				 size_t extra_ies_len)
584{
585	struct sk_buff *skb;
586	struct mwifiex_txinfo *tx_info;
587	int ret;
588	u16 skb_len;
589
590	skb_len = MWIFIEX_MIN_DATA_HEADER_LEN +
591		  max(sizeof(struct ieee80211_mgmt),
592		      sizeof(struct ieee80211_tdls_data)) +
593		  MWIFIEX_MGMT_FRAME_HEADER_SIZE +
594		  MWIFIEX_SUPPORTED_RATES +
595		  3 + /* Qos Info */
596		  sizeof(struct ieee_types_extcap) +
597		  sizeof(struct ieee80211_ht_cap) +
598		  sizeof(struct ieee_types_bss_co_2040) +
599		  sizeof(struct ieee80211_ht_operation) +
600		  sizeof(struct ieee80211_tdls_lnkie) +
601		  sizeof(struct ieee80211_wmm_param_ie) +
602		  extra_ies_len;
603
604	if (priv->adapter->is_hw_11ac_capable)
605		skb_len += sizeof(struct ieee_types_vht_cap) +
606			   sizeof(struct ieee_types_vht_oper) +
607			   sizeof(struct ieee_types_aid);
608
609	skb = dev_alloc_skb(skb_len);
610	if (!skb) {
611		dev_err(priv->adapter->dev,
612			"allocate skb failed for management frame\n");
613		return -ENOMEM;
614	}
615	skb_reserve(skb, MWIFIEX_MIN_DATA_HEADER_LEN);
616
617	switch (action_code) {
618	case WLAN_TDLS_SETUP_REQUEST:
619	case WLAN_TDLS_SETUP_CONFIRM:
620	case WLAN_TDLS_TEARDOWN:
621	case WLAN_TDLS_DISCOVERY_REQUEST:
622		ret = mwifiex_prep_tdls_encap_data(priv, peer, action_code,
623						   dialog_token, status_code,
624						   skb);
625		if (ret) {
626			dev_kfree_skb_any(skb);
627			return ret;
628		}
629		if (extra_ies_len)
630			memcpy(skb_put(skb, extra_ies_len), extra_ies,
631			       extra_ies_len);
632		mwifiex_tdls_add_link_ie(skb, priv->curr_addr, peer,
633					 priv->cfg_bssid);
634		break;
635	case WLAN_TDLS_SETUP_RESPONSE:
636		ret = mwifiex_prep_tdls_encap_data(priv, peer, action_code,
637						   dialog_token, status_code,
638						   skb);
639		if (ret) {
640			dev_kfree_skb_any(skb);
641			return ret;
642		}
643		if (extra_ies_len)
644			memcpy(skb_put(skb, extra_ies_len), extra_ies,
645			       extra_ies_len);
646		mwifiex_tdls_add_link_ie(skb, peer, priv->curr_addr,
647					 priv->cfg_bssid);
648		break;
649	}
650
651	switch (action_code) {
652	case WLAN_TDLS_SETUP_REQUEST:
653	case WLAN_TDLS_SETUP_RESPONSE:
654		skb->priority = MWIFIEX_PRIO_BK;
655		break;
656	default:
657		skb->priority = MWIFIEX_PRIO_VI;
658		break;
659	}
660
661	tx_info = MWIFIEX_SKB_TXCB(skb);
662	memset(tx_info, 0, sizeof(*tx_info));
663	tx_info->bss_num = priv->bss_num;
664	tx_info->bss_type = priv->bss_type;
665
666	__net_timestamp(skb);
667	mwifiex_queue_tx_pkt(priv, skb);
668
669	return 0;
670}
671
672static int
673mwifiex_construct_tdls_action_frame(struct mwifiex_private *priv,
674				    const u8 *peer,
675				    u8 action_code, u8 dialog_token,
676				    u16 status_code, struct sk_buff *skb)
677{
678	struct ieee80211_mgmt *mgmt;
679	u8 bc_addr[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
680	int ret;
681	u16 capab;
682	struct ieee80211_ht_cap *ht_cap;
683	u8 radio, *pos;
684
685	capab = priv->curr_bss_params.bss_descriptor.cap_info_bitmap;
686
687	mgmt = (void *)skb_put(skb, offsetof(struct ieee80211_mgmt, u));
688
689	memset(mgmt, 0, 24);
690	memcpy(mgmt->da, peer, ETH_ALEN);
691	memcpy(mgmt->sa, priv->curr_addr, ETH_ALEN);
692	memcpy(mgmt->bssid, priv->cfg_bssid, ETH_ALEN);
693	mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
694					  IEEE80211_STYPE_ACTION);
695
696	/* add address 4 */
697	pos = skb_put(skb, ETH_ALEN);
698
699	switch (action_code) {
700	case WLAN_PUB_ACTION_TDLS_DISCOVER_RES:
701		skb_put(skb, sizeof(mgmt->u.action.u.tdls_discover_resp) + 1);
702		mgmt->u.action.category = WLAN_CATEGORY_PUBLIC;
703		mgmt->u.action.u.tdls_discover_resp.action_code =
704					      WLAN_PUB_ACTION_TDLS_DISCOVER_RES;
705		mgmt->u.action.u.tdls_discover_resp.dialog_token =
706								   dialog_token;
707		mgmt->u.action.u.tdls_discover_resp.capability =
708							     cpu_to_le16(capab);
709		/* move back for addr4 */
710		memmove(pos + ETH_ALEN, &mgmt->u.action.category,
711			sizeof(mgmt->u.action.u.tdls_discover_resp));
712		/* init address 4 */
713		memcpy(pos, bc_addr, ETH_ALEN);
714
715		ret = mwifiex_tdls_append_rates_ie(priv, skb);
716		if (ret) {
717			dev_kfree_skb_any(skb);
718			return ret;
719		}
720
721		pos = (void *)skb_put(skb, sizeof(struct ieee80211_ht_cap) + 2);
722		*pos++ = WLAN_EID_HT_CAPABILITY;
723		*pos++ = sizeof(struct ieee80211_ht_cap);
724		ht_cap = (void *)pos;
725		radio = mwifiex_band_to_radio_type(priv->curr_bss_params.band);
726		ret = mwifiex_fill_cap_info(priv, radio, ht_cap);
727		if (ret) {
728			dev_kfree_skb_any(skb);
729			return ret;
730		}
731
732		if (priv->adapter->is_hw_11ac_capable) {
733			ret = mwifiex_tdls_add_vht_capab(priv, skb);
734			if (ret) {
735				dev_kfree_skb_any(skb);
736				return ret;
737			}
738			mwifiex_tdls_add_aid(priv, skb);
739		}
740
741		mwifiex_tdls_add_ext_capab(priv, skb);
742		mwifiex_tdls_add_qos_capab(skb);
743		break;
744	default:
745		dev_err(priv->adapter->dev, "Unknown TDLS action frame type\n");
746		return -EINVAL;
747	}
748
749	return 0;
750}
751
752int mwifiex_send_tdls_action_frame(struct mwifiex_private *priv, const u8 *peer,
753				   u8 action_code, u8 dialog_token,
754				   u16 status_code, const u8 *extra_ies,
755				   size_t extra_ies_len)
756{
757	struct sk_buff *skb;
758	struct mwifiex_txinfo *tx_info;
759	u8 *pos;
760	u32 pkt_type, tx_control;
761	u16 pkt_len, skb_len;
762
763	skb_len = MWIFIEX_MIN_DATA_HEADER_LEN +
764		  max(sizeof(struct ieee80211_mgmt),
765		      sizeof(struct ieee80211_tdls_data)) +
766		  MWIFIEX_MGMT_FRAME_HEADER_SIZE +
767		  MWIFIEX_SUPPORTED_RATES +
768		  sizeof(struct ieee_types_extcap) +
769		  sizeof(struct ieee80211_ht_cap) +
770		  sizeof(struct ieee_types_bss_co_2040) +
771		  sizeof(struct ieee80211_ht_operation) +
772		  sizeof(struct ieee80211_tdls_lnkie) +
773		  extra_ies_len +
774		  3 + /* Qos Info */
775		  ETH_ALEN; /* Address4 */
776
777	if (priv->adapter->is_hw_11ac_capable)
778		skb_len += sizeof(struct ieee_types_vht_cap) +
779			   sizeof(struct ieee_types_vht_oper) +
780			   sizeof(struct ieee_types_aid);
781
782	skb = dev_alloc_skb(skb_len);
783	if (!skb) {
784		dev_err(priv->adapter->dev,
785			"allocate skb failed for management frame\n");
786		return -ENOMEM;
787	}
788
789	skb_reserve(skb, MWIFIEX_MIN_DATA_HEADER_LEN);
790
791	pkt_type = PKT_TYPE_MGMT;
792	tx_control = 0;
793	pos = skb_put(skb, MWIFIEX_MGMT_FRAME_HEADER_SIZE + sizeof(pkt_len));
794	memset(pos, 0, MWIFIEX_MGMT_FRAME_HEADER_SIZE + sizeof(pkt_len));
795	memcpy(pos, &pkt_type, sizeof(pkt_type));
796	memcpy(pos + sizeof(pkt_type), &tx_control, sizeof(tx_control));
797
798	if (mwifiex_construct_tdls_action_frame(priv, peer, action_code,
799						dialog_token, status_code,
800						skb)) {
801		dev_kfree_skb_any(skb);
802		return -EINVAL;
803	}
804
805	if (extra_ies_len)
806		memcpy(skb_put(skb, extra_ies_len), extra_ies, extra_ies_len);
807
808	/* the TDLS link IE is always added last we are the responder */
809
810	mwifiex_tdls_add_link_ie(skb, peer, priv->curr_addr,
811				 priv->cfg_bssid);
812
813	skb->priority = MWIFIEX_PRIO_VI;
814
815	tx_info = MWIFIEX_SKB_TXCB(skb);
816	memset(tx_info, 0, sizeof(*tx_info));
817	tx_info->bss_num = priv->bss_num;
818	tx_info->bss_type = priv->bss_type;
819	tx_info->flags |= MWIFIEX_BUF_FLAG_TDLS_PKT;
820
821	pkt_len = skb->len - MWIFIEX_MGMT_FRAME_HEADER_SIZE - sizeof(pkt_len);
822	memcpy(skb->data + MWIFIEX_MGMT_FRAME_HEADER_SIZE, &pkt_len,
823	       sizeof(pkt_len));
824	__net_timestamp(skb);
825	mwifiex_queue_tx_pkt(priv, skb);
826
827	return 0;
828}
829
830/* This function process tdls action frame from peer.
831 * Peer capabilities are stored into station node structure.
832 */
833void mwifiex_process_tdls_action_frame(struct mwifiex_private *priv,
834				       u8 *buf, int len)
835{
836	struct mwifiex_sta_node *sta_ptr;
837	u8 *peer, *pos, *end;
838	u8 i, action, basic;
839	__le16 cap = 0;
840	int ie_len = 0;
841
842	if (len < (sizeof(struct ethhdr) + 3))
843		return;
844	if (*(buf + sizeof(struct ethhdr)) != WLAN_TDLS_SNAP_RFTYPE)
845		return;
846	if (*(buf + sizeof(struct ethhdr) + 1) != WLAN_CATEGORY_TDLS)
847		return;
848
849	peer = buf + ETH_ALEN;
850	action = *(buf + sizeof(struct ethhdr) + 2);
851	dev_dbg(priv->adapter->dev,
852		"rx:tdls action: peer=%pM, action=%d\n", peer, action);
853
854	switch (action) {
855	case WLAN_TDLS_SETUP_REQUEST:
856		if (len < (sizeof(struct ethhdr) + TDLS_REQ_FIX_LEN))
857			return;
858
859		pos = buf + sizeof(struct ethhdr) + 4;
860		/* payload 1+ category 1 + action 1 + dialog 1 */
861		cap = cpu_to_le16(*(u16 *)pos);
862		ie_len = len - sizeof(struct ethhdr) - TDLS_REQ_FIX_LEN;
863		pos += 2;
864		break;
865
866	case WLAN_TDLS_SETUP_RESPONSE:
867		if (len < (sizeof(struct ethhdr) + TDLS_RESP_FIX_LEN))
868			return;
869		/* payload 1+ category 1 + action 1 + dialog 1 + status code 2*/
870		pos = buf + sizeof(struct ethhdr) + 6;
871		cap = cpu_to_le16(*(u16 *)pos);
872		ie_len = len - sizeof(struct ethhdr) - TDLS_RESP_FIX_LEN;
873		pos += 2;
874		break;
875
876	case WLAN_TDLS_SETUP_CONFIRM:
877		if (len < (sizeof(struct ethhdr) + TDLS_CONFIRM_FIX_LEN))
878			return;
879		pos = buf + sizeof(struct ethhdr) + TDLS_CONFIRM_FIX_LEN;
880		ie_len = len - sizeof(struct ethhdr) - TDLS_CONFIRM_FIX_LEN;
881		break;
882	default:
883		dev_dbg(priv->adapter->dev, "Unknown TDLS frame type.\n");
884		return;
885	}
886
887	sta_ptr = mwifiex_add_sta_entry(priv, peer);
888	if (!sta_ptr)
889		return;
890
891	sta_ptr->tdls_cap.capab = cap;
892
893	for (end = pos + ie_len; pos + 1 < end; pos += 2 + pos[1]) {
894		if (pos + 2 + pos[1] > end)
895			break;
896
897		switch (*pos) {
898		case WLAN_EID_SUPP_RATES:
899			sta_ptr->tdls_cap.rates_len = pos[1];
900			for (i = 0; i < pos[1]; i++)
901				sta_ptr->tdls_cap.rates[i] = pos[i + 2];
902			break;
903
904		case WLAN_EID_EXT_SUPP_RATES:
905			basic = sta_ptr->tdls_cap.rates_len;
906			for (i = 0; i < pos[1]; i++)
907				sta_ptr->tdls_cap.rates[basic + i] = pos[i + 2];
908			sta_ptr->tdls_cap.rates_len += pos[1];
909			break;
910		case WLAN_EID_HT_CAPABILITY:
911			memcpy((u8 *)&sta_ptr->tdls_cap.ht_capb, pos,
912			       sizeof(struct ieee80211_ht_cap));
913			sta_ptr->is_11n_enabled = 1;
914			break;
915		case WLAN_EID_HT_OPERATION:
916			memcpy(&sta_ptr->tdls_cap.ht_oper, pos,
917			       sizeof(struct ieee80211_ht_operation));
918			break;
919		case WLAN_EID_BSS_COEX_2040:
920			sta_ptr->tdls_cap.coex_2040 = pos[2];
921			break;
922		case WLAN_EID_EXT_CAPABILITY:
923			memcpy((u8 *)&sta_ptr->tdls_cap.extcap, pos,
924			       sizeof(struct ieee_types_header) +
925			       min_t(u8, pos[1], 8));
926			break;
927		case WLAN_EID_RSN:
928			memcpy((u8 *)&sta_ptr->tdls_cap.rsn_ie, pos,
929			       sizeof(struct ieee_types_header) +
930			       min_t(u8, pos[1], IEEE_MAX_IE_SIZE -
931				     sizeof(struct ieee_types_header)));
932			break;
933		case WLAN_EID_QOS_CAPA:
934			sta_ptr->tdls_cap.qos_info = pos[2];
935			break;
936		case WLAN_EID_VHT_OPERATION:
937			if (priv->adapter->is_hw_11ac_capable)
938				memcpy(&sta_ptr->tdls_cap.vhtoper, pos,
939				       sizeof(struct ieee80211_vht_operation));
940			break;
941		case WLAN_EID_VHT_CAPABILITY:
942			if (priv->adapter->is_hw_11ac_capable) {
943				memcpy((u8 *)&sta_ptr->tdls_cap.vhtcap, pos,
944				       sizeof(struct ieee80211_vht_cap));
945				sta_ptr->is_11ac_enabled = 1;
946			}
947			break;
948		case WLAN_EID_AID:
949			if (priv->adapter->is_hw_11ac_capable)
950				sta_ptr->tdls_cap.aid =
951					      le16_to_cpu(*(__le16 *)(pos + 2));
952		default:
953			break;
954		}
955	}
956
957	return;
958}
959
960static int
961mwifiex_tdls_process_config_link(struct mwifiex_private *priv, const u8 *peer)
962{
963	struct mwifiex_sta_node *sta_ptr;
964	struct mwifiex_ds_tdls_oper tdls_oper;
965
966	memset(&tdls_oper, 0, sizeof(struct mwifiex_ds_tdls_oper));
967	sta_ptr = mwifiex_get_sta_entry(priv, peer);
968
969	if (!sta_ptr || sta_ptr->tdls_status == TDLS_SETUP_FAILURE) {
970		dev_err(priv->adapter->dev,
971			"link absent for peer %pM; cannot config\n", peer);
972		return -EINVAL;
973	}
974
975	memcpy(&tdls_oper.peer_mac, peer, ETH_ALEN);
976	tdls_oper.tdls_action = MWIFIEX_TDLS_CONFIG_LINK;
977	return mwifiex_send_cmd(priv, HostCmd_CMD_TDLS_OPER,
978				HostCmd_ACT_GEN_SET, 0, &tdls_oper, true);
979}
980
981static int
982mwifiex_tdls_process_create_link(struct mwifiex_private *priv, const u8 *peer)
983{
984	struct mwifiex_sta_node *sta_ptr;
985	struct mwifiex_ds_tdls_oper tdls_oper;
986
987	memset(&tdls_oper, 0, sizeof(struct mwifiex_ds_tdls_oper));
988	sta_ptr = mwifiex_get_sta_entry(priv, peer);
989
990	if (sta_ptr && sta_ptr->tdls_status == TDLS_SETUP_INPROGRESS) {
991		dev_dbg(priv->adapter->dev,
992			"Setup already in progress for peer %pM\n", peer);
993		return 0;
994	}
995
996	sta_ptr = mwifiex_add_sta_entry(priv, peer);
997	if (!sta_ptr)
998		return -ENOMEM;
999
1000	sta_ptr->tdls_status = TDLS_SETUP_INPROGRESS;
1001	mwifiex_hold_tdls_packets(priv, peer);
1002	memcpy(&tdls_oper.peer_mac, peer, ETH_ALEN);
1003	tdls_oper.tdls_action = MWIFIEX_TDLS_CREATE_LINK;
1004	return mwifiex_send_cmd(priv, HostCmd_CMD_TDLS_OPER,
1005				HostCmd_ACT_GEN_SET, 0, &tdls_oper, true);
1006}
1007
1008static int
1009mwifiex_tdls_process_disable_link(struct mwifiex_private *priv, const u8 *peer)
1010{
1011	struct mwifiex_sta_node *sta_ptr;
1012	struct mwifiex_ds_tdls_oper tdls_oper;
1013	unsigned long flags;
1014
1015	memset(&tdls_oper, 0, sizeof(struct mwifiex_ds_tdls_oper));
1016	sta_ptr = mwifiex_get_sta_entry(priv, peer);
1017
1018	if (sta_ptr) {
1019		if (sta_ptr->is_11n_enabled) {
1020			mwifiex_11n_cleanup_reorder_tbl(priv);
1021			spin_lock_irqsave(&priv->wmm.ra_list_spinlock,
1022					  flags);
1023			mwifiex_11n_delete_all_tx_ba_stream_tbl(priv);
1024			spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock,
1025					       flags);
1026		}
1027		mwifiex_del_sta_entry(priv, peer);
1028	}
1029
1030	mwifiex_restore_tdls_packets(priv, peer, TDLS_LINK_TEARDOWN);
1031	mwifiex_auto_tdls_update_peer_status(priv, peer, TDLS_NOT_SETUP);
1032	memcpy(&tdls_oper.peer_mac, peer, ETH_ALEN);
1033	tdls_oper.tdls_action = MWIFIEX_TDLS_DISABLE_LINK;
1034	return mwifiex_send_cmd(priv, HostCmd_CMD_TDLS_OPER,
1035				HostCmd_ACT_GEN_SET, 0, &tdls_oper, true);
1036}
1037
1038static int
1039mwifiex_tdls_process_enable_link(struct mwifiex_private *priv, const u8 *peer)
1040{
1041	struct mwifiex_sta_node *sta_ptr;
1042	struct ieee80211_mcs_info mcs;
1043	unsigned long flags;
1044	int i;
1045
1046	sta_ptr = mwifiex_get_sta_entry(priv, peer);
1047
1048	if (sta_ptr && (sta_ptr->tdls_status != TDLS_SETUP_FAILURE)) {
1049		dev_dbg(priv->adapter->dev,
1050			"tdls: enable link %pM success\n", peer);
1051
1052		sta_ptr->tdls_status = TDLS_SETUP_COMPLETE;
1053
1054		mcs = sta_ptr->tdls_cap.ht_capb.mcs;
1055		if (mcs.rx_mask[0] != 0xff)
1056			sta_ptr->is_11n_enabled = true;
1057		if (sta_ptr->is_11n_enabled) {
1058			if (le16_to_cpu(sta_ptr->tdls_cap.ht_capb.cap_info) &
1059			    IEEE80211_HT_CAP_MAX_AMSDU)
1060				sta_ptr->max_amsdu =
1061					MWIFIEX_TX_DATA_BUF_SIZE_8K;
1062			else
1063				sta_ptr->max_amsdu =
1064					MWIFIEX_TX_DATA_BUF_SIZE_4K;
1065
1066			for (i = 0; i < MAX_NUM_TID; i++)
1067				sta_ptr->ampdu_sta[i] =
1068					      priv->aggr_prio_tbl[i].ampdu_user;
1069		} else {
1070			for (i = 0; i < MAX_NUM_TID; i++)
1071				sta_ptr->ampdu_sta[i] = BA_STREAM_NOT_ALLOWED;
1072		}
1073
1074		memset(sta_ptr->rx_seq, 0xff, sizeof(sta_ptr->rx_seq));
1075		mwifiex_restore_tdls_packets(priv, peer, TDLS_SETUP_COMPLETE);
1076		mwifiex_auto_tdls_update_peer_status(priv, peer,
1077						     TDLS_SETUP_COMPLETE);
1078	} else {
1079		dev_dbg(priv->adapter->dev,
1080			"tdls: enable link %pM failed\n", peer);
1081		if (sta_ptr) {
1082			mwifiex_11n_cleanup_reorder_tbl(priv);
1083			spin_lock_irqsave(&priv->wmm.ra_list_spinlock,
1084					  flags);
1085			mwifiex_11n_delete_all_tx_ba_stream_tbl(priv);
1086			spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock,
1087					       flags);
1088			mwifiex_del_sta_entry(priv, peer);
1089		}
1090		mwifiex_restore_tdls_packets(priv, peer, TDLS_LINK_TEARDOWN);
1091		mwifiex_auto_tdls_update_peer_status(priv, peer,
1092						     TDLS_NOT_SETUP);
1093
1094		return -1;
1095	}
1096
1097	return 0;
1098}
1099
1100int mwifiex_tdls_oper(struct mwifiex_private *priv, const u8 *peer, u8 action)
1101{
1102	switch (action) {
1103	case MWIFIEX_TDLS_ENABLE_LINK:
1104		return mwifiex_tdls_process_enable_link(priv, peer);
1105	case MWIFIEX_TDLS_DISABLE_LINK:
1106		return mwifiex_tdls_process_disable_link(priv, peer);
1107	case MWIFIEX_TDLS_CREATE_LINK:
1108		return mwifiex_tdls_process_create_link(priv, peer);
1109	case MWIFIEX_TDLS_CONFIG_LINK:
1110		return mwifiex_tdls_process_config_link(priv, peer);
1111	}
1112	return 0;
1113}
1114
1115int mwifiex_get_tdls_link_status(struct mwifiex_private *priv, const u8 *mac)
1116{
1117	struct mwifiex_sta_node *sta_ptr;
1118
1119	sta_ptr = mwifiex_get_sta_entry(priv, mac);
1120	if (sta_ptr)
1121		return sta_ptr->tdls_status;
1122
1123	return TDLS_NOT_SETUP;
1124}
1125
1126int mwifiex_get_tdls_list(struct mwifiex_private *priv,
1127			  struct tdls_peer_info *buf)
1128{
1129	struct mwifiex_sta_node *sta_ptr;
1130	struct tdls_peer_info *peer = buf;
1131	int count = 0;
1132	unsigned long flags;
1133
1134	if (!ISSUPP_TDLS_ENABLED(priv->adapter->fw_cap_info))
1135		return 0;
1136
1137	/* make sure we are in station mode and connected */
1138	if (!(priv->bss_type == MWIFIEX_BSS_TYPE_STA && priv->media_connected))
1139		return 0;
1140
1141	spin_lock_irqsave(&priv->sta_list_spinlock, flags);
1142	list_for_each_entry(sta_ptr, &priv->sta_list, list) {
1143		if (sta_ptr->tdls_status == TDLS_SETUP_COMPLETE) {
1144			ether_addr_copy(peer->peer_addr, sta_ptr->mac_addr);
1145			peer++;
1146			count++;
1147			if (count >= MWIFIEX_MAX_TDLS_PEER_SUPPORTED)
1148				break;
1149		}
1150	}
1151	spin_unlock_irqrestore(&priv->sta_list_spinlock, flags);
1152
1153	return count;
1154}
1155
1156void mwifiex_disable_all_tdls_links(struct mwifiex_private *priv)
1157{
1158	struct mwifiex_sta_node *sta_ptr;
1159	struct mwifiex_ds_tdls_oper tdls_oper;
1160	unsigned long flags;
1161
1162	if (list_empty(&priv->sta_list))
1163		return;
1164
1165	list_for_each_entry(sta_ptr, &priv->sta_list, list) {
1166		memset(&tdls_oper, 0, sizeof(struct mwifiex_ds_tdls_oper));
1167
1168		if (sta_ptr->is_11n_enabled) {
1169			mwifiex_11n_cleanup_reorder_tbl(priv);
1170			spin_lock_irqsave(&priv->wmm.ra_list_spinlock,
1171					  flags);
1172			mwifiex_11n_delete_all_tx_ba_stream_tbl(priv);
1173			spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock,
1174					       flags);
1175		}
1176
1177		mwifiex_restore_tdls_packets(priv, sta_ptr->mac_addr,
1178					     TDLS_LINK_TEARDOWN);
1179		memcpy(&tdls_oper.peer_mac, sta_ptr->mac_addr, ETH_ALEN);
1180		tdls_oper.tdls_action = MWIFIEX_TDLS_DISABLE_LINK;
1181		if (mwifiex_send_cmd(priv, HostCmd_CMD_TDLS_OPER,
1182				     HostCmd_ACT_GEN_SET, 0, &tdls_oper, false))
1183			dev_warn(priv->adapter->dev,
1184				 "Disable link failed for TDLS peer %pM",
1185				 sta_ptr->mac_addr);
1186	}
1187
1188	mwifiex_del_all_sta_list(priv);
1189}
1190
1191int mwifiex_tdls_check_tx(struct mwifiex_private *priv, struct sk_buff *skb)
1192{
1193	struct mwifiex_auto_tdls_peer *peer;
1194	unsigned long flags;
1195	u8 mac[ETH_ALEN];
1196
1197	ether_addr_copy(mac, skb->data);
1198
1199	spin_lock_irqsave(&priv->auto_tdls_lock, flags);
1200	list_for_each_entry(peer, &priv->auto_tdls_list, list) {
1201		if (!memcmp(mac, peer->mac_addr, ETH_ALEN)) {
1202			if (peer->rssi <= MWIFIEX_TDLS_RSSI_HIGH &&
1203			    peer->tdls_status == TDLS_NOT_SETUP &&
1204			    (peer->failure_count <
1205			     MWIFIEX_TDLS_MAX_FAIL_COUNT)) {
1206				peer->tdls_status = TDLS_SETUP_INPROGRESS;
1207				dev_dbg(priv->adapter->dev,
1208					"setup TDLS link, peer=%pM rssi=%d\n",
1209					peer->mac_addr, peer->rssi);
1210
1211				cfg80211_tdls_oper_request(priv->netdev,
1212							   peer->mac_addr,
1213							   NL80211_TDLS_SETUP,
1214							   0, GFP_ATOMIC);
1215				peer->do_setup = false;
1216				priv->check_tdls_tx = false;
1217			} else if (peer->failure_count <
1218				   MWIFIEX_TDLS_MAX_FAIL_COUNT &&
1219				   peer->do_discover) {
1220				mwifiex_send_tdls_data_frame(priv,
1221							     peer->mac_addr,
1222						    WLAN_TDLS_DISCOVERY_REQUEST,
1223							     1, 0, NULL, 0);
1224				peer->do_discover = false;
1225			}
1226		}
1227	}
1228	spin_unlock_irqrestore(&priv->auto_tdls_lock, flags);
1229
1230	return 0;
1231}
1232
1233void mwifiex_flush_auto_tdls_list(struct mwifiex_private *priv)
1234{
1235	struct mwifiex_auto_tdls_peer *peer, *tmp_node;
1236	unsigned long flags;
1237
1238	spin_lock_irqsave(&priv->auto_tdls_lock, flags);
1239	list_for_each_entry_safe(peer, tmp_node, &priv->auto_tdls_list, list) {
1240		list_del(&peer->list);
1241		kfree(peer);
1242	}
1243
1244	INIT_LIST_HEAD(&priv->auto_tdls_list);
1245	spin_unlock_irqrestore(&priv->auto_tdls_lock, flags);
1246	priv->check_tdls_tx = false;
1247}
1248
1249void mwifiex_add_auto_tdls_peer(struct mwifiex_private *priv, const u8 *mac)
1250{
1251	struct mwifiex_auto_tdls_peer *tdls_peer;
1252	unsigned long flags;
1253
1254	if (!priv->adapter->auto_tdls)
1255		return;
1256
1257	spin_lock_irqsave(&priv->auto_tdls_lock, flags);
1258	list_for_each_entry(tdls_peer, &priv->auto_tdls_list, list) {
1259		if (!memcmp(tdls_peer->mac_addr, mac, ETH_ALEN)) {
1260			tdls_peer->tdls_status = TDLS_SETUP_INPROGRESS;
1261			tdls_peer->rssi_jiffies = jiffies;
1262			spin_unlock_irqrestore(&priv->auto_tdls_lock, flags);
1263			return;
1264		}
1265	}
1266
1267	/* create new TDLS peer */
1268	tdls_peer = kzalloc(sizeof(*tdls_peer), GFP_ATOMIC);
1269	if (tdls_peer) {
1270		ether_addr_copy(tdls_peer->mac_addr, mac);
1271		tdls_peer->tdls_status = TDLS_SETUP_INPROGRESS;
1272		tdls_peer->rssi_jiffies = jiffies;
1273		INIT_LIST_HEAD(&tdls_peer->list);
1274		list_add_tail(&tdls_peer->list, &priv->auto_tdls_list);
1275		dev_dbg(priv->adapter->dev, "Add auto TDLS peer= %pM to list\n",
1276			mac);
1277	}
1278
1279	spin_unlock_irqrestore(&priv->auto_tdls_lock, flags);
1280}
1281
1282void mwifiex_auto_tdls_update_peer_status(struct mwifiex_private *priv,
1283					  const u8 *mac, u8 link_status)
1284{
1285	struct mwifiex_auto_tdls_peer *peer;
1286	unsigned long flags;
1287
1288	if (!priv->adapter->auto_tdls)
1289		return;
1290
1291	spin_lock_irqsave(&priv->auto_tdls_lock, flags);
1292	list_for_each_entry(peer, &priv->auto_tdls_list, list) {
1293		if (!memcmp(peer->mac_addr, mac, ETH_ALEN)) {
1294			if ((link_status == TDLS_NOT_SETUP) &&
1295			    (peer->tdls_status == TDLS_SETUP_INPROGRESS))
1296				peer->failure_count++;
1297			else if (link_status == TDLS_SETUP_COMPLETE)
1298				peer->failure_count = 0;
1299
1300			peer->tdls_status = link_status;
1301			break;
1302		}
1303	}
1304	spin_unlock_irqrestore(&priv->auto_tdls_lock, flags);
1305}
1306
1307void mwifiex_auto_tdls_update_peer_signal(struct mwifiex_private *priv,
1308					  u8 *mac, s8 snr, s8 nflr)
1309{
1310	struct mwifiex_auto_tdls_peer *peer;
1311	unsigned long flags;
1312
1313	if (!priv->adapter->auto_tdls)
1314		return;
1315
1316	spin_lock_irqsave(&priv->auto_tdls_lock, flags);
1317	list_for_each_entry(peer, &priv->auto_tdls_list, list) {
1318		if (!memcmp(peer->mac_addr, mac, ETH_ALEN)) {
1319			peer->rssi = nflr - snr;
1320			peer->rssi_jiffies = jiffies;
1321			break;
1322		}
1323	}
1324	spin_unlock_irqrestore(&priv->auto_tdls_lock, flags);
1325}
1326
1327void mwifiex_check_auto_tdls(unsigned long context)
1328{
1329	struct mwifiex_private *priv = (struct mwifiex_private *)context;
1330	struct mwifiex_auto_tdls_peer *tdls_peer;
1331	unsigned long flags;
1332	u16 reason = WLAN_REASON_TDLS_TEARDOWN_UNSPECIFIED;
1333
1334	if (WARN_ON_ONCE(!priv || !priv->adapter)) {
1335		pr_err("mwifiex: %s: adapter or private structure is NULL\n",
1336		       __func__);
1337		return;
1338	}
1339
1340	if (unlikely(!priv->adapter->auto_tdls))
1341		return;
1342
1343	if (!priv->auto_tdls_timer_active) {
1344		dev_dbg(priv->adapter->dev,
1345			"auto TDLS timer inactive; return");
1346		return;
1347	}
1348
1349	priv->check_tdls_tx = false;
1350
1351	if (list_empty(&priv->auto_tdls_list)) {
1352		mod_timer(&priv->auto_tdls_timer,
1353			  jiffies +
1354			  msecs_to_jiffies(MWIFIEX_TIMER_10S));
1355		return;
1356	}
1357
1358	spin_lock_irqsave(&priv->auto_tdls_lock, flags);
1359	list_for_each_entry(tdls_peer, &priv->auto_tdls_list, list) {
1360		if ((jiffies - tdls_peer->rssi_jiffies) >
1361		    (MWIFIEX_AUTO_TDLS_IDLE_TIME * HZ)) {
1362			tdls_peer->rssi = 0;
1363			tdls_peer->do_discover = true;
1364			priv->check_tdls_tx = true;
1365		}
1366
1367		if (((tdls_peer->rssi >= MWIFIEX_TDLS_RSSI_LOW) ||
1368		     !tdls_peer->rssi) &&
1369		    tdls_peer->tdls_status == TDLS_SETUP_COMPLETE) {
1370			tdls_peer->tdls_status = TDLS_LINK_TEARDOWN;
1371			dev_dbg(priv->adapter->dev,
1372				"teardown TDLS link,peer=%pM rssi=%d\n",
1373				tdls_peer->mac_addr, -tdls_peer->rssi);
1374			tdls_peer->do_discover = true;
1375			priv->check_tdls_tx = true;
1376			cfg80211_tdls_oper_request(priv->netdev,
1377						   tdls_peer->mac_addr,
1378						   NL80211_TDLS_TEARDOWN,
1379						   reason, GFP_ATOMIC);
1380		} else if (tdls_peer->rssi &&
1381			   tdls_peer->rssi <= MWIFIEX_TDLS_RSSI_HIGH &&
1382			   tdls_peer->tdls_status == TDLS_NOT_SETUP &&
1383			   tdls_peer->failure_count <
1384			   MWIFIEX_TDLS_MAX_FAIL_COUNT) {
1385				priv->check_tdls_tx = true;
1386				tdls_peer->do_setup = true;
1387				dev_dbg(priv->adapter->dev,
1388					"check TDLS with peer=%pM rssi=%d\n",
1389					tdls_peer->mac_addr, -tdls_peer->rssi);
1390		}
1391	}
1392	spin_unlock_irqrestore(&priv->auto_tdls_lock, flags);
1393
1394	mod_timer(&priv->auto_tdls_timer,
1395		  jiffies + msecs_to_jiffies(MWIFIEX_TIMER_10S));
1396}
1397
1398void mwifiex_setup_auto_tdls_timer(struct mwifiex_private *priv)
1399{
1400	setup_timer(&priv->auto_tdls_timer, mwifiex_check_auto_tdls,
1401		    (unsigned long)priv);
1402	priv->auto_tdls_timer_active = true;
1403	mod_timer(&priv->auto_tdls_timer,
1404		  jiffies + msecs_to_jiffies(MWIFIEX_TIMER_10S));
1405}
1406
1407void mwifiex_clean_auto_tdls(struct mwifiex_private *priv)
1408{
1409	if (ISSUPP_TDLS_ENABLED(priv->adapter->fw_cap_info) &&
1410	    priv->adapter->auto_tdls &&
1411	    priv->bss_type == MWIFIEX_BSS_TYPE_STA) {
1412		priv->auto_tdls_timer_active = false;
1413		del_timer(&priv->auto_tdls_timer);
1414		mwifiex_flush_auto_tdls_list(priv);
1415	}
1416}
1417