xref: /wlan-driver/qcacld-3.0/os_if/tdls/src/wlan_cfg80211_tdls.c (revision 5113495b16420b49004c444715d2daae2066e7dc)
1*5113495bSYour Name /*
2*5113495bSYour Name  * Copyright (c) 2017-2021 The Linux Foundation. All rights reserved.
3*5113495bSYour Name  * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved.
4*5113495bSYour Name  *
5*5113495bSYour Name  * Permission to use, copy, modify, and/or distribute this software for
6*5113495bSYour Name  * any purpose with or without fee is hereby granted, provided that the
7*5113495bSYour Name  * above copyright notice and this permission notice appear in all
8*5113495bSYour Name  * copies.
9*5113495bSYour Name  *
10*5113495bSYour Name  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
11*5113495bSYour Name  * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
12*5113495bSYour Name  * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
13*5113495bSYour Name  * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
14*5113495bSYour Name  * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
15*5113495bSYour Name  * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
16*5113495bSYour Name  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17*5113495bSYour Name  * PERFORMANCE OF THIS SOFTWARE.
18*5113495bSYour Name  */
19*5113495bSYour Name 
20*5113495bSYour Name /**
21*5113495bSYour Name  * DOC: defines driver functions interfacing with linux kernel
22*5113495bSYour Name  */
23*5113495bSYour Name 
24*5113495bSYour Name #include <qdf_list.h>
25*5113495bSYour Name #include <qdf_status.h>
26*5113495bSYour Name #include <linux/wireless.h>
27*5113495bSYour Name #include <linux/netdevice.h>
28*5113495bSYour Name #include <net/cfg80211.h>
29*5113495bSYour Name #include <wlan_cfg80211.h>
30*5113495bSYour Name #include <wlan_cfg80211_tdls.h>
31*5113495bSYour Name #include <wlan_osif_priv.h>
32*5113495bSYour Name #include <wlan_tdls_public_structs.h>
33*5113495bSYour Name #include <wlan_tdls_ucfg_api.h>
34*5113495bSYour Name #include <qdf_mem.h>
35*5113495bSYour Name #include <wlan_utility.h>
36*5113495bSYour Name #include <wlan_reg_services_api.h>
37*5113495bSYour Name #include "wlan_cfg80211_mc_cp_stats.h"
38*5113495bSYour Name #include "sir_api.h"
39*5113495bSYour Name #include "wlan_tdls_ucfg_api.h"
40*5113495bSYour Name #include "wlan_cm_roam_api.h"
41*5113495bSYour Name #include "wlan_mlo_mgr_sta.h"
42*5113495bSYour Name #include "wlan_hdd_main.h"
43*5113495bSYour Name #include "wlan_hdd_object_manager.h"
44*5113495bSYour Name 
wlan_cfg80211_tdls_validate_mac_addr(const uint8_t * mac)45*5113495bSYour Name static int wlan_cfg80211_tdls_validate_mac_addr(const uint8_t *mac)
46*5113495bSYour Name {
47*5113495bSYour Name 	static const uint8_t temp_mac[QDF_MAC_ADDR_SIZE] = {0};
48*5113495bSYour Name 
49*5113495bSYour Name 	if (!qdf_mem_cmp(mac, temp_mac, QDF_MAC_ADDR_SIZE)) {
50*5113495bSYour Name 		osif_debug("Invalid Mac address " QDF_MAC_ADDR_FMT
51*5113495bSYour Name 			   " cmd declined.",
52*5113495bSYour Name 			   QDF_MAC_ADDR_REF(mac));
53*5113495bSYour Name 		return -EINVAL;
54*5113495bSYour Name 	}
55*5113495bSYour Name 
56*5113495bSYour Name 	return 0;
57*5113495bSYour Name }
58*5113495bSYour Name 
wlan_cfg80211_tdls_osif_priv_init(struct wlan_objmgr_vdev * vdev)59*5113495bSYour Name QDF_STATUS wlan_cfg80211_tdls_osif_priv_init(struct wlan_objmgr_vdev *vdev)
60*5113495bSYour Name {
61*5113495bSYour Name 	struct osif_tdls_vdev *tdls_priv;
62*5113495bSYour Name 	struct vdev_osif_priv *osif_priv;
63*5113495bSYour Name 
64*5113495bSYour Name 	osif_priv = wlan_vdev_get_ospriv(vdev);
65*5113495bSYour Name 	if (!osif_priv) {
66*5113495bSYour Name 		osif_err("osif_priv is NULL!");
67*5113495bSYour Name 		return QDF_STATUS_E_FAULT;
68*5113495bSYour Name 	}
69*5113495bSYour Name 
70*5113495bSYour Name 	osif_debug("initialize tdls os if layer private structure");
71*5113495bSYour Name 	tdls_priv = qdf_mem_malloc(sizeof(*tdls_priv));
72*5113495bSYour Name 	if (!tdls_priv)
73*5113495bSYour Name 		return QDF_STATUS_E_NOMEM;
74*5113495bSYour Name 
75*5113495bSYour Name 	init_completion(&tdls_priv->tdls_add_peer_comp);
76*5113495bSYour Name 	init_completion(&tdls_priv->tdls_del_peer_comp);
77*5113495bSYour Name 	init_completion(&tdls_priv->tdls_mgmt_comp);
78*5113495bSYour Name 	init_completion(&tdls_priv->tdls_link_establish_req_comp);
79*5113495bSYour Name 	init_completion(&tdls_priv->tdls_teardown_comp);
80*5113495bSYour Name 	init_completion(&tdls_priv->tdls_user_cmd_comp);
81*5113495bSYour Name 	init_completion(&tdls_priv->tdls_antenna_switch_comp);
82*5113495bSYour Name 
83*5113495bSYour Name 	osif_priv->osif_tdls = tdls_priv;
84*5113495bSYour Name 
85*5113495bSYour Name 	return QDF_STATUS_SUCCESS;
86*5113495bSYour Name }
87*5113495bSYour Name 
wlan_cfg80211_tdls_osif_priv_deinit(struct wlan_objmgr_vdev * vdev)88*5113495bSYour Name void wlan_cfg80211_tdls_osif_priv_deinit(struct wlan_objmgr_vdev *vdev)
89*5113495bSYour Name {
90*5113495bSYour Name 	struct vdev_osif_priv *osif_priv;
91*5113495bSYour Name 
92*5113495bSYour Name 	osif_priv = wlan_vdev_get_ospriv(vdev);
93*5113495bSYour Name 	if (!osif_priv) {
94*5113495bSYour Name 		osif_err("osif_priv is NULL!");
95*5113495bSYour Name 		return;
96*5113495bSYour Name 	}
97*5113495bSYour Name 
98*5113495bSYour Name 	osif_debug("deinitialize tdls os if layer private structure");
99*5113495bSYour Name 	if (osif_priv->osif_tdls)
100*5113495bSYour Name 		qdf_mem_free(osif_priv->osif_tdls);
101*5113495bSYour Name 	osif_priv->osif_tdls = NULL;
102*5113495bSYour Name }
103*5113495bSYour Name 
hdd_notify_tdls_reset_adapter(struct wlan_objmgr_vdev * vdev)104*5113495bSYour Name void hdd_notify_tdls_reset_adapter(struct wlan_objmgr_vdev *vdev)
105*5113495bSYour Name {
106*5113495bSYour Name 	ucfg_tdls_notify_reset_adapter(vdev);
107*5113495bSYour Name }
108*5113495bSYour Name 
wlan_cfg80211_tdls_add_peer(struct wlan_objmgr_vdev * vdev,const uint8_t * mac)109*5113495bSYour Name static int wlan_cfg80211_tdls_add_peer(struct wlan_objmgr_vdev *vdev,
110*5113495bSYour Name 				       const uint8_t *mac)
111*5113495bSYour Name {
112*5113495bSYour Name 	struct tdls_add_peer_params *add_peer_req;
113*5113495bSYour Name 	int status;
114*5113495bSYour Name 	struct vdev_osif_priv *osif_priv;
115*5113495bSYour Name 	struct osif_tdls_vdev *tdls_priv;
116*5113495bSYour Name 	unsigned long rc;
117*5113495bSYour Name 
118*5113495bSYour Name 	status = wlan_cfg80211_tdls_validate_mac_addr(mac);
119*5113495bSYour Name 
120*5113495bSYour Name 	if (status)
121*5113495bSYour Name 		return status;
122*5113495bSYour Name 
123*5113495bSYour Name 	osif_debug("Add TDLS peer " QDF_MAC_ADDR_FMT,
124*5113495bSYour Name 		   QDF_MAC_ADDR_REF(mac));
125*5113495bSYour Name 
126*5113495bSYour Name 	add_peer_req = qdf_mem_malloc(sizeof(*add_peer_req));
127*5113495bSYour Name 	if (!add_peer_req)
128*5113495bSYour Name 		return -EINVAL;
129*5113495bSYour Name 
130*5113495bSYour Name 	osif_priv = wlan_vdev_get_ospriv(vdev);
131*5113495bSYour Name 	if (!osif_priv || !osif_priv->osif_tdls) {
132*5113495bSYour Name 		osif_err("osif_tdls_vdev or osif_priv is NULL for the current vdev");
133*5113495bSYour Name 		status = -EINVAL;
134*5113495bSYour Name 		goto error;
135*5113495bSYour Name 	}
136*5113495bSYour Name 	tdls_priv = osif_priv->osif_tdls;
137*5113495bSYour Name 	add_peer_req->vdev_id = wlan_vdev_get_id(vdev);
138*5113495bSYour Name 
139*5113495bSYour Name 	qdf_mem_copy(add_peer_req->peer_addr, mac, QDF_MAC_ADDR_SIZE);
140*5113495bSYour Name 
141*5113495bSYour Name 	reinit_completion(&tdls_priv->tdls_add_peer_comp);
142*5113495bSYour Name 	status = ucfg_tdls_add_peer(vdev, add_peer_req);
143*5113495bSYour Name 	if (QDF_IS_STATUS_ERROR(status)) {
144*5113495bSYour Name 		osif_err("ucfg_tdls_add_peer returned err %d", status);
145*5113495bSYour Name 		status = -EIO;
146*5113495bSYour Name 		goto error;
147*5113495bSYour Name 	}
148*5113495bSYour Name 
149*5113495bSYour Name 	rc = wait_for_completion_timeout(
150*5113495bSYour Name 	    &tdls_priv->tdls_add_peer_comp,
151*5113495bSYour Name 	    msecs_to_jiffies(WAIT_TIME_TDLS_ADD_STA));
152*5113495bSYour Name 	if (!rc) {
153*5113495bSYour Name 		osif_err("timeout for tdls add peer indication %ld", rc);
154*5113495bSYour Name 		status = -EPERM;
155*5113495bSYour Name 		goto error;
156*5113495bSYour Name 	}
157*5113495bSYour Name 
158*5113495bSYour Name 	if (QDF_IS_STATUS_ERROR(tdls_priv->tdls_add_peer_status)) {
159*5113495bSYour Name 		osif_err("tdls add peer failed, status:%d",
160*5113495bSYour Name 			 tdls_priv->tdls_add_peer_status);
161*5113495bSYour Name 		status = -EPERM;
162*5113495bSYour Name 	}
163*5113495bSYour Name error:
164*5113495bSYour Name 	qdf_mem_free(add_peer_req);
165*5113495bSYour Name 	return status;
166*5113495bSYour Name }
167*5113495bSYour Name 
wlan_cfg80211_tdls_add_peer_mlo(struct hdd_adapter * adapter,const uint8_t * mac,uint8_t link_id)168*5113495bSYour Name int wlan_cfg80211_tdls_add_peer_mlo(struct hdd_adapter *adapter,
169*5113495bSYour Name 				    const uint8_t *mac, uint8_t link_id)
170*5113495bSYour Name {
171*5113495bSYour Name 	struct wlan_objmgr_vdev *vdev;
172*5113495bSYour Name 	bool is_mlo_vdev;
173*5113495bSYour Name 	int status;
174*5113495bSYour Name 
175*5113495bSYour Name 	vdev = hdd_objmgr_get_vdev_by_user(adapter->deflink, WLAN_OSIF_TDLS_ID);
176*5113495bSYour Name 	if (!vdev)
177*5113495bSYour Name 		return -EINVAL;
178*5113495bSYour Name 
179*5113495bSYour Name 	if (wlan_vdev_is_up(vdev) != QDF_STATUS_SUCCESS) {
180*5113495bSYour Name 		osif_debug("sta is not connected or disconnecting");
181*5113495bSYour Name 		hdd_objmgr_put_vdev_by_user(vdev, WLAN_OSIF_TDLS_ID);
182*5113495bSYour Name 		return -EINVAL;
183*5113495bSYour Name 	}
184*5113495bSYour Name 
185*5113495bSYour Name 	is_mlo_vdev = wlan_vdev_mlme_is_mlo_vdev(vdev);
186*5113495bSYour Name 	if (is_mlo_vdev) {
187*5113495bSYour Name 		hdd_objmgr_put_vdev_by_user(vdev, WLAN_OSIF_TDLS_ID);
188*5113495bSYour Name 
189*5113495bSYour Name 		vdev = wlan_key_get_link_vdev(adapter, WLAN_OSIF_TDLS_ID,
190*5113495bSYour Name 					      link_id);
191*5113495bSYour Name 		if (!vdev)
192*5113495bSYour Name 			return -EINVAL;
193*5113495bSYour Name 
194*5113495bSYour Name 		if (!ucfg_tdls_link_vdev_is_matching(vdev)) {
195*5113495bSYour Name 			wlan_key_put_link_vdev(vdev, WLAN_OSIF_TDLS_ID);
196*5113495bSYour Name 			return -EINVAL;
197*5113495bSYour Name 		}
198*5113495bSYour Name 
199*5113495bSYour Name 		osif_debug("tdls add peer for vdev %d", wlan_vdev_get_id(vdev));
200*5113495bSYour Name 		status = wlan_cfg80211_tdls_add_peer(vdev, mac);
201*5113495bSYour Name 		wlan_key_put_link_vdev(vdev, WLAN_OSIF_TDLS_ID);
202*5113495bSYour Name 	} else {
203*5113495bSYour Name 		status = wlan_cfg80211_tdls_add_peer(vdev, mac);
204*5113495bSYour Name 		hdd_objmgr_put_vdev_by_user(vdev, WLAN_OSIF_TDLS_ID);
205*5113495bSYour Name 	}
206*5113495bSYour Name 
207*5113495bSYour Name 	return status;
208*5113495bSYour Name }
209*5113495bSYour Name 
210*5113495bSYour Name static bool
is_duplicate_freq(qdf_freq_t * arr,uint8_t index,qdf_freq_t freq)211*5113495bSYour Name is_duplicate_freq(qdf_freq_t *arr, uint8_t index, qdf_freq_t freq)
212*5113495bSYour Name {
213*5113495bSYour Name 	int i;
214*5113495bSYour Name 
215*5113495bSYour Name 	for (i = 0; i < index; i++) {
216*5113495bSYour Name 		if (arr[i] == freq)
217*5113495bSYour Name 			return true;
218*5113495bSYour Name 	}
219*5113495bSYour Name 	return false;
220*5113495bSYour Name }
221*5113495bSYour Name 
222*5113495bSYour Name static uint8_t
tdls_fill_chan_freq_from_supported_ch_list(struct wlan_objmgr_pdev * pdev,const uint8_t * country,const uint8_t * src_chans,uint8_t src_chan_num,uint8_t src_opclass,uint8_t * num_freq,qdf_freq_t * freq_lst)223*5113495bSYour Name tdls_fill_chan_freq_from_supported_ch_list(struct wlan_objmgr_pdev *pdev,
224*5113495bSYour Name 					   const uint8_t *country,
225*5113495bSYour Name 					   const uint8_t *src_chans,
226*5113495bSYour Name 					   uint8_t src_chan_num,
227*5113495bSYour Name 					   uint8_t src_opclass,
228*5113495bSYour Name 					   uint8_t *num_freq,
229*5113495bSYour Name 					   qdf_freq_t *freq_lst)
230*5113495bSYour Name {
231*5113495bSYour Name 	uint8_t i = 0, j = 0, num_unique_freq = *num_freq;
232*5113495bSYour Name 	uint8_t chan_count;
233*5113495bSYour Name 	uint8_t wifi_chan_index;
234*5113495bSYour Name 	uint8_t next_ch;
235*5113495bSYour Name 	qdf_freq_t freq;
236*5113495bSYour Name 
237*5113495bSYour Name 	for (i = 0; i < src_chan_num &&
238*5113495bSYour Name 	     num_unique_freq < WLAN_MAC_MAX_SUPP_CHANNELS; i += 2) {
239*5113495bSYour Name 		freq = wlan_reg_country_chan_opclass_to_freq(pdev, country,
240*5113495bSYour Name 							     src_chans[i],
241*5113495bSYour Name 							     src_opclass,
242*5113495bSYour Name 							     false);
243*5113495bSYour Name 
244*5113495bSYour Name 		if (!freq || is_duplicate_freq(freq_lst, num_unique_freq, freq))
245*5113495bSYour Name 			continue;
246*5113495bSYour Name 
247*5113495bSYour Name 		if (wlan_reg_is_6ghz_chan_freq(freq) &&
248*5113495bSYour Name 		    !wlan_reg_is_6ghz_psc_chan_freq(freq)) {
249*5113495bSYour Name 			osif_debug("skipping non-psc channel %d", freq);
250*5113495bSYour Name 			continue;
251*5113495bSYour Name 		}
252*5113495bSYour Name 
253*5113495bSYour Name 		chan_count = src_chans[i + 1];
254*5113495bSYour Name 		wifi_chan_index = ((src_chans[i] <= WLAN_CHANNEL_14) ? 1 : 4);
255*5113495bSYour Name 		freq_lst[num_unique_freq] = freq;
256*5113495bSYour Name 		num_unique_freq++;
257*5113495bSYour Name 		next_ch = src_chans[i];
258*5113495bSYour Name 		osif_debug("freq %d index %d ", freq, num_unique_freq);
259*5113495bSYour Name 
260*5113495bSYour Name 		for (j = 1; j < chan_count &&
261*5113495bSYour Name 		     num_unique_freq < WLAN_MAC_MAX_SUPP_CHANNELS; j++) {
262*5113495bSYour Name 			next_ch += wifi_chan_index;
263*5113495bSYour Name 			freq = wlan_reg_country_chan_opclass_to_freq(
264*5113495bSYour Name 							pdev, country, next_ch,
265*5113495bSYour Name 							src_opclass, false);
266*5113495bSYour Name 
267*5113495bSYour Name 			if (!freq ||
268*5113495bSYour Name 			    is_duplicate_freq(freq_lst, num_unique_freq, freq))
269*5113495bSYour Name 				continue;
270*5113495bSYour Name 
271*5113495bSYour Name 			if (wlan_reg_is_6ghz_chan_freq(freq) &&
272*5113495bSYour Name 			    !wlan_reg_is_6ghz_psc_chan_freq(freq)) {
273*5113495bSYour Name 				osif_debug("skipping non-psc channel %d", freq);
274*5113495bSYour Name 				continue;
275*5113495bSYour Name 			}
276*5113495bSYour Name 
277*5113495bSYour Name 			freq_lst[num_unique_freq] = freq;
278*5113495bSYour Name 			osif_debug("freq %d index %d ", freq, num_unique_freq);
279*5113495bSYour Name 			num_unique_freq++;
280*5113495bSYour Name 
281*5113495bSYour Name 			if (num_unique_freq > NUM_CHANNELS) {
282*5113495bSYour Name 				osif_debug("num_unique_freq more than max num");
283*5113495bSYour Name 				break;
284*5113495bSYour Name 			}
285*5113495bSYour Name 		}
286*5113495bSYour Name 	}
287*5113495bSYour Name 	*num_freq = num_unique_freq;
288*5113495bSYour Name 
289*5113495bSYour Name 	return num_unique_freq;
290*5113495bSYour Name }
291*5113495bSYour Name 
292*5113495bSYour Name static void
tdls_calc_channels_from_staparams(struct wlan_objmgr_vdev * vdev,struct tdls_update_peer_params * req_info,struct station_parameters * params)293*5113495bSYour Name tdls_calc_channels_from_staparams(struct wlan_objmgr_vdev *vdev,
294*5113495bSYour Name 				  struct tdls_update_peer_params *req_info,
295*5113495bSYour Name 				  struct station_parameters *params)
296*5113495bSYour Name {
297*5113495bSYour Name 	uint8_t i = 0;
298*5113495bSYour Name 	uint8_t num_unique_freq = 0;
299*5113495bSYour Name 	const uint8_t *src_chans, *src_opclass;
300*5113495bSYour Name 	qdf_freq_t *dest_freq;
301*5113495bSYour Name 	uint8_t country[REG_ALPHA2_LEN + 1];
302*5113495bSYour Name 	QDF_STATUS status;
303*5113495bSYour Name 	struct wlan_objmgr_pdev *pdev;
304*5113495bSYour Name 
305*5113495bSYour Name 	if (!vdev) {
306*5113495bSYour Name 		osif_err("null vdev");
307*5113495bSYour Name 		return;
308*5113495bSYour Name 	}
309*5113495bSYour Name 
310*5113495bSYour Name 	pdev = wlan_vdev_get_pdev(vdev);
311*5113495bSYour Name 	if (!pdev) {
312*5113495bSYour Name 		osif_err("null pdev");
313*5113495bSYour Name 		return;
314*5113495bSYour Name 	}
315*5113495bSYour Name 	src_chans = params->supported_channels;
316*5113495bSYour Name 	src_opclass = params->supported_oper_classes;
317*5113495bSYour Name 	dest_freq = req_info->supported_chan_freq;
318*5113495bSYour Name 	pdev = wlan_vdev_get_pdev(vdev);
319*5113495bSYour Name 	status = wlan_cm_get_country_code(pdev, wlan_vdev_get_id(vdev),
320*5113495bSYour Name 					  country);
321*5113495bSYour Name 
322*5113495bSYour Name 	osif_debug("Country info from AP:%c%c 0x%x", country[0],
323*5113495bSYour Name 		   country[1], country[2]);
324*5113495bSYour Name 
325*5113495bSYour Name 	for (i = 0; i < params->supported_oper_classes_len; i++)
326*5113495bSYour Name 		tdls_fill_chan_freq_from_supported_ch_list(
327*5113495bSYour Name 						pdev, country, src_chans,
328*5113495bSYour Name 						params->supported_channels_len,
329*5113495bSYour Name 						src_opclass[i],
330*5113495bSYour Name 						&num_unique_freq,
331*5113495bSYour Name 						dest_freq);
332*5113495bSYour Name 
333*5113495bSYour Name 	osif_debug("Unique Channel List: supported_channels ");
334*5113495bSYour Name 	for (i = 0; i < num_unique_freq; i++)
335*5113495bSYour Name 		osif_debug(" %d,", dest_freq[i]);
336*5113495bSYour Name 
337*5113495bSYour Name 	req_info->supported_channels_len = num_unique_freq;
338*5113495bSYour Name 	osif_debug("After removing duplcates supported_channels_len: %d",
339*5113495bSYour Name 		   req_info->supported_channels_len);
340*5113495bSYour Name }
341*5113495bSYour Name 
342*5113495bSYour Name #ifdef WLAN_FEATURE_11AX
343*5113495bSYour Name #if defined(WLAN_LINK_STA_PARAMS_PRESENT) && defined(CONFIG_BAND_6GHZ)
344*5113495bSYour Name static void
wlan_cfg80211_tdls_extract_6ghz_params(struct tdls_update_peer_params * req_info,struct station_parameters * params)345*5113495bSYour Name wlan_cfg80211_tdls_extract_6ghz_params(struct tdls_update_peer_params *req_info,
346*5113495bSYour Name 				       struct station_parameters *params)
347*5113495bSYour Name {
348*5113495bSYour Name 	if (!params->link_sta_params.he_6ghz_capa) {
349*5113495bSYour Name 		osif_debug("6 Ghz he_capa not present");
350*5113495bSYour Name 		return;
351*5113495bSYour Name 	}
352*5113495bSYour Name 
353*5113495bSYour Name 	qdf_mem_copy(&req_info->he_6ghz_cap,
354*5113495bSYour Name 		     params->link_sta_params.he_6ghz_capa,
355*5113495bSYour Name 		     sizeof(req_info->he_6ghz_cap));
356*5113495bSYour Name }
357*5113495bSYour Name #elif (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 4, 0)) && defined(CONFIG_BAND_6GHZ)
358*5113495bSYour Name static void
wlan_cfg80211_tdls_extract_6ghz_params(struct tdls_update_peer_params * req_info,struct station_parameters * params)359*5113495bSYour Name wlan_cfg80211_tdls_extract_6ghz_params(struct tdls_update_peer_params *req_info,
360*5113495bSYour Name 				       struct station_parameters *params)
361*5113495bSYour Name {
362*5113495bSYour Name 	if (!params->he_6ghz_capa) {
363*5113495bSYour Name 		osif_debug("6 Ghz he_capa not present");
364*5113495bSYour Name 		return;
365*5113495bSYour Name 	}
366*5113495bSYour Name 
367*5113495bSYour Name 	qdf_mem_copy(&req_info->he_6ghz_cap, params->he_6ghz_capa,
368*5113495bSYour Name 		     sizeof(req_info->he_6ghz_cap));
369*5113495bSYour Name }
370*5113495bSYour Name #else
371*5113495bSYour Name static void
wlan_cfg80211_tdls_extract_6ghz_params(struct tdls_update_peer_params * req_info,struct station_parameters * params)372*5113495bSYour Name wlan_cfg80211_tdls_extract_6ghz_params(struct tdls_update_peer_params *req_info,
373*5113495bSYour Name 				       struct station_parameters *params)
374*5113495bSYour Name {
375*5113495bSYour Name 	osif_debug("kernel don't support tdls 6 ghz band");
376*5113495bSYour Name }
377*5113495bSYour Name #endif
378*5113495bSYour Name 
379*5113495bSYour Name #ifdef WLAN_LINK_STA_PARAMS_PRESENT
380*5113495bSYour Name static void
wlan_cfg80211_tdls_extract_he_params(struct tdls_update_peer_params * req_info,struct station_parameters * params,bool tdls_6g_support)381*5113495bSYour Name wlan_cfg80211_tdls_extract_he_params(struct tdls_update_peer_params *req_info,
382*5113495bSYour Name 				     struct station_parameters *params,
383*5113495bSYour Name 				     bool tdls_6g_support)
384*5113495bSYour Name {
385*5113495bSYour Name 	if (params->link_sta_params.he_capa_len < MIN_TDLS_HE_CAP_LEN) {
386*5113495bSYour Name 		osif_debug("he_capa_len %d less than MIN_TDLS_HE_CAP_LEN",
387*5113495bSYour Name 			   params->link_sta_params.he_capa_len);
388*5113495bSYour Name 		return;
389*5113495bSYour Name 	}
390*5113495bSYour Name 
391*5113495bSYour Name 	if (!params->link_sta_params.he_capa) {
392*5113495bSYour Name 		osif_debug("he_capa not present");
393*5113495bSYour Name 		return;
394*5113495bSYour Name 	}
395*5113495bSYour Name 
396*5113495bSYour Name 	req_info->he_cap_len = params->link_sta_params.he_capa_len;
397*5113495bSYour Name 	if (req_info->he_cap_len > MAX_TDLS_HE_CAP_LEN)
398*5113495bSYour Name 		req_info->he_cap_len = MAX_TDLS_HE_CAP_LEN;
399*5113495bSYour Name 
400*5113495bSYour Name 	qdf_mem_copy(&req_info->he_cap, params->link_sta_params.he_capa,
401*5113495bSYour Name 		     req_info->he_cap_len);
402*5113495bSYour Name 
403*5113495bSYour Name 	if (tdls_6g_support)
404*5113495bSYour Name 		wlan_cfg80211_tdls_extract_6ghz_params(req_info, params);
405*5113495bSYour Name }
406*5113495bSYour Name #else
407*5113495bSYour Name static void
wlan_cfg80211_tdls_extract_he_params(struct tdls_update_peer_params * req_info,struct station_parameters * params,bool tdls_6g_support)408*5113495bSYour Name wlan_cfg80211_tdls_extract_he_params(struct tdls_update_peer_params *req_info,
409*5113495bSYour Name 				     struct station_parameters *params,
410*5113495bSYour Name 				     bool tdls_6g_support)
411*5113495bSYour Name {
412*5113495bSYour Name 	if (params->he_capa_len < MIN_TDLS_HE_CAP_LEN) {
413*5113495bSYour Name 		osif_debug("he_capa_len %d less than MIN_TDLS_HE_CAP_LEN",
414*5113495bSYour Name 			   params->he_capa_len);
415*5113495bSYour Name 		return;
416*5113495bSYour Name 	}
417*5113495bSYour Name 
418*5113495bSYour Name 	if (!params->he_capa) {
419*5113495bSYour Name 		osif_debug("he_capa not present");
420*5113495bSYour Name 		return;
421*5113495bSYour Name 	}
422*5113495bSYour Name 
423*5113495bSYour Name 	req_info->he_cap_len = params->he_capa_len;
424*5113495bSYour Name 	if (req_info->he_cap_len > MAX_TDLS_HE_CAP_LEN)
425*5113495bSYour Name 		req_info->he_cap_len = MAX_TDLS_HE_CAP_LEN;
426*5113495bSYour Name 
427*5113495bSYour Name 	qdf_mem_copy(&req_info->he_cap, params->he_capa,
428*5113495bSYour Name 		     req_info->he_cap_len);
429*5113495bSYour Name 
430*5113495bSYour Name 	if (tdls_6g_support)
431*5113495bSYour Name 		wlan_cfg80211_tdls_extract_6ghz_params(req_info, params);
432*5113495bSYour Name }
433*5113495bSYour Name #endif
434*5113495bSYour Name #else
435*5113495bSYour Name static inline void
wlan_cfg80211_tdls_extract_he_params(struct tdls_update_peer_params * req_info,struct station_parameters * params,bool tdls_6g_support)436*5113495bSYour Name wlan_cfg80211_tdls_extract_he_params(struct tdls_update_peer_params *req_info,
437*5113495bSYour Name 				     struct station_parameters *params,
438*5113495bSYour Name 				     bool tdls_6g_support)
439*5113495bSYour Name {
440*5113495bSYour Name }
441*5113495bSYour Name #endif
442*5113495bSYour Name 
443*5113495bSYour Name #ifdef WLAN_FEATURE_11BE
444*5113495bSYour Name #ifdef WLAN_LINK_STA_PARAMS_PRESENT
445*5113495bSYour Name static void
wlan_cfg80211_tdls_extract_eht_params(struct tdls_update_peer_params * req_info,struct station_parameters * params)446*5113495bSYour Name wlan_cfg80211_tdls_extract_eht_params(struct tdls_update_peer_params *req_info,
447*5113495bSYour Name 				      struct station_parameters *params)
448*5113495bSYour Name {
449*5113495bSYour Name 	if (params->link_sta_params.eht_capa) {
450*5113495bSYour Name 		osif_debug("eht capa is present");
451*5113495bSYour Name 		req_info->ehtcap_present = 1;
452*5113495bSYour Name 		req_info->eht_cap_len = params->link_sta_params.eht_capa_len;
453*5113495bSYour Name 		qdf_mem_copy(&req_info->eht_cap,
454*5113495bSYour Name 			     params->link_sta_params.eht_capa,
455*5113495bSYour Name 			     sizeof(struct ehtcap));
456*5113495bSYour Name 	} else {
457*5113495bSYour Name 		req_info->ehtcap_present = 0;
458*5113495bSYour Name 	}
459*5113495bSYour Name }
460*5113495bSYour Name #elif defined(WLAN_EHT_CAPABILITY_PRESENT)
461*5113495bSYour Name static void
wlan_cfg80211_tdls_extract_eht_params(struct tdls_update_peer_params * req_info,struct station_parameters * params)462*5113495bSYour Name wlan_cfg80211_tdls_extract_eht_params(struct tdls_update_peer_params *req_info,
463*5113495bSYour Name 				      struct station_parameters *params)
464*5113495bSYour Name {
465*5113495bSYour Name 	if (params->eht_capa) {
466*5113495bSYour Name 		osif_debug("eht capa is present");
467*5113495bSYour Name 		req_info->ehtcap_present = 1;
468*5113495bSYour Name 		req_info->eht_cap_len = params->eht_capa_len;
469*5113495bSYour Name 		qdf_mem_copy(&req_info->eht_cap, params->eht_capa,
470*5113495bSYour Name 			     sizeof(struct ehtcap));
471*5113495bSYour Name 	} else {
472*5113495bSYour Name 		req_info->ehtcap_present = 0;
473*5113495bSYour Name 	}
474*5113495bSYour Name }
475*5113495bSYour Name #else
476*5113495bSYour Name static inline void
wlan_cfg80211_tdls_extract_eht_params(struct tdls_update_peer_params * req_info,struct station_parameters * params)477*5113495bSYour Name wlan_cfg80211_tdls_extract_eht_params(struct tdls_update_peer_params *req_info,
478*5113495bSYour Name 				      struct station_parameters *params)
479*5113495bSYour Name {
480*5113495bSYour Name }
481*5113495bSYour Name #endif
482*5113495bSYour Name #else
483*5113495bSYour Name static inline void
wlan_cfg80211_tdls_extract_eht_params(struct tdls_update_peer_params * req_info,struct station_parameters * params)484*5113495bSYour Name wlan_cfg80211_tdls_extract_eht_params(struct tdls_update_peer_params *req_info,
485*5113495bSYour Name 				      struct station_parameters *params)
486*5113495bSYour Name {
487*5113495bSYour Name }
488*5113495bSYour Name #endif
489*5113495bSYour Name 
490*5113495bSYour Name #ifdef WLAN_LINK_STA_PARAMS_PRESENT
491*5113495bSYour Name static void
wlan_cfg80211_tdls_extract_params(struct wlan_objmgr_vdev * vdev,struct tdls_update_peer_params * req_info,struct station_parameters * params,bool tdls_11ax_support,bool tdls_6g_support)492*5113495bSYour Name wlan_cfg80211_tdls_extract_params(struct wlan_objmgr_vdev *vdev,
493*5113495bSYour Name 				  struct tdls_update_peer_params *req_info,
494*5113495bSYour Name 				  struct station_parameters *params,
495*5113495bSYour Name 				  bool tdls_11ax_support, bool tdls_6g_support)
496*5113495bSYour Name {
497*5113495bSYour Name 	int i;
498*5113495bSYour Name 
499*5113495bSYour Name 	osif_debug("sta cap %d, uapsd_queue %d, max_sp %d",
500*5113495bSYour Name 		   params->capability,
501*5113495bSYour Name 		   params->uapsd_queues, params->max_sp);
502*5113495bSYour Name 
503*5113495bSYour Name 	if (!req_info) {
504*5113495bSYour Name 		osif_err("reg_info is NULL");
505*5113495bSYour Name 		return;
506*5113495bSYour Name 	}
507*5113495bSYour Name 	req_info->capability = params->capability;
508*5113495bSYour Name 	req_info->uapsd_queues = params->uapsd_queues;
509*5113495bSYour Name 	req_info->max_sp = params->max_sp;
510*5113495bSYour Name 
511*5113495bSYour Name 	if (params->supported_oper_classes_len > WLAN_MAX_SUPP_OPER_CLASSES) {
512*5113495bSYour Name 		osif_debug("received oper classes:%d, resetting it to max supported: %d",
513*5113495bSYour Name 			   params->supported_oper_classes_len,
514*5113495bSYour Name 			   WLAN_MAX_SUPP_OPER_CLASSES);
515*5113495bSYour Name 		params->supported_oper_classes_len = WLAN_MAX_SUPP_OPER_CLASSES;
516*5113495bSYour Name 	}
517*5113495bSYour Name 
518*5113495bSYour Name 	qdf_mem_copy(req_info->supported_oper_classes,
519*5113495bSYour Name 		     params->supported_oper_classes,
520*5113495bSYour Name 		     params->supported_oper_classes_len);
521*5113495bSYour Name 	req_info->supported_oper_classes_len =
522*5113495bSYour Name 		params->supported_oper_classes_len;
523*5113495bSYour Name 
524*5113495bSYour Name 	if (params->supported_channels_len)
525*5113495bSYour Name 		tdls_calc_channels_from_staparams(vdev, req_info, params);
526*5113495bSYour Name 
527*5113495bSYour Name 	if (params->ext_capab_len)
528*5113495bSYour Name 		qdf_mem_copy(req_info->extn_capability, params->ext_capab,
529*5113495bSYour Name 			     sizeof(req_info->extn_capability));
530*5113495bSYour Name 
531*5113495bSYour Name 	if (params->link_sta_params.ht_capa) {
532*5113495bSYour Name 		req_info->htcap_present = 1;
533*5113495bSYour Name 		qdf_mem_copy(&req_info->ht_cap, params->link_sta_params.ht_capa,
534*5113495bSYour Name 			     sizeof(struct htcap_cmn_ie));
535*5113495bSYour Name 	}
536*5113495bSYour Name 
537*5113495bSYour Name 	req_info->supported_rates_len =
538*5113495bSYour Name 				params->link_sta_params.supported_rates_len;
539*5113495bSYour Name 
540*5113495bSYour Name 	/* Note: The Maximum size of supported_rates sent by the Supplicant is
541*5113495bSYour Name 	 * 32. The supported_rates array, for all the structures propagating
542*5113495bSYour Name 	 * until Add Sta to the firmware, has to be modified if the supplicant
543*5113495bSYour Name 	 * (ieee80211) is modified to send more rates.
544*5113495bSYour Name 	 */
545*5113495bSYour Name 
546*5113495bSYour Name 	/* To avoid Data Corruption, set to max length to SIR_MAC_MAX_SUPP_RATES
547*5113495bSYour Name 	 */
548*5113495bSYour Name 	if (req_info->supported_rates_len > WLAN_MAC_MAX_SUPP_RATES)
549*5113495bSYour Name 		req_info->supported_rates_len = WLAN_MAC_MAX_SUPP_RATES;
550*5113495bSYour Name 
551*5113495bSYour Name 	if (req_info->supported_rates_len) {
552*5113495bSYour Name 		qdf_mem_copy(req_info->supported_rates,
553*5113495bSYour Name 			     params->link_sta_params.supported_rates,
554*5113495bSYour Name 			     req_info->supported_rates_len);
555*5113495bSYour Name 		osif_debug("Supported Rates with Length %d",
556*5113495bSYour Name 			   req_info->supported_rates_len);
557*5113495bSYour Name 
558*5113495bSYour Name 		for (i = 0; i < req_info->supported_rates_len; i++)
559*5113495bSYour Name 			osif_debug("[%d]: %0x", i,
560*5113495bSYour Name 				   req_info->supported_rates[i]);
561*5113495bSYour Name 	}
562*5113495bSYour Name 
563*5113495bSYour Name 	if (params->link_sta_params.vht_capa) {
564*5113495bSYour Name 		req_info->vhtcap_present = 1;
565*5113495bSYour Name 		qdf_mem_copy(&req_info->vht_cap,
566*5113495bSYour Name 			     params->link_sta_params.vht_capa,
567*5113495bSYour Name 			     sizeof(struct vhtcap));
568*5113495bSYour Name 	}
569*5113495bSYour Name 
570*5113495bSYour Name 	if (params->link_sta_params.ht_capa ||
571*5113495bSYour Name 	    params->link_sta_params.vht_capa ||
572*5113495bSYour Name 	    (params->sta_flags_set & BIT(NL80211_STA_FLAG_WME)))
573*5113495bSYour Name 		req_info->is_qos_wmm_sta = true;
574*5113495bSYour Name 	if (params->sta_flags_set & BIT(NL80211_STA_FLAG_MFP)) {
575*5113495bSYour Name 		osif_debug("TDLS peer pmf capable");
576*5113495bSYour Name 		req_info->is_pmf = 1;
577*5113495bSYour Name 	}
578*5113495bSYour Name 	if (tdls_11ax_support)
579*5113495bSYour Name 		wlan_cfg80211_tdls_extract_he_params(req_info, params,
580*5113495bSYour Name 						     tdls_6g_support);
581*5113495bSYour Name 	else
582*5113495bSYour Name 		osif_debug("tdls ax disabled");
583*5113495bSYour Name 
584*5113495bSYour Name 	wlan_cfg80211_tdls_extract_eht_params(req_info, params);
585*5113495bSYour Name }
586*5113495bSYour Name #else
587*5113495bSYour Name static void
wlan_cfg80211_tdls_extract_params(struct wlan_objmgr_vdev * vdev,struct tdls_update_peer_params * req_info,struct station_parameters * params,bool tdls_11ax_support,bool tdls_6g_support)588*5113495bSYour Name wlan_cfg80211_tdls_extract_params(struct wlan_objmgr_vdev *vdev,
589*5113495bSYour Name 				  struct tdls_update_peer_params *req_info,
590*5113495bSYour Name 				  struct station_parameters *params,
591*5113495bSYour Name 				  bool tdls_11ax_support, bool tdls_6g_support)
592*5113495bSYour Name {
593*5113495bSYour Name 	int i;
594*5113495bSYour Name 
595*5113495bSYour Name 	osif_debug("sta cap %d, uapsd_queue %d, max_sp %d",
596*5113495bSYour Name 		   params->capability,
597*5113495bSYour Name 		   params->uapsd_queues, params->max_sp);
598*5113495bSYour Name 
599*5113495bSYour Name 	if (!req_info) {
600*5113495bSYour Name 		osif_err("reg_info is NULL");
601*5113495bSYour Name 		return;
602*5113495bSYour Name 	}
603*5113495bSYour Name 	req_info->capability = params->capability;
604*5113495bSYour Name 	req_info->uapsd_queues = params->uapsd_queues;
605*5113495bSYour Name 	req_info->max_sp = params->max_sp;
606*5113495bSYour Name 
607*5113495bSYour Name 	if (params->supported_oper_classes_len > WLAN_MAX_SUPP_OPER_CLASSES) {
608*5113495bSYour Name 		osif_debug("received oper classes:%d, resetting it to max supported: %d",
609*5113495bSYour Name 			   params->supported_oper_classes_len,
610*5113495bSYour Name 			   WLAN_MAX_SUPP_OPER_CLASSES);
611*5113495bSYour Name 		params->supported_oper_classes_len = WLAN_MAX_SUPP_OPER_CLASSES;
612*5113495bSYour Name 	}
613*5113495bSYour Name 
614*5113495bSYour Name 	qdf_mem_copy(req_info->supported_oper_classes,
615*5113495bSYour Name 		     params->supported_oper_classes,
616*5113495bSYour Name 		     params->supported_oper_classes_len);
617*5113495bSYour Name 	req_info->supported_oper_classes_len =
618*5113495bSYour Name 		params->supported_oper_classes_len;
619*5113495bSYour Name 
620*5113495bSYour Name 	if (params->supported_channels_len)
621*5113495bSYour Name 		tdls_calc_channels_from_staparams(vdev, req_info, params);
622*5113495bSYour Name 
623*5113495bSYour Name 	if (params->ext_capab_len)
624*5113495bSYour Name 		qdf_mem_copy(req_info->extn_capability, params->ext_capab,
625*5113495bSYour Name 			     sizeof(req_info->extn_capability));
626*5113495bSYour Name 
627*5113495bSYour Name 	if (params->ht_capa) {
628*5113495bSYour Name 		req_info->htcap_present = 1;
629*5113495bSYour Name 		qdf_mem_copy(&req_info->ht_cap, params->ht_capa,
630*5113495bSYour Name 			     sizeof(struct htcap_cmn_ie));
631*5113495bSYour Name 	}
632*5113495bSYour Name 
633*5113495bSYour Name 	req_info->supported_rates_len = params->supported_rates_len;
634*5113495bSYour Name 
635*5113495bSYour Name 	/* Note : The Maximum sizeof supported_rates sent by the Supplicant is
636*5113495bSYour Name 	 * 32. The supported_rates array , for all the structures propagating
637*5113495bSYour Name 	 * till Add Sta to the firmware has to be modified , if the supplicant
638*5113495bSYour Name 	 * (ieee80211) is modified to send more rates.
639*5113495bSYour Name 	 */
640*5113495bSYour Name 
641*5113495bSYour Name 	/* To avoid Data Currption , set to max length to SIR_MAC_MAX_SUPP_RATES
642*5113495bSYour Name 	 */
643*5113495bSYour Name 	if (req_info->supported_rates_len > WLAN_MAC_MAX_SUPP_RATES)
644*5113495bSYour Name 		req_info->supported_rates_len = WLAN_MAC_MAX_SUPP_RATES;
645*5113495bSYour Name 
646*5113495bSYour Name 	if (req_info->supported_rates_len) {
647*5113495bSYour Name 		qdf_mem_copy(req_info->supported_rates,
648*5113495bSYour Name 			     params->supported_rates,
649*5113495bSYour Name 			     req_info->supported_rates_len);
650*5113495bSYour Name 		osif_debug("Supported Rates with Length %d",
651*5113495bSYour Name 			   req_info->supported_rates_len);
652*5113495bSYour Name 
653*5113495bSYour Name 		for (i = 0; i < req_info->supported_rates_len; i++)
654*5113495bSYour Name 			osif_debug("[%d]: %0x", i,
655*5113495bSYour Name 				   req_info->supported_rates[i]);
656*5113495bSYour Name 	}
657*5113495bSYour Name 
658*5113495bSYour Name 	if (params->vht_capa) {
659*5113495bSYour Name 		req_info->vhtcap_present = 1;
660*5113495bSYour Name 		qdf_mem_copy(&req_info->vht_cap, params->vht_capa,
661*5113495bSYour Name 			     sizeof(struct vhtcap));
662*5113495bSYour Name 	}
663*5113495bSYour Name 
664*5113495bSYour Name 	if (params->ht_capa || params->vht_capa ||
665*5113495bSYour Name 	    (params->sta_flags_set & BIT(NL80211_STA_FLAG_WME)))
666*5113495bSYour Name 		req_info->is_qos_wmm_sta = true;
667*5113495bSYour Name 	if (params->sta_flags_set & BIT(NL80211_STA_FLAG_MFP)) {
668*5113495bSYour Name 		osif_debug("TDLS peer pmf capable");
669*5113495bSYour Name 		req_info->is_pmf = 1;
670*5113495bSYour Name 	}
671*5113495bSYour Name 	if (tdls_11ax_support)
672*5113495bSYour Name 		wlan_cfg80211_tdls_extract_he_params(req_info, params,
673*5113495bSYour Name 						     tdls_6g_support);
674*5113495bSYour Name 	else
675*5113495bSYour Name 		osif_debug("tdls ax disabled");
676*5113495bSYour Name 
677*5113495bSYour Name 	wlan_cfg80211_tdls_extract_eht_params(req_info, params);
678*5113495bSYour Name }
679*5113495bSYour Name #endif
680*5113495bSYour Name 
wlan_cfg80211_tdls_update_peer(struct wlan_objmgr_vdev * vdev,const uint8_t * mac,struct station_parameters * params)681*5113495bSYour Name int wlan_cfg80211_tdls_update_peer(struct wlan_objmgr_vdev *vdev,
682*5113495bSYour Name 				   const uint8_t *mac,
683*5113495bSYour Name 				   struct station_parameters *params)
684*5113495bSYour Name {
685*5113495bSYour Name 	struct tdls_update_peer_params *req_info;
686*5113495bSYour Name 	int status;
687*5113495bSYour Name 	struct vdev_osif_priv *osif_priv;
688*5113495bSYour Name 	struct osif_tdls_vdev *tdls_priv;
689*5113495bSYour Name 	unsigned long rc;
690*5113495bSYour Name 	struct wlan_objmgr_psoc *psoc;
691*5113495bSYour Name 	bool tdls_11ax_support = false;
692*5113495bSYour Name 	bool tdls_6g_support = false;
693*5113495bSYour Name 	bool is_mlo_vdev;
694*5113495bSYour Name 
695*5113495bSYour Name 	status = wlan_cfg80211_tdls_validate_mac_addr(mac);
696*5113495bSYour Name 
697*5113495bSYour Name 	if (status)
698*5113495bSYour Name 		return status;
699*5113495bSYour Name 
700*5113495bSYour Name 	osif_debug("Update TDLS peer " QDF_MAC_ADDR_FMT,
701*5113495bSYour Name 		   QDF_MAC_ADDR_REF(mac));
702*5113495bSYour Name 
703*5113495bSYour Name 	is_mlo_vdev = wlan_vdev_mlme_is_mlo_vdev(vdev);
704*5113495bSYour Name 	if (is_mlo_vdev) {
705*5113495bSYour Name 		vdev = ucfg_tdls_get_tdls_link_vdev(vdev, WLAN_OSIF_TDLS_ID);
706*5113495bSYour Name 		if (!vdev) {
707*5113495bSYour Name 			osif_err("no tdls link vdev");
708*5113495bSYour Name 			return -EINVAL;
709*5113495bSYour Name 		}
710*5113495bSYour Name 	}
711*5113495bSYour Name 
712*5113495bSYour Name 	psoc = wlan_vdev_get_psoc(vdev);
713*5113495bSYour Name 	if (!psoc) {
714*5113495bSYour Name 		osif_err_rl("Invalid psoc");
715*5113495bSYour Name 		goto relref;
716*5113495bSYour Name 	}
717*5113495bSYour Name 
718*5113495bSYour Name 	req_info = qdf_mem_malloc(sizeof(*req_info));
719*5113495bSYour Name 	if (!req_info) {
720*5113495bSYour Name 		status = -EINVAL;
721*5113495bSYour Name 		goto relref;
722*5113495bSYour Name 	}
723*5113495bSYour Name 
724*5113495bSYour Name 	tdls_11ax_support = ucfg_tdls_is_fw_11ax_capable(psoc);
725*5113495bSYour Name 	tdls_6g_support = ucfg_tdls_is_fw_6g_capable(psoc);
726*5113495bSYour Name 	wlan_cfg80211_tdls_extract_params(vdev, req_info, params,
727*5113495bSYour Name 					  tdls_11ax_support,
728*5113495bSYour Name 					  tdls_6g_support);
729*5113495bSYour Name 
730*5113495bSYour Name 	osif_priv = wlan_vdev_get_ospriv(vdev);
731*5113495bSYour Name 	if (!osif_priv || !osif_priv->osif_tdls) {
732*5113495bSYour Name 		osif_err("osif priv or tdls priv is NULL");
733*5113495bSYour Name 		status = -EINVAL;
734*5113495bSYour Name 		goto error;
735*5113495bSYour Name 	}
736*5113495bSYour Name 	tdls_priv = osif_priv->osif_tdls;
737*5113495bSYour Name 	req_info->vdev_id = wlan_vdev_get_id(vdev);
738*5113495bSYour Name 	qdf_mem_copy(req_info->peer_addr, mac, QDF_MAC_ADDR_SIZE);
739*5113495bSYour Name 
740*5113495bSYour Name 	reinit_completion(&tdls_priv->tdls_add_peer_comp);
741*5113495bSYour Name 	status = ucfg_tdls_update_peer(vdev, req_info);
742*5113495bSYour Name 	if (QDF_IS_STATUS_ERROR(status)) {
743*5113495bSYour Name 		osif_err("ucfg_tdls_update_peer returned err %d", status);
744*5113495bSYour Name 		status = -EIO;
745*5113495bSYour Name 		goto error;
746*5113495bSYour Name 	}
747*5113495bSYour Name 
748*5113495bSYour Name 	rc = wait_for_completion_timeout(
749*5113495bSYour Name 		&tdls_priv->tdls_add_peer_comp,
750*5113495bSYour Name 		msecs_to_jiffies(WAIT_TIME_TDLS_ADD_STA));
751*5113495bSYour Name 	if (!rc) {
752*5113495bSYour Name 		osif_err("timeout for tdls update peer indication %ld", rc);
753*5113495bSYour Name 		status = -EPERM;
754*5113495bSYour Name 		goto error;
755*5113495bSYour Name 	}
756*5113495bSYour Name 
757*5113495bSYour Name 	if (QDF_IS_STATUS_ERROR(tdls_priv->tdls_add_peer_status)) {
758*5113495bSYour Name 		osif_err("tdls update peer failed, status:%d",
759*5113495bSYour Name 			 tdls_priv->tdls_add_peer_status);
760*5113495bSYour Name 		status = -EPERM;
761*5113495bSYour Name 	}
762*5113495bSYour Name error:
763*5113495bSYour Name 	qdf_mem_free(req_info);
764*5113495bSYour Name relref:
765*5113495bSYour Name 	if (is_mlo_vdev)
766*5113495bSYour Name 		ucfg_tdls_put_tdls_link_vdev(vdev, WLAN_OSIF_TDLS_ID);
767*5113495bSYour Name 	return status;
768*5113495bSYour Name }
769*5113495bSYour Name 
tdls_oper_to_str(enum nl80211_tdls_operation oper)770*5113495bSYour Name static char *tdls_oper_to_str(enum nl80211_tdls_operation oper)
771*5113495bSYour Name {
772*5113495bSYour Name 	switch (oper) {
773*5113495bSYour Name 	case NL80211_TDLS_ENABLE_LINK:
774*5113495bSYour Name 		return "TDLS_ENABLE_LINK";
775*5113495bSYour Name 	case NL80211_TDLS_DISABLE_LINK:
776*5113495bSYour Name 		return "TDLS_DISABLE_LINK";
777*5113495bSYour Name 	case NL80211_TDLS_TEARDOWN:
778*5113495bSYour Name 		return "TDLS_TEARDOWN";
779*5113495bSYour Name 	case NL80211_TDLS_SETUP:
780*5113495bSYour Name 		return "TDLS_SETUP";
781*5113495bSYour Name 	default:
782*5113495bSYour Name 		return "UNKNOWN:ERR";
783*5113495bSYour Name 	}
784*5113495bSYour Name }
785*5113495bSYour Name 
tdls_oper_to_cmd(enum nl80211_tdls_operation oper)786*5113495bSYour Name static enum tdls_command_type tdls_oper_to_cmd(enum nl80211_tdls_operation oper)
787*5113495bSYour Name {
788*5113495bSYour Name 	if (oper == NL80211_TDLS_ENABLE_LINK)
789*5113495bSYour Name 		return TDLS_CMD_ENABLE_LINK;
790*5113495bSYour Name 	else if (oper == NL80211_TDLS_DISABLE_LINK)
791*5113495bSYour Name 		return TDLS_CMD_DISABLE_LINK;
792*5113495bSYour Name 	else if (oper == NL80211_TDLS_TEARDOWN)
793*5113495bSYour Name 		return TDLS_CMD_REMOVE_FORCE_PEER;
794*5113495bSYour Name 	else if (oper == NL80211_TDLS_SETUP)
795*5113495bSYour Name 		return TDLS_CMD_CONFIG_FORCE_PEER;
796*5113495bSYour Name 	else
797*5113495bSYour Name 		return 0;
798*5113495bSYour Name }
799*5113495bSYour Name 
wlan_cfg80211_tdls_configure_mode(struct wlan_objmgr_vdev * vdev,uint32_t trigger_mode)800*5113495bSYour Name int wlan_cfg80211_tdls_configure_mode(struct wlan_objmgr_vdev *vdev,
801*5113495bSYour Name 						uint32_t trigger_mode)
802*5113495bSYour Name {
803*5113495bSYour Name 	enum tdls_feature_mode tdls_mode;
804*5113495bSYour Name 	struct tdls_set_mode_params set_mode_params;
805*5113495bSYour Name 	int status;
806*5113495bSYour Name 
807*5113495bSYour Name 	if (!vdev)
808*5113495bSYour Name 		return -EINVAL;
809*5113495bSYour Name 
810*5113495bSYour Name 	switch (trigger_mode) {
811*5113495bSYour Name 	case WLAN_VENDOR_TDLS_TRIGGER_MODE_EXPLICIT:
812*5113495bSYour Name 		tdls_mode = TDLS_SUPPORT_EXP_TRIG_ONLY;
813*5113495bSYour Name 		return 0;
814*5113495bSYour Name 	case WLAN_VENDOR_TDLS_TRIGGER_MODE_EXTERNAL:
815*5113495bSYour Name 		tdls_mode = TDLS_SUPPORT_EXT_CONTROL;
816*5113495bSYour Name 		break;
817*5113495bSYour Name 	case WLAN_VENDOR_TDLS_TRIGGER_MODE_IMPLICIT:
818*5113495bSYour Name 		tdls_mode = TDLS_SUPPORT_IMP_MODE;
819*5113495bSYour Name 		return 0;
820*5113495bSYour Name 	default:
821*5113495bSYour Name 		osif_err("Invalid TDLS trigger mode");
822*5113495bSYour Name 		return -EINVAL;
823*5113495bSYour Name 	}
824*5113495bSYour Name 
825*5113495bSYour Name 	osif_notice("cfg80211 tdls trigger mode %d", trigger_mode);
826*5113495bSYour Name 	set_mode_params.source = TDLS_SET_MODE_SOURCE_USER;
827*5113495bSYour Name 	set_mode_params.tdls_mode = tdls_mode;
828*5113495bSYour Name 	set_mode_params.update_last = false;
829*5113495bSYour Name 	set_mode_params.vdev = vdev;
830*5113495bSYour Name 
831*5113495bSYour Name 	status = ucfg_tdls_set_operating_mode(&set_mode_params);
832*5113495bSYour Name 	return status;
833*5113495bSYour Name }
834*5113495bSYour Name 
wlan_cfg80211_tdls_oper(struct wlan_objmgr_vdev * vdev,const uint8_t * peer,enum nl80211_tdls_operation oper)835*5113495bSYour Name int wlan_cfg80211_tdls_oper(struct wlan_objmgr_vdev *vdev,
836*5113495bSYour Name 			    const uint8_t *peer,
837*5113495bSYour Name 			    enum nl80211_tdls_operation oper)
838*5113495bSYour Name {
839*5113495bSYour Name 	struct vdev_osif_priv *osif_priv;
840*5113495bSYour Name 	struct osif_tdls_vdev *tdls_priv;
841*5113495bSYour Name 	int status;
842*5113495bSYour Name 	unsigned long rc;
843*5113495bSYour Name 	enum tdls_command_type cmd;
844*5113495bSYour Name 	bool is_mlo_vdev;
845*5113495bSYour Name 
846*5113495bSYour Name 	status = wlan_cfg80211_tdls_validate_mac_addr(peer);
847*5113495bSYour Name 
848*5113495bSYour Name 	if (status)
849*5113495bSYour Name 		return status;
850*5113495bSYour Name 
851*5113495bSYour Name 	if (NL80211_TDLS_DISCOVERY_REQ == oper) {
852*5113495bSYour Name 		osif_warn(
853*5113495bSYour Name 			"We don't support in-driver setup/teardown/discovery");
854*5113495bSYour Name 		return -ENOTSUPP;
855*5113495bSYour Name 	}
856*5113495bSYour Name 
857*5113495bSYour Name 	is_mlo_vdev = wlan_vdev_mlme_is_mlo_vdev(vdev);
858*5113495bSYour Name 	if (is_mlo_vdev) {
859*5113495bSYour Name 		vdev = ucfg_tdls_get_tdls_link_vdev(vdev, WLAN_OSIF_TDLS_ID);
860*5113495bSYour Name 		if (!vdev) {
861*5113495bSYour Name 			osif_err("no tdls link vdev");
862*5113495bSYour Name 			return -EINVAL;
863*5113495bSYour Name 		}
864*5113495bSYour Name 	}
865*5113495bSYour Name 
866*5113495bSYour Name 	osif_debug("%s start", tdls_oper_to_str(oper));
867*5113495bSYour Name 	cmd = tdls_oper_to_cmd(oper);
868*5113495bSYour Name 	switch (oper) {
869*5113495bSYour Name 	case NL80211_TDLS_ENABLE_LINK:
870*5113495bSYour Name 	case NL80211_TDLS_TEARDOWN:
871*5113495bSYour Name 	case NL80211_TDLS_SETUP:
872*5113495bSYour Name 		status = ucfg_tdls_oper(vdev, peer, cmd);
873*5113495bSYour Name 		if (QDF_IS_STATUS_ERROR(status)) {
874*5113495bSYour Name 			osif_err("%s fail %d",
875*5113495bSYour Name 				 tdls_oper_to_str(oper), status);
876*5113495bSYour Name 			status = -EIO;
877*5113495bSYour Name 			goto error;
878*5113495bSYour Name 		}
879*5113495bSYour Name 		break;
880*5113495bSYour Name 	case NL80211_TDLS_DISABLE_LINK:
881*5113495bSYour Name 		wlan_vdev_mlme_feat_ext2_cap_clear(vdev,
882*5113495bSYour Name 						   WLAN_VDEV_FEXT2_MLO_STA_TDLS);
883*5113495bSYour Name 
884*5113495bSYour Name 		osif_priv = wlan_vdev_get_ospriv(vdev);
885*5113495bSYour Name 
886*5113495bSYour Name 		if (!osif_priv || !osif_priv->osif_tdls) {
887*5113495bSYour Name 			osif_err("osif priv or tdls priv is NULL");
888*5113495bSYour Name 			status = -EINVAL;
889*5113495bSYour Name 			goto error;
890*5113495bSYour Name 		}
891*5113495bSYour Name 		tdls_priv = osif_priv->osif_tdls;
892*5113495bSYour Name 		reinit_completion(&tdls_priv->tdls_del_peer_comp);
893*5113495bSYour Name 		status = ucfg_tdls_oper(vdev, peer, cmd);
894*5113495bSYour Name 		if (QDF_IS_STATUS_ERROR(status)) {
895*5113495bSYour Name 			osif_err("ucfg_tdls_disable_link fail %d", status);
896*5113495bSYour Name 			status = -EIO;
897*5113495bSYour Name 			goto error;
898*5113495bSYour Name 		}
899*5113495bSYour Name 
900*5113495bSYour Name 		rc = wait_for_completion_timeout(
901*5113495bSYour Name 			&tdls_priv->tdls_del_peer_comp,
902*5113495bSYour Name 			msecs_to_jiffies(WAIT_TIME_TDLS_DEL_STA));
903*5113495bSYour Name 		if (!rc) {
904*5113495bSYour Name 			osif_err("timeout for tdls disable link %ld", rc);
905*5113495bSYour Name 			status = -EPERM;
906*5113495bSYour Name 		}
907*5113495bSYour Name 		break;
908*5113495bSYour Name 	default:
909*5113495bSYour Name 		osif_err("unsupported event %d", oper);
910*5113495bSYour Name 		status = -ENOTSUPP;
911*5113495bSYour Name 	}
912*5113495bSYour Name 
913*5113495bSYour Name error:
914*5113495bSYour Name 	if (is_mlo_vdev)
915*5113495bSYour Name 		ucfg_tdls_put_tdls_link_vdev(vdev, WLAN_OSIF_TDLS_ID);
916*5113495bSYour Name 	return status;
917*5113495bSYour Name }
918*5113495bSYour Name 
wlan_cfg80211_tdls_rx_callback(void * user_data,struct tdls_rx_mgmt_frame * rx_frame)919*5113495bSYour Name void wlan_cfg80211_tdls_rx_callback(void *user_data,
920*5113495bSYour Name 	struct tdls_rx_mgmt_frame *rx_frame)
921*5113495bSYour Name {
922*5113495bSYour Name 	struct wlan_objmgr_psoc *psoc;
923*5113495bSYour Name 	struct wlan_objmgr_vdev *vdev, *assoc_vdev;
924*5113495bSYour Name 	struct vdev_osif_priv *osif_priv;
925*5113495bSYour Name 	struct wireless_dev *wdev;
926*5113495bSYour Name 	enum QDF_OPMODE opmode;
927*5113495bSYour Name 
928*5113495bSYour Name 	psoc = user_data;
929*5113495bSYour Name 	if (!psoc) {
930*5113495bSYour Name 		osif_err("psoc is null");
931*5113495bSYour Name 		return;
932*5113495bSYour Name 	}
933*5113495bSYour Name 
934*5113495bSYour Name 	vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc,
935*5113495bSYour Name 		rx_frame->vdev_id, WLAN_TDLS_NB_ID);
936*5113495bSYour Name 	if (!vdev) {
937*5113495bSYour Name 		osif_err("vdev is null");
938*5113495bSYour Name 		return;
939*5113495bSYour Name 	}
940*5113495bSYour Name 
941*5113495bSYour Name 	assoc_vdev = vdev;
942*5113495bSYour Name 	opmode = wlan_vdev_mlme_get_opmode(vdev);
943*5113495bSYour Name 
944*5113495bSYour Name 	if ((opmode == QDF_STA_MODE || opmode == QDF_TDLS_MODE) &&
945*5113495bSYour Name 	    wlan_vdev_mlme_is_mlo_vdev(vdev)) {
946*5113495bSYour Name 		assoc_vdev = ucfg_mlo_get_assoc_link_vdev(vdev);
947*5113495bSYour Name 		if (!assoc_vdev) {
948*5113495bSYour Name 			osif_err("assoc vdev is null");
949*5113495bSYour Name 			goto fail;
950*5113495bSYour Name 		}
951*5113495bSYour Name 	}
952*5113495bSYour Name 
953*5113495bSYour Name 	osif_priv = wlan_vdev_get_ospriv(assoc_vdev);
954*5113495bSYour Name 	if (!osif_priv) {
955*5113495bSYour Name 		osif_err("osif_priv is null");
956*5113495bSYour Name 		goto fail;
957*5113495bSYour Name 	}
958*5113495bSYour Name 
959*5113495bSYour Name 	wdev = osif_priv->wdev;
960*5113495bSYour Name 	if (!wdev) {
961*5113495bSYour Name 		osif_err("wdev is null");
962*5113495bSYour Name 		goto fail;
963*5113495bSYour Name 	}
964*5113495bSYour Name 
965*5113495bSYour Name 	osif_notice("Indicate frame over nl80211, vdev id:%d, idx:%d",
966*5113495bSYour Name 		    rx_frame->vdev_id, wdev->netdev->ifindex);
967*5113495bSYour Name 
968*5113495bSYour Name #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 18, 0))
969*5113495bSYour Name 	cfg80211_rx_mgmt(wdev, rx_frame->rx_freq, rx_frame->rx_rssi * 100,
970*5113495bSYour Name 			 rx_frame->buf, rx_frame->frame_len,
971*5113495bSYour Name 			 NL80211_RXMGMT_FLAG_ANSWERED);
972*5113495bSYour Name #elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 12, 0))
973*5113495bSYour Name 	cfg80211_rx_mgmt(wdev, rx_frame->rx_freq, rx_frame->rx_rssi * 100,
974*5113495bSYour Name 			 rx_frame->buf, rx_frame->frame_len,
975*5113495bSYour Name 			 NL80211_RXMGMT_FLAG_ANSWERED, GFP_ATOMIC);
976*5113495bSYour Name #else
977*5113495bSYour Name 	cfg80211_rx_mgmt(wdev, rx_frame->rx_freq, rx_frame->rx_rssi * 100,
978*5113495bSYour Name 			 rx_frame->buf, rx_frame->frame_len, GFP_ATOMIC);
979*5113495bSYour Name #endif /* LINUX_VERSION_CODE */
980*5113495bSYour Name fail:
981*5113495bSYour Name 	wlan_objmgr_vdev_release_ref(vdev, WLAN_TDLS_NB_ID);
982*5113495bSYour Name }
983*5113495bSYour Name 
wlan_cfg80211_update_tdls_peers_rssi(struct wlan_objmgr_vdev * vdev)984*5113495bSYour Name static void wlan_cfg80211_update_tdls_peers_rssi(struct wlan_objmgr_vdev *vdev)
985*5113495bSYour Name {
986*5113495bSYour Name 	int ret = 0, i;
987*5113495bSYour Name 	struct stats_event *rssi_info;
988*5113495bSYour Name 	struct qdf_mac_addr bcast_mac = QDF_MAC_ADDR_BCAST_INIT;
989*5113495bSYour Name 
990*5113495bSYour Name 	rssi_info = wlan_cfg80211_mc_cp_stats_get_peer_rssi(
991*5113495bSYour Name 			vdev, bcast_mac.bytes,
992*5113495bSYour Name 			&ret);
993*5113495bSYour Name 	if (ret || !rssi_info) {
994*5113495bSYour Name 		osif_err("get peer rssi fail");
995*5113495bSYour Name 		wlan_cfg80211_mc_cp_stats_free_stats_event(rssi_info);
996*5113495bSYour Name 		return;
997*5113495bSYour Name 	}
998*5113495bSYour Name 
999*5113495bSYour Name 	for (i = 0; i < rssi_info->num_peer_stats; i++)
1000*5113495bSYour Name 		ucfg_tdls_set_rssi(vdev, rssi_info->peer_stats[i].peer_macaddr,
1001*5113495bSYour Name 				   rssi_info->peer_stats[i].peer_rssi);
1002*5113495bSYour Name 
1003*5113495bSYour Name 	wlan_cfg80211_mc_cp_stats_free_stats_event(rssi_info);
1004*5113495bSYour Name }
1005*5113495bSYour Name 
wlan_cfg80211_tdls_get_all_peers(struct wlan_objmgr_vdev * vdev,char * buf,int buflen)1006*5113495bSYour Name int wlan_cfg80211_tdls_get_all_peers(struct wlan_objmgr_vdev *vdev,
1007*5113495bSYour Name 				char *buf, int buflen)
1008*5113495bSYour Name {
1009*5113495bSYour Name 	struct vdev_osif_priv *osif_priv;
1010*5113495bSYour Name 	struct osif_tdls_vdev *tdls_priv;
1011*5113495bSYour Name 	int32_t len;
1012*5113495bSYour Name 	QDF_STATUS status;
1013*5113495bSYour Name 	unsigned long rc;
1014*5113495bSYour Name 
1015*5113495bSYour Name 	osif_priv = wlan_vdev_get_ospriv(vdev);
1016*5113495bSYour Name 	if (!osif_priv || !osif_priv->osif_tdls) {
1017*5113495bSYour Name 		osif_err("osif_tdls_vdev or osif_priv is NULL for the current vdev");
1018*5113495bSYour Name 		return -EINVAL;
1019*5113495bSYour Name 	}
1020*5113495bSYour Name 
1021*5113495bSYour Name 	tdls_priv = osif_priv->osif_tdls;
1022*5113495bSYour Name 
1023*5113495bSYour Name 	/*
1024*5113495bSYour Name 	 * We shouldn't use completion_done here for checking for completion
1025*5113495bSYour Name 	 * as this will always return false, as tdls_user_cmd_comp.done will
1026*5113495bSYour Name 	 * remain in init state always. So, the very first command will also
1027*5113495bSYour Name 	 * not work.
1028*5113495bSYour Name 	 * In general completion_done is used to check if there are multiple
1029*5113495bSYour Name 	 * threads waiting on the complete event that's why it will return true
1030*5113495bSYour Name 	 * only when tdls_user_cmd_comp.done is set with complete()
1031*5113495bSYour Name 	 * In general completion_done will return true only when
1032*5113495bSYour Name 	 * tdls_user_cmd_comp.done is set that will happen in complete().
1033*5113495bSYour Name 	 * Also, if there is already a thread waiting for wait_for_completion,
1034*5113495bSYour Name 	 * this function will
1035*5113495bSYour Name 	 * return true only after the wait timer is over or condition is
1036*5113495bSYour Name 	 * met as wait_for_completion will hold out the hold lock and will
1037*5113495bSYour Name 	 * will prevent completion_done from returning.
1038*5113495bSYour Name 	 * Better to use a flag to determine command condition.
1039*5113495bSYour Name 	 */
1040*5113495bSYour Name 	if (tdls_priv->tdls_user_cmd_in_progress) {
1041*5113495bSYour Name 		osif_err("TDLS user cmd still in progress, reject this one");
1042*5113495bSYour Name 		return -EBUSY;
1043*5113495bSYour Name 	}
1044*5113495bSYour Name 
1045*5113495bSYour Name 	tdls_priv->tdls_user_cmd_in_progress = true;
1046*5113495bSYour Name 	wlan_cfg80211_update_tdls_peers_rssi(vdev);
1047*5113495bSYour Name 
1048*5113495bSYour Name 	reinit_completion(&tdls_priv->tdls_user_cmd_comp);
1049*5113495bSYour Name 	status = ucfg_tdls_get_all_peers(vdev, buf, buflen);
1050*5113495bSYour Name 	if (QDF_IS_STATUS_ERROR(status)) {
1051*5113495bSYour Name 		osif_err("ucfg_tdls_get_all_peers failed err %d", status);
1052*5113495bSYour Name 		len = scnprintf(buf, buflen,
1053*5113495bSYour Name 				"\nucfg_tdls_send_mgmt failed\n");
1054*5113495bSYour Name 		goto error_get_tdls_peers;
1055*5113495bSYour Name 	}
1056*5113495bSYour Name 
1057*5113495bSYour Name 	osif_debug("Wait for tdls_user_cmd_comp. Timeout %u ms",
1058*5113495bSYour Name 		   WAIT_TIME_FOR_TDLS_USER_CMD);
1059*5113495bSYour Name 
1060*5113495bSYour Name 	rc = wait_for_completion_timeout(
1061*5113495bSYour Name 		&tdls_priv->tdls_user_cmd_comp,
1062*5113495bSYour Name 		msecs_to_jiffies(WAIT_TIME_FOR_TDLS_USER_CMD));
1063*5113495bSYour Name 
1064*5113495bSYour Name 	if (0 == rc) {
1065*5113495bSYour Name 		osif_err("TDLS user cmd get all peers timed out rc %ld",
1066*5113495bSYour Name 			 rc);
1067*5113495bSYour Name 		len = scnprintf(buf, buflen,
1068*5113495bSYour Name 				"\nTDLS user cmd get all peers timed out\n");
1069*5113495bSYour Name 		goto error_get_tdls_peers;
1070*5113495bSYour Name 	}
1071*5113495bSYour Name 
1072*5113495bSYour Name 	len = tdls_priv->tdls_user_cmd_len;
1073*5113495bSYour Name 
1074*5113495bSYour Name error_get_tdls_peers:
1075*5113495bSYour Name 	tdls_priv->tdls_user_cmd_in_progress = false;
1076*5113495bSYour Name 	return len;
1077*5113495bSYour Name }
1078*5113495bSYour Name 
wlan_cfg80211_tdls_is_fw_wideband_capable(struct wlan_objmgr_vdev * vdev)1079*5113495bSYour Name bool wlan_cfg80211_tdls_is_fw_wideband_capable(struct wlan_objmgr_vdev *vdev)
1080*5113495bSYour Name {
1081*5113495bSYour Name 	struct wlan_objmgr_psoc *psoc = wlan_vdev_get_psoc(vdev);
1082*5113495bSYour Name 
1083*5113495bSYour Name 	if (!psoc)
1084*5113495bSYour Name 		return false;
1085*5113495bSYour Name 
1086*5113495bSYour Name 	return ucfg_tdls_is_fw_wideband_capable(psoc);
1087*5113495bSYour Name }
1088*5113495bSYour Name 
1089*5113495bSYour Name #ifdef WLAN_FEATURE_11AX
wlan_cfg80211_tdls_is_fw_6ghz_capable(struct wlan_objmgr_vdev * vdev)1090*5113495bSYour Name bool wlan_cfg80211_tdls_is_fw_6ghz_capable(struct wlan_objmgr_vdev *vdev)
1091*5113495bSYour Name {
1092*5113495bSYour Name 	struct wlan_objmgr_psoc *psoc = wlan_vdev_get_psoc(vdev);
1093*5113495bSYour Name 
1094*5113495bSYour Name 	if (!psoc)
1095*5113495bSYour Name 		return false;
1096*5113495bSYour Name 
1097*5113495bSYour Name 	return ucfg_tdls_is_fw_6g_capable(psoc);
1098*5113495bSYour Name }
1099*5113495bSYour Name #endif
1100*5113495bSYour Name 
1101*5113495bSYour Name static int
wlan_cfg80211_tdls_mgmt(struct wlan_objmgr_vdev * vdev,const uint8_t * peer_mac,uint8_t action_code,uint8_t dialog_token,uint16_t status_code,uint32_t peer_capability,const uint8_t * buf,size_t len,int link_id)1102*5113495bSYour Name wlan_cfg80211_tdls_mgmt(struct wlan_objmgr_vdev *vdev,
1103*5113495bSYour Name 			const uint8_t *peer_mac,
1104*5113495bSYour Name 			uint8_t action_code, uint8_t dialog_token,
1105*5113495bSYour Name 			uint16_t status_code, uint32_t peer_capability,
1106*5113495bSYour Name 			const uint8_t *buf, size_t len, int link_id)
1107*5113495bSYour Name {
1108*5113495bSYour Name 	struct tdls_action_frame_request mgmt_req;
1109*5113495bSYour Name 	struct vdev_osif_priv *osif_priv;
1110*5113495bSYour Name 	struct osif_tdls_vdev *tdls_priv;
1111*5113495bSYour Name 	int status;
1112*5113495bSYour Name 	unsigned long rc;
1113*5113495bSYour Name 	struct tdls_set_responder_req set_responder;
1114*5113495bSYour Name 
1115*5113495bSYour Name 	status = wlan_cfg80211_tdls_validate_mac_addr(peer_mac);
1116*5113495bSYour Name 
1117*5113495bSYour Name 	if (status)
1118*5113495bSYour Name 		return status;
1119*5113495bSYour Name 
1120*5113495bSYour Name 	osif_priv = wlan_vdev_get_ospriv(vdev);
1121*5113495bSYour Name 
1122*5113495bSYour Name 	if (!osif_priv || !osif_priv->osif_tdls) {
1123*5113495bSYour Name 		osif_err("osif priv or tdls priv is NULL");
1124*5113495bSYour Name 		return -EINVAL;
1125*5113495bSYour Name 	}
1126*5113495bSYour Name 
1127*5113495bSYour Name 	tdls_priv = osif_priv->osif_tdls;
1128*5113495bSYour Name 
1129*5113495bSYour Name 	/* make sure doesn't call send_mgmt() while it is pending */
1130*5113495bSYour Name 	if (TDLS_VDEV_MAGIC == tdls_priv->mgmt_tx_completion_status) {
1131*5113495bSYour Name 		osif_err(QDF_MAC_ADDR_FMT " action %d couldn't sent, as one is pending. return EBUSY",
1132*5113495bSYour Name 			 QDF_MAC_ADDR_REF(peer_mac), action_code);
1133*5113495bSYour Name 		return -EBUSY;
1134*5113495bSYour Name 	}
1135*5113495bSYour Name 
1136*5113495bSYour Name 	/* Reset TDLS VDEV magic */
1137*5113495bSYour Name 	tdls_priv->mgmt_tx_completion_status = TDLS_VDEV_MAGIC;
1138*5113495bSYour Name 
1139*5113495bSYour Name 
1140*5113495bSYour Name 	/*prepare the request */
1141*5113495bSYour Name 
1142*5113495bSYour Name 	/* Validate the management Request */
1143*5113495bSYour Name 	mgmt_req.chk_frame.action_code = action_code;
1144*5113495bSYour Name 	qdf_mem_copy(mgmt_req.chk_frame.peer_mac, peer_mac, QDF_MAC_ADDR_SIZE);
1145*5113495bSYour Name 	mgmt_req.chk_frame.dialog_token = dialog_token;
1146*5113495bSYour Name 	mgmt_req.chk_frame.action_code = action_code;
1147*5113495bSYour Name 	mgmt_req.chk_frame.status_code = status_code;
1148*5113495bSYour Name 	mgmt_req.chk_frame.len = len;
1149*5113495bSYour Name 
1150*5113495bSYour Name 	mgmt_req.vdev = vdev;
1151*5113495bSYour Name 	mgmt_req.vdev_id = wlan_vdev_get_id(vdev);
1152*5113495bSYour Name 	mgmt_req.session_id = mgmt_req.vdev_id;
1153*5113495bSYour Name 	/* populate management req params */
1154*5113495bSYour Name 	qdf_mem_copy(mgmt_req.tdls_mgmt.peer_mac.bytes,
1155*5113495bSYour Name 		     peer_mac, QDF_MAC_ADDR_SIZE);
1156*5113495bSYour Name 	mgmt_req.tdls_mgmt.dialog = dialog_token;
1157*5113495bSYour Name 	mgmt_req.tdls_mgmt.frame_type = action_code;
1158*5113495bSYour Name 	mgmt_req.tdls_mgmt.len = len;
1159*5113495bSYour Name 	mgmt_req.tdls_mgmt.peer_capability = peer_capability;
1160*5113495bSYour Name 	mgmt_req.tdls_mgmt.status_code = mgmt_req.chk_frame.status_code;
1161*5113495bSYour Name 
1162*5113495bSYour Name 	mgmt_req.link_active = false;
1163*5113495bSYour Name 	mgmt_req.link_id = link_id;
1164*5113495bSYour Name 	/*populate the additional IE's */
1165*5113495bSYour Name 	mgmt_req.cmd_buf = buf;
1166*5113495bSYour Name 	mgmt_req.len = len;
1167*5113495bSYour Name 
1168*5113495bSYour Name 	reinit_completion(&tdls_priv->tdls_mgmt_comp);
1169*5113495bSYour Name 	status = ucfg_tdls_send_mgmt_frame(&mgmt_req);
1170*5113495bSYour Name 	if (QDF_IS_STATUS_ERROR(status)) {
1171*5113495bSYour Name 		osif_err("ucfg_tdls_send_mgmt failed err %d", status);
1172*5113495bSYour Name 		status = -EIO;
1173*5113495bSYour Name 		tdls_priv->mgmt_tx_completion_status = false;
1174*5113495bSYour Name 		goto error_mgmt_req;
1175*5113495bSYour Name 	}
1176*5113495bSYour Name 
1177*5113495bSYour Name 	osif_debug("Wait for tdls_mgmt_comp. Timeout %u ms",
1178*5113495bSYour Name 		   WAIT_TIME_FOR_TDLS_MGMT);
1179*5113495bSYour Name 
1180*5113495bSYour Name 	rc = wait_for_completion_timeout(
1181*5113495bSYour Name 		&tdls_priv->tdls_mgmt_comp,
1182*5113495bSYour Name 		msecs_to_jiffies(WAIT_TIME_FOR_TDLS_MGMT));
1183*5113495bSYour Name 
1184*5113495bSYour Name 	if ((0 == rc) || (QDF_STATUS_SUCCESS !=
1185*5113495bSYour Name 				tdls_priv->mgmt_tx_completion_status)) {
1186*5113495bSYour Name 		osif_err("%s rc %ld mgmtTxCompletionStatus %u",
1187*5113495bSYour Name 			 !rc ? "Mgmt Tx Completion timed out" :
1188*5113495bSYour Name 			 "Mgmt Tx Completion failed",
1189*5113495bSYour Name 			 rc, tdls_priv->mgmt_tx_completion_status);
1190*5113495bSYour Name 
1191*5113495bSYour Name 		tdls_priv->mgmt_tx_completion_status = false;
1192*5113495bSYour Name 		status = -EINVAL;
1193*5113495bSYour Name 		goto error_mgmt_req;
1194*5113495bSYour Name 	}
1195*5113495bSYour Name 
1196*5113495bSYour Name 	osif_debug("Mgmt Tx Completion status %ld TxCompletion %u",
1197*5113495bSYour Name 		   rc, tdls_priv->mgmt_tx_completion_status);
1198*5113495bSYour Name 
1199*5113495bSYour Name 	if (TDLS_SETUP_RESPONSE == action_code ||
1200*5113495bSYour Name 	    TDLS_SETUP_CONFIRM == action_code) {
1201*5113495bSYour Name 		qdf_mem_copy(set_responder.peer_mac, peer_mac,
1202*5113495bSYour Name 			     QDF_MAC_ADDR_SIZE);
1203*5113495bSYour Name 		set_responder.vdev = vdev;
1204*5113495bSYour Name 		if (TDLS_SETUP_RESPONSE == action_code)
1205*5113495bSYour Name 			set_responder.responder = false;
1206*5113495bSYour Name 		if (TDLS_SETUP_CONFIRM == action_code)
1207*5113495bSYour Name 			set_responder.responder = true;
1208*5113495bSYour Name 		ucfg_tdls_responder(&set_responder);
1209*5113495bSYour Name 	}
1210*5113495bSYour Name 
1211*5113495bSYour Name error_mgmt_req:
1212*5113495bSYour Name 	return status;
1213*5113495bSYour Name }
1214*5113495bSYour Name 
1215*5113495bSYour Name int
wlan_cfg80211_tdls_mgmt_mlo(struct hdd_adapter * adapter,const uint8_t * peer,uint8_t action_code,uint8_t dialog_token,uint16_t status_code,uint32_t peer_capability,const uint8_t * buf,size_t len,int link_id)1216*5113495bSYour Name wlan_cfg80211_tdls_mgmt_mlo(struct hdd_adapter *adapter, const uint8_t *peer,
1217*5113495bSYour Name 			    uint8_t action_code, uint8_t dialog_token,
1218*5113495bSYour Name 			    uint16_t status_code, uint32_t peer_capability,
1219*5113495bSYour Name 			    const uint8_t *buf, size_t len, int link_id)
1220*5113495bSYour Name {
1221*5113495bSYour Name 	struct wlan_objmgr_vdev *tdls_link_vdev = NULL;
1222*5113495bSYour Name 	struct wlan_objmgr_vdev *mlo_vdev = NULL;
1223*5113495bSYour Name 	struct wlan_objmgr_vdev *vdev;
1224*5113495bSYour Name 	bool is_mlo_vdev;
1225*5113495bSYour Name 	bool link_id_vdev = false;
1226*5113495bSYour Name 	bool dis_req_more = false;
1227*5113495bSYour Name 	uint8_t i;
1228*5113495bSYour Name 	int ret = 0;
1229*5113495bSYour Name 
1230*5113495bSYour Name 	vdev = hdd_objmgr_get_vdev_by_user(adapter->deflink, WLAN_OSIF_TDLS_ID);
1231*5113495bSYour Name 	if (!vdev)
1232*5113495bSYour Name 		return -EINVAL;
1233*5113495bSYour Name 
1234*5113495bSYour Name 	/* STA should be connected before sending any TDLS frame */
1235*5113495bSYour Name 	if (wlan_vdev_is_up(vdev) != QDF_STATUS_SUCCESS) {
1236*5113495bSYour Name 		osif_err("STA is not connected");
1237*5113495bSYour Name 		hdd_objmgr_put_vdev_by_user(vdev, WLAN_OSIF_TDLS_ID);
1238*5113495bSYour Name 		return -EAGAIN;
1239*5113495bSYour Name 	}
1240*5113495bSYour Name 
1241*5113495bSYour Name 	is_mlo_vdev = wlan_vdev_mlme_is_mlo_vdev(vdev);
1242*5113495bSYour Name 	if (is_mlo_vdev) {
1243*5113495bSYour Name 		tdls_link_vdev =
1244*5113495bSYour Name 			ucfg_tdls_get_tdls_link_vdev(vdev, WLAN_OSIF_TDLS_ID);
1245*5113495bSYour Name 		if (!tdls_link_vdev) {
1246*5113495bSYour Name 			if (action_code == TDLS_DISCOVERY_RESPONSE) {
1247*5113495bSYour Name 				hdd_objmgr_put_vdev_by_user(vdev,
1248*5113495bSYour Name 							    WLAN_OSIF_TDLS_ID);
1249*5113495bSYour Name 				if (link_id < 0) {
1250*5113495bSYour Name 					osif_err("link id is invalid");
1251*5113495bSYour Name 					return -EINVAL;
1252*5113495bSYour Name 				}
1253*5113495bSYour Name 				/* Get the candidate vdev per link id */
1254*5113495bSYour Name 				link_id_vdev = true;
1255*5113495bSYour Name 				vdev = wlan_key_get_link_vdev(adapter,
1256*5113495bSYour Name 							      WLAN_OSIF_TDLS_ID,
1257*5113495bSYour Name 							      link_id);
1258*5113495bSYour Name 				if (!vdev) {
1259*5113495bSYour Name 					osif_err("vdev is null");
1260*5113495bSYour Name 					return -EINVAL;
1261*5113495bSYour Name 				}
1262*5113495bSYour Name 			} else if (action_code == TDLS_DISCOVERY_REQUEST) {
1263*5113495bSYour Name 				if (ucfg_tdls_discovery_on_going(vdev)) {
1264*5113495bSYour Name 					osif_err("discovery request is going");
1265*5113495bSYour Name 					hdd_objmgr_put_vdev_by_user(vdev,
1266*5113495bSYour Name 							     WLAN_OSIF_TDLS_ID);
1267*5113495bSYour Name 					return -EAGAIN;
1268*5113495bSYour Name 				}
1269*5113495bSYour Name 				dis_req_more = true;
1270*5113495bSYour Name 			}
1271*5113495bSYour Name 		} else {
1272*5113495bSYour Name 			hdd_objmgr_put_vdev_by_user(vdev, WLAN_OSIF_TDLS_ID);
1273*5113495bSYour Name 			vdev = tdls_link_vdev;
1274*5113495bSYour Name 		}
1275*5113495bSYour Name 	}
1276*5113495bSYour Name 
1277*5113495bSYour Name 	if (dis_req_more) {
1278*5113495bSYour Name 		/* it needs to send discovery request on each vdev */
1279*5113495bSYour Name 		for (i = 0 ;  i < WLAN_UMAC_MLO_MAX_VDEVS; i++) {
1280*5113495bSYour Name 			mlo_vdev = ucfg_tdls_get_mlo_vdev(vdev, i,
1281*5113495bSYour Name 							  WLAN_OSIF_TDLS_ID);
1282*5113495bSYour Name 			if (!mlo_vdev) {
1283*5113495bSYour Name 				osif_err("mlo vdev is NULL");
1284*5113495bSYour Name 				continue;
1285*5113495bSYour Name 			}
1286*5113495bSYour Name 			ret = wlan_cfg80211_tdls_mgmt(mlo_vdev, peer,
1287*5113495bSYour Name 						      action_code,
1288*5113495bSYour Name 						      dialog_token, status_code,
1289*5113495bSYour Name 						      peer_capability, buf, len,
1290*5113495bSYour Name 						      link_id);
1291*5113495bSYour Name 			ucfg_tdls_release_mlo_vdev(mlo_vdev, WLAN_OSIF_TDLS_ID);
1292*5113495bSYour Name 		}
1293*5113495bSYour Name 	} else {
1294*5113495bSYour Name 		ret = wlan_cfg80211_tdls_mgmt(vdev, peer,
1295*5113495bSYour Name 					      action_code, dialog_token,
1296*5113495bSYour Name 					      status_code, peer_capability,
1297*5113495bSYour Name 					      buf, len, link_id);
1298*5113495bSYour Name 	}
1299*5113495bSYour Name 
1300*5113495bSYour Name 	if (vdev && link_id_vdev)
1301*5113495bSYour Name 		wlan_key_put_link_vdev(vdev, WLAN_OSIF_TDLS_ID);
1302*5113495bSYour Name 	else if (tdls_link_vdev)
1303*5113495bSYour Name 		ucfg_tdls_put_tdls_link_vdev(tdls_link_vdev, WLAN_OSIF_TDLS_ID);
1304*5113495bSYour Name 	else
1305*5113495bSYour Name 		hdd_objmgr_put_vdev_by_user(vdev, WLAN_OSIF_TDLS_ID);
1306*5113495bSYour Name 
1307*5113495bSYour Name 	return ret;
1308*5113495bSYour Name }
1309*5113495bSYour Name 
wlan_tdls_antenna_switch(struct wlan_objmgr_vdev * vdev,uint32_t mode)1310*5113495bSYour Name int wlan_tdls_antenna_switch(struct wlan_objmgr_vdev *vdev, uint32_t mode)
1311*5113495bSYour Name {
1312*5113495bSYour Name 	struct vdev_osif_priv *osif_priv;
1313*5113495bSYour Name 	struct osif_tdls_vdev *tdls_priv;
1314*5113495bSYour Name 	int ret;
1315*5113495bSYour Name 	unsigned long rc;
1316*5113495bSYour Name 
1317*5113495bSYour Name 	if (!vdev) {
1318*5113495bSYour Name 		osif_err("vdev is NULL");
1319*5113495bSYour Name 		return -EAGAIN;
1320*5113495bSYour Name 	}
1321*5113495bSYour Name 
1322*5113495bSYour Name 	osif_priv = wlan_vdev_get_ospriv(vdev);
1323*5113495bSYour Name 	if (!osif_priv || !osif_priv->osif_tdls) {
1324*5113495bSYour Name 		osif_err("osif priv or tdls priv is NULL");
1325*5113495bSYour Name 		ret = -EINVAL;
1326*5113495bSYour Name 		goto error;
1327*5113495bSYour Name 	}
1328*5113495bSYour Name 	tdls_priv = osif_priv->osif_tdls;
1329*5113495bSYour Name 
1330*5113495bSYour Name 	reinit_completion(&tdls_priv->tdls_antenna_switch_comp);
1331*5113495bSYour Name 	ret = ucfg_tdls_antenna_switch(vdev, mode);
1332*5113495bSYour Name 	if (QDF_IS_STATUS_ERROR(ret)) {
1333*5113495bSYour Name 		osif_err("ucfg_tdls_antenna_switch failed err %d", ret);
1334*5113495bSYour Name 		ret = -EAGAIN;
1335*5113495bSYour Name 		goto error;
1336*5113495bSYour Name 	}
1337*5113495bSYour Name 
1338*5113495bSYour Name 	rc = wait_for_completion_timeout(
1339*5113495bSYour Name 		&tdls_priv->tdls_antenna_switch_comp,
1340*5113495bSYour Name 		msecs_to_jiffies(WAIT_TIME_FOR_TDLS_ANTENNA_SWITCH));
1341*5113495bSYour Name 	if (!rc) {
1342*5113495bSYour Name 		osif_err("timeout for tdls antenna switch %ld", rc);
1343*5113495bSYour Name 		ret = -EAGAIN;
1344*5113495bSYour Name 		goto error;
1345*5113495bSYour Name 	}
1346*5113495bSYour Name 
1347*5113495bSYour Name 	ret = tdls_priv->tdls_antenna_switch_status;
1348*5113495bSYour Name 	osif_debug("tdls antenna switch status:%d", ret);
1349*5113495bSYour Name error:
1350*5113495bSYour Name 	return ret;
1351*5113495bSYour Name }
1352*5113495bSYour Name 
1353*5113495bSYour Name #ifdef TDLS_MGMT_VERSION5
1354*5113495bSYour Name static void
wlan_cfg80211_tdls_indicate_discovery(struct tdls_osif_indication * ind)1355*5113495bSYour Name wlan_cfg80211_tdls_indicate_discovery(struct tdls_osif_indication *ind)
1356*5113495bSYour Name {
1357*5113495bSYour Name 	struct vdev_osif_priv *osif_vdev;
1358*5113495bSYour Name 
1359*5113495bSYour Name 	osif_vdev = wlan_vdev_get_ospriv(ind->vdev);
1360*5113495bSYour Name 
1361*5113495bSYour Name 	cfg80211_tdls_oper_request(osif_vdev->wdev->netdev,
1362*5113495bSYour Name 				   ind->peer_mac, -1,
1363*5113495bSYour Name 				   NL80211_TDLS_DISCOVERY_REQ,
1364*5113495bSYour Name 				   false, GFP_KERNEL);
1365*5113495bSYour Name }
1366*5113495bSYour Name 
1367*5113495bSYour Name static void
wlan_cfg80211_tdls_indicate_setup(struct tdls_osif_indication * ind)1368*5113495bSYour Name wlan_cfg80211_tdls_indicate_setup(struct tdls_osif_indication *ind)
1369*5113495bSYour Name {
1370*5113495bSYour Name 	struct vdev_osif_priv *osif_vdev;
1371*5113495bSYour Name 	int link_id = -1;
1372*5113495bSYour Name 
1373*5113495bSYour Name 	osif_vdev = wlan_vdev_get_ospriv(ind->vdev);
1374*5113495bSYour Name 	if (wlan_vdev_mlme_is_mlo_vdev(ind->vdev))
1375*5113495bSYour Name 		link_id = wlan_vdev_get_link_id(ind->vdev);
1376*5113495bSYour Name 
1377*5113495bSYour Name 	osif_debug("Indication to request TDLS setup on link id %d", link_id);
1378*5113495bSYour Name 	cfg80211_tdls_oper_request(osif_vdev->wdev->netdev,
1379*5113495bSYour Name 				   ind->peer_mac, link_id,
1380*5113495bSYour Name 				   NL80211_TDLS_SETUP, false,
1381*5113495bSYour Name 				   GFP_KERNEL);
1382*5113495bSYour Name }
1383*5113495bSYour Name 
1384*5113495bSYour Name static void
wlan_cfg80211_tdls_indicate_teardown(struct tdls_osif_indication * ind)1385*5113495bSYour Name wlan_cfg80211_tdls_indicate_teardown(struct tdls_osif_indication *ind)
1386*5113495bSYour Name {
1387*5113495bSYour Name 	struct vdev_osif_priv *osif_vdev;
1388*5113495bSYour Name 
1389*5113495bSYour Name 	osif_vdev = wlan_vdev_get_ospriv(ind->vdev);
1390*5113495bSYour Name 
1391*5113495bSYour Name 	osif_debug("Teardown reason %d", ind->reason);
1392*5113495bSYour Name 	cfg80211_tdls_oper_request(osif_vdev->wdev->netdev,
1393*5113495bSYour Name 				   ind->peer_mac, -1, NL80211_TDLS_TEARDOWN,
1394*5113495bSYour Name 				   ind->reason, GFP_KERNEL);
1395*5113495bSYour Name }
1396*5113495bSYour Name #else
1397*5113495bSYour Name static void
wlan_cfg80211_tdls_indicate_discovery(struct tdls_osif_indication * ind)1398*5113495bSYour Name wlan_cfg80211_tdls_indicate_discovery(struct tdls_osif_indication *ind)
1399*5113495bSYour Name {
1400*5113495bSYour Name 	struct vdev_osif_priv *osif_vdev;
1401*5113495bSYour Name 
1402*5113495bSYour Name 	osif_vdev = wlan_vdev_get_ospriv(ind->vdev);
1403*5113495bSYour Name 
1404*5113495bSYour Name 	cfg80211_tdls_oper_request(osif_vdev->wdev->netdev,
1405*5113495bSYour Name 				   ind->peer_mac, NL80211_TDLS_DISCOVERY_REQ,
1406*5113495bSYour Name 				   false, GFP_KERNEL);
1407*5113495bSYour Name }
1408*5113495bSYour Name 
1409*5113495bSYour Name static void
wlan_cfg80211_tdls_indicate_setup(struct tdls_osif_indication * ind)1410*5113495bSYour Name wlan_cfg80211_tdls_indicate_setup(struct tdls_osif_indication *ind)
1411*5113495bSYour Name {
1412*5113495bSYour Name 	struct vdev_osif_priv *osif_vdev;
1413*5113495bSYour Name 
1414*5113495bSYour Name 	osif_vdev = wlan_vdev_get_ospriv(ind->vdev);
1415*5113495bSYour Name 
1416*5113495bSYour Name 	osif_debug("Indication to request TDLS setup");
1417*5113495bSYour Name 	cfg80211_tdls_oper_request(osif_vdev->wdev->netdev,
1418*5113495bSYour Name 				   ind->peer_mac, NL80211_TDLS_SETUP, false,
1419*5113495bSYour Name 				   GFP_KERNEL);
1420*5113495bSYour Name }
1421*5113495bSYour Name 
1422*5113495bSYour Name static void
wlan_cfg80211_tdls_indicate_teardown(struct tdls_osif_indication * ind)1423*5113495bSYour Name wlan_cfg80211_tdls_indicate_teardown(struct tdls_osif_indication *ind)
1424*5113495bSYour Name {
1425*5113495bSYour Name 	struct vdev_osif_priv *osif_vdev;
1426*5113495bSYour Name 
1427*5113495bSYour Name 	osif_vdev = wlan_vdev_get_ospriv(ind->vdev);
1428*5113495bSYour Name 
1429*5113495bSYour Name 	osif_debug("Teardown reason %d", ind->reason);
1430*5113495bSYour Name 	cfg80211_tdls_oper_request(osif_vdev->wdev->netdev,
1431*5113495bSYour Name 				   ind->peer_mac, NL80211_TDLS_TEARDOWN,
1432*5113495bSYour Name 				   ind->reason, GFP_KERNEL);
1433*5113495bSYour Name }
1434*5113495bSYour Name #endif
1435*5113495bSYour Name 
wlan_cfg80211_tdls_event_callback(void * user_data,enum tdls_event_type type,struct tdls_osif_indication * ind)1436*5113495bSYour Name void wlan_cfg80211_tdls_event_callback(void *user_data,
1437*5113495bSYour Name 				       enum tdls_event_type type,
1438*5113495bSYour Name 				       struct tdls_osif_indication *ind)
1439*5113495bSYour Name {
1440*5113495bSYour Name 	struct vdev_osif_priv *osif_vdev;
1441*5113495bSYour Name 	struct osif_tdls_vdev *tdls_priv;
1442*5113495bSYour Name 
1443*5113495bSYour Name 	if (!ind || !ind->vdev) {
1444*5113495bSYour Name 		osif_err("ind: %pK", ind);
1445*5113495bSYour Name 		return;
1446*5113495bSYour Name 	}
1447*5113495bSYour Name 	osif_vdev = wlan_vdev_get_ospriv(ind->vdev);
1448*5113495bSYour Name 
1449*5113495bSYour Name 	if (!osif_vdev || !osif_vdev->osif_tdls) {
1450*5113495bSYour Name 		osif_err("osif priv or tdls priv is NULL");
1451*5113495bSYour Name 		return;
1452*5113495bSYour Name 	}
1453*5113495bSYour Name 
1454*5113495bSYour Name 	tdls_priv = osif_vdev->osif_tdls;
1455*5113495bSYour Name 
1456*5113495bSYour Name 	switch (type) {
1457*5113495bSYour Name 	case TDLS_EVENT_MGMT_TX_ACK_CNF:
1458*5113495bSYour Name 		tdls_priv->mgmt_tx_completion_status = ind->status;
1459*5113495bSYour Name 		complete(&tdls_priv->tdls_mgmt_comp);
1460*5113495bSYour Name 		break;
1461*5113495bSYour Name 	case TDLS_EVENT_ADD_PEER:
1462*5113495bSYour Name 		tdls_priv->tdls_add_peer_status = ind->status;
1463*5113495bSYour Name 		complete(&tdls_priv->tdls_add_peer_comp);
1464*5113495bSYour Name 		break;
1465*5113495bSYour Name 	case TDLS_EVENT_DEL_PEER:
1466*5113495bSYour Name 		complete(&tdls_priv->tdls_del_peer_comp);
1467*5113495bSYour Name 		break;
1468*5113495bSYour Name 	case TDLS_EVENT_DISCOVERY_REQ:
1469*5113495bSYour Name 		wlan_cfg80211_tdls_indicate_discovery(ind);
1470*5113495bSYour Name 		break;
1471*5113495bSYour Name 	case TDLS_EVENT_TEARDOWN_REQ:
1472*5113495bSYour Name 		wlan_cfg80211_tdls_indicate_teardown(ind);
1473*5113495bSYour Name 		break;
1474*5113495bSYour Name 	case TDLS_EVENT_SETUP_REQ:
1475*5113495bSYour Name 		wlan_cfg80211_tdls_indicate_setup(ind);
1476*5113495bSYour Name 		break;
1477*5113495bSYour Name 	case TDLS_EVENT_USER_CMD:
1478*5113495bSYour Name 		tdls_priv->tdls_user_cmd_len = ind->status;
1479*5113495bSYour Name 		complete(&tdls_priv->tdls_user_cmd_comp);
1480*5113495bSYour Name 		break;
1481*5113495bSYour Name 
1482*5113495bSYour Name 	case TDLS_EVENT_ANTENNA_SWITCH:
1483*5113495bSYour Name 		tdls_priv->tdls_antenna_switch_status = ind->status;
1484*5113495bSYour Name 		complete(&tdls_priv->tdls_antenna_switch_comp);
1485*5113495bSYour Name 		break;
1486*5113495bSYour Name 	default:
1487*5113495bSYour Name 		break;
1488*5113495bSYour Name 	}
1489*5113495bSYour Name }
1490