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, ¤t_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