xref: /wlan-driver/qcacld-3.0/core/hdd/src/wlan_hdd_tdls.c (revision 5113495b16420b49004c444715d2daae2066e7dc)
1*5113495bSYour Name /*
2*5113495bSYour Name  * Copyright (c) 2012-2020 The Linux Foundation. All rights reserved.
3*5113495bSYour Name  * Copyright (c) 2022-2024 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: wlan_hdd_tdls.c
22*5113495bSYour Name  *
23*5113495bSYour Name  * WLAN Host Device Driver implementation for TDLS
24*5113495bSYour Name  */
25*5113495bSYour Name 
26*5113495bSYour Name #include <wlan_hdd_includes.h>
27*5113495bSYour Name #include <ani_global.h>
28*5113495bSYour Name #include "osif_sync.h"
29*5113495bSYour Name #include <wlan_hdd_hostapd.h>
30*5113495bSYour Name #include <wlan_hdd_trace.h>
31*5113495bSYour Name #include <net/cfg80211.h>
32*5113495bSYour Name #include <linux/netdevice.h>
33*5113495bSYour Name #include <linux/skbuff.h>
34*5113495bSYour Name #include <linux/list.h>
35*5113495bSYour Name #include <linux/etherdevice.h>
36*5113495bSYour Name #include <net/ieee80211_radiotap.h>
37*5113495bSYour Name #include "wlan_hdd_tdls.h"
38*5113495bSYour Name #include "wlan_hdd_cfg80211.h"
39*5113495bSYour Name #include "wlan_hdd_assoc.h"
40*5113495bSYour Name #include "sme_api.h"
41*5113495bSYour Name #include "cds_sched.h"
42*5113495bSYour Name #include "wma_types.h"
43*5113495bSYour Name #include "wlan_policy_mgr_api.h"
44*5113495bSYour Name #include <qca_vendor.h>
45*5113495bSYour Name #include "wlan_tdls_cfg_api.h"
46*5113495bSYour Name #include "wlan_hdd_object_manager.h"
47*5113495bSYour Name #include <wlan_reg_ucfg_api.h>
48*5113495bSYour Name #include "wlan_tdls_api.h"
49*5113495bSYour Name 
50*5113495bSYour Name /**
51*5113495bSYour Name  * enum qca_wlan_vendor_tdls_trigger_mode_hdd_map: Maps the user space TDLS
52*5113495bSYour Name  *	trigger mode in the host driver.
53*5113495bSYour Name  * @WLAN_HDD_VENDOR_TDLS_TRIGGER_MODE_EXPLICIT: TDLS Connection and
54*5113495bSYour Name  *	disconnection handled by user space.
55*5113495bSYour Name  * @WLAN_HDD_VENDOR_TDLS_TRIGGER_MODE_IMPLICIT: TDLS connection and
56*5113495bSYour Name  *	disconnection controlled by host driver based on data traffic.
57*5113495bSYour Name  * @WLAN_HDD_VENDOR_TDLS_TRIGGER_MODE_EXTERNAL: TDLS connection and
58*5113495bSYour Name  *	disconnection jointly controlled by user space and host driver.
59*5113495bSYour Name  */
60*5113495bSYour Name enum qca_wlan_vendor_tdls_trigger_mode_hdd_map {
61*5113495bSYour Name 	WLAN_HDD_VENDOR_TDLS_TRIGGER_MODE_EXPLICIT =
62*5113495bSYour Name 		QCA_WLAN_VENDOR_TDLS_TRIGGER_MODE_EXPLICIT,
63*5113495bSYour Name 	WLAN_HDD_VENDOR_TDLS_TRIGGER_MODE_IMPLICIT =
64*5113495bSYour Name 		QCA_WLAN_VENDOR_TDLS_TRIGGER_MODE_IMPLICIT,
65*5113495bSYour Name 	WLAN_HDD_VENDOR_TDLS_TRIGGER_MODE_EXTERNAL =
66*5113495bSYour Name 		((QCA_WLAN_VENDOR_TDLS_TRIGGER_MODE_EXPLICIT |
67*5113495bSYour Name 		  QCA_WLAN_VENDOR_TDLS_TRIGGER_MODE_IMPLICIT) << 1),
68*5113495bSYour Name };
69*5113495bSYour Name 
70*5113495bSYour Name /**
71*5113495bSYour Name  * wlan_hdd_tdls_get_all_peers() - dump all TDLS peer info into output string
72*5113495bSYour Name  * @adapter: HDD adapter
73*5113495bSYour Name  * @buf: output string buffer to hold the peer info
74*5113495bSYour Name  * @buflen: the size of output string buffer
75*5113495bSYour Name  *
76*5113495bSYour Name  * Return: The size (in bytes) of the valid peer info in the output buffer
77*5113495bSYour Name  */
wlan_hdd_tdls_get_all_peers(struct hdd_adapter * adapter,char * buf,int buflen)78*5113495bSYour Name int wlan_hdd_tdls_get_all_peers(struct hdd_adapter *adapter,
79*5113495bSYour Name 				char *buf, int buflen)
80*5113495bSYour Name {
81*5113495bSYour Name 	int len;
82*5113495bSYour Name 	struct hdd_context *hdd_ctx;
83*5113495bSYour Name 	struct wlan_objmgr_vdev *vdev;
84*5113495bSYour Name 	struct wlan_objmgr_vdev *link_vdev;
85*5113495bSYour Name 	int ret;
86*5113495bSYour Name 
87*5113495bSYour Name 	hdd_enter();
88*5113495bSYour Name 
89*5113495bSYour Name 	hdd_ctx = WLAN_HDD_GET_CTX(adapter);
90*5113495bSYour Name 	if (0 != (wlan_hdd_validate_context(hdd_ctx))) {
91*5113495bSYour Name 		len = scnprintf(buf, buflen,
92*5113495bSYour Name 				"\nHDD context is not valid\n");
93*5113495bSYour Name 		return len;
94*5113495bSYour Name 	}
95*5113495bSYour Name 
96*5113495bSYour Name 	if ((QDF_STA_MODE != adapter->device_mode) &&
97*5113495bSYour Name 	    (QDF_P2P_CLIENT_MODE != adapter->device_mode)) {
98*5113495bSYour Name 		len = scnprintf(buf, buflen,
99*5113495bSYour Name 				"\nNo TDLS support for this adapter\n");
100*5113495bSYour Name 		return len;
101*5113495bSYour Name 	}
102*5113495bSYour Name 
103*5113495bSYour Name 	vdev = hdd_objmgr_get_vdev_by_user(adapter->deflink, WLAN_OSIF_TDLS_ID);
104*5113495bSYour Name 	if (!vdev) {
105*5113495bSYour Name 		len = scnprintf(buf, buflen, "\nVDEV is NULL\n");
106*5113495bSYour Name 		return len;
107*5113495bSYour Name 	}
108*5113495bSYour Name 
109*5113495bSYour Name 	link_vdev = ucfg_tdls_get_tdls_link_vdev(vdev, WLAN_OSIF_TDLS_ID);
110*5113495bSYour Name 	if (link_vdev) {
111*5113495bSYour Name 		ret = wlan_cfg80211_tdls_get_all_peers(link_vdev, buf, buflen);
112*5113495bSYour Name 		ucfg_tdls_put_tdls_link_vdev(link_vdev, WLAN_OSIF_TDLS_ID);
113*5113495bSYour Name 	} else {
114*5113495bSYour Name 		ret = wlan_cfg80211_tdls_get_all_peers(vdev, buf, buflen);
115*5113495bSYour Name 	}
116*5113495bSYour Name 
117*5113495bSYour Name 	hdd_objmgr_put_vdev_by_user(vdev, WLAN_OSIF_TDLS_ID);
118*5113495bSYour Name 
119*5113495bSYour Name 	return ret;
120*5113495bSYour Name }
121*5113495bSYour Name 
122*5113495bSYour Name static const struct nla_policy
123*5113495bSYour Name 	wlan_hdd_tdls_config_enable_policy[QCA_WLAN_VENDOR_ATTR_TDLS_ENABLE_MAX +
124*5113495bSYour Name 					   1] = {
125*5113495bSYour Name 	[QCA_WLAN_VENDOR_ATTR_TDLS_ENABLE_MAC_ADDR] =
126*5113495bSYour Name 		VENDOR_NLA_POLICY_MAC_ADDR,
127*5113495bSYour Name 	[QCA_WLAN_VENDOR_ATTR_TDLS_ENABLE_CHANNEL] = {.type = NLA_U32},
128*5113495bSYour Name 	[QCA_WLAN_VENDOR_ATTR_TDLS_ENABLE_GLOBAL_OPERATING_CLASS] = {.type =
129*5113495bSYour Name 								NLA_U32},
130*5113495bSYour Name 	[QCA_WLAN_VENDOR_ATTR_TDLS_ENABLE_MAX_LATENCY_MS] = {.type = NLA_U32},
131*5113495bSYour Name 	[QCA_WLAN_VENDOR_ATTR_TDLS_ENABLE_MIN_BANDWIDTH_KBPS] = {.type =
132*5113495bSYour Name 								NLA_U32},
133*5113495bSYour Name };
134*5113495bSYour Name static const struct nla_policy
135*5113495bSYour Name 	wlan_hdd_tdls_config_disable_policy[QCA_WLAN_VENDOR_ATTR_TDLS_DISABLE_MAX +
136*5113495bSYour Name 					    1] = {
137*5113495bSYour Name 	[QCA_WLAN_VENDOR_ATTR_TDLS_DISABLE_MAC_ADDR] =
138*5113495bSYour Name 		VENDOR_NLA_POLICY_MAC_ADDR,
139*5113495bSYour Name };
140*5113495bSYour Name static const struct nla_policy
141*5113495bSYour Name 	wlan_hdd_tdls_config_state_change_policy[QCA_WLAN_VENDOR_ATTR_TDLS_STATE_MAX
142*5113495bSYour Name 						 + 1] = {
143*5113495bSYour Name 	[QCA_WLAN_VENDOR_ATTR_TDLS_STATE_MAC_ADDR] =
144*5113495bSYour Name 		VENDOR_NLA_POLICY_MAC_ADDR,
145*5113495bSYour Name 	[QCA_WLAN_VENDOR_ATTR_TDLS_STATE_NEW_STATE] = {.type = NLA_U32},
146*5113495bSYour Name 	[QCA_WLAN_VENDOR_ATTR_TDLS_STATE_REASON] = {.type = NLA_S32},
147*5113495bSYour Name 	[QCA_WLAN_VENDOR_ATTR_TDLS_STATE_CHANNEL] = {.type = NLA_U32},
148*5113495bSYour Name 	[QCA_WLAN_VENDOR_ATTR_TDLS_STATE_GLOBAL_OPERATING_CLASS] = {.type =
149*5113495bSYour Name 								NLA_U32},
150*5113495bSYour Name };
151*5113495bSYour Name static const struct nla_policy
152*5113495bSYour Name 	wlan_hdd_tdls_config_get_status_policy
153*5113495bSYour Name [QCA_WLAN_VENDOR_ATTR_TDLS_GET_STATUS_MAX + 1] = {
154*5113495bSYour Name 	[QCA_WLAN_VENDOR_ATTR_TDLS_GET_STATUS_MAC_ADDR] =
155*5113495bSYour Name 		VENDOR_NLA_POLICY_MAC_ADDR,
156*5113495bSYour Name 	[QCA_WLAN_VENDOR_ATTR_TDLS_GET_STATUS_STATE] = {.type = NLA_U32},
157*5113495bSYour Name 	[QCA_WLAN_VENDOR_ATTR_TDLS_GET_STATUS_REASON] = {.type = NLA_S32},
158*5113495bSYour Name 	[QCA_WLAN_VENDOR_ATTR_TDLS_GET_STATUS_CHANNEL] = {.type = NLA_U32},
159*5113495bSYour Name 	[QCA_WLAN_VENDOR_ATTR_TDLS_GET_STATUS_GLOBAL_OPERATING_CLASS] = {
160*5113495bSYour Name 							.type = NLA_U32},
161*5113495bSYour Name };
162*5113495bSYour Name 
163*5113495bSYour Name const struct nla_policy
164*5113495bSYour Name 	wlan_hdd_tdls_disc_rsp_policy
165*5113495bSYour Name 	[QCA_WLAN_VENDOR_ATTR_TDLS_DISC_RSP_EXT_MAX + 1] = {
166*5113495bSYour Name 		[QCA_WLAN_VENDOR_ATTR_TDLS_DISC_RSP_EXT_TX_LINK] = {
167*5113495bSYour Name 						.type = NLA_U8},
168*5113495bSYour Name };
169*5113495bSYour Name 
170*5113495bSYour Name const struct nla_policy
171*5113495bSYour Name 	wlan_hdd_tdls_mode_configuration_policy
172*5113495bSYour Name 	[QCA_WLAN_VENDOR_ATTR_TDLS_CONFIG_MAX + 1] = {
173*5113495bSYour Name 		[QCA_WLAN_VENDOR_ATTR_TDLS_CONFIG_TRIGGER_MODE] = {
174*5113495bSYour Name 						.type = NLA_U32},
175*5113495bSYour Name 		[QCA_WLAN_VENDOR_ATTR_TDLS_CONFIG_TX_STATS_PERIOD] = {
176*5113495bSYour Name 						.type = NLA_U32},
177*5113495bSYour Name 		[QCA_WLAN_VENDOR_ATTR_TDLS_CONFIG_TX_THRESHOLD] = {
178*5113495bSYour Name 						.type = NLA_U32},
179*5113495bSYour Name 		[QCA_WLAN_VENDOR_ATTR_TDLS_CONFIG_DISCOVERY_PERIOD] = {
180*5113495bSYour Name 						.type = NLA_U32},
181*5113495bSYour Name 		[QCA_WLAN_VENDOR_ATTR_TDLS_CONFIG_MAX_DISCOVERY_ATTEMPT] = {
182*5113495bSYour Name 						.type = NLA_U32},
183*5113495bSYour Name 		[QCA_WLAN_VENDOR_ATTR_TDLS_CONFIG_IDLE_TIMEOUT] = {
184*5113495bSYour Name 						.type = NLA_U32},
185*5113495bSYour Name 		[QCA_WLAN_VENDOR_ATTR_TDLS_CONFIG_IDLE_PACKET_THRESHOLD] = {
186*5113495bSYour Name 						.type = NLA_U32},
187*5113495bSYour Name 		[QCA_WLAN_VENDOR_ATTR_TDLS_CONFIG_SETUP_RSSI_THRESHOLD] = {
188*5113495bSYour Name 						.type = NLA_S32},
189*5113495bSYour Name 		[QCA_WLAN_VENDOR_ATTR_TDLS_CONFIG_TEARDOWN_RSSI_THRESHOLD] = {
190*5113495bSYour Name 						.type = NLA_S32},
191*5113495bSYour Name };
192*5113495bSYour Name 
wlan_hdd_is_tdls_allowed(struct hdd_context * hdd_ctx,struct wlan_objmgr_vdev * vdev)193*5113495bSYour Name static bool wlan_hdd_is_tdls_allowed(struct hdd_context *hdd_ctx,
194*5113495bSYour Name 				     struct wlan_objmgr_vdev *vdev)
195*5113495bSYour Name {
196*5113495bSYour Name 	bool tdls_support;
197*5113495bSYour Name 
198*5113495bSYour Name 	if ((cfg_tdls_get_support_enable(hdd_ctx->psoc, &tdls_support) ==
199*5113495bSYour Name 		QDF_STATUS_SUCCESS) && !tdls_support) {
200*5113495bSYour Name 		hdd_debug("TDLS feature not Enabled or Not supported in FW");
201*5113495bSYour Name 		return false;
202*5113495bSYour Name 	}
203*5113495bSYour Name 
204*5113495bSYour Name 	if (!wlan_cm_is_vdev_connected(vdev)) {
205*5113495bSYour Name 		hdd_debug("Failed due to Not associated");
206*5113495bSYour Name 		return false;
207*5113495bSYour Name 	}
208*5113495bSYour Name 
209*5113495bSYour Name 	if (wlan_cm_roaming_in_progress(hdd_ctx->pdev,
210*5113495bSYour Name 					wlan_vdev_get_id(vdev))) {
211*5113495bSYour Name 		hdd_debug("Failed due to Roaming is in progress");
212*5113495bSYour Name 		return false;
213*5113495bSYour Name 	}
214*5113495bSYour Name 
215*5113495bSYour Name 	if (!ucfg_tdls_check_is_tdls_allowed(vdev)) {
216*5113495bSYour Name 		hdd_debug("TDLS is not allowed");
217*5113495bSYour Name 		return false;
218*5113495bSYour Name 	}
219*5113495bSYour Name 
220*5113495bSYour Name 	if (ucfg_mlme_get_tdls_prohibited(vdev)) {
221*5113495bSYour Name 		hdd_debug("TDLS is prohobited by AP");
222*5113495bSYour Name 		return false;
223*5113495bSYour Name 	}
224*5113495bSYour Name 
225*5113495bSYour Name 	return true;
226*5113495bSYour Name }
227*5113495bSYour Name 
wlan_hdd_get_tdls_allowed(struct hdd_context * hdd_ctx,struct hdd_adapter * adapter)228*5113495bSYour Name static bool wlan_hdd_get_tdls_allowed(struct hdd_context *hdd_ctx,
229*5113495bSYour Name 				      struct hdd_adapter *adapter)
230*5113495bSYour Name {
231*5113495bSYour Name 	struct wlan_hdd_link_info *link_info;
232*5113495bSYour Name 	struct wlan_objmgr_vdev *vdev;
233*5113495bSYour Name 	bool is_tdls_avail = false;
234*5113495bSYour Name 
235*5113495bSYour Name 	hdd_adapter_for_each_active_link_info(adapter, link_info) {
236*5113495bSYour Name 		vdev = hdd_objmgr_get_vdev_by_user(link_info, WLAN_TDLS_NB_ID);
237*5113495bSYour Name 		if (!vdev)
238*5113495bSYour Name 			return false;
239*5113495bSYour Name 
240*5113495bSYour Name 		is_tdls_avail = wlan_hdd_is_tdls_allowed(hdd_ctx, vdev);
241*5113495bSYour Name 
242*5113495bSYour Name 		/* Return is_tdls_avail for non-MLO case */
243*5113495bSYour Name 		if (!wlan_vdev_mlme_is_mlo_vdev(vdev)) {
244*5113495bSYour Name 			hdd_objmgr_put_vdev_by_user(vdev, WLAN_TDLS_NB_ID);
245*5113495bSYour Name 			return is_tdls_avail;
246*5113495bSYour Name 		}
247*5113495bSYour Name 
248*5113495bSYour Name 		hdd_objmgr_put_vdev_by_user(vdev, WLAN_TDLS_NB_ID);
249*5113495bSYour Name 
250*5113495bSYour Name 		if (is_tdls_avail)
251*5113495bSYour Name 			return is_tdls_avail;
252*5113495bSYour Name 	}
253*5113495bSYour Name 
254*5113495bSYour Name 	return false;
255*5113495bSYour Name }
256*5113495bSYour Name 
257*5113495bSYour Name /**
258*5113495bSYour Name  * __wlan_hdd_cfg80211_exttdls_get_status() - handle get status cfg80211 command
259*5113495bSYour Name  * @wiphy: wiphy
260*5113495bSYour Name  * @wdev: wireless dev
261*5113495bSYour Name  * @data: netlink buffer with the mac address of the peer to get the status for
262*5113495bSYour Name  * @data_len: length of data in bytes
263*5113495bSYour Name  */
264*5113495bSYour Name static int
__wlan_hdd_cfg80211_exttdls_get_status(struct wiphy * wiphy,struct wireless_dev * wdev,const void * data,int data_len)265*5113495bSYour Name __wlan_hdd_cfg80211_exttdls_get_status(struct wiphy *wiphy,
266*5113495bSYour Name 					 struct wireless_dev *wdev,
267*5113495bSYour Name 					 const void *data,
268*5113495bSYour Name 					 int data_len)
269*5113495bSYour Name {
270*5113495bSYour Name 	struct net_device *dev = wdev->netdev;
271*5113495bSYour Name 	struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
272*5113495bSYour Name 	struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
273*5113495bSYour Name 	struct sk_buff *skb;
274*5113495bSYour Name 	uint32_t connected_peer_count = 0;
275*5113495bSYour Name 	int status;
276*5113495bSYour Name 	bool is_tdls_avail = true;
277*5113495bSYour Name 	int ret = 0;
278*5113495bSYour Name 	int attr;
279*5113495bSYour Name 
280*5113495bSYour Name 	hdd_enter_dev(wdev->netdev);
281*5113495bSYour Name 	if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
282*5113495bSYour Name 		hdd_err("Command not allowed in FTM mode");
283*5113495bSYour Name 		return -EPERM;
284*5113495bSYour Name 	}
285*5113495bSYour Name 
286*5113495bSYour Name 	status = wlan_hdd_validate_context(hdd_ctx);
287*5113495bSYour Name 	if (status)
288*5113495bSYour Name 		return -EINVAL;
289*5113495bSYour Name 
290*5113495bSYour Name 	skb = wlan_cfg80211_vendor_cmd_alloc_reply_skb(wiphy,
291*5113495bSYour Name 						sizeof(u32) + sizeof(bool) +
292*5113495bSYour Name 						NLMSG_HDRLEN);
293*5113495bSYour Name 
294*5113495bSYour Name 	if (!skb) {
295*5113495bSYour Name 		hdd_err("wlan_cfg80211_vendor_cmd_alloc_reply_skb failed");
296*5113495bSYour Name 		return -ENOMEM;
297*5113495bSYour Name 	}
298*5113495bSYour Name 
299*5113495bSYour Name 	if (adapter->device_mode != QDF_STA_MODE &&
300*5113495bSYour Name 	    adapter->device_mode != QDF_P2P_CLIENT_MODE) {
301*5113495bSYour Name 		hdd_debug("Failed to get TDLS info due to opmode:%d",
302*5113495bSYour Name 			  adapter->device_mode);
303*5113495bSYour Name 		ret = -EOPNOTSUPP;
304*5113495bSYour Name 		goto fail;
305*5113495bSYour Name 	}
306*5113495bSYour Name 
307*5113495bSYour Name 	connected_peer_count = cfg_tdls_get_connected_peer_count(hdd_ctx->psoc);
308*5113495bSYour Name 	is_tdls_avail = wlan_hdd_get_tdls_allowed(hdd_ctx, adapter);
309*5113495bSYour Name 
310*5113495bSYour Name 	if (connected_peer_count >=
311*5113495bSYour Name 			cfg_tdls_get_max_peer_count(hdd_ctx->psoc)) {
312*5113495bSYour Name 		hdd_debug("Failed due to max no. of connected peer:%d reached",
313*5113495bSYour Name 			  connected_peer_count);
314*5113495bSYour Name 		is_tdls_avail = false;
315*5113495bSYour Name 	}
316*5113495bSYour Name 
317*5113495bSYour Name 	hdd_debug("Send TDLS_available: %d, no. of connected peer:%d to userspace",
318*5113495bSYour Name 		  is_tdls_avail, connected_peer_count);
319*5113495bSYour Name 
320*5113495bSYour Name 	attr = QCA_WLAN_VENDOR_ATTR_TDLS_GET_STATUS_NUM_SESSIONS;
321*5113495bSYour Name 	if (nla_put_u32(skb, attr, connected_peer_count)) {
322*5113495bSYour Name 		hdd_err("nla put fail");
323*5113495bSYour Name 		ret = -EINVAL;
324*5113495bSYour Name 		goto fail;
325*5113495bSYour Name 	}
326*5113495bSYour Name 
327*5113495bSYour Name 	attr = QCA_WLAN_VENDOR_ATTR_TDLS_GET_STATUS_AVAILABLE;
328*5113495bSYour Name 	if (is_tdls_avail && nla_put_flag(skb, attr)) {
329*5113495bSYour Name 		hdd_err("nla put fail");
330*5113495bSYour Name 		ret = -EINVAL;
331*5113495bSYour Name 		goto fail;
332*5113495bSYour Name 	}
333*5113495bSYour Name 
334*5113495bSYour Name 	return wlan_cfg80211_vendor_cmd_reply(skb);
335*5113495bSYour Name fail:
336*5113495bSYour Name 	wlan_cfg80211_vendor_free_skb(skb);
337*5113495bSYour Name 	return ret;
338*5113495bSYour Name }
339*5113495bSYour Name 
340*5113495bSYour Name static int
__wlan_hdd_cfg80211_exttdls_set_link_id(struct wiphy * wiphy,struct wireless_dev * wdev,const void * data,int data_len)341*5113495bSYour Name __wlan_hdd_cfg80211_exttdls_set_link_id(struct wiphy *wiphy,
342*5113495bSYour Name 					struct wireless_dev *wdev,
343*5113495bSYour Name 					const void *data,
344*5113495bSYour Name 					int data_len)
345*5113495bSYour Name {
346*5113495bSYour Name 	struct net_device *dev = wdev->netdev;
347*5113495bSYour Name 	struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
348*5113495bSYour Name 	struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
349*5113495bSYour Name 	struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_TDLS_DISC_RSP_EXT_MAX + 1];
350*5113495bSYour Name 	int ret;
351*5113495bSYour Name 	uint32_t link_id;
352*5113495bSYour Name 
353*5113495bSYour Name 	hdd_enter_dev(dev);
354*5113495bSYour Name 
355*5113495bSYour Name 	if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
356*5113495bSYour Name 		hdd_err("Command not allowed in FTM mode");
357*5113495bSYour Name 		return -EPERM;
358*5113495bSYour Name 	}
359*5113495bSYour Name 
360*5113495bSYour Name 	ret = wlan_hdd_validate_context(hdd_ctx);
361*5113495bSYour Name 	if (0 != ret)
362*5113495bSYour Name 		return -EINVAL;
363*5113495bSYour Name 
364*5113495bSYour Name 	if (!adapter)
365*5113495bSYour Name 		return -EINVAL;
366*5113495bSYour Name 
367*5113495bSYour Name 	if (wlan_cfg80211_nla_parse(tb,
368*5113495bSYour Name 				    QCA_WLAN_VENDOR_ATTR_TDLS_DISC_RSP_EXT_MAX,
369*5113495bSYour Name 				    data, data_len,
370*5113495bSYour Name 				    wlan_hdd_tdls_disc_rsp_policy)) {
371*5113495bSYour Name 		hdd_err("Invalid attribute");
372*5113495bSYour Name 		return -EINVAL;
373*5113495bSYour Name 	}
374*5113495bSYour Name 
375*5113495bSYour Name 	if (!tb[QCA_WLAN_VENDOR_ATTR_TDLS_DISC_RSP_EXT_TX_LINK]) {
376*5113495bSYour Name 		hdd_err("attr tdls link id failed");
377*5113495bSYour Name 		return -EINVAL;
378*5113495bSYour Name 	}
379*5113495bSYour Name 
380*5113495bSYour Name 	link_id =
381*5113495bSYour Name 		nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_TDLS_DISC_RSP_EXT_TX_LINK]);
382*5113495bSYour Name 	hdd_debug("TDLS link id %d", link_id);
383*5113495bSYour Name 
384*5113495bSYour Name 	ret = cfg_tdls_set_link_id(hdd_ctx->psoc, link_id);
385*5113495bSYour Name 
386*5113495bSYour Name 	return ret;
387*5113495bSYour Name }
388*5113495bSYour Name 
389*5113495bSYour Name /**
390*5113495bSYour Name  * __wlan_hdd_cfg80211_configure_tdls_mode() - configure the tdls mode
391*5113495bSYour Name  * @wiphy: wiphy
392*5113495bSYour Name  * @wdev: wireless dev
393*5113495bSYour Name  * @data: netlink buffer
394*5113495bSYour Name  * @data_len: length of data in bytes
395*5113495bSYour Name  *
396*5113495bSYour Name  * Return 0 for success and error code for failure
397*5113495bSYour Name  */
398*5113495bSYour Name static int
__wlan_hdd_cfg80211_configure_tdls_mode(struct wiphy * wiphy,struct wireless_dev * wdev,const void * data,int data_len)399*5113495bSYour Name __wlan_hdd_cfg80211_configure_tdls_mode(struct wiphy *wiphy,
400*5113495bSYour Name 					 struct wireless_dev *wdev,
401*5113495bSYour Name 					 const void *data,
402*5113495bSYour Name 					 int data_len)
403*5113495bSYour Name {
404*5113495bSYour Name 	struct net_device *dev = wdev->netdev;
405*5113495bSYour Name 	struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
406*5113495bSYour Name 	struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
407*5113495bSYour Name 	struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_TDLS_CONFIG_MAX + 1];
408*5113495bSYour Name 	int ret;
409*5113495bSYour Name 	uint32_t trigger_mode;
410*5113495bSYour Name 	struct wlan_objmgr_vdev *vdev;
411*5113495bSYour Name 
412*5113495bSYour Name 	hdd_enter_dev(dev);
413*5113495bSYour Name 
414*5113495bSYour Name 	if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
415*5113495bSYour Name 		hdd_err("Command not allowed in FTM mode");
416*5113495bSYour Name 		return -EPERM;
417*5113495bSYour Name 	}
418*5113495bSYour Name 
419*5113495bSYour Name 	ret = wlan_hdd_validate_context(hdd_ctx);
420*5113495bSYour Name 	if (0 != ret)
421*5113495bSYour Name 		return -EINVAL;
422*5113495bSYour Name 
423*5113495bSYour Name 	if (!adapter)
424*5113495bSYour Name 		return -EINVAL;
425*5113495bSYour Name 
426*5113495bSYour Name 	if (wlan_cfg80211_nla_parse(tb, QCA_WLAN_VENDOR_ATTR_TDLS_CONFIG_MAX,
427*5113495bSYour Name 				    data, data_len,
428*5113495bSYour Name 				    wlan_hdd_tdls_mode_configuration_policy)) {
429*5113495bSYour Name 		hdd_err("Invalid attribute");
430*5113495bSYour Name 		return -EINVAL;
431*5113495bSYour Name 	}
432*5113495bSYour Name 
433*5113495bSYour Name 	if (!tb[QCA_WLAN_VENDOR_ATTR_TDLS_CONFIG_TRIGGER_MODE]) {
434*5113495bSYour Name 		hdd_err("attr tdls trigger mode failed");
435*5113495bSYour Name 		return -EINVAL;
436*5113495bSYour Name 	}
437*5113495bSYour Name 	trigger_mode = nla_get_u32(tb[QCA_WLAN_VENDOR_ATTR_TDLS_CONFIG_TRIGGER_MODE]);
438*5113495bSYour Name 	hdd_debug("TDLS trigger mode %d", trigger_mode);
439*5113495bSYour Name 
440*5113495bSYour Name 	if (!hdd_ctx->tdls_umac_comp_active)
441*5113495bSYour Name 		return -EINVAL;
442*5113495bSYour Name 
443*5113495bSYour Name 	vdev = hdd_objmgr_get_vdev_by_user(adapter->deflink, WLAN_OSIF_TDLS_ID);
444*5113495bSYour Name 	if (!vdev)
445*5113495bSYour Name 		return -EINVAL;
446*5113495bSYour Name 
447*5113495bSYour Name 	ret = wlan_cfg80211_tdls_configure_mode(vdev, trigger_mode);
448*5113495bSYour Name 	hdd_objmgr_put_vdev_by_user(vdev, WLAN_OSIF_TDLS_ID);
449*5113495bSYour Name 	return ret;
450*5113495bSYour Name }
451*5113495bSYour Name 
452*5113495bSYour Name /**
453*5113495bSYour Name  * wlan_hdd_cfg80211_configure_tdls_mode() - configure tdls mode
454*5113495bSYour Name  * @wiphy:   pointer to wireless wiphy structure.
455*5113495bSYour Name  * @wdev:    pointer to wireless_dev structure.
456*5113495bSYour Name  * @data:    Pointer to the data to be passed via vendor interface
457*5113495bSYour Name  * @data_len:Length of the data to be passed
458*5113495bSYour Name  *
459*5113495bSYour Name  * Return:   Return the Success or Failure code.
460*5113495bSYour Name  */
wlan_hdd_cfg80211_configure_tdls_mode(struct wiphy * wiphy,struct wireless_dev * wdev,const void * data,int data_len)461*5113495bSYour Name int wlan_hdd_cfg80211_configure_tdls_mode(struct wiphy *wiphy,
462*5113495bSYour Name 					struct wireless_dev *wdev,
463*5113495bSYour Name 					const void *data,
464*5113495bSYour Name 					int data_len)
465*5113495bSYour Name {
466*5113495bSYour Name 	int errno;
467*5113495bSYour Name 	struct osif_vdev_sync *vdev_sync;
468*5113495bSYour Name 
469*5113495bSYour Name 	errno = osif_vdev_sync_op_start(wdev->netdev, &vdev_sync);
470*5113495bSYour Name 	if (errno)
471*5113495bSYour Name 		return errno;
472*5113495bSYour Name 
473*5113495bSYour Name 	errno = __wlan_hdd_cfg80211_configure_tdls_mode(wiphy, wdev, data,
474*5113495bSYour Name 							data_len);
475*5113495bSYour Name 
476*5113495bSYour Name 	osif_vdev_sync_op_stop(vdev_sync);
477*5113495bSYour Name 
478*5113495bSYour Name 	return errno;
479*5113495bSYour Name }
480*5113495bSYour Name 
481*5113495bSYour Name /**
482*5113495bSYour Name  * wlan_hdd_cfg80211_exttdls_get_status() - get ext tdls status
483*5113495bSYour Name  * @wiphy:   pointer to wireless wiphy structure.
484*5113495bSYour Name  * @wdev:    pointer to wireless_dev structure.
485*5113495bSYour Name  * @data:    Pointer to the data to be passed via vendor interface
486*5113495bSYour Name  * @data_len:Length of the data to be passed
487*5113495bSYour Name  *
488*5113495bSYour Name  * Return:   Return the Success or Failure code.
489*5113495bSYour Name  */
wlan_hdd_cfg80211_exttdls_get_status(struct wiphy * wiphy,struct wireless_dev * wdev,const void * data,int data_len)490*5113495bSYour Name int wlan_hdd_cfg80211_exttdls_get_status(struct wiphy *wiphy,
491*5113495bSYour Name 					struct wireless_dev *wdev,
492*5113495bSYour Name 					const void *data,
493*5113495bSYour Name 					int data_len)
494*5113495bSYour Name {
495*5113495bSYour Name 	int errno;
496*5113495bSYour Name 	struct osif_vdev_sync *vdev_sync;
497*5113495bSYour Name 
498*5113495bSYour Name 	errno = osif_vdev_sync_op_start(wdev->netdev, &vdev_sync);
499*5113495bSYour Name 	if (errno)
500*5113495bSYour Name 		return errno;
501*5113495bSYour Name 
502*5113495bSYour Name 	errno = __wlan_hdd_cfg80211_exttdls_get_status(wiphy, wdev,
503*5113495bSYour Name 						       data, data_len);
504*5113495bSYour Name 
505*5113495bSYour Name 	osif_vdev_sync_op_stop(vdev_sync);
506*5113495bSYour Name 
507*5113495bSYour Name 	return errno;
508*5113495bSYour Name }
509*5113495bSYour Name 
wlan_hdd_cfg80211_exttdls_set_link_id(struct wiphy * wiphy,struct wireless_dev * wdev,const void * data,int data_len)510*5113495bSYour Name int wlan_hdd_cfg80211_exttdls_set_link_id(struct wiphy *wiphy,
511*5113495bSYour Name 					  struct wireless_dev *wdev,
512*5113495bSYour Name 					  const void *data,
513*5113495bSYour Name 					  int data_len)
514*5113495bSYour Name {
515*5113495bSYour Name 	int errno;
516*5113495bSYour Name 	struct osif_vdev_sync *vdev_sync;
517*5113495bSYour Name 
518*5113495bSYour Name 	errno = osif_vdev_sync_op_start(wdev->netdev, &vdev_sync);
519*5113495bSYour Name 	if (errno)
520*5113495bSYour Name 		return errno;
521*5113495bSYour Name 
522*5113495bSYour Name 	errno = __wlan_hdd_cfg80211_exttdls_set_link_id(wiphy, wdev,
523*5113495bSYour Name 							data, data_len);
524*5113495bSYour Name 
525*5113495bSYour Name 	osif_vdev_sync_op_stop(vdev_sync);
526*5113495bSYour Name 
527*5113495bSYour Name 	return errno;
528*5113495bSYour Name }
529*5113495bSYour Name 
wlan_hdd_tdls_enable(struct hdd_context * hdd_ctx,struct hdd_adapter * adapter)530*5113495bSYour Name static int wlan_hdd_tdls_enable(struct hdd_context *hdd_ctx,
531*5113495bSYour Name 				struct hdd_adapter *adapter)
532*5113495bSYour Name {
533*5113495bSYour Name 	struct wlan_hdd_link_info *link_info;
534*5113495bSYour Name 	struct wlan_objmgr_vdev *vdev;
535*5113495bSYour Name 	bool tdls_chan_switch_prohibited;
536*5113495bSYour Name 	bool tdls_prohibited;
537*5113495bSYour Name 
538*5113495bSYour Name 	hdd_adapter_for_each_active_link_info(adapter, link_info) {
539*5113495bSYour Name 		vdev = hdd_objmgr_get_vdev_by_user(link_info, WLAN_TDLS_NB_ID);
540*5113495bSYour Name 		if (!vdev)
541*5113495bSYour Name 			return -EINVAL;
542*5113495bSYour Name 
543*5113495bSYour Name 		tdls_chan_switch_prohibited =
544*5113495bSYour Name 			ucfg_mlme_get_tdls_chan_switch_prohibited(vdev);
545*5113495bSYour Name 		tdls_prohibited = ucfg_mlme_get_tdls_prohibited(vdev);
546*5113495bSYour Name 
547*5113495bSYour Name 		ucfg_tdls_set_user_tdls_enable(vdev, true);
548*5113495bSYour Name 
549*5113495bSYour Name 		wlan_tdls_notify_sta_connect(wlan_vdev_get_id(vdev),
550*5113495bSYour Name 					     tdls_chan_switch_prohibited,
551*5113495bSYour Name 					     tdls_prohibited, vdev);
552*5113495bSYour Name 		if (!wlan_vdev_mlme_is_mlo_vdev(vdev)) {
553*5113495bSYour Name 			hdd_objmgr_put_vdev_by_user(vdev, WLAN_TDLS_NB_ID);
554*5113495bSYour Name 			return 0;
555*5113495bSYour Name 		}
556*5113495bSYour Name 
557*5113495bSYour Name 		hdd_objmgr_put_vdev_by_user(vdev, WLAN_TDLS_NB_ID);
558*5113495bSYour Name 	}
559*5113495bSYour Name 
560*5113495bSYour Name 	return 0;
561*5113495bSYour Name }
562*5113495bSYour Name 
563*5113495bSYour Name /**
564*5113495bSYour Name  * __wlan_hdd_cfg80211_exttdls_enable() - enable an externally controllable
565*5113495bSYour Name  *                                      TDLS peer and set parameters
566*5113495bSYour Name  * @wiphy: pointer to wireless wiphy structure.
567*5113495bSYour Name  * @wdev: wireless dev pointer
568*5113495bSYour Name  * @data: netlink buffer with peer MAC address and configuration parameters
569*5113495bSYour Name  * @data_len: size of data in bytes
570*5113495bSYour Name  *
571*5113495bSYour Name  * This function sets channel, operation class, maximum latency and minimal
572*5113495bSYour Name  * bandwidth parameters on a TDLS peer that's externally controllable.
573*5113495bSYour Name  *
574*5113495bSYour Name  * Return: 0 for success; negative errno otherwise
575*5113495bSYour Name  */
576*5113495bSYour Name static int
__wlan_hdd_cfg80211_exttdls_enable(struct wiphy * wiphy,struct wireless_dev * wdev,const void * data,int data_len)577*5113495bSYour Name __wlan_hdd_cfg80211_exttdls_enable(struct wiphy *wiphy,
578*5113495bSYour Name 				     struct wireless_dev *wdev,
579*5113495bSYour Name 				     const void *data,
580*5113495bSYour Name 				     int data_len)
581*5113495bSYour Name {
582*5113495bSYour Name 	struct net_device *dev = wdev->netdev;
583*5113495bSYour Name 	struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
584*5113495bSYour Name 	struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
585*5113495bSYour Name 	int ret = 0;
586*5113495bSYour Name 
587*5113495bSYour Name 	hdd_enter_dev(wdev->netdev);
588*5113495bSYour Name 	if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
589*5113495bSYour Name 		hdd_err("Command not allowed in FTM mode");
590*5113495bSYour Name 		return -EPERM;
591*5113495bSYour Name 	}
592*5113495bSYour Name 
593*5113495bSYour Name 	if (wlan_hdd_validate_context(hdd_ctx))
594*5113495bSYour Name 		return -EINVAL;
595*5113495bSYour Name 
596*5113495bSYour Name 	if (adapter->device_mode != QDF_STA_MODE &&
597*5113495bSYour Name 	    adapter->device_mode != QDF_P2P_CLIENT_MODE) {
598*5113495bSYour Name 		hdd_debug("Failed to get TDLS info due to opmode:%d",
599*5113495bSYour Name 			  adapter->device_mode);
600*5113495bSYour Name 		return -EOPNOTSUPP;
601*5113495bSYour Name 	}
602*5113495bSYour Name 
603*5113495bSYour Name 	ret = wlan_hdd_tdls_enable(hdd_ctx, adapter);
604*5113495bSYour Name 
605*5113495bSYour Name 	return ret;
606*5113495bSYour Name }
607*5113495bSYour Name 
608*5113495bSYour Name /**
609*5113495bSYour Name  * wlan_hdd_cfg80211_exttdls_enable() - enable ext tdls
610*5113495bSYour Name  * @wiphy:   pointer to wireless wiphy structure.
611*5113495bSYour Name  * @wdev:    pointer to wireless_dev structure.
612*5113495bSYour Name  * @data:    Pointer to the data to be passed via vendor interface
613*5113495bSYour Name  * @data_len:Length of the data to be passed
614*5113495bSYour Name  *
615*5113495bSYour Name  * Return:   Return the Success or Failure code.
616*5113495bSYour Name  */
wlan_hdd_cfg80211_exttdls_enable(struct wiphy * wiphy,struct wireless_dev * wdev,const void * data,int data_len)617*5113495bSYour Name int wlan_hdd_cfg80211_exttdls_enable(struct wiphy *wiphy,
618*5113495bSYour Name 					struct wireless_dev *wdev,
619*5113495bSYour Name 					const void *data,
620*5113495bSYour Name 					int data_len)
621*5113495bSYour Name {
622*5113495bSYour Name 	int errno;
623*5113495bSYour Name 	struct osif_vdev_sync *vdev_sync;
624*5113495bSYour Name 
625*5113495bSYour Name 	errno = osif_vdev_sync_op_start(wdev->netdev, &vdev_sync);
626*5113495bSYour Name 	if (errno)
627*5113495bSYour Name 		return errno;
628*5113495bSYour Name 
629*5113495bSYour Name 	errno = __wlan_hdd_cfg80211_exttdls_enable(wiphy, wdev, data, data_len);
630*5113495bSYour Name 
631*5113495bSYour Name 	osif_vdev_sync_op_stop(vdev_sync);
632*5113495bSYour Name 
633*5113495bSYour Name 	return errno;
634*5113495bSYour Name }
635*5113495bSYour Name 
wlan_hdd_tdls_disable(struct hdd_context * hdd_ctx,struct hdd_adapter * adapter)636*5113495bSYour Name static int wlan_hdd_tdls_disable(struct hdd_context *hdd_ctx,
637*5113495bSYour Name 				 struct hdd_adapter *adapter)
638*5113495bSYour Name {
639*5113495bSYour Name 	struct wlan_hdd_link_info *link_info;
640*5113495bSYour Name 	struct wlan_objmgr_vdev *vdev;
641*5113495bSYour Name 	bool tdls_chan_switch_prohibited;
642*5113495bSYour Name 
643*5113495bSYour Name 	hdd_adapter_for_each_active_link_info(adapter, link_info) {
644*5113495bSYour Name 		vdev = hdd_objmgr_get_vdev_by_user(link_info, WLAN_TDLS_NB_ID);
645*5113495bSYour Name 		if (!vdev)
646*5113495bSYour Name 			return -EINVAL;
647*5113495bSYour Name 
648*5113495bSYour Name 		tdls_chan_switch_prohibited =
649*5113495bSYour Name 				ucfg_mlme_get_tdls_chan_switch_prohibited(vdev);
650*5113495bSYour Name 
651*5113495bSYour Name 		wlan_tdls_notify_sta_disconnect(wlan_vdev_get_id(vdev),
652*5113495bSYour Name 						tdls_chan_switch_prohibited,
653*5113495bSYour Name 						true, vdev);
654*5113495bSYour Name 
655*5113495bSYour Name 		ucfg_tdls_set_user_tdls_enable(vdev, false);
656*5113495bSYour Name 
657*5113495bSYour Name 		if (!wlan_vdev_mlme_is_mlo_vdev(vdev)) {
658*5113495bSYour Name 			hdd_objmgr_put_vdev_by_user(vdev, WLAN_TDLS_NB_ID);
659*5113495bSYour Name 			return 0;
660*5113495bSYour Name 		}
661*5113495bSYour Name 
662*5113495bSYour Name 		hdd_objmgr_put_vdev_by_user(vdev, WLAN_TDLS_NB_ID);
663*5113495bSYour Name 	}
664*5113495bSYour Name 
665*5113495bSYour Name 	return 0;
666*5113495bSYour Name }
667*5113495bSYour Name 
668*5113495bSYour Name /**
669*5113495bSYour Name  * __wlan_hdd_cfg80211_exttdls_disable() - disable an externally controllable
670*5113495bSYour Name  *                                       TDLS peer
671*5113495bSYour Name  * @wiphy: wiphy
672*5113495bSYour Name  * @wdev: wireless dev pointer
673*5113495bSYour Name  * @data: netlink buffer with peer MAC address
674*5113495bSYour Name  * @data_len: size of data in bytes
675*5113495bSYour Name  *
676*5113495bSYour Name  * This function disables an externally controllable TDLS peer
677*5113495bSYour Name  *
678*5113495bSYour Name  * Return: 0 for success; negative errno otherwise
679*5113495bSYour Name  */
__wlan_hdd_cfg80211_exttdls_disable(struct wiphy * wiphy,struct wireless_dev * wdev,const void * data,int data_len)680*5113495bSYour Name static int __wlan_hdd_cfg80211_exttdls_disable(struct wiphy *wiphy,
681*5113495bSYour Name 				      struct wireless_dev *wdev,
682*5113495bSYour Name 				      const void *data,
683*5113495bSYour Name 				      int data_len)
684*5113495bSYour Name {
685*5113495bSYour Name 	struct net_device *dev = wdev->netdev;
686*5113495bSYour Name 	struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
687*5113495bSYour Name 	struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
688*5113495bSYour Name 	int ret = 0;
689*5113495bSYour Name 
690*5113495bSYour Name 	hdd_enter_dev(wdev->netdev);
691*5113495bSYour Name 	if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
692*5113495bSYour Name 		hdd_err("Command not allowed in FTM mode");
693*5113495bSYour Name 		return -EPERM;
694*5113495bSYour Name 	}
695*5113495bSYour Name 
696*5113495bSYour Name 	if (wlan_hdd_validate_context(hdd_ctx))
697*5113495bSYour Name 		return -EINVAL;
698*5113495bSYour Name 
699*5113495bSYour Name 	if (adapter->device_mode != QDF_STA_MODE &&
700*5113495bSYour Name 	    adapter->device_mode != QDF_P2P_CLIENT_MODE) {
701*5113495bSYour Name 		hdd_debug("Failed to get TDLS info due to opmode:%d",
702*5113495bSYour Name 			  adapter->device_mode);
703*5113495bSYour Name 		return -EOPNOTSUPP;
704*5113495bSYour Name 	}
705*5113495bSYour Name 
706*5113495bSYour Name 	ret = wlan_hdd_tdls_disable(hdd_ctx, adapter);
707*5113495bSYour Name 
708*5113495bSYour Name 	return ret;
709*5113495bSYour Name }
710*5113495bSYour Name 
711*5113495bSYour Name /**
712*5113495bSYour Name  * wlan_hdd_cfg80211_exttdls_disable() - disable ext tdls
713*5113495bSYour Name  * @wiphy:   pointer to wireless wiphy structure.
714*5113495bSYour Name  * @wdev:    pointer to wireless_dev structure.
715*5113495bSYour Name  * @data:    Pointer to the data to be passed via vendor interface
716*5113495bSYour Name  * @data_len:Length of the data to be passed
717*5113495bSYour Name  *
718*5113495bSYour Name  * Return:   Return the Success or Failure code.
719*5113495bSYour Name  */
wlan_hdd_cfg80211_exttdls_disable(struct wiphy * wiphy,struct wireless_dev * wdev,const void * data,int data_len)720*5113495bSYour Name int wlan_hdd_cfg80211_exttdls_disable(struct wiphy *wiphy,
721*5113495bSYour Name 					struct wireless_dev *wdev,
722*5113495bSYour Name 					const void *data,
723*5113495bSYour Name 					int data_len)
724*5113495bSYour Name {
725*5113495bSYour Name 	int errno;
726*5113495bSYour Name 	struct osif_vdev_sync *vdev_sync;
727*5113495bSYour Name 
728*5113495bSYour Name 	errno = osif_vdev_sync_op_start(wdev->netdev, &vdev_sync);
729*5113495bSYour Name 	if (errno)
730*5113495bSYour Name 		return errno;
731*5113495bSYour Name 
732*5113495bSYour Name 	errno = __wlan_hdd_cfg80211_exttdls_disable(wiphy, wdev,
733*5113495bSYour Name 						    data, data_len);
734*5113495bSYour Name 
735*5113495bSYour Name 	osif_vdev_sync_op_stop(vdev_sync);
736*5113495bSYour Name 
737*5113495bSYour Name 	return errno;
738*5113495bSYour Name }
739*5113495bSYour Name 
740*5113495bSYour Name #ifdef TDLS_MGMT_VERSION5
wlan_hdd_get_tdls_link_id(struct hdd_context * hdd_ctx,int id)741*5113495bSYour Name static int wlan_hdd_get_tdls_link_id(struct hdd_context *hdd_ctx, int id)
742*5113495bSYour Name {
743*5113495bSYour Name 	return id;
744*5113495bSYour Name }
745*5113495bSYour Name #else
wlan_hdd_get_tdls_link_id(struct hdd_context * hdd_ctx,int id)746*5113495bSYour Name static int wlan_hdd_get_tdls_link_id(struct hdd_context *hdd_ctx, int id)
747*5113495bSYour Name {
748*5113495bSYour Name 	int link_id;
749*5113495bSYour Name 
750*5113495bSYour Name 	link_id = cfg_tdls_get_link_id(hdd_ctx->psoc);
751*5113495bSYour Name 
752*5113495bSYour Name 	return link_id;
753*5113495bSYour Name }
754*5113495bSYour Name #endif
755*5113495bSYour Name 
756*5113495bSYour Name #ifdef TDLS_MGMT_VERSION5
757*5113495bSYour Name /**
758*5113495bSYour Name  * __wlan_hdd_cfg80211_tdls_mgmt() - handle management actions on a given peer
759*5113495bSYour Name  * @wiphy: wiphy
760*5113495bSYour Name  * @dev: net device
761*5113495bSYour Name  * @peer: MAC address of the TDLS peer
762*5113495bSYour Name  * @action_code: action code
763*5113495bSYour Name  * @dialog_token: dialog token
764*5113495bSYour Name  * @status_code: status code
765*5113495bSYour Name  * @peer_capability: peer capability
766*5113495bSYour Name  * @initiator: tdls initiator flag
767*5113495bSYour Name  * @buf: additional IE to include
768*5113495bSYour Name  * @len: length of buf in bytes
769*5113495bSYour Name  * @link_id: link id for mld device
770*5113495bSYour Name  *
771*5113495bSYour Name  * Return: 0 if success; negative errno otherwise
772*5113495bSYour Name  */
__wlan_hdd_cfg80211_tdls_mgmt(struct wiphy * wiphy,struct net_device * dev,const uint8_t * peer,uint8_t action_code,uint8_t dialog_token,uint16_t status_code,uint32_t peer_capability,bool initiator,const uint8_t * buf,size_t len,int link_id)773*5113495bSYour Name static int __wlan_hdd_cfg80211_tdls_mgmt(struct wiphy *wiphy,
774*5113495bSYour Name 				struct net_device *dev, const uint8_t *peer,
775*5113495bSYour Name 				uint8_t action_code, uint8_t dialog_token,
776*5113495bSYour Name 				uint16_t status_code, uint32_t peer_capability,
777*5113495bSYour Name 				bool initiator, const uint8_t *buf,
778*5113495bSYour Name 				size_t len, int link_id)
779*5113495bSYour Name 
780*5113495bSYour Name #elif (LINUX_VERSION_CODE >= KERNEL_VERSION(6, 5, 0))
781*5113495bSYour Name static int __wlan_hdd_cfg80211_tdls_mgmt(struct wiphy *wiphy,
782*5113495bSYour Name 				struct net_device *dev,
783*5113495bSYour Name 				const u8 *peer, int link_id,
784*5113495bSYour Name 				u8 action_code, u8 dialog_token,
785*5113495bSYour Name 				u16 status_code, u32 peer_capability,
786*5113495bSYour Name 				bool initiator, const u8 *buf,
787*5113495bSYour Name 				size_t len)
788*5113495bSYour Name 
789*5113495bSYour Name #elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 17, 0))
790*5113495bSYour Name static int __wlan_hdd_cfg80211_tdls_mgmt(struct wiphy *wiphy,
791*5113495bSYour Name 				struct net_device *dev, const uint8_t *peer,
792*5113495bSYour Name 				uint8_t action_code, uint8_t dialog_token,
793*5113495bSYour Name 				uint16_t status_code, uint32_t peer_capability,
794*5113495bSYour Name 				bool initiator, const uint8_t *buf,
795*5113495bSYour Name 				size_t len)
796*5113495bSYour Name #elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
797*5113495bSYour Name static int __wlan_hdd_cfg80211_tdls_mgmt(struct wiphy *wiphy,
798*5113495bSYour Name 				struct net_device *dev, const uint8_t *peer,
799*5113495bSYour Name 				uint8_t action_code, uint8_t dialog_token,
800*5113495bSYour Name 				uint16_t status_code, uint32_t peer_capability,
801*5113495bSYour Name 				const uint8_t *buf, size_t len)
802*5113495bSYour Name #elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0)) || defined(TDLS_MGMT_VERSION2)
803*5113495bSYour Name static int __wlan_hdd_cfg80211_tdls_mgmt(struct wiphy *wiphy,
804*5113495bSYour Name 				struct net_device *dev, uint8_t *peer,
805*5113495bSYour Name 				uint8_t action_code, uint8_t dialog_token,
806*5113495bSYour Name 				uint16_t status_code, uint32_t peer_capability,
807*5113495bSYour Name 				const uint8_t *buf, size_t len)
808*5113495bSYour Name #else
809*5113495bSYour Name static int __wlan_hdd_cfg80211_tdls_mgmt(struct wiphy *wiphy,
810*5113495bSYour Name 				struct net_device *dev, uint8_t *peer,
811*5113495bSYour Name 				uint8_t action_code, uint8_t dialog_token,
812*5113495bSYour Name 				uint16_t status_code, const uint8_t *buf,
813*5113495bSYour Name 				size_t len)
814*5113495bSYour Name #endif
815*5113495bSYour Name {
816*5113495bSYour Name 	struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
817*5113495bSYour Name 	struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
818*5113495bSYour Name 	bool tdls_support;
819*5113495bSYour Name #if !defined(TDLS_MGMT_VERSION5) && \
820*5113495bSYour Name 	(LINUX_VERSION_CODE < KERNEL_VERSION(6, 5, 0))
821*5113495bSYour Name 	int link_id = -1;
822*5113495bSYour Name #endif
823*5113495bSYour Name #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 15, 0))
824*5113495bSYour Name #if !(TDLS_MGMT_VERSION2)
825*5113495bSYour Name 	u32 peer_capability;
826*5113495bSYour Name 
827*5113495bSYour Name 	peer_capability = 0;
828*5113495bSYour Name #endif
829*5113495bSYour Name #endif
830*5113495bSYour Name 
831*5113495bSYour Name 	if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
832*5113495bSYour Name 		hdd_err("Command not allowed in FTM mode");
833*5113495bSYour Name 		return -EINVAL;
834*5113495bSYour Name 	}
835*5113495bSYour Name 
836*5113495bSYour Name 	if (wlan_hdd_validate_vdev_id(adapter->deflink->vdev_id))
837*5113495bSYour Name 		return -EINVAL;
838*5113495bSYour Name 
839*5113495bSYour Name 	qdf_mtrace(QDF_MODULE_ID_HDD, QDF_MODULE_ID_HDD,
840*5113495bSYour Name 		   TRACE_CODE_HDD_CFG80211_TDLS_MGMT,
841*5113495bSYour Name 		   adapter->deflink->vdev_id, action_code);
842*5113495bSYour Name 
843*5113495bSYour Name 	if (wlan_hdd_validate_context(hdd_ctx))
844*5113495bSYour Name 		return -EINVAL;
845*5113495bSYour Name 
846*5113495bSYour Name 	cfg_tdls_get_support_enable(hdd_ctx->psoc, &tdls_support);
847*5113495bSYour Name 	if (!tdls_support) {
848*5113495bSYour Name 		hdd_debug("TDLS Disabled in INI OR not enabled in FW. "
849*5113495bSYour Name 			"Cannot process TDLS commands");
850*5113495bSYour Name 		return -ENOTSUPP;
851*5113495bSYour Name 	}
852*5113495bSYour Name 
853*5113495bSYour Name 	if (hdd_ctx->tdls_umac_comp_active) {
854*5113495bSYour Name 		int ret;
855*5113495bSYour Name 
856*5113495bSYour Name 		link_id = wlan_hdd_get_tdls_link_id(hdd_ctx, link_id);
857*5113495bSYour Name 		ret = wlan_cfg80211_tdls_mgmt_mlo(adapter, peer,
858*5113495bSYour Name 						  action_code, dialog_token,
859*5113495bSYour Name 						  status_code, peer_capability,
860*5113495bSYour Name 						  buf, len, link_id);
861*5113495bSYour Name 		return ret;
862*5113495bSYour Name 	}
863*5113495bSYour Name 
864*5113495bSYour Name 	return -EINVAL;
865*5113495bSYour Name }
866*5113495bSYour Name 
867*5113495bSYour Name #ifdef TDLS_MGMT_VERSION5
868*5113495bSYour Name /**
869*5113495bSYour Name  * wlan_hdd_cfg80211_tdls_mgmt() - cfg80211 tdls mgmt handler function
870*5113495bSYour Name  * @wiphy: Pointer to wiphy structure.
871*5113495bSYour Name  * @dev: Pointer to net_device structure.
872*5113495bSYour Name  * @peer: peer address
873*5113495bSYour Name  * @action_code: action code
874*5113495bSYour Name  * @dialog_token: dialog token
875*5113495bSYour Name  * @status_code: status code
876*5113495bSYour Name  * @peer_capability: peer capability
877*5113495bSYour Name  * @initiator: tdls initiator flag
878*5113495bSYour Name  * @buf: buffer
879*5113495bSYour Name  * @len: Length of @buf
880*5113495bSYour Name  * @link_id: link id for mld device
881*5113495bSYour Name  *
882*5113495bSYour Name  * This is the cfg80211 tdls mgmt handler function which invokes
883*5113495bSYour Name  * the internal function @__wlan_hdd_cfg80211_tdls_mgmt with
884*5113495bSYour Name  * SSR protection.
885*5113495bSYour Name  *
886*5113495bSYour Name  * Return: 0 for success, error number on failure.
887*5113495bSYour Name  */
wlan_hdd_cfg80211_tdls_mgmt(struct wiphy * wiphy,struct net_device * dev,const u8 * peer,u8 action_code,u8 dialog_token,u16 status_code,u32 peer_capability,bool initiator,const u8 * buf,size_t len,int link_id)888*5113495bSYour Name int wlan_hdd_cfg80211_tdls_mgmt(struct wiphy *wiphy,
889*5113495bSYour Name 					struct net_device *dev,
890*5113495bSYour Name 					const u8 *peer, u8 action_code,
891*5113495bSYour Name 					u8 dialog_token, u16 status_code,
892*5113495bSYour Name 					u32 peer_capability, bool initiator,
893*5113495bSYour Name 					const u8 *buf, size_t len, int link_id)
894*5113495bSYour Name 
895*5113495bSYour Name #elif (LINUX_VERSION_CODE >= KERNEL_VERSION(6, 5, 0))
896*5113495bSYour Name int wlan_hdd_cfg80211_tdls_mgmt(struct wiphy *wiphy,
897*5113495bSYour Name 					struct net_device *dev,
898*5113495bSYour Name 					const u8 *peer, int link_id,
899*5113495bSYour Name 					u8 action_code, u8 dialog_token,
900*5113495bSYour Name 					u16 status_code, u32 peer_capability,
901*5113495bSYour Name 					bool initiator, const u8 *buf,
902*5113495bSYour Name 					size_t len)
903*5113495bSYour Name 
904*5113495bSYour Name #elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 17, 0)) || defined(WITH_BACKPORTS)
905*5113495bSYour Name int wlan_hdd_cfg80211_tdls_mgmt(struct wiphy *wiphy,
906*5113495bSYour Name 					struct net_device *dev,
907*5113495bSYour Name 					const u8 *peer, u8 action_code,
908*5113495bSYour Name 					u8 dialog_token, u16 status_code,
909*5113495bSYour Name 					u32 peer_capability, bool initiator,
910*5113495bSYour Name 					const u8 *buf, size_t len)
911*5113495bSYour Name #elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
912*5113495bSYour Name int wlan_hdd_cfg80211_tdls_mgmt(struct wiphy *wiphy,
913*5113495bSYour Name 					struct net_device *dev,
914*5113495bSYour Name 					const u8 *peer, u8 action_code,
915*5113495bSYour Name 					u8 dialog_token, u16 status_code,
916*5113495bSYour Name 					u32 peer_capability, const u8 *buf,
917*5113495bSYour Name 					size_t len)
918*5113495bSYour Name #elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0)) || defined(TDLS_MGMT_VERSION2)
919*5113495bSYour Name int wlan_hdd_cfg80211_tdls_mgmt(struct wiphy *wiphy,
920*5113495bSYour Name 					struct net_device *dev,
921*5113495bSYour Name 					u8 *peer, u8 action_code,
922*5113495bSYour Name 					u8 dialog_token,
923*5113495bSYour Name 					u16 status_code, u32 peer_capability,
924*5113495bSYour Name 					const u8 *buf, size_t len)
925*5113495bSYour Name #else
926*5113495bSYour Name int wlan_hdd_cfg80211_tdls_mgmt(struct wiphy *wiphy,
927*5113495bSYour Name 					struct net_device *dev,
928*5113495bSYour Name 					u8 *peer, u8 action_code,
929*5113495bSYour Name 					u8 dialog_token,
930*5113495bSYour Name 					u16 status_code, const u8 *buf,
931*5113495bSYour Name 					size_t len)
932*5113495bSYour Name #endif
933*5113495bSYour Name {
934*5113495bSYour Name 	int errno;
935*5113495bSYour Name 	struct osif_vdev_sync *vdev_sync;
936*5113495bSYour Name 
937*5113495bSYour Name 	errno = osif_vdev_sync_op_start(dev, &vdev_sync);
938*5113495bSYour Name 	if (errno)
939*5113495bSYour Name 		return errno;
940*5113495bSYour Name 
941*5113495bSYour Name #ifdef TDLS_MGMT_VERSION5
942*5113495bSYour Name 	errno = __wlan_hdd_cfg80211_tdls_mgmt(wiphy, dev, peer, action_code,
943*5113495bSYour Name 					      dialog_token, status_code,
944*5113495bSYour Name 					      peer_capability, initiator,
945*5113495bSYour Name 					      buf, len, link_id);
946*5113495bSYour Name #elif (LINUX_VERSION_CODE >= KERNEL_VERSION(6, 5, 0))
947*5113495bSYour Name 	errno = __wlan_hdd_cfg80211_tdls_mgmt(wiphy, dev, peer, link_id,
948*5113495bSYour Name 					      action_code, dialog_token,
949*5113495bSYour Name 					      status_code, peer_capability,
950*5113495bSYour Name 					      initiator, buf, len);
951*5113495bSYour Name #elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 17, 0)) || defined(WITH_BACKPORTS)
952*5113495bSYour Name 	errno = __wlan_hdd_cfg80211_tdls_mgmt(wiphy, dev, peer, action_code,
953*5113495bSYour Name 					      dialog_token, status_code,
954*5113495bSYour Name 					      peer_capability, initiator,
955*5113495bSYour Name 					      buf, len);
956*5113495bSYour Name #elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
957*5113495bSYour Name 	errno = __wlan_hdd_cfg80211_tdls_mgmt(wiphy, dev, peer, action_code,
958*5113495bSYour Name 					      dialog_token, status_code,
959*5113495bSYour Name 					      peer_capability, buf, len);
960*5113495bSYour Name #elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0)) || defined(TDLS_MGMT_VERSION2)
961*5113495bSYour Name 	errno = __wlan_hdd_cfg80211_tdls_mgmt(wiphy, dev, peer, action_code,
962*5113495bSYour Name 					      dialog_token, status_code,
963*5113495bSYour Name 					      peer_capability, buf, len);
964*5113495bSYour Name #else
965*5113495bSYour Name 	errno = __wlan_hdd_cfg80211_tdls_mgmt(wiphy, dev, peer, action_code,
966*5113495bSYour Name 					      dialog_token, status_code,
967*5113495bSYour Name 					      buf, len);
968*5113495bSYour Name #endif
969*5113495bSYour Name 
970*5113495bSYour Name 	osif_vdev_sync_op_stop(vdev_sync);
971*5113495bSYour Name 
972*5113495bSYour Name 	return errno;
973*5113495bSYour Name }
974*5113495bSYour Name 
975*5113495bSYour Name static bool
hdd_is_sta_legacy(struct wlan_hdd_link_info * link_info)976*5113495bSYour Name hdd_is_sta_legacy(struct wlan_hdd_link_info *link_info)
977*5113495bSYour Name {
978*5113495bSYour Name 	struct hdd_station_ctx *sta_ctx;
979*5113495bSYour Name 
980*5113495bSYour Name 	sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(link_info);
981*5113495bSYour Name 	if (!sta_ctx)
982*5113495bSYour Name 		return false;
983*5113495bSYour Name 
984*5113495bSYour Name 	if ((sta_ctx->conn_info.dot11mode == eCSR_CFG_DOT11_MODE_AUTO) ||
985*5113495bSYour Name 	    (sta_ctx->conn_info.dot11mode == eCSR_CFG_DOT11_MODE_11N) ||
986*5113495bSYour Name 	    (sta_ctx->conn_info.dot11mode == eCSR_CFG_DOT11_MODE_11AC) ||
987*5113495bSYour Name 	    (sta_ctx->conn_info.dot11mode == eCSR_CFG_DOT11_MODE_11N_ONLY) ||
988*5113495bSYour Name 	    (sta_ctx->conn_info.dot11mode == eCSR_CFG_DOT11_MODE_11AC_ONLY) ||
989*5113495bSYour Name 	    (sta_ctx->conn_info.dot11mode == eCSR_CFG_DOT11_MODE_11AX) ||
990*5113495bSYour Name 	    (sta_ctx->conn_info.dot11mode == eCSR_CFG_DOT11_MODE_11AX_ONLY))
991*5113495bSYour Name 		return false;
992*5113495bSYour Name 
993*5113495bSYour Name 	return true;
994*5113495bSYour Name }
995*5113495bSYour Name 
996*5113495bSYour Name uint16_t
hdd_get_tdls_connected_peer_count(struct wlan_hdd_link_info * link_info)997*5113495bSYour Name hdd_get_tdls_connected_peer_count(struct wlan_hdd_link_info *link_info)
998*5113495bSYour Name {
999*5113495bSYour Name 	struct wlan_objmgr_vdev *vdev;
1000*5113495bSYour Name 	uint16_t peer_count;
1001*5113495bSYour Name 
1002*5113495bSYour Name 	vdev = hdd_objmgr_get_vdev_by_user(link_info, WLAN_OSIF_TDLS_ID);
1003*5113495bSYour Name 	if (!vdev) {
1004*5113495bSYour Name 		hdd_err("Invalid vdev");
1005*5113495bSYour Name 		return -EINVAL;
1006*5113495bSYour Name 	}
1007*5113495bSYour Name 
1008*5113495bSYour Name 	peer_count = ucfg_get_tdls_conn_peer_count(vdev);
1009*5113495bSYour Name 	wlan_objmgr_vdev_release_ref(vdev, WLAN_OSIF_TDLS_ID);
1010*5113495bSYour Name 
1011*5113495bSYour Name 	return peer_count;
1012*5113495bSYour Name }
1013*5113495bSYour Name 
1014*5113495bSYour Name void
hdd_check_and_set_tdls_conn_params(struct wlan_objmgr_vdev * vdev)1015*5113495bSYour Name hdd_check_and_set_tdls_conn_params(struct wlan_objmgr_vdev *vdev)
1016*5113495bSYour Name {
1017*5113495bSYour Name 	uint8_t vdev_id;
1018*5113495bSYour Name 	enum hdd_dot11_mode selfdot11mode;
1019*5113495bSYour Name 	struct wlan_hdd_link_info *link_info;
1020*5113495bSYour Name 	struct wlan_objmgr_psoc *psoc;
1021*5113495bSYour Name 	struct hdd_context *hdd_ctx;
1022*5113495bSYour Name 
1023*5113495bSYour Name 	psoc = wlan_vdev_get_psoc(vdev);
1024*5113495bSYour Name 	if (!psoc)
1025*5113495bSYour Name 		return;
1026*5113495bSYour Name 
1027*5113495bSYour Name 	/*
1028*5113495bSYour Name 	 * Only need to set this if STA link is in legacy mode
1029*5113495bSYour Name 	 */
1030*5113495bSYour Name 	vdev_id = wlan_vdev_get_id(vdev);
1031*5113495bSYour Name 	link_info = wlan_hdd_get_link_info_from_vdev(psoc, vdev_id);
1032*5113495bSYour Name 	if (!link_info || !hdd_is_sta_legacy(link_info))
1033*5113495bSYour Name 		return;
1034*5113495bSYour Name 
1035*5113495bSYour Name 	hdd_ctx = WLAN_HDD_GET_CTX(link_info->adapter);
1036*5113495bSYour Name 	if (!hdd_ctx)
1037*5113495bSYour Name 		return;
1038*5113495bSYour Name 
1039*5113495bSYour Name 	selfdot11mode = hdd_ctx->config->dot11Mode;
1040*5113495bSYour Name 	/*
1041*5113495bSYour Name 	 * When STA connection is made in legacy mode (11a, 11b and 11g) and
1042*5113495bSYour Name 	 * selfdot11Mode is either 11ax, 11ac or 11n, TDLS connection can be
1043*5113495bSYour Name 	 * made upto supporting selfdot11mode. Since, TDLS shares same netdev
1044*5113495bSYour Name 	 * that of STA, checksum/TSO will be disabled during STA connection.
1045*5113495bSYour Name 	 * For better TDLS throughput, enable checksum/TSO which were already
1046*5113495bSYour Name 	 * disabled during STA connection.
1047*5113495bSYour Name 	 */
1048*5113495bSYour Name 	if (selfdot11mode == eHDD_DOT11_MODE_AUTO ||
1049*5113495bSYour Name 	    selfdot11mode == eHDD_DOT11_MODE_11ax ||
1050*5113495bSYour Name 	    selfdot11mode == eHDD_DOT11_MODE_11ax_ONLY ||
1051*5113495bSYour Name 	    selfdot11mode == eHDD_DOT11_MODE_11ac_ONLY ||
1052*5113495bSYour Name 	    selfdot11mode == eHDD_DOT11_MODE_11ac ||
1053*5113495bSYour Name 	    selfdot11mode == eHDD_DOT11_MODE_11n ||
1054*5113495bSYour Name 	    selfdot11mode == eHDD_DOT11_MODE_11n_ONLY)
1055*5113495bSYour Name 		hdd_cm_netif_queue_enable(link_info->adapter);
1056*5113495bSYour Name }
1057*5113495bSYour Name 
1058*5113495bSYour Name void
hdd_check_and_set_tdls_disconn_params(struct wlan_objmgr_vdev * vdev)1059*5113495bSYour Name hdd_check_and_set_tdls_disconn_params(struct wlan_objmgr_vdev *vdev)
1060*5113495bSYour Name {
1061*5113495bSYour Name 	uint8_t vdev_id;
1062*5113495bSYour Name 	struct wlan_objmgr_psoc *psoc;
1063*5113495bSYour Name 	struct wlan_hdd_link_info *link_info;
1064*5113495bSYour Name 
1065*5113495bSYour Name 	psoc = wlan_vdev_get_psoc(vdev);
1066*5113495bSYour Name 	if (!psoc)
1067*5113495bSYour Name 		return;
1068*5113495bSYour Name 
1069*5113495bSYour Name 	/*
1070*5113495bSYour Name 	 * Only need to set this if STA link is in legacy mode
1071*5113495bSYour Name 	 */
1072*5113495bSYour Name 	vdev_id = wlan_vdev_get_id(vdev);
1073*5113495bSYour Name 	link_info = wlan_hdd_get_link_info_from_vdev(psoc, vdev_id);
1074*5113495bSYour Name 	if (!link_info || !hdd_is_sta_legacy(link_info))
1075*5113495bSYour Name 		return;
1076*5113495bSYour Name 
1077*5113495bSYour Name 	hdd_cm_netif_queue_enable(link_info->adapter);
1078*5113495bSYour Name }
1079*5113495bSYour Name 
1080*5113495bSYour Name /**
1081*5113495bSYour Name  * __wlan_hdd_cfg80211_tdls_oper() - helper function to handle cfg80211 operation
1082*5113495bSYour Name  *                                   on an TDLS peer
1083*5113495bSYour Name  * @wiphy: wiphy
1084*5113495bSYour Name  * @dev: net device
1085*5113495bSYour Name  * @peer: MAC address of the TDLS peer
1086*5113495bSYour Name  * @oper: cfg80211 TDLS operation
1087*5113495bSYour Name  *
1088*5113495bSYour Name  * Return: 0 on success; negative errno otherwise
1089*5113495bSYour Name  */
__wlan_hdd_cfg80211_tdls_oper(struct wiphy * wiphy,struct net_device * dev,const uint8_t * peer,enum nl80211_tdls_operation oper)1090*5113495bSYour Name static int __wlan_hdd_cfg80211_tdls_oper(struct wiphy *wiphy,
1091*5113495bSYour Name 					 struct net_device *dev,
1092*5113495bSYour Name 					 const uint8_t *peer,
1093*5113495bSYour Name 					 enum nl80211_tdls_operation oper)
1094*5113495bSYour Name {
1095*5113495bSYour Name 	struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
1096*5113495bSYour Name 	struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
1097*5113495bSYour Name 	int status;
1098*5113495bSYour Name 	bool tdls_support;
1099*5113495bSYour Name 	struct wlan_objmgr_vdev *vdev;
1100*5113495bSYour Name 
1101*5113495bSYour Name 	hdd_enter();
1102*5113495bSYour Name 
1103*5113495bSYour Name 	if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
1104*5113495bSYour Name 		hdd_err("Command not allowed in FTM mode");
1105*5113495bSYour Name 		return -EINVAL;
1106*5113495bSYour Name 	}
1107*5113495bSYour Name 
1108*5113495bSYour Name 	if (wlan_hdd_validate_vdev_id(adapter->deflink->vdev_id))
1109*5113495bSYour Name 		return -EINVAL;
1110*5113495bSYour Name 
1111*5113495bSYour Name 	cfg_tdls_get_support_enable(hdd_ctx->psoc, &tdls_support);
1112*5113495bSYour Name 	if (!tdls_support) {
1113*5113495bSYour Name 		hdd_debug("TDLS Disabled in INI OR not enabled in FW. "
1114*5113495bSYour Name 			"Cannot process TDLS commands");
1115*5113495bSYour Name 		return -ENOTSUPP;
1116*5113495bSYour Name 	}
1117*5113495bSYour Name 
1118*5113495bSYour Name 	qdf_mtrace(QDF_MODULE_ID_HDD, QDF_MODULE_ID_HDD,
1119*5113495bSYour Name 		   TRACE_CODE_HDD_CFG80211_TDLS_OPER,
1120*5113495bSYour Name 		   adapter->deflink->vdev_id, oper);
1121*5113495bSYour Name 
1122*5113495bSYour Name 	if (!peer) {
1123*5113495bSYour Name 		hdd_err("Invalid arguments");
1124*5113495bSYour Name 		return -EINVAL;
1125*5113495bSYour Name 	}
1126*5113495bSYour Name 
1127*5113495bSYour Name 	status = wlan_hdd_validate_context(hdd_ctx);
1128*5113495bSYour Name 
1129*5113495bSYour Name 	if (0 != status)
1130*5113495bSYour Name 		return status;
1131*5113495bSYour Name 
1132*5113495bSYour Name 	if (!hdd_ctx->tdls_umac_comp_active) {
1133*5113495bSYour Name 		status = -EINVAL;
1134*5113495bSYour Name 		goto exit;
1135*5113495bSYour Name 	}
1136*5113495bSYour Name 
1137*5113495bSYour Name 	vdev = hdd_objmgr_get_vdev_by_user(adapter->deflink, WLAN_OSIF_TDLS_ID);
1138*5113495bSYour Name 	if (!vdev)
1139*5113495bSYour Name 		return -EINVAL;
1140*5113495bSYour Name 	status = wlan_cfg80211_tdls_oper(vdev, peer, oper);
1141*5113495bSYour Name 	hdd_objmgr_put_vdev_by_user(vdev, WLAN_OSIF_TDLS_ID);
1142*5113495bSYour Name 
1143*5113495bSYour Name exit:
1144*5113495bSYour Name 	hdd_exit();
1145*5113495bSYour Name 	return status;
1146*5113495bSYour Name }
1147*5113495bSYour Name 
1148*5113495bSYour Name /**
1149*5113495bSYour Name  * wlan_hdd_cfg80211_tdls_oper() - handle cfg80211 operation on an TDLS peer
1150*5113495bSYour Name  * @wiphy: wiphy
1151*5113495bSYour Name  * @dev: net device
1152*5113495bSYour Name  * @peer: MAC address of the TDLS peer
1153*5113495bSYour Name  * @oper: cfg80211 TDLS operation
1154*5113495bSYour Name  *
1155*5113495bSYour Name  * Return: 0 on success; negative errno otherwise
1156*5113495bSYour Name  */
1157*5113495bSYour Name #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
wlan_hdd_cfg80211_tdls_oper(struct wiphy * wiphy,struct net_device * dev,const uint8_t * peer,enum nl80211_tdls_operation oper)1158*5113495bSYour Name int wlan_hdd_cfg80211_tdls_oper(struct wiphy *wiphy,
1159*5113495bSYour Name 				struct net_device *dev,
1160*5113495bSYour Name 				const uint8_t *peer,
1161*5113495bSYour Name 				enum nl80211_tdls_operation oper)
1162*5113495bSYour Name #else
1163*5113495bSYour Name int wlan_hdd_cfg80211_tdls_oper(struct wiphy *wiphy,
1164*5113495bSYour Name 				struct net_device *dev,
1165*5113495bSYour Name 				uint8_t *peer,
1166*5113495bSYour Name 				enum nl80211_tdls_operation oper)
1167*5113495bSYour Name #endif
1168*5113495bSYour Name {
1169*5113495bSYour Name 	int errno;
1170*5113495bSYour Name 	struct osif_vdev_sync *vdev_sync;
1171*5113495bSYour Name 
1172*5113495bSYour Name 	errno = osif_vdev_sync_op_start(dev, &vdev_sync);
1173*5113495bSYour Name 	if (errno)
1174*5113495bSYour Name 		return errno;
1175*5113495bSYour Name 
1176*5113495bSYour Name 	errno = __wlan_hdd_cfg80211_tdls_oper(wiphy, dev, peer, oper);
1177*5113495bSYour Name 
1178*5113495bSYour Name 	osif_vdev_sync_op_stop(vdev_sync);
1179*5113495bSYour Name 
1180*5113495bSYour Name 	return errno;
1181*5113495bSYour Name }
1182*5113495bSYour Name 
hdd_set_tdls_offchannel(struct hdd_context * hdd_ctx,struct hdd_adapter * adapter,int offchannel)1183*5113495bSYour Name int hdd_set_tdls_offchannel(struct hdd_context *hdd_ctx,
1184*5113495bSYour Name 			    struct hdd_adapter *adapter,
1185*5113495bSYour Name 			    int offchannel)
1186*5113495bSYour Name {
1187*5113495bSYour Name 	struct wlan_objmgr_vdev *vdev;
1188*5113495bSYour Name 	QDF_STATUS status = QDF_STATUS_E_FAILURE;
1189*5113495bSYour Name 
1190*5113495bSYour Name 	if (!hdd_ctx->tdls_umac_comp_active)
1191*5113495bSYour Name 		return qdf_status_to_os_return(status);
1192*5113495bSYour Name 
1193*5113495bSYour Name 	vdev = hdd_objmgr_get_vdev_by_user(adapter->deflink, WLAN_OSIF_TDLS_ID);
1194*5113495bSYour Name 	if (vdev) {
1195*5113495bSYour Name 		status = ucfg_set_tdls_offchannel(vdev, offchannel);
1196*5113495bSYour Name 		hdd_objmgr_put_vdev_by_user(vdev, WLAN_OSIF_TDLS_ID);
1197*5113495bSYour Name 	}
1198*5113495bSYour Name 	return qdf_status_to_os_return(status);
1199*5113495bSYour Name }
1200*5113495bSYour Name 
hdd_set_tdls_secoffchanneloffset(struct hdd_context * hdd_ctx,struct hdd_adapter * adapter,int offchanoffset)1201*5113495bSYour Name int hdd_set_tdls_secoffchanneloffset(struct hdd_context *hdd_ctx,
1202*5113495bSYour Name 				     struct hdd_adapter *adapter,
1203*5113495bSYour Name 				     int offchanoffset)
1204*5113495bSYour Name {
1205*5113495bSYour Name 	struct wlan_objmgr_vdev *vdev;
1206*5113495bSYour Name 	QDF_STATUS status = QDF_STATUS_E_FAILURE;
1207*5113495bSYour Name 
1208*5113495bSYour Name 	if (!hdd_ctx->tdls_umac_comp_active)
1209*5113495bSYour Name 		return qdf_status_to_os_return(status);
1210*5113495bSYour Name 
1211*5113495bSYour Name 	vdev = hdd_objmgr_get_vdev_by_user(adapter->deflink, WLAN_OSIF_TDLS_ID);
1212*5113495bSYour Name 	if (vdev) {
1213*5113495bSYour Name 		status = ucfg_set_tdls_secoffchanneloffset(vdev, offchanoffset);
1214*5113495bSYour Name 		hdd_objmgr_put_vdev_by_user(vdev, WLAN_OSIF_TDLS_ID);
1215*5113495bSYour Name 	}
1216*5113495bSYour Name 	return qdf_status_to_os_return(status);
1217*5113495bSYour Name }
1218*5113495bSYour Name 
hdd_set_tdls_offchannelmode(struct hdd_context * hdd_ctx,struct hdd_adapter * adapter,int offchanmode)1219*5113495bSYour Name int hdd_set_tdls_offchannelmode(struct hdd_context *hdd_ctx,
1220*5113495bSYour Name 				struct hdd_adapter *adapter,
1221*5113495bSYour Name 				int offchanmode)
1222*5113495bSYour Name {
1223*5113495bSYour Name 	struct wlan_objmgr_vdev *vdev;
1224*5113495bSYour Name 	QDF_STATUS status = QDF_STATUS_E_FAILURE;
1225*5113495bSYour Name 	bool tdls_off_ch;
1226*5113495bSYour Name 
1227*5113495bSYour Name 	if (cfg_tdls_get_off_channel_enable(
1228*5113495bSYour Name 		hdd_ctx->psoc, &tdls_off_ch) !=
1229*5113495bSYour Name 	    QDF_STATUS_SUCCESS) {
1230*5113495bSYour Name 		hdd_err("cfg get tdls off ch failed");
1231*5113495bSYour Name 		return qdf_status_to_os_return(status);
1232*5113495bSYour Name 	}
1233*5113495bSYour Name 	if (!tdls_off_ch) {
1234*5113495bSYour Name 		hdd_debug("tdls off ch is false, do nothing");
1235*5113495bSYour Name 		return qdf_status_to_os_return(status);
1236*5113495bSYour Name 	}
1237*5113495bSYour Name 
1238*5113495bSYour Name 	if (!hdd_ctx->tdls_umac_comp_active)
1239*5113495bSYour Name 		return qdf_status_to_os_return(status);
1240*5113495bSYour Name 
1241*5113495bSYour Name 	vdev = hdd_objmgr_get_vdev_by_user(adapter->deflink, WLAN_OSIF_TDLS_ID);
1242*5113495bSYour Name 	if (vdev) {
1243*5113495bSYour Name 		status = ucfg_set_tdls_offchan_mode(vdev, offchanmode);
1244*5113495bSYour Name 		hdd_objmgr_put_vdev_by_user(vdev, WLAN_OSIF_TDLS_ID);
1245*5113495bSYour Name 	}
1246*5113495bSYour Name 	return qdf_status_to_os_return(status);
1247*5113495bSYour Name }
1248*5113495bSYour Name 
1249*5113495bSYour Name /**
1250*5113495bSYour Name  * hdd_set_tdls_scan_type - set scan during active tdls session
1251*5113495bSYour Name  * @hdd_ctx: ptr to hdd context.
1252*5113495bSYour Name  * @val: scan type value: 0 or 1.
1253*5113495bSYour Name  *
1254*5113495bSYour Name  * Set scan type during tdls session. If set to 1, that means driver
1255*5113495bSYour Name  * shall maintain tdls link and allow scan regardless if tdls peer is
1256*5113495bSYour Name  * buffer sta capable or not and/or if device is sleep sta capable or
1257*5113495bSYour Name  * not. If tdls peer is not buffer sta capable then during scan there
1258*5113495bSYour Name  * will be loss of Rx packets and Tx would stop when device moves away
1259*5113495bSYour Name  * from tdls channel. If set to 0, then driver shall teardown tdls link
1260*5113495bSYour Name  * before initiating scan if peer is not buffer sta capable and device
1261*5113495bSYour Name  * is not sleep sta capable. By default, scan type is set to 0.
1262*5113495bSYour Name  *
1263*5113495bSYour Name  * Return: success (0) or failure (errno value)
1264*5113495bSYour Name  */
hdd_set_tdls_scan_type(struct hdd_context * hdd_ctx,int val)1265*5113495bSYour Name int hdd_set_tdls_scan_type(struct hdd_context *hdd_ctx, int val)
1266*5113495bSYour Name {
1267*5113495bSYour Name 	if ((val != 0) && (val != 1)) {
1268*5113495bSYour Name 		hdd_err("Incorrect value of tdls scan type: %d", val);
1269*5113495bSYour Name 		return -EINVAL;
1270*5113495bSYour Name 	}
1271*5113495bSYour Name 
1272*5113495bSYour Name 	cfg_tdls_set_scan_enable(hdd_ctx->psoc, (bool)val);
1273*5113495bSYour Name 
1274*5113495bSYour Name 	return 0;
1275*5113495bSYour Name }
1276*5113495bSYour Name 
wlan_hdd_tdls_antenna_switch(struct wlan_hdd_link_info * link_info,uint32_t mode)1277*5113495bSYour Name int wlan_hdd_tdls_antenna_switch(struct wlan_hdd_link_info *link_info,
1278*5113495bSYour Name 				 uint32_t mode)
1279*5113495bSYour Name {
1280*5113495bSYour Name 	int ret;
1281*5113495bSYour Name 	struct wlan_objmgr_vdev *vdev;
1282*5113495bSYour Name 
1283*5113495bSYour Name 	if (!link_info->adapter->hdd_ctx->tdls_umac_comp_active)
1284*5113495bSYour Name 		return 0;
1285*5113495bSYour Name 
1286*5113495bSYour Name 	vdev = hdd_objmgr_get_vdev_by_user(link_info, WLAN_OSIF_TDLS_ID);
1287*5113495bSYour Name 	if (!vdev)
1288*5113495bSYour Name 		return -EINVAL;
1289*5113495bSYour Name 
1290*5113495bSYour Name 	ret = wlan_tdls_antenna_switch(vdev, mode);
1291*5113495bSYour Name 	hdd_objmgr_put_vdev_by_user(vdev, WLAN_OSIF_TDLS_ID);
1292*5113495bSYour Name 	return ret;
1293*5113495bSYour Name }
1294*5113495bSYour Name 
hdd_tdls_register_peer(void * userdata,uint32_t vdev_id,const uint8_t * mac,uint8_t qos)1295*5113495bSYour Name QDF_STATUS hdd_tdls_register_peer(void *userdata, uint32_t vdev_id,
1296*5113495bSYour Name 				  const uint8_t *mac, uint8_t qos)
1297*5113495bSYour Name {
1298*5113495bSYour Name 	struct hdd_context *hddctx;
1299*5113495bSYour Name 	struct wlan_hdd_link_info *link_info;
1300*5113495bSYour Name 
1301*5113495bSYour Name 	hddctx = userdata;
1302*5113495bSYour Name 	if (!hddctx) {
1303*5113495bSYour Name 		hdd_err("Invalid hddctx");
1304*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
1305*5113495bSYour Name 	}
1306*5113495bSYour Name 
1307*5113495bSYour Name 	link_info = hdd_get_link_info_by_vdev(hddctx, vdev_id);
1308*5113495bSYour Name 	if (!link_info) {
1309*5113495bSYour Name 		hdd_err("Invalid vdev");
1310*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
1311*5113495bSYour Name 	}
1312*5113495bSYour Name 
1313*5113495bSYour Name 	return hdd_roam_register_tdlssta(link_info->adapter, mac, qos);
1314*5113495bSYour Name }
1315*5113495bSYour Name 
hdd_init_tdls_config(struct tdls_start_params * tdls_cfg)1316*5113495bSYour Name void hdd_init_tdls_config(struct tdls_start_params *tdls_cfg)
1317*5113495bSYour Name {
1318*5113495bSYour Name 	tdls_cfg->tdls_send_mgmt_req = eWNI_SME_TDLS_SEND_MGMT_REQ;
1319*5113495bSYour Name 	tdls_cfg->tdls_add_sta_req = eWNI_SME_TDLS_ADD_STA_REQ;
1320*5113495bSYour Name 	tdls_cfg->tdls_del_sta_req = eWNI_SME_TDLS_DEL_STA_REQ;
1321*5113495bSYour Name 	tdls_cfg->tdls_update_peer_state = WMA_UPDATE_TDLS_PEER_STATE;
1322*5113495bSYour Name }
1323*5113495bSYour Name 
hdd_config_tdls_with_band_switch(struct hdd_context * hdd_ctx)1324*5113495bSYour Name void hdd_config_tdls_with_band_switch(struct hdd_context *hdd_ctx)
1325*5113495bSYour Name {
1326*5113495bSYour Name 	struct wlan_objmgr_vdev *tdls_obj_vdev;
1327*5113495bSYour Name 	int offchmode;
1328*5113495bSYour Name 	uint32_t current_band;
1329*5113495bSYour Name 	bool tdls_off_ch;
1330*5113495bSYour Name 
1331*5113495bSYour Name 	if (!hdd_ctx) {
1332*5113495bSYour Name 		hdd_err("Invalid hdd_ctx");
1333*5113495bSYour Name 		return;
1334*5113495bSYour Name 	}
1335*5113495bSYour Name 
1336*5113495bSYour Name 	if (ucfg_reg_get_band(hdd_ctx->pdev, &current_band) !=
1337*5113495bSYour Name 	    QDF_STATUS_SUCCESS) {
1338*5113495bSYour Name 		hdd_err("Failed to get current band config");
1339*5113495bSYour Name 		return;
1340*5113495bSYour Name 	}
1341*5113495bSYour Name 
1342*5113495bSYour Name 	/**
1343*5113495bSYour Name 	 * If all bands are supported, in below condition off channel enable
1344*5113495bSYour Name 	 * orig is false and nothing is need to do
1345*5113495bSYour Name 	 * 1. band switch does not happen.
1346*5113495bSYour Name 	 * 2. band switch happens and it already restores
1347*5113495bSYour Name 	 * 3. tdls off channel is disabled by default.
1348*5113495bSYour Name 	 * If 2g or 5g is not supported. Disable tdls off channel only when
1349*5113495bSYour Name 	 * tdls off channel is enabled currently.
1350*5113495bSYour Name 	 */
1351*5113495bSYour Name 	if ((current_band & BIT(REG_BAND_2G)) &&
1352*5113495bSYour Name 	    (current_band & BIT(REG_BAND_5G))) {
1353*5113495bSYour Name 		if (cfg_tdls_get_off_channel_enable_orig(
1354*5113495bSYour Name 			hdd_ctx->psoc, &tdls_off_ch) !=
1355*5113495bSYour Name 		    QDF_STATUS_SUCCESS) {
1356*5113495bSYour Name 			hdd_err("cfg get tdls off ch orig failed");
1357*5113495bSYour Name 			return;
1358*5113495bSYour Name 		}
1359*5113495bSYour Name 		if (!tdls_off_ch) {
1360*5113495bSYour Name 			hdd_debug("tdls off ch orig is false, do nothing");
1361*5113495bSYour Name 			return;
1362*5113495bSYour Name 		}
1363*5113495bSYour Name 		offchmode = ENABLE_CHANSWITCH;
1364*5113495bSYour Name 		cfg_tdls_restore_off_channel_enable(hdd_ctx->psoc);
1365*5113495bSYour Name 	} else {
1366*5113495bSYour Name 		if (cfg_tdls_get_off_channel_enable(
1367*5113495bSYour Name 			hdd_ctx->psoc, &tdls_off_ch) !=
1368*5113495bSYour Name 		    QDF_STATUS_SUCCESS) {
1369*5113495bSYour Name 			hdd_err("cfg get tdls off ch failed");
1370*5113495bSYour Name 			return;
1371*5113495bSYour Name 		}
1372*5113495bSYour Name 		if (!tdls_off_ch) {
1373*5113495bSYour Name 			hdd_debug("tdls off ch is false, do nothing");
1374*5113495bSYour Name 			return;
1375*5113495bSYour Name 		}
1376*5113495bSYour Name 		offchmode = DISABLE_CHANSWITCH;
1377*5113495bSYour Name 		cfg_tdls_store_off_channel_enable(hdd_ctx->psoc);
1378*5113495bSYour Name 		cfg_tdls_set_off_channel_enable(hdd_ctx->psoc, false);
1379*5113495bSYour Name 	}
1380*5113495bSYour Name 	tdls_obj_vdev = ucfg_get_tdls_vdev(hdd_ctx->psoc, WLAN_TDLS_NB_ID);
1381*5113495bSYour Name 	if (tdls_obj_vdev) {
1382*5113495bSYour Name 		ucfg_set_tdls_offchan_mode(tdls_obj_vdev, offchmode);
1383*5113495bSYour Name 		wlan_objmgr_vdev_release_ref(tdls_obj_vdev, WLAN_TDLS_NB_ID);
1384*5113495bSYour Name 	}
1385*5113495bSYour Name }
1386