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