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