blob: 89c5aef54a952a92ad9a1a2226465b5f2fc91827 [file] [log] [blame]
Frank Liu7e890d62017-03-02 17:17:53 +08001/*
Bala Venkatesh2a773822019-02-04 19:52:27 +05302 * Copyright (c) 2017-2019 The Linux Foundation. All rights reserved.
Frank Liu7e890d62017-03-02 17:17:53 +08003 *
4 * Permission to use, copy, modify, and/or distribute this software for
5 * any purpose with or without fee is hereby granted, provided that the
6 * above copyright notice and this permission notice appear in all
7 * copies.
8 *
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
10 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
11 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
12 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
13 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
14 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
15 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
16 * PERFORMANCE OF THIS SOFTWARE.
17 */
18
19/**
20 * DOC: wlan_tdls_main.c
21 *
22 * TDLS core function definitions
23 */
24
25#include "wlan_tdls_main.h"
Frank Liuc3aad432017-03-13 21:30:21 +080026#include "wlan_tdls_cmds_process.h"
27#include "wlan_tdls_peer.h"
Kabilan Kannan00619ab2017-03-20 01:59:24 -070028#include "wlan_tdls_ct.h"
Kabilan Kannan61442d22017-03-26 18:19:19 -070029#include "wlan_tdls_mgmt.h"
Kabilan Kannan03429f42017-02-28 20:28:54 -080030#include "wlan_tdls_tgt_api.h"
31#include "wlan_policy_mgr_public_struct.h"
32#include "wlan_policy_mgr_api.h"
Kabilan Kannanf3f11a72017-03-26 18:52:47 -070033#include "wlan_scan_ucfg_api.h"
34
Kabilan Kannan03429f42017-02-28 20:28:54 -080035
Kabilan Kannanb4c693d2017-03-27 23:42:04 -070036/* Global tdls soc pvt object
37 * this is useful for some functions which does not receive either vdev or psoc
38 * objects.
39 */
40static struct tdls_soc_priv_obj *tdls_soc_global;
Frank Liu7e890d62017-03-02 17:17:53 +080041
Bala Venkatesh76dd1432019-02-05 13:06:43 +053042#ifdef WLAN_DEBUG
43/**
44 * tdls_get_cmd_type_str() - parse cmd to string
45 * @cmd_type: tdls cmd type
46 *
47 * This function parse tdls cmd to string.
48 *
49 * Return: command string
50 */
51static char *tdls_get_cmd_type_str(enum tdls_command_type cmd_type)
52{
53 switch (cmd_type) {
54 case TDLS_CMD_TX_ACTION:
55 return "TDLS_CMD_TX_ACTION";
56 case TDLS_CMD_ADD_STA:
57 return "TDLS_CMD_ADD_STA";
58 case TDLS_CMD_CHANGE_STA:
59 return "TDLS_CMD_CHANGE_STA";
60 case TDLS_CMD_ENABLE_LINK:
61 return "TDLS_CMD_ENABLE_LINK";
62 case TDLS_CMD_DISABLE_LINK:
63 return "TDLS_CMD_DISABLE_LINK";
64 case TDLS_CMD_CONFIG_FORCE_PEER:
65 return "TDLS_CMD_CONFIG_FORCE_PEER";
66 case TDLS_CMD_REMOVE_FORCE_PEER:
67 return "TDLS_CMD_REMOVE_FORCE_PEER";
68 case TDLS_CMD_STATS_UPDATE:
69 return "TDLS_CMD_STATS_UPDATE";
70 case TDLS_CMD_CONFIG_UPDATE:
71 return "TDLS_CMD_CONFIG_UPDATE";
72 case TDLS_CMD_SET_RESPONDER:
73 return "TDLS_CMD_SET_RESPONDER";
74 case TDLS_CMD_SCAN_DONE:
75 return "TDLS_CMD_SCAN_DONE";
76 case TDLS_NOTIFY_STA_CONNECTION:
77 return "TDLS_NOTIFY_STA_CONNECTION";
78 case TDLS_NOTIFY_STA_DISCONNECTION:
79 return "TDLS_NOTIFY_STA_DISCONNECTION";
80 case TDLS_CMD_SET_TDLS_MODE:
81 return "TDLS_CMD_SET_TDLS_MODE";
82 case TDLS_CMD_SESSION_DECREMENT:
83 return "TDLS_CMD_SESSION_DECREMENT";
84 case TDLS_CMD_SESSION_INCREMENT:
85 return "TDLS_CMD_SESSION_INCREMENT";
86 case TDLS_CMD_TEARDOWN_LINKS:
87 return "TDLS_CMD_TEARDOWN_LINKS";
88 case TDLS_NOTIFY_RESET_ADAPTERS:
89 return "TDLS_NOTIFY_RESET_ADAPTERS";
90 case TDLS_CMD_ANTENNA_SWITCH:
91 return "TDLS_CMD_ANTENNA_SWITCH";
92
93 default:
94 return "Invalid TDLS command";
95 }
96}
97
98/**
99 * tdls_get_event_type_str() - parase event to string
100 * @event_type: tdls event type
101 *
102 * This function parse tdls event to string.
103 *
104 * Return: event string
105 */
106static char *tdls_get_event_type_str(enum tdls_event_type event_type)
107{
108 switch (event_type) {
109 case TDLS_SHOULD_DISCOVER:
110 return "TDLS_SHOULD_DISCOVER";
111 case TDLS_SHOULD_TEARDOWN:
112 return "TDLS_SHOULD_TEARDOWN";
113 case TDLS_PEER_DISCONNECTED:
114 return "TDLS_PEER_DISCONNECTED";
115 case TDLS_CONNECTION_TRACKER_NOTIFY:
116 return "TDLS_CONNECTION_TRACKER_NOTIFY";
117
118 default:
119 return "Invalid TDLS event";
120 }
121}
122#else
123static char *tdls_get_cmd_type_str(enum tdls_command_type cmd_type)
124{
125 return "";
126}
127
128static char *tdls_get_event_type_str(enum tdls_event_type event_type)
129{
130 return "";
131}
132#endif
133
Frank Liu7e890d62017-03-02 17:17:53 +0800134QDF_STATUS tdls_psoc_obj_create_notification(struct wlan_objmgr_psoc *psoc,
135 void *arg_list)
136{
137 QDF_STATUS status;
138 struct tdls_soc_priv_obj *tdls_soc_obj;
139
140 tdls_soc_obj = qdf_mem_malloc(sizeof(*tdls_soc_obj));
Frank Liuc3aad432017-03-13 21:30:21 +0800141 if (!tdls_soc_obj) {
Frank Liu7e890d62017-03-02 17:17:53 +0800142 tdls_err("Failed to allocate memory for tdls object");
143 return QDF_STATUS_E_NOMEM;
144 }
145
146 tdls_soc_obj->soc = psoc;
147
148 status = wlan_objmgr_psoc_component_obj_attach(psoc,
149 WLAN_UMAC_COMP_TDLS,
150 (void *)tdls_soc_obj,
151 QDF_STATUS_SUCCESS);
152
153 if (QDF_IS_STATUS_ERROR(status)) {
154 tdls_err("Failed to attach psoc tdls component");
155 qdf_mem_free(tdls_soc_obj);
Zhu Jianminab137692018-01-09 12:49:35 +0800156 return status;
Frank Liu7e890d62017-03-02 17:17:53 +0800157 }
158
Kabilan Kannanb4c693d2017-03-27 23:42:04 -0700159 tdls_soc_global = tdls_soc_obj;
Frank Liu7e890d62017-03-02 17:17:53 +0800160 tdls_notice("TDLS obj attach to psoc successfully");
161
162 return status;
163}
164
165QDF_STATUS tdls_psoc_obj_destroy_notification(struct wlan_objmgr_psoc *psoc,
166 void *arg_list)
167{
168 QDF_STATUS status;
169 struct tdls_soc_priv_obj *tdls_soc_obj;
170
171 tdls_soc_obj = wlan_objmgr_psoc_get_comp_private_obj(psoc,
172 WLAN_UMAC_COMP_TDLS);
Frank Liuc3aad432017-03-13 21:30:21 +0800173 if (!tdls_soc_obj) {
Frank Liu7e890d62017-03-02 17:17:53 +0800174 tdls_err("Failed to get tdls obj in psoc");
175 return QDF_STATUS_E_FAILURE;
176 }
177
178 status = wlan_objmgr_psoc_component_obj_detach(psoc,
179 WLAN_UMAC_COMP_TDLS,
180 tdls_soc_obj);
181
182 if (QDF_IS_STATUS_ERROR(status))
183 tdls_err("Failed to detach psoc tdls component");
Frank Liu7e890d62017-03-02 17:17:53 +0800184 qdf_mem_free(tdls_soc_obj);
185
186 return status;
187}
188
Frank Liuc3aad432017-03-13 21:30:21 +0800189static QDF_STATUS tdls_vdev_init(struct tdls_vdev_priv_obj *vdev_obj)
Frank Liu7e890d62017-03-02 17:17:53 +0800190{
191 uint8_t i;
Frank Liuc3aad432017-03-13 21:30:21 +0800192 struct tdls_config_params *config;
193 struct tdls_user_config *user_config;
194 struct tdls_soc_priv_obj *soc_obj;
Frank Liu7e890d62017-03-02 17:17:53 +0800195
Frank Liuc3aad432017-03-13 21:30:21 +0800196 soc_obj = wlan_vdev_get_tdls_soc_obj(vdev_obj->vdev);
197 if (!soc_obj) {
198 tdls_err("tdls soc obj NULL");
199 return QDF_STATUS_E_FAILURE;
Frank Liu7e890d62017-03-02 17:17:53 +0800200 }
201
Frank Liuc3aad432017-03-13 21:30:21 +0800202 config = &vdev_obj->threshold_config;
203 user_config = &soc_obj->tdls_configs;
204 config->tx_period_t = user_config->tdls_tx_states_period;
205 config->tx_packet_n = user_config->tdls_tx_pkt_threshold;
206 config->discovery_tries_n = user_config->tdls_max_discovery_attempt;
207 config->idle_timeout_t = user_config->tdls_idle_timeout;
208 config->idle_packet_n = user_config->tdls_idle_pkt_threshold;
209 config->rssi_trigger_threshold =
210 user_config->tdls_rssi_trigger_threshold;
211 config->rssi_teardown_threshold =
212 user_config->tdls_rssi_teardown_threshold;
213 config->rssi_delta = user_config->tdls_rssi_delta;
214
215 for (i = 0; i < WLAN_TDLS_PEER_LIST_SIZE; i++) {
216 qdf_list_create(&vdev_obj->peer_list[i],
217 WLAN_TDLS_PEER_SUB_LIST_SIZE);
218 }
219 qdf_mc_timer_init(&vdev_obj->peer_update_timer, QDF_TIMER_TYPE_SW,
Kabilan Kannan00619ab2017-03-20 01:59:24 -0700220 tdls_ct_handler, vdev_obj->vdev);
Frank Liuc3aad432017-03-13 21:30:21 +0800221 qdf_mc_timer_init(&vdev_obj->peer_discovery_timer, QDF_TIMER_TYPE_SW,
Kabilan Kannan00619ab2017-03-20 01:59:24 -0700222 tdls_discovery_timeout_peer_cb, vdev_obj);
223
Frank Liuc3aad432017-03-13 21:30:21 +0800224 return QDF_STATUS_SUCCESS;
225}
226
227static void tdls_vdev_deinit(struct tdls_vdev_priv_obj *vdev_obj)
228{
229 qdf_mc_timer_stop(&vdev_obj->peer_update_timer);
230 qdf_mc_timer_stop(&vdev_obj->peer_discovery_timer);
231
232 qdf_mc_timer_destroy(&vdev_obj->peer_update_timer);
233 qdf_mc_timer_destroy(&vdev_obj->peer_discovery_timer);
234
235 tdls_peer_idle_timers_destroy(vdev_obj);
236 tdls_free_peer_list(vdev_obj);
Frank Liu7e890d62017-03-02 17:17:53 +0800237}
238
239QDF_STATUS tdls_vdev_obj_create_notification(struct wlan_objmgr_vdev *vdev,
240 void *arg)
241{
242 QDF_STATUS status;
243 struct tdls_vdev_priv_obj *tdls_vdev_obj;
Kabilan Kannanb4c693d2017-03-27 23:42:04 -0700244 struct wlan_objmgr_pdev *pdev;
Frank Liu2688ed72018-04-24 16:50:40 +0800245 struct tdls_soc_priv_obj *tdls_soc_obj;
246 uint32_t tdls_feature_flags;
Frank Liu7e890d62017-03-02 17:17:53 +0800247
Sandeep Puligillae345d852018-08-18 12:42:41 -0700248 tdls_debug("tdls vdev mode %d", wlan_vdev_mlme_get_opmode(vdev));
Frank Liu7e890d62017-03-02 17:17:53 +0800249 if (wlan_vdev_mlme_get_opmode(vdev) != QDF_STA_MODE &&
250 wlan_vdev_mlme_get_opmode(vdev) != QDF_P2P_CLIENT_MODE)
251 return QDF_STATUS_SUCCESS;
252
Frank Liu2688ed72018-04-24 16:50:40 +0800253 tdls_soc_obj = wlan_vdev_get_tdls_soc_obj(vdev);
254 if (!tdls_soc_obj) {
255 tdls_err("get soc by vdev failed");
256 return QDF_STATUS_E_NOMEM;
257 }
258
259 tdls_feature_flags = tdls_soc_obj->tdls_configs.tdls_feature_flags;
260 if (!TDLS_IS_ENABLED(tdls_feature_flags)) {
261 tdls_debug("disabled in ini");
262 return QDF_STATUS_E_NOSUPPORT;
263 }
264
Jingxiang Ge37204fd2019-05-24 18:14:29 +0800265 if (tdls_soc_obj->tdls_osif_init_cb) {
266 status = tdls_soc_obj->tdls_osif_init_cb(vdev);
267 if (QDF_IS_STATUS_ERROR(status))
268 return status;
269 }
270
Frank Liu7e890d62017-03-02 17:17:53 +0800271 /* TODO: Add concurrency check */
272
273 tdls_vdev_obj = qdf_mem_malloc(sizeof(*tdls_vdev_obj));
Frank Liuc3aad432017-03-13 21:30:21 +0800274 if (!tdls_vdev_obj) {
Frank Liu7e890d62017-03-02 17:17:53 +0800275 tdls_err("Failed to allocate memory for tdls vdev object");
Arun Kumar Khandavallie8a01b82019-08-12 19:03:14 +0530276 status = QDF_STATUS_E_NOMEM;
277 goto err;
Frank Liu7e890d62017-03-02 17:17:53 +0800278 }
279
Frank Liu7e890d62017-03-02 17:17:53 +0800280 status = wlan_objmgr_vdev_component_obj_attach(vdev,
281 WLAN_UMAC_COMP_TDLS,
282 (void *)tdls_vdev_obj,
283 QDF_STATUS_SUCCESS);
284 if (QDF_IS_STATUS_ERROR(status)) {
285 tdls_err("Failed to attach vdev tdls component");
Frank Liu2688ed72018-04-24 16:50:40 +0800286 goto err;
Frank Liu7e890d62017-03-02 17:17:53 +0800287 }
Frank Liuc3aad432017-03-13 21:30:21 +0800288 tdls_vdev_obj->vdev = vdev;
289 status = tdls_vdev_init(tdls_vdev_obj);
290 if (QDF_IS_STATUS_ERROR(status))
Frank Liu2688ed72018-04-24 16:50:40 +0800291 goto err;
Kabilan Kannanb4c693d2017-03-27 23:42:04 -0700292
293 pdev = wlan_vdev_get_pdev(vdev);
294
295 status = ucfg_scan_register_event_handler(pdev,
296 tdls_scan_complete_event_handler,
Frank Liu2688ed72018-04-24 16:50:40 +0800297 tdls_soc_obj);
Kabilan Kannanb4c693d2017-03-27 23:42:04 -0700298
299 if (QDF_STATUS_SUCCESS != status) {
300 tdls_err("scan event register failed ");
Frank Liu2688ed72018-04-24 16:50:40 +0800301 tdls_vdev_deinit(tdls_vdev_obj);
302 goto err;
Kabilan Kannanb4c693d2017-03-27 23:42:04 -0700303 }
304
Sandeep Puligillae345d852018-08-18 12:42:41 -0700305 tdls_debug("tdls object attach to vdev successfully");
Frank Liu2688ed72018-04-24 16:50:40 +0800306 return status;
307err:
Arun Kumar Khandavallie8a01b82019-08-12 19:03:14 +0530308 if (tdls_soc_obj->tdls_osif_deinit_cb)
309 tdls_soc_obj->tdls_osif_deinit_cb(vdev);
310 if (tdls_vdev_obj) {
311 qdf_mem_free(tdls_vdev_obj);
312 tdls_vdev_obj = NULL;
313 }
Frank Liu7e890d62017-03-02 17:17:53 +0800314 return status;
315}
316
317QDF_STATUS tdls_vdev_obj_destroy_notification(struct wlan_objmgr_vdev *vdev,
318 void *arg)
319{
320 QDF_STATUS status;
321 void *tdls_vdev_obj;
Frank Liu2688ed72018-04-24 16:50:40 +0800322 struct tdls_soc_priv_obj *tdls_soc_obj;
323 uint32_t tdls_feature_flags;
Frank Liu7e890d62017-03-02 17:17:53 +0800324
Yeshwanth Sriram Guntukad50ff212018-08-23 18:25:28 +0530325 tdls_debug("tdls vdev mode %d", wlan_vdev_mlme_get_opmode(vdev));
Frank Liu7e890d62017-03-02 17:17:53 +0800326 if (wlan_vdev_mlme_get_opmode(vdev) != QDF_STA_MODE &&
327 wlan_vdev_mlme_get_opmode(vdev) != QDF_P2P_CLIENT_MODE)
328 return QDF_STATUS_SUCCESS;
329
Frank Liu2688ed72018-04-24 16:50:40 +0800330 tdls_soc_obj = wlan_vdev_get_tdls_soc_obj(vdev);
331 if (!tdls_soc_obj) {
332 tdls_err("get soc by vdev failed");
333 return QDF_STATUS_E_NOMEM;
334 }
335
336 tdls_feature_flags = tdls_soc_obj->tdls_configs.tdls_feature_flags;
337 if (!TDLS_IS_ENABLED(tdls_feature_flags)) {
338 tdls_debug("disabled in ini");
339 return QDF_STATUS_E_NOSUPPORT;
340 }
341
Frank Liu7e890d62017-03-02 17:17:53 +0800342 tdls_vdev_obj = wlan_objmgr_vdev_get_comp_private_obj(vdev,
343 WLAN_UMAC_COMP_TDLS);
Frank Liuc3aad432017-03-13 21:30:21 +0800344 if (!tdls_vdev_obj) {
Frank Liu7e890d62017-03-02 17:17:53 +0800345 tdls_err("Failed to get tdls vdev object");
346 return QDF_STATUS_E_FAILURE;
347 }
348
349 status = wlan_objmgr_vdev_component_obj_detach(vdev,
350 WLAN_UMAC_COMP_TDLS,
351 tdls_vdev_obj);
352 if (QDF_IS_STATUS_ERROR(status))
353 tdls_err("Failed to detach vdev tdls component");
354
Frank Liuc3aad432017-03-13 21:30:21 +0800355 tdls_vdev_deinit(tdls_vdev_obj);
Frank Liu7e890d62017-03-02 17:17:53 +0800356 qdf_mem_free(tdls_vdev_obj);
Arun Kumar Khandavalli43fdd252019-04-24 18:34:18 +0530357 if (tdls_soc_obj->tdls_osif_deinit_cb)
358 tdls_soc_obj->tdls_osif_deinit_cb(vdev);
Frank Liu7e890d62017-03-02 17:17:53 +0800359
360 return status;
361}
Frank Liuc3aad432017-03-13 21:30:21 +0800362
Bala Venkateshdfa388a2018-09-09 13:24:17 +0530363/**
364 * __tdls_get_all_peers_from_list() - get all the tdls peers from the list
365 * @get_tdls_peers: get_tdls_peers object
366 *
367 * Return: int
368 */
369static int __tdls_get_all_peers_from_list(
370 struct tdls_get_all_peers *get_tdls_peers)
371{
372 int i;
373 int len, init_len;
374 qdf_list_t *head;
375 qdf_list_node_t *p_node;
376 struct tdls_peer *curr_peer;
377 char *buf;
378 int buf_len;
379 struct tdls_vdev_priv_obj *tdls_vdev;
380 QDF_STATUS status;
381
382 tdls_notice("Enter ");
383
384 buf = get_tdls_peers->buf;
385 buf_len = get_tdls_peers->buf_len;
386
Bala Venkatesh0f745452019-03-29 11:16:22 +0530387 if (wlan_vdev_is_up(get_tdls_peers->vdev) != QDF_STATUS_SUCCESS) {
Bala Venkateshdfa388a2018-09-09 13:24:17 +0530388 len = qdf_scnprintf(buf, buf_len,
389 "\nSTA is not associated\n");
390 return len;
391 }
392
393 tdls_vdev = wlan_vdev_get_tdls_vdev_obj(get_tdls_peers->vdev);
394
395 if (!tdls_vdev) {
396 len = qdf_scnprintf(buf, buf_len, "TDLS not enabled\n");
397 return len;
398 }
399
400 init_len = buf_len;
401 len = qdf_scnprintf(buf, buf_len,
402 "\n%-18s%-3s%-4s%-3s%-5s\n",
403 "MAC", "Id", "cap", "up", "RSSI");
404 buf += len;
405 buf_len -= len;
406 len = qdf_scnprintf(buf, buf_len,
407 "---------------------------------\n");
408 buf += len;
409 buf_len -= len;
410
411 for (i = 0; i < WLAN_TDLS_PEER_LIST_SIZE; i++) {
412 head = &tdls_vdev->peer_list[i];
413 status = qdf_list_peek_front(head, &p_node);
414 while (QDF_IS_STATUS_SUCCESS(status)) {
415 curr_peer = qdf_container_of(p_node,
416 struct tdls_peer, node);
417 if (buf_len < 32 + 1)
418 break;
419 len = qdf_scnprintf(buf, buf_len,
Yeshwanth Sriram Guntuka4ac15842019-07-16 15:47:21 +0530420 QDF_MAC_ADDR_STR "%4s%3s%5d\n",
Bala Venkateshdfa388a2018-09-09 13:24:17 +0530421 QDF_MAC_ADDR_ARRAY(curr_peer->peer_mac.bytes),
Bala Venkateshdfa388a2018-09-09 13:24:17 +0530422 (curr_peer->tdls_support ==
423 TDLS_CAP_SUPPORTED) ? "Y" : "N",
424 TDLS_IS_LINK_CONNECTED(curr_peer) ? "Y" :
425 "N", curr_peer->rssi);
426 buf += len;
427 buf_len -= len;
428 status = qdf_list_peek_next(head, p_node, &p_node);
429 }
430 }
431
432 tdls_notice("Exit ");
433 return init_len - buf_len;
434}
435
436/**
437 * tdls_get_all_peers_from_list() - get all the tdls peers from the list
438 * @get_tdls_peers: get_tdls_peers object
439 *
440 * Return: None
441 */
442static void tdls_get_all_peers_from_list(
443 struct tdls_get_all_peers *get_tdls_peers)
444{
445 int32_t len;
446 struct tdls_soc_priv_obj *tdls_soc_obj;
447 struct tdls_osif_indication indication;
448
449 if (!get_tdls_peers->vdev) {
450 qdf_mem_free(get_tdls_peers);
451 return;
452 }
453 len = __tdls_get_all_peers_from_list(get_tdls_peers);
454
455 indication.status = len;
456 indication.vdev = get_tdls_peers->vdev;
457
458 tdls_soc_obj = wlan_vdev_get_tdls_soc_obj(get_tdls_peers->vdev);
459 if (tdls_soc_obj && tdls_soc_obj->tdls_event_cb)
460 tdls_soc_obj->tdls_event_cb(tdls_soc_obj->tdls_evt_cb_data,
461 TDLS_EVENT_USER_CMD, &indication);
462
463 qdf_mem_free(get_tdls_peers);
464}
465
Bala Venkatesha82fdd9562018-10-11 14:34:37 +0530466/**
467 * tdls_process_reset_all_peers() - Reset all tdls peers
468 * @delete_all_peers_ind: Delete all peers indication
469 *
470 * This function is called to reset all tdls peers and
471 * notify upper layers of teardown inidcation
472 *
473 * Return: QDF_STATUS
474 */
475
476static QDF_STATUS tdls_process_reset_all_peers(struct wlan_objmgr_vdev *vdev)
477{
478 QDF_STATUS status = QDF_STATUS_SUCCESS;
479 uint8_t staidx;
480 struct tdls_peer *curr_peer = NULL;
481 struct tdls_vdev_priv_obj *tdls_vdev;
482 struct tdls_soc_priv_obj *tdls_soc;
483 uint8_t reset_session_id;
484
485 status = tdls_get_vdev_objects(vdev, &tdls_vdev, &tdls_soc);
486 if (QDF_STATUS_SUCCESS != status) {
487 tdls_err("tdls objects are NULL ");
488 return status;
489 }
490
Bala Venkatesha82fdd9562018-10-11 14:34:37 +0530491 reset_session_id = tdls_vdev->session_id;
492 for (staidx = 0; staidx < tdls_soc->max_num_tdls_sta;
493 staidx++) {
Yeshwanth Sriram Guntuka4ac15842019-07-16 15:47:21 +0530494 if (!tdls_soc->tdls_conn_info[staidx].valid_entry)
Bala Venkatesha82fdd9562018-10-11 14:34:37 +0530495 continue;
496 if (tdls_soc->tdls_conn_info[staidx].session_id !=
497 reset_session_id)
498 continue;
499
500 curr_peer =
501 tdls_find_all_peer(tdls_soc,
502 tdls_soc->tdls_conn_info[staidx].
503 peer_mac.bytes);
504 if (!curr_peer)
505 continue;
506
Yeshwanth Sriram Guntuka4ac15842019-07-16 15:47:21 +0530507 tdls_notice("indicate TDLS teardown %pM",
508 curr_peer->peer_mac.bytes);
Bala Venkatesha82fdd9562018-10-11 14:34:37 +0530509
510 /* Indicate teardown to supplicant */
511 tdls_indicate_teardown(tdls_vdev,
512 curr_peer,
513 TDLS_TEARDOWN_PEER_UNSPEC_REASON);
514
515 tdls_reset_peer(tdls_vdev, curr_peer->peer_mac.bytes);
516
517 if (tdls_soc->tdls_dereg_peer)
518 tdls_soc->tdls_dereg_peer(
519 tdls_soc->tdls_peer_context,
520 wlan_vdev_get_id(vdev),
Yeshwanth Sriram Guntuka4fb838c2019-08-02 18:28:33 +0530521 &curr_peer->peer_mac);
Bala Venkatesha82fdd9562018-10-11 14:34:37 +0530522 tdls_decrement_peer_count(tdls_soc);
Yeshwanth Sriram Guntuka4ac15842019-07-16 15:47:21 +0530523 tdls_soc->tdls_conn_info[staidx].valid_entry = false;
Bala Venkatesha82fdd9562018-10-11 14:34:37 +0530524 tdls_soc->tdls_conn_info[staidx].session_id = 255;
Bala Venkatesh2a773822019-02-04 19:52:27 +0530525 tdls_soc->tdls_conn_info[staidx].index =
526 INVALID_TDLS_PEER_INDEX;
Bala Venkatesha82fdd9562018-10-11 14:34:37 +0530527
528 qdf_mem_zero(&tdls_soc->tdls_conn_info[staidx].peer_mac,
529 sizeof(struct qdf_mac_addr));
530 }
531 return status;
532}
533
534/**
535 * tdls_reset_all_peers() - Reset all tdls peers
536 * @delete_all_peers_ind: Delete all peers indication
537 *
538 * This function is called to reset all tdls peers and
539 * notify upper layers of teardown inidcation
540 *
541 * Return: QDF_STATUS
542 */
543static QDF_STATUS tdls_reset_all_peers(
544 struct tdls_delete_all_peers_params *delete_all_peers_ind)
545{
546 QDF_STATUS status;
547
548 if (!delete_all_peers_ind || !delete_all_peers_ind->vdev) {
549 tdls_err("invalid param");
550 return QDF_STATUS_E_INVAL;
551 }
552
553 status = tdls_process_reset_all_peers(delete_all_peers_ind->vdev);
554
Frank Liuaf02af52018-10-24 15:08:00 +0800555 wlan_objmgr_vdev_release_ref(delete_all_peers_ind->vdev,
556 WLAN_TDLS_SB_ID);
Bala Venkatesha82fdd9562018-10-11 14:34:37 +0530557 qdf_mem_free(delete_all_peers_ind);
Frank Liuaf02af52018-10-24 15:08:00 +0800558
Bala Venkatesha82fdd9562018-10-11 14:34:37 +0530559 return status;
560}
561
Frank Liuc3aad432017-03-13 21:30:21 +0800562QDF_STATUS tdls_process_cmd(struct scheduler_msg *msg)
563{
564 QDF_STATUS status = QDF_STATUS_SUCCESS;
565
566 if (!msg || !msg->bodyptr) {
Jeff Johnson6ada3cd2017-09-18 10:07:54 -0700567 tdls_err("msg: 0x%pK", msg);
Frank Liuc3aad432017-03-13 21:30:21 +0800568 QDF_ASSERT(0);
569 return QDF_STATUS_E_NULL_VALUE;
570 }
Bala Venkatesh76dd1432019-02-05 13:06:43 +0530571 tdls_debug("TDLS process command: %s(%d)",
572 tdls_get_cmd_type_str(msg->type), msg->type);
Frank Liuc3aad432017-03-13 21:30:21 +0800573
574 switch (msg->type) {
575 case TDLS_CMD_TX_ACTION:
Kabilan Kannan61442d22017-03-26 18:19:19 -0700576 tdls_process_mgmt_req(msg->bodyptr);
Frank Liuc3aad432017-03-13 21:30:21 +0800577 break;
578 case TDLS_CMD_ADD_STA:
579 tdls_process_add_peer(msg->bodyptr);
580 break;
581 case TDLS_CMD_CHANGE_STA:
582 tdls_process_update_peer(msg->bodyptr);
583 break;
584 case TDLS_CMD_ENABLE_LINK:
Frank Liu8cbcde22017-03-20 14:39:07 +0800585 tdls_process_enable_link(msg->bodyptr);
Frank Liuc3aad432017-03-13 21:30:21 +0800586 break;
587 case TDLS_CMD_DISABLE_LINK:
588 tdls_process_del_peer(msg->bodyptr);
589 break;
590 case TDLS_CMD_CONFIG_FORCE_PEER:
Frank Liu8cbcde22017-03-20 14:39:07 +0800591 tdls_process_setup_peer(msg->bodyptr);
Frank Liuc3aad432017-03-13 21:30:21 +0800592 break;
593 case TDLS_CMD_REMOVE_FORCE_PEER:
Frank Liu8cbcde22017-03-20 14:39:07 +0800594 tdls_process_remove_force_peer(msg->bodyptr);
Frank Liuc3aad432017-03-13 21:30:21 +0800595 break;
596 case TDLS_CMD_STATS_UPDATE:
597 break;
598 case TDLS_CMD_CONFIG_UPDATE:
599 break;
Kabilan Kannan53f502c2017-04-14 23:36:42 -0700600 case TDLS_CMD_SET_RESPONDER:
601 tdls_set_responder(msg->bodyptr);
602 break;
Kabilan Kannanb4c693d2017-03-27 23:42:04 -0700603 case TDLS_CMD_SCAN_DONE:
604 tdls_scan_done_callback(msg->bodyptr);
605 break;
Kabilan Kannan53f502c2017-04-14 23:36:42 -0700606 case TDLS_NOTIFY_STA_CONNECTION:
607 tdls_notify_sta_connect(msg->bodyptr);
608 break;
609 case TDLS_NOTIFY_STA_DISCONNECTION:
610 tdls_notify_sta_disconnect(msg->bodyptr);
611 break;
612 case TDLS_CMD_SET_TDLS_MODE:
613 tdls_set_operation_mode(msg->bodyptr);
614 break;
Kabilan Kannan53f502c2017-04-14 23:36:42 -0700615 case TDLS_CMD_SESSION_DECREMENT:
Bala Venkateshc8bbb002018-12-18 19:55:48 +0530616 tdls_process_decrement_active_session(msg->bodyptr);
617 /*Fall through to take decision on connection tracker.*/
618 case TDLS_CMD_SESSION_INCREMENT:
Kabilan Kannan53f502c2017-04-14 23:36:42 -0700619 tdls_process_policy_mgr_notification(msg->bodyptr);
620 break;
Kabilan Kannance5880e2017-04-17 21:53:42 -0700621 case TDLS_CMD_TEARDOWN_LINKS:
622 tdls_teardown_connections(msg->bodyptr);
623 break;
Kabilan Kannan52eb3c72017-06-06 19:40:03 -0700624 case TDLS_NOTIFY_RESET_ADAPTERS:
625 tdls_notify_reset_adapter(msg->bodyptr);
Kabilan Kannan9b84b212017-12-14 17:02:55 -0800626 break;
Frank Liu7fc7beb2017-07-21 18:02:02 +0800627 case TDLS_CMD_ANTENNA_SWITCH:
628 tdls_process_antenna_switch(msg->bodyptr);
Kabilan Kannan52eb3c72017-06-06 19:40:03 -0700629 break;
Kabilan Kannan4058ac52017-11-14 17:19:29 -0800630 case TDLS_CMD_GET_ALL_PEERS:
631 tdls_get_all_peers_from_list(msg->bodyptr);
632 break;
Bala Venkatesh5304ace2018-08-30 15:28:14 +0530633 case TDLS_CMD_SET_OFFCHANNEL:
634 tdls_process_set_offchannel(msg->bodyptr);
635 break;
636 case TDLS_CMD_SET_OFFCHANMODE:
637 tdls_process_set_offchan_mode(msg->bodyptr);
638 break;
639 case TDLS_CMD_SET_SECOFFCHANOFFSET:
640 tdls_process_set_secoffchanneloffset(msg->bodyptr);
641 break;
Bala Venkatesha82fdd9562018-10-11 14:34:37 +0530642 case TDLS_DELETE_ALL_PEERS_INDICATION:
643 tdls_reset_all_peers(msg->bodyptr);
644 break;
Frank Liuc3aad432017-03-13 21:30:21 +0800645 default:
646 break;
647 }
648
649 return status;
650}
Frank Liu57d308c2017-03-16 19:28:51 +0800651
652QDF_STATUS tdls_process_evt(struct scheduler_msg *msg)
653{
654 struct wlan_objmgr_vdev *vdev;
655 struct tdls_event_notify *notify;
656 struct tdls_event_info *event;
657
658 if (!msg || !msg->bodyptr) {
Jeff Johnson6ada3cd2017-09-18 10:07:54 -0700659 tdls_err("msg is not valid: %pK", msg);
Frank Liu57d308c2017-03-16 19:28:51 +0800660 return QDF_STATUS_E_NULL_VALUE;
661 }
662 notify = msg->bodyptr;
663 vdev = notify->vdev;
664 if (!vdev) {
665 tdls_err("NULL vdev object");
666 qdf_mem_free(notify);
667 return QDF_STATUS_E_NULL_VALUE;
668 }
669 event = &notify->event;
670
Bala Venkatesh76dd1432019-02-05 13:06:43 +0530671 tdls_debug("evt type: %s(%d)",
672 tdls_get_event_type_str(event->message_type),
673 event->message_type);
674
Frank Liu57d308c2017-03-16 19:28:51 +0800675 switch (event->message_type) {
676 case TDLS_SHOULD_DISCOVER:
677 tdls_process_should_discover(vdev, event);
678 break;
679 case TDLS_SHOULD_TEARDOWN:
680 case TDLS_PEER_DISCONNECTED:
681 tdls_process_should_teardown(vdev, event);
682 break;
683 case TDLS_CONNECTION_TRACKER_NOTIFY:
684 tdls_process_connection_tracker_notify(vdev, event);
685 break;
686 default:
687 break;
688 }
689
690 wlan_objmgr_vdev_release_ref(vdev, WLAN_TDLS_SB_ID);
691 qdf_mem_free(notify);
692
693 return QDF_STATUS_SUCCESS;
694}
Kabilan Kannan712cbfe2017-03-27 17:20:33 -0700695
696void tdls_timer_restart(struct wlan_objmgr_vdev *vdev,
697 qdf_mc_timer_t *timer,
698 uint32_t expiration_time)
699{
Kabilan Kannan712cbfe2017-03-27 17:20:33 -0700700 qdf_mc_timer_start(timer, expiration_time);
701}
702
703/**
704 * wlan_hdd_tdls_monitor_timers_stop() - stop all monitoring timers
705 * @hdd_tdls_ctx: TDLS context
706 *
707 * Return: none
708 */
709static void tdls_monitor_timers_stop(struct tdls_vdev_priv_obj *tdls_vdev)
710{
711 qdf_mc_timer_stop(&tdls_vdev->peer_discovery_timer);
712}
713
714/**
715 * tdls_peer_idle_timers_stop() - stop peer idle timers
716 * @tdls_vdev: TDLS vdev object
717 *
718 * Loop through the idle peer list and stop their timers
719 *
720 * Return: None
721 */
722static void tdls_peer_idle_timers_stop(struct tdls_vdev_priv_obj *tdls_vdev)
723{
724 int i;
725 qdf_list_t *head;
726 qdf_list_node_t *p_node;
727 struct tdls_peer *curr_peer;
728 QDF_STATUS status;
729
730 tdls_vdev->discovery_peer_cnt = 0;
731
732 for (i = 0; i < WLAN_TDLS_PEER_LIST_SIZE; i++) {
733 head = &tdls_vdev->peer_list[i];
734 status = qdf_list_peek_front(head, &p_node);
735 while (QDF_IS_STATUS_SUCCESS(status)) {
736 curr_peer = qdf_container_of(p_node, struct tdls_peer,
737 node);
738 if (curr_peer->is_peer_idle_timer_initialised)
739 qdf_mc_timer_stop(&curr_peer->peer_idle_timer);
740 status = qdf_list_peek_next(head, p_node, &p_node);
741 }
742 }
743
744}
745
746/**
747 * wlan_hdd_tdls_ct_timers_stop() - stop tdls connection tracker timers
748 * @tdls_vdev: TDLS vdev
749 *
750 * Return: None
751 */
752static void tdls_ct_timers_stop(struct tdls_vdev_priv_obj *tdls_vdev)
753{
754 qdf_mc_timer_stop(&tdls_vdev->peer_update_timer);
755 tdls_peer_idle_timers_stop(tdls_vdev);
756}
757
758/**
759 * wlan_hdd_tdls_timers_stop() - stop all the tdls timers running
760 * @tdls_vdev: TDLS vdev
761 *
762 * Return: none
763 */
764void tdls_timers_stop(struct tdls_vdev_priv_obj *tdls_vdev)
765{
766 tdls_monitor_timers_stop(tdls_vdev);
767 tdls_ct_timers_stop(tdls_vdev);
768}
Kabilan Kannan00619ab2017-03-20 01:59:24 -0700769
770QDF_STATUS tdls_get_vdev_objects(struct wlan_objmgr_vdev *vdev,
771 struct tdls_vdev_priv_obj **tdls_vdev_obj,
772 struct tdls_soc_priv_obj **tdls_soc_obj)
773{
Jeff Johnson19867852017-11-09 09:54:12 -0800774 enum QDF_OPMODE device_mode;
Kabilan Kannan00619ab2017-03-20 01:59:24 -0700775
Jeff Johnsonbdc473f2019-03-18 13:45:10 -0700776 if (!vdev)
Kabilan Kannan00619ab2017-03-20 01:59:24 -0700777 return QDF_STATUS_E_FAILURE;
778
779 *tdls_vdev_obj = wlan_vdev_get_tdls_vdev_obj(vdev);
780 if (NULL == (*tdls_vdev_obj))
781 return QDF_STATUS_E_FAILURE;
782
783 *tdls_soc_obj = wlan_vdev_get_tdls_soc_obj(vdev);
784 if (NULL == (*tdls_soc_obj))
785 return QDF_STATUS_E_FAILURE;
786
Kabilan Kannan00619ab2017-03-20 01:59:24 -0700787 device_mode = wlan_vdev_mlme_get_opmode(vdev);
Kabilan Kannan00619ab2017-03-20 01:59:24 -0700788
789 if (device_mode != QDF_STA_MODE &&
790 device_mode != QDF_P2P_CLIENT_MODE)
791 return QDF_STATUS_E_FAILURE;
792
793 return QDF_STATUS_SUCCESS;
794}
Kabilan Kannan03429f42017-02-28 20:28:54 -0800795
796/**
797 * tdls_state_param_setting_dump() - print tdls state & parameters to send to fw
798 * @info: tdls setting to be sent to fw
799 *
800 * Return: void
801 */
802static void tdls_state_param_setting_dump(struct tdls_info *info)
803{
804 if (!info)
805 return;
806
Bala Venkateshff86f892019-11-04 12:41:06 +0530807 tdls_debug("Setting tdls state and param in fw: vdev_id: %d, tdls_state: %d, notification_interval_ms: %d, tx_discovery_threshold: %d, tx_teardown_threshold: %d, rssi_teardown_threshold: %d, rssi_delta: %d, tdls_options: 0x%x, peer_traffic_ind_window: %d, peer_traffic_response_timeout: %d, puapsd_mask: 0x%x, puapsd_inactivity_time: %d, puapsd_rx_frame_threshold: %d, teardown_notification_ms: %d, tdls_peer_kickout_threshold: %d, tdls_discovery_wake_timeout: %d",
Kabilan Kannan03429f42017-02-28 20:28:54 -0800808 info->vdev_id,
809 info->tdls_state,
810 info->notification_interval_ms,
811 info->tx_discovery_threshold,
812 info->tx_teardown_threshold,
813 info->rssi_teardown_threshold,
814 info->rssi_delta,
815 info->tdls_options,
816 info->peer_traffic_ind_window,
817 info->peer_traffic_response_timeout,
818 info->puapsd_mask,
819 info->puapsd_inactivity_time,
820 info->puapsd_rx_frame_threshold,
821 info->teardown_notification_ms,
Bala Venkateshff86f892019-11-04 12:41:06 +0530822 info->tdls_peer_kickout_threshold,
823 info->tdls_discovery_wake_timeout);
Kabilan Kannan03429f42017-02-28 20:28:54 -0800824
825}
826
Kabilan Kannance5880e2017-04-17 21:53:42 -0700827QDF_STATUS tdls_set_offchan_mode(struct wlan_objmgr_psoc *psoc,
828 struct tdls_channel_switch_params *param)
829{
830 QDF_STATUS status;
831
832 /* wmi_unified_set_tdls_offchan_mode_cmd() will be called directly */
833 status = tgt_tdls_set_offchan_mode(psoc, param);
834
835 if (!QDF_IS_STATUS_SUCCESS(status))
836 status = QDF_STATUS_E_FAILURE;
837
838 return status;
839}
840
Kabilan Kannan03429f42017-02-28 20:28:54 -0800841/**
842 * tdls_update_fw_tdls_state() - update tdls status info
843 * @tdls_soc_obj: TDLS soc object
844 * @tdls_info_to_fw: TDLS state info to update in f/w.
845 *
846 * send message to WMA to set TDLS state in f/w
847 *
848 * Return: QDF_STATUS.
849 */
850static
851QDF_STATUS tdls_update_fw_tdls_state(struct tdls_soc_priv_obj *tdls_soc_obj,
852 struct tdls_info *tdls_info_to_fw)
853{
854 QDF_STATUS status;
855
856 /* wmi_unified_update_fw_tdls_state_cmd() will be called directly */
857 status = tgt_tdls_set_fw_state(tdls_soc_obj->soc, tdls_info_to_fw);
858
859 if (!QDF_IS_STATUS_SUCCESS(status))
860 status = QDF_STATUS_E_FAILURE;
861
862 return status;
863}
864
865bool tdls_check_is_tdls_allowed(struct wlan_objmgr_vdev *vdev)
866{
867 struct tdls_vdev_priv_obj *tdls_vdev_obj;
868 struct tdls_soc_priv_obj *tdls_soc_obj;
869 bool state = false;
870
871 if (QDF_STATUS_SUCCESS != wlan_objmgr_vdev_try_get_ref(vdev,
872 WLAN_TDLS_NB_ID))
873 return state;
874
875 if (QDF_STATUS_SUCCESS != tdls_get_vdev_objects(vdev, &tdls_vdev_obj,
876 &tdls_soc_obj)) {
877 wlan_objmgr_vdev_release_ref(vdev,
878 WLAN_TDLS_NB_ID);
879 return state;
880 }
881
882 if (policy_mgr_get_connection_count(tdls_soc_obj->soc) == 1)
883 state = true;
884 else
885 tdls_warn("Concurrent sessions are running or TDLS disabled");
886 /* If any concurrency is detected */
887 /* print session information */
888 wlan_objmgr_vdev_release_ref(vdev,
889 WLAN_TDLS_NB_ID);
890 return state;
891}
892
893/**
894 * cds_set_tdls_ct_mode() - Set the tdls connection tracker mode
895 * @hdd_ctx: hdd context
896 *
897 * This routine is called to set the tdls connection tracker operation status
898 *
899 * Return: NONE
900 */
901void tdls_set_ct_mode(struct wlan_objmgr_psoc *psoc)
902{
903 bool state = false;
904 struct tdls_soc_priv_obj *tdls_soc_obj;
905
906 tdls_soc_obj = wlan_psoc_get_tdls_soc_obj(psoc);
Jeff Johnsonbdc473f2019-03-18 13:45:10 -0700907 if (!tdls_soc_obj)
Kabilan Kannan03429f42017-02-28 20:28:54 -0800908 return;
909
910 /* If any concurrency is detected, skip tdls pkt tracker */
911 if (policy_mgr_get_connection_count(psoc) > 1) {
912 state = false;
913 goto set_state;
914 }
915
916 if (TDLS_SUPPORT_DISABLED == tdls_soc_obj->tdls_current_mode ||
917 TDLS_SUPPORT_SUSPENDED == tdls_soc_obj->tdls_current_mode ||
918 !TDLS_IS_IMPLICIT_TRIG_ENABLED(
919 tdls_soc_obj->tdls_configs.tdls_feature_flags)) {
920 state = false;
921 goto set_state;
922 } else if (policy_mgr_mode_specific_connection_count(psoc,
923 PM_STA_MODE,
924 NULL) == 1) {
925 state = true;
926 } else if (policy_mgr_mode_specific_connection_count(psoc,
927 PM_P2P_CLIENT_MODE,
928 NULL) == 1){
929 state = true;
930 } else {
931 state = false;
932 goto set_state;
933 }
934
935 /* In case of TDLS external control, peer should be added
936 * by the user space to start connection tracker.
937 */
938 if (TDLS_IS_EXTERNAL_CONTROL_ENABLED(
939 tdls_soc_obj->tdls_configs.tdls_feature_flags)) {
940 if (tdls_soc_obj->tdls_external_peer_count)
941 state = true;
942 else
943 state = false;
944 }
945
946set_state:
947 tdls_soc_obj->enable_tdls_connection_tracker = state;
948
Kiran Kumar Lokere8fc14c22017-11-29 15:32:58 -0800949 tdls_debug("enable_tdls_connection_tracker %d",
Kabilan Kannan03429f42017-02-28 20:28:54 -0800950 tdls_soc_obj->enable_tdls_connection_tracker);
951}
952
953QDF_STATUS
954tdls_process_policy_mgr_notification(struct wlan_objmgr_psoc *psoc)
955{
Bala Venkateshc8bbb002018-12-18 19:55:48 +0530956 struct tdls_vdev_priv_obj *tdls_priv_vdev;
957 struct wlan_objmgr_vdev *tdls_obj_vdev;
958 struct tdls_soc_priv_obj *tdls_priv_soc;
959
Kabilan Kannan03429f42017-02-28 20:28:54 -0800960 if (!psoc) {
Jeff Johnson6ada3cd2017-09-18 10:07:54 -0700961 tdls_err("psoc: %pK", psoc);
Kabilan Kannan03429f42017-02-28 20:28:54 -0800962 return QDF_STATUS_E_NULL_VALUE;
963 }
Bala Venkateshc8bbb002018-12-18 19:55:48 +0530964 tdls_obj_vdev = tdls_get_vdev(psoc, WLAN_TDLS_NB_ID);
Kabilan Kannan03429f42017-02-28 20:28:54 -0800965 tdls_debug("enter ");
966 tdls_set_ct_mode(psoc);
Bala Venkateshc8bbb002018-12-18 19:55:48 +0530967 if (tdls_obj_vdev && (tdls_get_vdev_objects(tdls_obj_vdev,
968 &tdls_priv_vdev, &tdls_priv_soc) == QDF_STATUS_SUCCESS) &&
969 tdls_priv_soc->enable_tdls_connection_tracker)
970 tdls_implicit_enable(tdls_priv_vdev);
971
972 if (tdls_obj_vdev)
973 wlan_objmgr_vdev_release_ref(tdls_obj_vdev, WLAN_TDLS_NB_ID);
974
Kabilan Kannan03429f42017-02-28 20:28:54 -0800975 tdls_debug("exit ");
976 return QDF_STATUS_SUCCESS;
977}
978
Bala Venkateshc8bbb002018-12-18 19:55:48 +0530979QDF_STATUS
980tdls_process_decrement_active_session(struct wlan_objmgr_psoc *psoc)
981{
982 struct tdls_soc_priv_obj *tdls_priv_soc;
983 struct tdls_vdev_priv_obj *tdls_priv_vdev;
984 struct wlan_objmgr_vdev *tdls_obj_vdev;
985 uint8_t vdev_id;
986
987 tdls_debug("Enter");
988 if (!psoc)
989 return QDF_STATUS_E_NULL_VALUE;
Bala Venkateshab30be32019-09-20 13:07:21 +0530990 if(!policy_mgr_is_hw_dbs_2x2_capable(psoc) &&
Liangwei Dong897b4392019-11-05 19:16:02 +0800991 !policy_mgr_is_hw_dbs_required_for_band(
992 psoc, HW_MODE_MAC_BAND_2G) &&
Bala Venkateshab30be32019-09-20 13:07:21 +0530993 policy_mgr_is_current_hwmode_dbs(psoc)) {
994 tdls_err("Current HW mode is 1*1 DBS. Wait for Opportunistic timer to expire to enable TDLS in FW");
995 return QDF_STATUS_SUCCESS;
996 }
Bala Venkateshc8bbb002018-12-18 19:55:48 +0530997 tdls_obj_vdev = tdls_get_vdev(psoc, WLAN_TDLS_NB_ID);
998 if (tdls_obj_vdev) {
999 tdls_debug("Enable TDLS in FW and host as only one active sta/p2p_cli interface is present");
1000 vdev_id = wlan_vdev_get_id(tdls_obj_vdev);
1001 if (tdls_get_vdev_objects(tdls_obj_vdev, &tdls_priv_vdev,
1002 &tdls_priv_soc) == QDF_STATUS_SUCCESS)
1003 tdls_send_update_to_fw(tdls_priv_vdev, tdls_priv_soc,
1004 false, false, true, vdev_id);
1005 wlan_objmgr_vdev_release_ref(tdls_obj_vdev, WLAN_TDLS_NB_ID);
1006 }
1007
1008 return QDF_STATUS_SUCCESS;
1009}
1010
Kabilan Kannan03429f42017-02-28 20:28:54 -08001011/**
1012 * tdls_get_vdev() - Get tdls specific vdev object manager
1013 * @psoc: wlan psoc object manager
1014 * @dbg_id: debug id
1015 *
1016 * If TDLS possible, return the corresponding vdev
1017 * to enable TDLS in the system.
1018 *
1019 * Return: vdev manager pointer or NULL.
1020 */
1021struct wlan_objmgr_vdev *tdls_get_vdev(struct wlan_objmgr_psoc *psoc,
1022 wlan_objmgr_ref_dbgid dbg_id)
1023{
Kabilan Kannan952df192017-05-15 20:28:05 -07001024 uint32_t vdev_id;
1025
Kabilan Kannan03429f42017-02-28 20:28:54 -08001026 if (policy_mgr_get_connection_count(psoc) > 1)
1027 return NULL;
Kabilan Kannan952df192017-05-15 20:28:05 -07001028
1029 vdev_id = policy_mgr_mode_specific_vdev_id(psoc, PM_STA_MODE);
1030
1031 if (WLAN_INVALID_VDEV_ID != vdev_id)
1032 return wlan_objmgr_get_vdev_by_id_from_psoc(psoc,
1033 vdev_id,
1034 dbg_id);
1035
1036 vdev_id = policy_mgr_mode_specific_vdev_id(psoc, PM_P2P_CLIENT_MODE);
1037
1038 if (WLAN_INVALID_VDEV_ID != vdev_id)
1039 return wlan_objmgr_get_vdev_by_id_from_psoc(psoc,
1040 vdev_id,
1041 dbg_id);
1042
Kabilan Kannan03429f42017-02-28 20:28:54 -08001043 return NULL;
1044}
1045
Frank Liuaf02af52018-10-24 15:08:00 +08001046static QDF_STATUS tdls_post_msg_flush_cb(struct scheduler_msg *msg)
1047{
1048 void *ptr = msg->bodyptr;
1049 struct wlan_objmgr_vdev *vdev = NULL;
1050
1051 switch (msg->type) {
1052 case TDLS_NOTIFY_STA_DISCONNECTION:
1053 vdev = ((struct tdls_sta_notify_params *)ptr)->vdev;
1054 wlan_objmgr_vdev_release_ref(vdev, WLAN_TDLS_NB_ID);
1055 qdf_mem_free(ptr);
1056 break;
1057
1058 case TDLS_DELETE_ALL_PEERS_INDICATION:
1059 vdev = ((struct tdls_delete_all_peers_params *)ptr)->vdev;
1060 wlan_objmgr_vdev_release_ref(vdev, WLAN_TDLS_SB_ID);
1061 qdf_mem_free(ptr);
1062 break;
1063
1064 case TDLS_CMD_SCAN_DONE:
1065 case TDLS_CMD_SESSION_INCREMENT:
1066 case TDLS_CMD_SESSION_DECREMENT:
1067 break;
1068 }
1069
1070 return QDF_STATUS_SUCCESS;
1071}
1072
Kabilan Kannan03429f42017-02-28 20:28:54 -08001073/**
1074 * tdls_process_session_update() - update session count information
1075 * @psoc: soc object
1076 * @notification: TDLS os if notification
1077 *
1078 * update the session information in connection tracker
1079 *
1080 * Return: None
1081 */
1082static void tdls_process_session_update(struct wlan_objmgr_psoc *psoc,
1083 enum tdls_command_type cmd_type)
1084{
1085 struct scheduler_msg msg = {0};
1086 QDF_STATUS status;
1087
1088 msg.bodyptr = psoc;
1089 msg.callback = tdls_process_cmd;
Frank Liuaf02af52018-10-24 15:08:00 +08001090 msg.flush_callback = tdls_post_msg_flush_cb;
Kabilan Kannan03429f42017-02-28 20:28:54 -08001091 msg.type = (uint16_t)cmd_type;
1092
gaurank kathpaliac5d02282018-08-28 19:50:21 +05301093 status = scheduler_post_message(QDF_MODULE_ID_TDLS,
1094 QDF_MODULE_ID_TDLS,
1095 QDF_MODULE_ID_OS_IF, &msg);
Kabilan Kannan03429f42017-02-28 20:28:54 -08001096 if (QDF_IS_STATUS_ERROR(status))
1097 tdls_alert("message post failed ");
1098}
1099
1100void tdls_notify_increment_session(struct wlan_objmgr_psoc *psoc)
1101{
1102 tdls_process_session_update(psoc, TDLS_CMD_SESSION_INCREMENT);
1103}
1104
1105void tdls_notify_decrement_session(struct wlan_objmgr_psoc *psoc)
1106{
1107 tdls_process_session_update(psoc, TDLS_CMD_SESSION_DECREMENT);
1108}
1109
Bala Venkatesh10a46e92018-09-06 14:38:13 +05301110void tdls_send_update_to_fw(struct tdls_vdev_priv_obj *tdls_vdev_obj,
1111 struct tdls_soc_priv_obj *tdls_soc_obj,
1112 bool tdls_prohibited,
1113 bool tdls_chan_swit_prohibited,
1114 bool sta_connect_event,
1115 uint8_t session_id)
Kabilan Kannan03429f42017-02-28 20:28:54 -08001116{
1117 struct tdls_info *tdls_info_to_fw;
1118 struct tdls_config_params *threshold_params;
1119 uint32_t tdls_feature_flags;
1120 QDF_STATUS status;
Bala Venkateshc8bbb002018-12-18 19:55:48 +05301121 uint8_t set_state_cnt;
Kabilan Kannan03429f42017-02-28 20:28:54 -08001122
Bala Venkateshc8bbb002018-12-18 19:55:48 +05301123 tdls_debug("Enter");
Kabilan Kannan952df192017-05-15 20:28:05 -07001124 tdls_feature_flags = tdls_soc_obj->tdls_configs.tdls_feature_flags;
1125 if (!TDLS_IS_ENABLED(tdls_feature_flags)) {
1126 tdls_debug("TDLS mode is not enabled");
Kabilan Kannan03429f42017-02-28 20:28:54 -08001127 return;
1128 }
1129
Bala Venkateshc8bbb002018-12-18 19:55:48 +05301130 set_state_cnt = tdls_soc_obj->set_state_info.set_state_cnt;
1131 if ((set_state_cnt == 0 && !sta_connect_event) ||
1132 (set_state_cnt && sta_connect_event)) {
1133 tdls_debug("FW TDLS state is already in requested state");
Kabilan Kannan03429f42017-02-28 20:28:54 -08001134 return;
1135 }
1136
Kabilan Kannan03429f42017-02-28 20:28:54 -08001137 /* If AP or caller indicated TDLS Prohibited then disable tdls mode */
Kabilan Kannan952df192017-05-15 20:28:05 -07001138 if (sta_connect_event) {
1139 if (tdls_prohibited) {
1140 tdls_soc_obj->tdls_current_mode =
1141 TDLS_SUPPORT_DISABLED;
1142 } else {
1143 tdls_debug("TDLS feature flags from ini %d ",
Kabilan Kannan03429f42017-02-28 20:28:54 -08001144 tdls_feature_flags);
Kabilan Kannan952df192017-05-15 20:28:05 -07001145 if (!TDLS_IS_IMPLICIT_TRIG_ENABLED(tdls_feature_flags))
1146 tdls_soc_obj->tdls_current_mode =
1147 TDLS_SUPPORT_EXP_TRIG_ONLY;
1148 else if (TDLS_IS_EXTERNAL_CONTROL_ENABLED(
1149 tdls_feature_flags))
1150 tdls_soc_obj->tdls_current_mode =
1151 TDLS_SUPPORT_EXT_CONTROL;
1152 else
1153 tdls_soc_obj->tdls_current_mode =
1154 TDLS_SUPPORT_IMP_MODE;
1155 }
1156 } else {
1157 tdls_soc_obj->tdls_current_mode =
1158 TDLS_SUPPORT_DISABLED;
Kabilan Kannan03429f42017-02-28 20:28:54 -08001159 }
1160
1161 tdls_info_to_fw = qdf_mem_malloc(sizeof(struct tdls_info));
1162
1163 if (!tdls_info_to_fw) {
1164 tdls_err("memory allocation failed for tdlsParams");
1165 QDF_ASSERT(0);
1166 return;
1167 }
1168
1169 threshold_params = &tdls_vdev_obj->threshold_config;
1170
1171 tdls_info_to_fw->notification_interval_ms =
1172 threshold_params->tx_period_t;
1173 tdls_info_to_fw->tx_discovery_threshold =
1174 threshold_params->tx_packet_n;
1175 tdls_info_to_fw->tx_teardown_threshold =
1176 threshold_params->idle_packet_n;
1177 tdls_info_to_fw->rssi_teardown_threshold =
1178 threshold_params->rssi_teardown_threshold;
1179 tdls_info_to_fw->rssi_delta = threshold_params->rssi_delta;
Bala Venkateshc8bbb002018-12-18 19:55:48 +05301180 tdls_info_to_fw->vdev_id = session_id;
Kabilan Kannan03429f42017-02-28 20:28:54 -08001181
Kabilan Kannance5880e2017-04-17 21:53:42 -07001182 /* record the session id in vdev context */
1183 tdls_vdev_obj->session_id = session_id;
Kabilan Kannan03429f42017-02-28 20:28:54 -08001184 tdls_info_to_fw->tdls_state = tdls_soc_obj->tdls_current_mode;
1185 tdls_info_to_fw->tdls_options = 0;
1186
1187 /* Do not enable TDLS offchannel, if AP prohibited TDLS
1188 * channel switch
1189 */
1190 if (TDLS_IS_OFF_CHANNEL_ENABLED(tdls_feature_flags) &&
1191 (!tdls_chan_swit_prohibited))
1192 tdls_info_to_fw->tdls_options = ENA_TDLS_OFFCHAN;
1193
1194 if (TDLS_IS_BUFFER_STA_ENABLED(tdls_feature_flags))
1195 tdls_info_to_fw->tdls_options |= ENA_TDLS_BUFFER_STA;
1196 if (TDLS_IS_SLEEP_STA_ENABLED(tdls_feature_flags))
1197 tdls_info_to_fw->tdls_options |= ENA_TDLS_SLEEP_STA;
1198
1199
1200 tdls_info_to_fw->peer_traffic_ind_window =
1201 tdls_soc_obj->tdls_configs.tdls_uapsd_pti_window;
1202 tdls_info_to_fw->peer_traffic_response_timeout =
1203 tdls_soc_obj->tdls_configs.tdls_uapsd_ptr_timeout;
1204 tdls_info_to_fw->puapsd_mask =
1205 tdls_soc_obj->tdls_configs.tdls_uapsd_mask;
1206 tdls_info_to_fw->puapsd_inactivity_time =
1207 tdls_soc_obj->tdls_configs.tdls_uapsd_inactivity_time;
1208 tdls_info_to_fw->puapsd_rx_frame_threshold =
1209 tdls_soc_obj->tdls_configs.tdls_rx_pkt_threshold;
1210 tdls_info_to_fw->teardown_notification_ms =
1211 tdls_soc_obj->tdls_configs.tdls_idle_timeout;
1212 tdls_info_to_fw->tdls_peer_kickout_threshold =
1213 tdls_soc_obj->tdls_configs.tdls_peer_kickout_threshold;
Bala Venkateshff86f892019-11-04 12:41:06 +05301214 tdls_info_to_fw->tdls_discovery_wake_timeout =
1215 tdls_soc_obj->tdls_configs.tdls_discovery_wake_timeout;
Kabilan Kannan03429f42017-02-28 20:28:54 -08001216
1217 tdls_state_param_setting_dump(tdls_info_to_fw);
1218
1219 status = tdls_update_fw_tdls_state(tdls_soc_obj, tdls_info_to_fw);
Kabilan Kannan1ac9c552017-04-20 10:33:39 -07001220 if (QDF_STATUS_SUCCESS != status)
Kabilan Kannan03429f42017-02-28 20:28:54 -08001221 goto done;
Kabilan Kannan03429f42017-02-28 20:28:54 -08001222
1223 if (sta_connect_event) {
1224 tdls_soc_obj->set_state_info.set_state_cnt++;
1225 tdls_soc_obj->set_state_info.vdev_id = session_id;
1226 } else {
1227 tdls_soc_obj->set_state_info.set_state_cnt--;
1228 }
1229
1230 tdls_debug("TDLS Set state cnt %d",
1231 tdls_soc_obj->set_state_info.set_state_cnt);
Kabilan Kannan03429f42017-02-28 20:28:54 -08001232done:
Kabilan Kannan1ac9c552017-04-20 10:33:39 -07001233 qdf_mem_free(tdls_info_to_fw);
Kabilan Kannan03429f42017-02-28 20:28:54 -08001234 return;
1235}
1236
1237static QDF_STATUS
1238tdls_process_sta_connect(struct tdls_sta_notify_params *notify)
1239{
1240 struct tdls_vdev_priv_obj *tdls_vdev_obj;
1241 struct tdls_soc_priv_obj *tdls_soc_obj;
1242
1243 if (QDF_STATUS_SUCCESS != tdls_get_vdev_objects(notify->vdev,
1244 &tdls_vdev_obj,
1245 &tdls_soc_obj))
1246 return QDF_STATUS_E_INVAL;
1247
1248
1249 tdls_debug("Check and update TDLS state");
1250
Kabilan Kannan952df192017-05-15 20:28:05 -07001251 if (policy_mgr_get_connection_count(tdls_soc_obj->soc) > 1) {
1252 tdls_debug("Concurrent sessions exist, TDLS can't be enabled");
1253 return QDF_STATUS_SUCCESS;
1254 }
1255
Kabilan Kannan03429f42017-02-28 20:28:54 -08001256 /* Association event */
1257 if (!tdls_soc_obj->tdls_disable_in_progress) {
1258 tdls_send_update_to_fw(tdls_vdev_obj,
1259 tdls_soc_obj,
1260 notify->tdls_prohibited,
1261 notify->tdls_chan_swit_prohibited,
1262 true,
1263 notify->session_id);
1264 }
1265
1266 /* check and set the connection tracker */
1267 tdls_set_ct_mode(tdls_soc_obj->soc);
1268 if (tdls_soc_obj->enable_tdls_connection_tracker)
1269 tdls_implicit_enable(tdls_vdev_obj);
1270
1271 return QDF_STATUS_SUCCESS;
1272}
1273
1274QDF_STATUS tdls_notify_sta_connect(struct tdls_sta_notify_params *notify)
1275{
1276 QDF_STATUS status;
1277
Jingxiang Gea551f692018-07-13 15:16:03 +08001278 if (!notify || !notify->vdev) {
1279 tdls_err("invalid param");
Kabilan Kannan03429f42017-02-28 20:28:54 -08001280 return QDF_STATUS_E_INVAL;
Kabilan Kannan952df192017-05-15 20:28:05 -07001281 }
Kabilan Kannan03429f42017-02-28 20:28:54 -08001282
1283 status = tdls_process_sta_connect(notify);
1284
Frank Liuaf02af52018-10-24 15:08:00 +08001285 wlan_objmgr_vdev_release_ref(notify->vdev, WLAN_TDLS_NB_ID);
Kabilan Kannan03429f42017-02-28 20:28:54 -08001286 qdf_mem_free(notify);
Frank Liuaf02af52018-10-24 15:08:00 +08001287
Kabilan Kannan03429f42017-02-28 20:28:54 -08001288 return status;
1289}
1290
1291static QDF_STATUS
1292tdls_process_sta_disconnect(struct tdls_sta_notify_params *notify)
1293{
1294 struct tdls_vdev_priv_obj *tdls_vdev_obj;
1295 struct tdls_vdev_priv_obj *curr_tdls_vdev;
1296 struct tdls_soc_priv_obj *tdls_soc_obj;
1297 struct tdls_soc_priv_obj *curr_tdls_soc;
1298 struct wlan_objmgr_vdev *temp_vdev = NULL;
Bala Venkateshef8692e2019-03-08 13:04:06 +05301299 uint8_t vdev_id;
Kabilan Kannan03429f42017-02-28 20:28:54 -08001300
1301
1302 QDF_STATUS status = QDF_STATUS_SUCCESS;
1303
1304 if (QDF_STATUS_SUCCESS != tdls_get_vdev_objects(notify->vdev,
1305 &tdls_vdev_obj,
1306 &tdls_soc_obj))
1307 return QDF_STATUS_E_INVAL;
1308
Kabilan Kannan51c7fde2017-10-10 01:36:39 -07001309 /* if the disconnect comes from user space, we have to delete all the
1310 * tdls peers before sending the set state cmd.
1311 */
1312 if (notify->user_disconnect)
1313 return tdls_delete_all_tdls_peers(notify->vdev, tdls_soc_obj);
1314
Kabilan Kannan03429f42017-02-28 20:28:54 -08001315 tdls_debug("Check and update TDLS state");
1316
1317 curr_tdls_vdev = tdls_vdev_obj;
1318 curr_tdls_soc = tdls_soc_obj;
1319
1320 /* Disassociation event */
1321 if (!tdls_soc_obj->tdls_disable_in_progress)
1322 tdls_send_update_to_fw(tdls_vdev_obj, tdls_soc_obj, false,
1323 false, false, notify->session_id);
1324
1325 /* If concurrency is not marked, then we have to
1326 * check, whether TDLS could be enabled in the
1327 * system after this disassoc event.
1328 */
1329 if (!notify->lfr_roam && !tdls_soc_obj->tdls_disable_in_progress) {
1330 temp_vdev = tdls_get_vdev(tdls_soc_obj->soc, WLAN_TDLS_NB_ID);
Jeff Johnsonbdc473f2019-03-18 13:45:10 -07001331 if (temp_vdev) {
Bala Venkateshef8692e2019-03-08 13:04:06 +05301332 vdev_id = wlan_vdev_get_id(temp_vdev);
Kabilan Kannan03429f42017-02-28 20:28:54 -08001333 status = tdls_get_vdev_objects(temp_vdev,
1334 &tdls_vdev_obj,
1335 &tdls_soc_obj);
1336 if (QDF_STATUS_SUCCESS == status) {
1337 tdls_send_update_to_fw(tdls_vdev_obj,
1338 tdls_soc_obj,
1339 false,
1340 false,
1341 true,
Bala Venkateshef8692e2019-03-08 13:04:06 +05301342 vdev_id);
Kabilan Kannan03429f42017-02-28 20:28:54 -08001343 curr_tdls_vdev = tdls_vdev_obj;
1344 curr_tdls_soc = tdls_soc_obj;
1345 }
1346 }
1347 }
1348
1349 /* Check and set the connection tracker and implicit timers */
1350 tdls_set_ct_mode(curr_tdls_soc->soc);
1351 if (curr_tdls_soc->enable_tdls_connection_tracker)
1352 tdls_implicit_enable(curr_tdls_vdev);
1353 else
1354 tdls_implicit_disable(curr_tdls_vdev);
1355
1356 /* release the vdev ref , if temp vdev was acquired */
1357 if (temp_vdev)
1358 wlan_objmgr_vdev_release_ref(temp_vdev,
1359 WLAN_TDLS_NB_ID);
1360
1361 return status;
1362}
1363
1364QDF_STATUS tdls_notify_sta_disconnect(struct tdls_sta_notify_params *notify)
1365{
1366 QDF_STATUS status;
1367
Jingxiang Gea551f692018-07-13 15:16:03 +08001368 if (!notify || !notify->vdev) {
1369 tdls_err("invalid param");
Kabilan Kannan03429f42017-02-28 20:28:54 -08001370 return QDF_STATUS_E_INVAL;
Kabilan Kannan952df192017-05-15 20:28:05 -07001371 }
Kabilan Kannan03429f42017-02-28 20:28:54 -08001372
1373 status = tdls_process_sta_disconnect(notify);
1374
Frank Liuaf02af52018-10-24 15:08:00 +08001375 wlan_objmgr_vdev_release_ref(notify->vdev, WLAN_TDLS_NB_ID);
Kabilan Kannan03429f42017-02-28 20:28:54 -08001376 qdf_mem_free(notify);
Frank Liuaf02af52018-10-24 15:08:00 +08001377
Kabilan Kannan03429f42017-02-28 20:28:54 -08001378 return status;
1379}
1380
Kabilan Kannan52eb3c72017-06-06 19:40:03 -07001381static void tdls_process_reset_adapter(struct wlan_objmgr_vdev *vdev)
1382{
1383 struct tdls_vdev_priv_obj *tdls_vdev;
1384
1385 tdls_vdev = wlan_vdev_get_tdls_vdev_obj(vdev);
1386 if (!tdls_vdev)
1387 return;
1388 tdls_timers_stop(tdls_vdev);
1389}
1390
1391void tdls_notify_reset_adapter(struct wlan_objmgr_vdev *vdev)
1392{
1393 if (!vdev) {
1394 QDF_ASSERT(0);
1395 return;
1396 }
1397
1398 if (QDF_STATUS_SUCCESS != wlan_objmgr_vdev_try_get_ref(vdev,
1399 WLAN_TDLS_NB_ID))
1400 return;
1401
1402 tdls_process_reset_adapter(vdev);
1403 wlan_objmgr_vdev_release_ref(vdev, WLAN_TDLS_NB_ID);
1404}
1405
Frank Liuaf02af52018-10-24 15:08:00 +08001406QDF_STATUS tdls_peers_deleted_notification(struct wlan_objmgr_psoc *psoc,
1407 uint8_t vdev_id)
Kabilan Kannan952df192017-05-15 20:28:05 -07001408{
Kabilan Kannan9098eac2018-04-09 16:08:22 -07001409 struct scheduler_msg msg = {0, };
Kabilan Kannan952df192017-05-15 20:28:05 -07001410 struct tdls_sta_notify_params *notify;
Kabilan Kannan9098eac2018-04-09 16:08:22 -07001411 QDF_STATUS status;
Frank Liuaf02af52018-10-24 15:08:00 +08001412 struct wlan_objmgr_vdev *vdev;
Kabilan Kannan952df192017-05-15 20:28:05 -07001413
1414 notify = qdf_mem_malloc(sizeof(*notify));
1415 if (!notify) {
1416 tdls_err("memory allocation failed !!!");
Jingxiang Gea551f692018-07-13 15:16:03 +08001417 return QDF_STATUS_E_NULL_VALUE;
Kabilan Kannan952df192017-05-15 20:28:05 -07001418 }
1419
Frank Liuaf02af52018-10-24 15:08:00 +08001420 vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc,
1421 vdev_id,
1422 WLAN_TDLS_NB_ID);
1423
1424 if (!vdev) {
1425 tdls_err("vdev not exist for the vdev id %d",
1426 vdev_id);
1427 qdf_mem_free(notify);
1428 return QDF_STATUS_E_INVAL;
1429 }
1430
1431 notify->lfr_roam = true;
1432 notify->tdls_chan_swit_prohibited = false;
1433 notify->tdls_prohibited = false;
1434 notify->session_id = vdev_id;
1435 notify->vdev = vdev;
1436 notify->user_disconnect = false;
Kabilan Kannan952df192017-05-15 20:28:05 -07001437
Kabilan Kannan9098eac2018-04-09 16:08:22 -07001438 msg.bodyptr = notify;
1439 msg.callback = tdls_process_cmd;
Frank Liuaf02af52018-10-24 15:08:00 +08001440 msg.flush_callback = tdls_post_msg_flush_cb;
Kabilan Kannan9098eac2018-04-09 16:08:22 -07001441 msg.type = TDLS_NOTIFY_STA_DISCONNECTION;
1442
gaurank kathpaliac5d02282018-08-28 19:50:21 +05301443 status = scheduler_post_message(QDF_MODULE_ID_TDLS,
1444 QDF_MODULE_ID_TDLS,
1445 QDF_MODULE_ID_OS_IF, &msg);
Kabilan Kannan9098eac2018-04-09 16:08:22 -07001446 if (QDF_IS_STATUS_ERROR(status)) {
Frank Liuaf02af52018-10-24 15:08:00 +08001447 wlan_objmgr_vdev_release_ref(vdev, WLAN_TDLS_NB_ID);
Kabilan Kannan9098eac2018-04-09 16:08:22 -07001448 qdf_mem_free(notify);
1449 tdls_alert("message post failed ");
Frank Liuaf02af52018-10-24 15:08:00 +08001450
Jingxiang Gea551f692018-07-13 15:16:03 +08001451 return QDF_STATUS_E_FAILURE;
Kabilan Kannan9098eac2018-04-09 16:08:22 -07001452 }
Jingxiang Gea551f692018-07-13 15:16:03 +08001453
1454 return QDF_STATUS_SUCCESS;
Kabilan Kannan952df192017-05-15 20:28:05 -07001455}
1456
Frank Liuaf02af52018-10-24 15:08:00 +08001457QDF_STATUS tdls_delete_all_peers_indication(struct wlan_objmgr_psoc *psoc,
1458 uint8_t vdev_id)
Bala Venkatesha82fdd9562018-10-11 14:34:37 +05301459{
1460 struct scheduler_msg msg = {0, };
1461 struct tdls_delete_all_peers_params *indication;
1462 QDF_STATUS status;
Frank Liuaf02af52018-10-24 15:08:00 +08001463 struct wlan_objmgr_vdev *vdev;
Bala Venkatesha82fdd9562018-10-11 14:34:37 +05301464
1465 indication = qdf_mem_malloc(sizeof(*indication));
1466 if (!indication) {
1467 tdls_err("memory allocation failed !!!");
1468 return QDF_STATUS_E_NULL_VALUE;
1469 }
1470
Frank Liuaf02af52018-10-24 15:08:00 +08001471 vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc,
1472 vdev_id,
1473 WLAN_TDLS_SB_ID);
1474
1475 if (!vdev) {
1476 tdls_err("vdev not exist for the session id %d",
1477 vdev_id);
1478 qdf_mem_free(indication);
1479 return QDF_STATUS_E_INVAL;
1480 }
1481
1482 indication->vdev = vdev;
Bala Venkatesha82fdd9562018-10-11 14:34:37 +05301483
1484 msg.bodyptr = indication;
1485 msg.callback = tdls_process_cmd;
1486 msg.type = TDLS_DELETE_ALL_PEERS_INDICATION;
Frank Liuaf02af52018-10-24 15:08:00 +08001487 msg.flush_callback = tdls_post_msg_flush_cb;
Bala Venkatesha82fdd9562018-10-11 14:34:37 +05301488
1489 status = scheduler_post_message(QDF_MODULE_ID_TDLS,
1490 QDF_MODULE_ID_TDLS,
1491 QDF_MODULE_ID_OS_IF, &msg);
1492 if (QDF_IS_STATUS_ERROR(status)) {
Frank Liuaf02af52018-10-24 15:08:00 +08001493 wlan_objmgr_vdev_release_ref(vdev, WLAN_TDLS_SB_ID);
Bala Venkatesha82fdd9562018-10-11 14:34:37 +05301494 qdf_mem_free(indication);
1495 tdls_alert("message post failed ");
1496 return QDF_STATUS_E_FAILURE;
1497 }
1498
1499 return QDF_STATUS_SUCCESS;
1500}
1501
Kabilan Kannan03429f42017-02-28 20:28:54 -08001502/**
1503 * tdls_set_mode_in_vdev() - set TDLS mode
1504 * @tdls_vdev: tdls vdev object
1505 * @tdls_soc: tdls soc object
1506 * @tdls_mode: TDLS mode
1507 * @source: TDLS disable source enum values
1508 *
1509 * Return: Void
1510 */
1511static void tdls_set_mode_in_vdev(struct tdls_vdev_priv_obj *tdls_vdev,
1512 struct tdls_soc_priv_obj *tdls_soc,
1513 enum tdls_feature_mode tdls_mode,
1514 enum tdls_disable_sources source)
1515{
1516 if (!tdls_vdev)
1517 return;
1518 tdls_debug("enter tdls mode is %d", tdls_mode);
1519
1520 if (TDLS_SUPPORT_IMP_MODE == tdls_mode ||
1521 TDLS_SUPPORT_EXT_CONTROL == tdls_mode) {
1522 clear_bit((unsigned long)source,
1523 &tdls_soc->tdls_source_bitmap);
1524 /*
1525 * Check if any TDLS source bit is set and if
1526 * bitmap is not zero then we should not
1527 * enable TDLS
1528 */
1529 if (tdls_soc->tdls_source_bitmap) {
1530 tdls_notice("Don't enable TDLS, source bitmap: %lu",
1531 tdls_soc->tdls_source_bitmap);
1532 return;
1533 }
1534 tdls_implicit_enable(tdls_vdev);
1535 /* tdls implicit mode is enabled, so
1536 * enable the connection tracker
1537 */
1538 tdls_soc->enable_tdls_connection_tracker =
1539 true;
1540 } else if (TDLS_SUPPORT_DISABLED == tdls_mode) {
1541 set_bit((unsigned long)source,
1542 &tdls_soc->tdls_source_bitmap);
1543 tdls_implicit_disable(tdls_vdev);
1544 /* If tdls implicit mode is disabled, then
1545 * stop the connection tracker.
1546 */
1547 tdls_soc->enable_tdls_connection_tracker =
1548 false;
1549 } else if (TDLS_SUPPORT_EXP_TRIG_ONLY ==
1550 tdls_mode) {
1551 clear_bit((unsigned long)source,
1552 &tdls_soc->tdls_source_bitmap);
1553 tdls_implicit_disable(tdls_vdev);
1554 /* If tdls implicit mode is disabled, then
1555 * stop the connection tracker.
1556 */
1557 tdls_soc->enable_tdls_connection_tracker =
1558 false;
1559
1560 /*
1561 * Check if any TDLS source bit is set and if
1562 * bitmap is not zero then we should not
1563 * enable TDLS
1564 */
1565 if (tdls_soc->tdls_source_bitmap)
1566 return;
1567 }
1568 tdls_debug("exit ");
1569
1570}
1571
1572/**
1573 * tdls_set_current_mode() - set TDLS mode
1574 * @tdls_soc: tdls soc object
1575 * @tdls_mode: TDLS mode
1576 * @update_last: indicate to record the last tdls mode
1577 * @source: TDLS disable source enum values
1578 *
1579 * Return: Void
1580 */
1581static void tdls_set_current_mode(struct tdls_soc_priv_obj *tdls_soc,
1582 enum tdls_feature_mode tdls_mode,
1583 bool update_last,
1584 enum tdls_disable_sources source)
1585{
1586 struct wlan_objmgr_vdev *vdev;
1587 struct tdls_vdev_priv_obj *tdls_vdev;
1588
1589 if (!tdls_soc)
1590 return;
1591
1592 tdls_debug("mode %d", (int)tdls_mode);
1593
1594 if (update_last)
1595 tdls_soc->tdls_last_mode = tdls_mode;
1596
1597 if (tdls_soc->tdls_current_mode == tdls_mode) {
1598 tdls_debug("already in mode %d", tdls_mode);
1599
1600 switch (tdls_mode) {
1601 /* TDLS is already enabled hence clear source mask, return */
1602 case TDLS_SUPPORT_IMP_MODE:
1603 case TDLS_SUPPORT_EXP_TRIG_ONLY:
1604 case TDLS_SUPPORT_EXT_CONTROL:
1605 clear_bit((unsigned long)source,
1606 &tdls_soc->tdls_source_bitmap);
1607 tdls_debug("clear source mask:%d", source);
1608 return;
1609 /* TDLS is already disabled hence set source mask, return */
1610 case TDLS_SUPPORT_DISABLED:
1611 set_bit((unsigned long)source,
1612 &tdls_soc->tdls_source_bitmap);
1613 tdls_debug("set source mask:%d", source);
1614 return;
1615 default:
1616 return;
1617 }
1618 }
1619
1620 /* get sta vdev */
1621 vdev = wlan_objmgr_get_vdev_by_opmode_from_psoc(tdls_soc->soc,
1622 QDF_STA_MODE,
1623 WLAN_TDLS_NB_ID);
Jeff Johnsonbdc473f2019-03-18 13:45:10 -07001624 if (vdev) {
Kabilan Kannan03429f42017-02-28 20:28:54 -08001625 tdls_debug("set mode in tdls vdev ");
1626 tdls_vdev = wlan_vdev_get_tdls_vdev_obj(vdev);
1627 if (!tdls_vdev)
1628 tdls_set_mode_in_vdev(tdls_vdev, tdls_soc,
1629 tdls_mode, source);
1630 wlan_objmgr_vdev_release_ref(vdev, WLAN_TDLS_NB_ID);
1631 }
1632
1633 /* get p2p client vdev */
1634 vdev = wlan_objmgr_get_vdev_by_opmode_from_psoc(tdls_soc->soc,
1635 QDF_P2P_CLIENT_MODE,
1636 WLAN_TDLS_NB_ID);
Jeff Johnsonbdc473f2019-03-18 13:45:10 -07001637 if (vdev) {
Kabilan Kannan03429f42017-02-28 20:28:54 -08001638 tdls_debug("set mode in tdls vdev ");
1639 tdls_vdev = wlan_vdev_get_tdls_vdev_obj(vdev);
1640 if (!tdls_vdev)
1641 tdls_set_mode_in_vdev(tdls_vdev, tdls_soc,
1642 tdls_mode, source);
1643 wlan_objmgr_vdev_release_ref(vdev, WLAN_TDLS_NB_ID);
1644 }
1645
1646 if (!update_last)
1647 tdls_soc->tdls_last_mode = tdls_soc->tdls_current_mode;
1648
1649 tdls_soc->tdls_current_mode = tdls_mode;
1650
1651}
Kabilan Kannan53f502c2017-04-14 23:36:42 -07001652
1653QDF_STATUS tdls_set_operation_mode(struct tdls_set_mode_params *tdls_set_mode)
1654{
1655 struct tdls_soc_priv_obj *tdls_soc;
1656 struct tdls_vdev_priv_obj *tdls_vdev;
1657 QDF_STATUS status;
1658
1659 if (!tdls_set_mode || !tdls_set_mode->vdev)
1660 return QDF_STATUS_E_INVAL;
1661
Kabilan Kannan53f502c2017-04-14 23:36:42 -07001662 status = tdls_get_vdev_objects(tdls_set_mode->vdev,
1663 &tdls_vdev, &tdls_soc);
1664
Frank Liuaf02af52018-10-24 15:08:00 +08001665 if (QDF_IS_STATUS_ERROR(status))
Kabilan Kannan53f502c2017-04-14 23:36:42 -07001666 goto release_mode_ref;
1667
1668 tdls_set_current_mode(tdls_soc,
1669 tdls_set_mode->tdls_mode,
1670 tdls_set_mode->update_last,
1671 tdls_set_mode->source);
1672
1673release_mode_ref:
1674 wlan_objmgr_vdev_release_ref(tdls_set_mode->vdev, WLAN_TDLS_NB_ID);
1675 qdf_mem_free(tdls_set_mode);
1676 return status;
1677}
1678
Kabilan Kannanb4c693d2017-03-27 23:42:04 -07001679/**
1680 * wlan_hdd_tdls_scan_done_callback() - callback for tdls scan done event
1681 * @pAdapter: HDD adapter
1682 *
1683 * Return: Void
1684 */
1685void tdls_scan_done_callback(struct tdls_soc_priv_obj *tdls_soc)
1686{
1687 if (!tdls_soc)
1688 return;
1689
1690 if (TDLS_SUPPORT_DISABLED == tdls_soc->tdls_current_mode) {
Sandeep Puligillae345d852018-08-18 12:42:41 -07001691 tdls_debug("TDLS mode is disabled OR not enabled");
Kabilan Kannanb4c693d2017-03-27 23:42:04 -07001692 return;
1693 }
1694
1695 /* if tdls was enabled before scan, re-enable tdls mode */
1696 if (TDLS_SUPPORT_IMP_MODE == tdls_soc->tdls_last_mode ||
1697 TDLS_SUPPORT_EXT_CONTROL == tdls_soc->tdls_last_mode ||
1698 TDLS_SUPPORT_EXP_TRIG_ONLY == tdls_soc->tdls_last_mode) {
Tushnim Bhattacharyya618adb82018-06-01 15:16:53 -07001699 tdls_debug("revert tdls mode %d",
Kabilan Kannanb4c693d2017-03-27 23:42:04 -07001700 tdls_soc->tdls_last_mode);
1701
1702 tdls_set_current_mode(tdls_soc, tdls_soc->tdls_last_mode,
1703 false,
1704 TDLS_SET_MODE_SOURCE_SCAN);
1705 }
1706}
1707
1708/**
1709 * tdls_post_scan_done_msg() - post scan done message to tdls cmd queue
1710 * @tdls_soc: tdls soc object
1711 *
1712 * Return: QDF_STATUS_SUCCESS or QDF_STATUS_E_NULL_VALUE
1713 */
1714static QDF_STATUS tdls_post_scan_done_msg(struct tdls_soc_priv_obj *tdls_soc)
1715{
1716 struct scheduler_msg msg = {0, };
1717
1718 if (!tdls_soc) {
Jeff Johnson6ada3cd2017-09-18 10:07:54 -07001719 tdls_err("tdls_soc: %pK ", tdls_soc);
Kabilan Kannanb4c693d2017-03-27 23:42:04 -07001720 return QDF_STATUS_E_NULL_VALUE;
1721 }
1722
1723 msg.bodyptr = tdls_soc;
1724 msg.callback = tdls_process_cmd;
Frank Liuaf02af52018-10-24 15:08:00 +08001725 msg.flush_callback = tdls_post_msg_flush_cb;
Kabilan Kannanb4c693d2017-03-27 23:42:04 -07001726 msg.type = TDLS_CMD_SCAN_DONE;
Kabilan Kannanb4c693d2017-03-27 23:42:04 -07001727
Frank Liuaf02af52018-10-24 15:08:00 +08001728 return scheduler_post_message(QDF_MODULE_ID_TDLS,
1729 QDF_MODULE_ID_TDLS,
1730 QDF_MODULE_ID_OS_IF, &msg);
Kabilan Kannanb4c693d2017-03-27 23:42:04 -07001731}
1732
1733void tdls_scan_complete_event_handler(struct wlan_objmgr_vdev *vdev,
1734 struct scan_event *event,
1735 void *arg)
1736{
Jeff Johnson19867852017-11-09 09:54:12 -08001737 enum QDF_OPMODE device_mode;
Kabilan Kannanb4c693d2017-03-27 23:42:04 -07001738 struct tdls_soc_priv_obj *tdls_soc;
1739
1740 if (!vdev || !event || !arg)
1741 return;
1742
1743 if (SCAN_EVENT_TYPE_COMPLETED != event->type)
1744 return;
1745
1746 device_mode = wlan_vdev_mlme_get_opmode(vdev);
1747
1748 if (device_mode != QDF_STA_MODE &&
1749 device_mode != QDF_P2P_CLIENT_MODE)
1750 return;
1751 tdls_soc = (struct tdls_soc_priv_obj *) arg;
1752 tdls_post_scan_done_msg(tdls_soc);
1753}
1754
1755QDF_STATUS tdls_scan_callback(struct tdls_soc_priv_obj *tdls_soc)
1756{
Kabilan Kannanb4c693d2017-03-27 23:42:04 -07001757 struct tdls_vdev_priv_obj *tdls_vdev;
1758 struct wlan_objmgr_vdev *vdev;
1759 QDF_STATUS status = QDF_STATUS_SUCCESS;
1760
1761 /* if tdls is not enabled, then continue scan */
1762 if (TDLS_SUPPORT_DISABLED == tdls_soc->tdls_current_mode)
1763 return status;
1764
1765 /* Get the vdev based on vdev operating mode*/
1766 vdev = tdls_get_vdev(tdls_soc->soc, WLAN_TDLS_NB_ID);
1767 if (!vdev)
1768 return status;
1769
1770 tdls_vdev = wlan_vdev_get_tdls_vdev_obj(vdev);
1771 if (!tdls_vdev)
1772 goto return_success;
1773
Bala Venkatesh4a3de452019-04-16 15:49:21 +05301774 if (tdls_is_progress(tdls_vdev, NULL, 0)) {
Kabilan Kannanb4c693d2017-03-27 23:42:04 -07001775 if (tdls_soc->scan_reject_count++ >= TDLS_SCAN_REJECT_MAX) {
Bala Venkatesh4a3de452019-04-16 15:49:21 +05301776 tdls_notice("Allow this scan req. as already max no of scan's are rejected");
Kabilan Kannanb4c693d2017-03-27 23:42:04 -07001777 tdls_soc->scan_reject_count = 0;
Kabilan Kannanb4c693d2017-03-27 23:42:04 -07001778 status = QDF_STATUS_SUCCESS;
Bala Venkatesh4a3de452019-04-16 15:49:21 +05301779
Kabilan Kannanb4c693d2017-03-27 23:42:04 -07001780 } else {
1781 tdls_warn("tdls in progress. scan rejected %d",
1782 tdls_soc->scan_reject_count);
1783 status = QDF_STATUS_E_BUSY;
1784 }
1785 }
1786return_success:
1787 wlan_objmgr_vdev_release_ref(vdev,
1788 WLAN_TDLS_NB_ID);
1789 return status;
1790}
1791
Varun Reddy Yeturucccf0992017-08-10 13:37:08 -07001792void tdls_scan_serialization_comp_info_cb(struct wlan_objmgr_vdev *vdev,
Kabilan Kannanb4c693d2017-03-27 23:42:04 -07001793 union wlan_serialization_rules_info *comp_info)
1794{
1795 struct tdls_soc_priv_obj *tdls_soc;
1796 QDF_STATUS status;
1797 if (!comp_info)
1798 return;
1799
1800 tdls_soc = tdls_soc_global;
1801 comp_info->scan_info.is_tdls_in_progress = false;
1802 status = tdls_scan_callback(tdls_soc);
1803 if (QDF_STATUS_E_BUSY == status)
1804 comp_info->scan_info.is_tdls_in_progress = true;
1805}
1806
1807
Bala Venkatesh36c69752019-08-20 18:32:03 +05301808uint8_t tdls_get_opclass_from_bandwidth(struct tdls_soc_priv_obj *soc_obj,
1809 uint8_t channel, uint8_t bw_offset)
1810{
1811 uint8_t opclass;
1812
1813 if (bw_offset & (1 << BW_80_OFFSET_BIT)) {
1814 opclass = tdls_find_opclass(soc_obj->soc,
1815 channel, BW80);
1816 } else if (bw_offset & (1 << BW_40_OFFSET_BIT)) {
1817 opclass = tdls_find_opclass(soc_obj->soc,
1818 channel, BW40_LOW_PRIMARY);
1819 if (!opclass) {
1820 opclass = tdls_find_opclass(soc_obj->soc,
1821 channel, BW40_HIGH_PRIMARY);
1822 }
1823 } else if (bw_offset & (1 << BW_20_OFFSET_BIT)) {
1824 opclass = tdls_find_opclass(soc_obj->soc,
1825 channel, BW20);
1826 } else {
1827 opclass = tdls_find_opclass(soc_obj->soc,
1828 channel, BWALL);
1829 }
1830
1831 return opclass;
1832}