xref: /wlan-driver/qcacld-3.0/components/tdls/core/src/wlan_tdls_ct.c (revision 5113495b16420b49004c444715d2daae2066e7dc)
1 /*
2  * Copyright (c) 2017-2021 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_tdls_ct.c
22  *
23  * TDLS connection tracker function definitions
24  */
25 
26 #include "wlan_tdls_main.h"
27 #include "wlan_tdls_peer.h"
28 #include "wlan_tdls_ct.h"
29 #include "wlan_tdls_mgmt.h"
30 #include "wlan_mlo_mgr_sta.h"
31 #include "wlan_tdls_cmds_process.h"
32 #include "wlan_reg_services_api.h"
33 #include "wlan_policy_mgr_api.h"
34 #include "wlan_tdls_tgt_api.h"
35 
tdls_is_vdev_authenticated(struct wlan_objmgr_vdev * vdev)36 bool tdls_is_vdev_authenticated(struct wlan_objmgr_vdev *vdev)
37 {
38 	struct wlan_objmgr_peer *peer;
39 	bool is_authenticated = false;
40 
41 	peer = wlan_objmgr_vdev_try_get_bsspeer(vdev, WLAN_TDLS_NB_ID);
42 	if (!peer) {
43 		tdls_err("peer is null");
44 		return false;
45 	}
46 
47 	is_authenticated = wlan_peer_mlme_get_auth_state(peer);
48 	wlan_objmgr_peer_release_ref(peer, WLAN_TDLS_NB_ID);
49 	return is_authenticated;
50 }
51 
52 /**
53  * tdls_peer_reset_discovery_processed() - reset discovery status
54  * @tdls_vdev: TDLS vdev object
55  *
56  * This function resets discovery processing bit for all TDLS peers
57  *
58  * Caller has to take the lock before calling this function
59  *
60  * Return: 0
61  */
tdls_peer_reset_discovery_processed(struct tdls_vdev_priv_obj * tdls_vdev)62 static int32_t tdls_peer_reset_discovery_processed(
63 					struct tdls_vdev_priv_obj *tdls_vdev)
64 {
65 	int i;
66 	qdf_list_t *head;
67 	qdf_list_node_t *p_node;
68 	struct tdls_peer *peer;
69 	QDF_STATUS status;
70 
71 	tdls_vdev->discovery_peer_cnt = 0;
72 
73 	for (i = 0; i < WLAN_TDLS_PEER_LIST_SIZE; i++) {
74 		head = &tdls_vdev->peer_list[i];
75 		status = qdf_list_peek_front(head, &p_node);
76 		while (QDF_IS_STATUS_SUCCESS(status)) {
77 			peer = qdf_container_of(p_node, struct tdls_peer, node);
78 			peer->discovery_processed = 0;
79 			status = qdf_list_peek_next(head, p_node, &p_node);
80 		}
81 	}
82 
83 	return 0;
84 }
85 
tdls_discovery_timeout_peer_cb(void * user_data)86 void tdls_discovery_timeout_peer_cb(void *user_data)
87 {
88 	int i;
89 	qdf_list_t *head;
90 	qdf_list_node_t *p_node;
91 	struct tdls_peer *peer;
92 	QDF_STATUS status;
93 	struct tdls_vdev_priv_obj *tdls_vdev;
94 	struct tdls_soc_priv_obj *tdls_soc;
95 	struct wlan_objmgr_vdev *vdev;
96 	struct wlan_objmgr_vdev *select_vdev;
97 	struct wlan_objmgr_vdev *tdls_link_vdev;
98 	struct tdls_rx_mgmt_frame *rx_mgmt;
99 	uint8_t *mac;
100 	bool unforce = true;
101 
102 	vdev = user_data;
103 	if (!vdev) {
104 		tdls_err("discovery time out vdev is null");
105 		return;
106 	}
107 
108 	tdls_soc = wlan_vdev_get_tdls_soc_obj(vdev);
109 	if (!tdls_soc)
110 		return;
111 
112 	/* timer_cnt is reset when link switch happens */
113 	if (wlan_vdev_mlme_is_mlo_vdev(vdev) &&
114 	    qdf_atomic_read(&tdls_soc->timer_cnt) == 0)
115 		return;
116 
117 	if (wlan_vdev_mlme_is_mlo_vdev(vdev) &&
118 	    qdf_atomic_dec_and_test(&tdls_soc->timer_cnt)) {
119 		tdls_process_mlo_cal_tdls_link_score(vdev);
120 		select_vdev = tdls_process_mlo_choice_tdls_vdev(vdev);
121 		tdls_link_vdev = tdls_mlo_get_tdls_link_vdev(vdev);
122 		if (select_vdev) {
123 			tdls_vdev =
124 			      wlan_objmgr_vdev_get_comp_private_obj(select_vdev,
125 							   WLAN_UMAC_COMP_TDLS);
126 			rx_mgmt = tdls_vdev->rx_mgmt;
127 			if (tdls_link_vdev && tdls_link_vdev != select_vdev) {
128 				tdls_debug("tdls link created on vdev %d",
129 					   wlan_vdev_get_id(tdls_link_vdev));
130 			} else {
131 				mac =
132 				     &rx_mgmt->buf[TDLS_80211_PEER_ADDR_OFFSET];
133 				tdls_notice("[TDLS] TDLS Discovery Response,"
134 					    "QDF_MAC_ADDR_FMT RSSI[%d]<---OTA",
135 					    rx_mgmt->rx_rssi);
136 				tdls_debug("discovery resp on vdev %d",
137 					   wlan_vdev_get_id(tdls_vdev->vdev));
138 				tdls_recv_discovery_resp(tdls_vdev, mac);
139 				tdls_set_rssi(tdls_vdev->vdev, mac,
140 					      rx_mgmt->rx_rssi);
141 				if (tdls_soc && tdls_soc->tdls_rx_cb)
142 					tdls_soc->tdls_rx_cb(
143 						     tdls_soc->tdls_rx_cb_data,
144 						     rx_mgmt);
145 			}
146 
147 			qdf_mem_free(tdls_vdev->rx_mgmt);
148 			tdls_vdev->rx_mgmt = NULL;
149 			tdls_vdev->link_score = 0;
150 
151 			return;
152 		}
153 
154 		tdls_debug("no discovery response");
155 	}
156 
157 	tdls_vdev = wlan_vdev_get_tdls_vdev_obj(vdev);
158 	if (!tdls_vdev)
159 		return;
160 
161 	for (i = 0; i < WLAN_TDLS_PEER_LIST_SIZE; i++) {
162 		head = &tdls_vdev->peer_list[i];
163 		status = qdf_list_peek_front(head, &p_node);
164 		while (QDF_IS_STATUS_SUCCESS(status)) {
165 			peer = qdf_container_of(p_node, struct tdls_peer,
166 						node);
167 
168 			tdls_debug("Peer: " QDF_MAC_ADDR_FMT " link status %d, vdev id %d",
169 				   QDF_MAC_ADDR_REF(peer->peer_mac.bytes),
170 				   peer->link_status, wlan_vdev_get_id(vdev));
171 
172 			if (peer->link_status != TDLS_LINK_DISCOVERING &&
173 			    peer->link_status != TDLS_LINK_IDLE)
174 				unforce = false;
175 
176 			if (TDLS_LINK_DISCOVERING != peer->link_status) {
177 				status = qdf_list_peek_next(head, p_node,
178 							    &p_node);
179 				continue;
180 			}
181 			tdls_debug(QDF_MAC_ADDR_FMT " to idle state",
182 				   QDF_MAC_ADDR_REF(peer->peer_mac.bytes));
183 			tdls_set_peer_link_status(peer,
184 						  TDLS_LINK_IDLE,
185 						  TDLS_LINK_NOT_SUPPORTED);
186 		}
187 	}
188 
189 	if (wlan_vdev_mlme_is_mlo_vdev(vdev) && unforce) {
190 		tdls_debug("try to set vdev %d to unforce",
191 			   wlan_vdev_get_id(vdev));
192 		tdls_set_link_unforce(vdev);
193 	}
194 
195 	tdls_vdev->discovery_sent_cnt = 0;
196 	/* add tdls power save prohibited */
197 
198 	return;
199 }
200 
201 /**
202  * tdls_reset_tx_rx() - reset tx/rx counters for all tdls peers
203  * @tdls_vdev: TDLS vdev object
204  *
205  * Caller has to take the TDLS lock before calling this function
206  *
207  * Return: Void
208  */
tdls_reset_tx_rx(struct tdls_vdev_priv_obj * tdls_vdev)209 static void tdls_reset_tx_rx(struct tdls_vdev_priv_obj *tdls_vdev)
210 {
211 	int i;
212 	qdf_list_t *head;
213 	qdf_list_node_t *p_node;
214 	struct tdls_peer *peer;
215 	QDF_STATUS status;
216 	struct tdls_soc_priv_obj *tdls_soc;
217 
218 	tdls_soc = wlan_vdev_get_tdls_soc_obj(tdls_vdev->vdev);
219 	if (!tdls_soc)
220 		return;
221 
222 	/* reset stale connection tracker */
223 	qdf_spin_lock_bh(&tdls_soc->tdls_ct_spinlock);
224 	tdls_vdev->valid_mac_entries = 0;
225 	qdf_spin_unlock_bh(&tdls_soc->tdls_ct_spinlock);
226 
227 	for (i = 0; i < WLAN_TDLS_PEER_LIST_SIZE; i++) {
228 		head = &tdls_vdev->peer_list[i];
229 		status = qdf_list_peek_front(head, &p_node);
230 		while (QDF_IS_STATUS_SUCCESS(status)) {
231 			peer = qdf_container_of(p_node, struct tdls_peer, node);
232 			peer->tx_pkt = 0;
233 			peer->rx_pkt = 0;
234 			status = qdf_list_peek_next(head, p_node, &p_node);
235 		}
236 	}
237 	return;
238 }
239 
tdls_implicit_disable(struct tdls_vdev_priv_obj * tdls_vdev)240 void tdls_implicit_disable(struct tdls_vdev_priv_obj *tdls_vdev)
241 {
242 	tdls_debug("Disable Implicit TDLS");
243 	tdls_timers_stop(tdls_vdev);
244 }
245 
246 /**
247  * tdls_implicit_enable() - enable implicit tdls triggering
248  * @tdls_vdev: TDLS vdev
249  *
250  * Return: Void
251  */
tdls_implicit_enable(struct tdls_vdev_priv_obj * tdls_vdev)252 void tdls_implicit_enable(struct tdls_vdev_priv_obj *tdls_vdev)
253 {
254 	if (!tdls_vdev)
255 		return;
256 
257 	tdls_debug("vdev:%d Enable Implicit TDLS",
258 		   wlan_vdev_get_id(tdls_vdev->vdev));
259 
260 	tdls_peer_reset_discovery_processed(tdls_vdev);
261 	tdls_reset_tx_rx(tdls_vdev);
262 	/* TODO check whether tdls power save prohibited */
263 
264 	/* Restart the connection tracker timer */
265 	tdls_timer_restart(tdls_vdev->vdev, &tdls_vdev->peer_update_timer,
266 			   tdls_vdev->threshold_config.tx_period_t);
267 }
268 
269 /**
270  * tdls_ct_sampling_tx_rx() - collect tx/rx traffic sample
271  * @tdls_vdev: tdls vdev object
272  * @tdls_soc: tdls soc object
273  *
274  * Function to update data traffic information in tdls connection
275  * tracker data structure for connection tracker operation
276  *
277  * Return: None
278  */
tdls_ct_sampling_tx_rx(struct tdls_vdev_priv_obj * tdls_vdev,struct tdls_soc_priv_obj * tdls_soc)279 static void tdls_ct_sampling_tx_rx(struct tdls_vdev_priv_obj *tdls_vdev,
280 				   struct tdls_soc_priv_obj *tdls_soc)
281 {
282 	struct tdls_peer *curr_peer;
283 	uint8_t mac[QDF_MAC_ADDR_SIZE];
284 	uint8_t mac_cnt;
285 	uint8_t mac_entries;
286 	struct tdls_conn_tracker_mac_table mac_table[WLAN_TDLS_CT_TABLE_SIZE];
287 
288 	qdf_spin_lock_bh(&tdls_soc->tdls_ct_spinlock);
289 
290 	if (0 == tdls_vdev->valid_mac_entries) {
291 		qdf_spin_unlock_bh(&tdls_soc->tdls_ct_spinlock);
292 		return;
293 	}
294 
295 	mac_entries = QDF_MIN(tdls_vdev->valid_mac_entries,
296 			      WLAN_TDLS_CT_TABLE_SIZE);
297 
298 	qdf_mem_copy(mac_table, tdls_vdev->ct_peer_table,
299 	       (sizeof(struct tdls_conn_tracker_mac_table)) * mac_entries);
300 
301 	qdf_mem_zero(tdls_vdev->ct_peer_table,
302 	       (sizeof(struct tdls_conn_tracker_mac_table)) * mac_entries);
303 
304 	tdls_vdev->valid_mac_entries = 0;
305 
306 	qdf_spin_unlock_bh(&tdls_soc->tdls_ct_spinlock);
307 
308 	for (mac_cnt = 0; mac_cnt < mac_entries; mac_cnt++) {
309 		qdf_mem_copy(mac, mac_table[mac_cnt].mac_address.bytes,
310 		       QDF_MAC_ADDR_SIZE);
311 		curr_peer = tdls_get_peer(tdls_vdev, mac);
312 		if (curr_peer) {
313 			curr_peer->tx_pkt =
314 			mac_table[mac_cnt].tx_packet_cnt;
315 			curr_peer->rx_pkt =
316 			mac_table[mac_cnt].rx_packet_cnt;
317 		}
318 	}
319 }
320 
tdls_update_rx_pkt_cnt(struct wlan_objmgr_vdev * vdev,struct qdf_mac_addr * mac_addr,struct qdf_mac_addr * dest_mac_addr)321 void tdls_update_rx_pkt_cnt(struct wlan_objmgr_vdev *vdev,
322 				 struct qdf_mac_addr *mac_addr,
323 				 struct qdf_mac_addr *dest_mac_addr)
324 {
325 	struct tdls_vdev_priv_obj *tdls_vdev_obj;
326 	struct tdls_soc_priv_obj *tdls_soc_obj;
327 	uint8_t mac_cnt;
328 	uint8_t valid_mac_entries;
329 	struct tdls_conn_tracker_mac_table *mac_table;
330 	struct wlan_objmgr_peer *bss_peer;
331 
332 	if (QDF_STATUS_SUCCESS != tdls_get_vdev_objects(vdev, &tdls_vdev_obj,
333 							&tdls_soc_obj))
334 		return;
335 
336 	if (!tdls_soc_obj->enable_tdls_connection_tracker)
337 		return;
338 
339 	/* Here we do without lock to ensure that in high throughput scenarios
340 	 * its fast and we quickly check the right mac entry and increment
341 	 * the pkt count. Here it may happen that
342 	 * "tdls_vdev_obj->valid_mac_entries", "tdls_vdev_obj->ct_peer_table"
343 	 * becomes zero in another thread but we are ok as this will not
344 	 * lead to any crash.
345 	 */
346 	valid_mac_entries = tdls_vdev_obj->valid_mac_entries;
347 	mac_table = tdls_vdev_obj->ct_peer_table;
348 
349 	for (mac_cnt = 0; mac_cnt < valid_mac_entries; mac_cnt++) {
350 		if (qdf_mem_cmp(mac_table[mac_cnt].mac_address.bytes,
351 		    mac_addr, QDF_MAC_ADDR_SIZE) == 0) {
352 			mac_table[mac_cnt].rx_packet_cnt++;
353 			return;
354 		}
355 	}
356 
357 	if (qdf_is_macaddr_group(mac_addr))
358 		return;
359 
360 	if (qdf_is_macaddr_group(dest_mac_addr))
361 		return;
362 
363 	if (!qdf_mem_cmp(vdev->vdev_mlme.macaddr, mac_addr,
364 			 QDF_MAC_ADDR_SIZE))
365 		return;
366 
367 	bss_peer = wlan_objmgr_vdev_try_get_bsspeer(vdev, WLAN_TDLS_NB_ID);
368 	if (bss_peer) {
369 		if (!qdf_mem_cmp(bss_peer->macaddr, mac_addr,
370 				 QDF_MAC_ADDR_SIZE)) {
371 			wlan_objmgr_peer_release_ref(bss_peer, WLAN_TDLS_NB_ID);
372 			return;
373 		}
374 		wlan_objmgr_peer_release_ref(bss_peer, WLAN_TDLS_NB_ID);
375 	}
376 	qdf_spin_lock_bh(&tdls_soc_obj->tdls_ct_spinlock);
377 
378 	/* when we take the lock we need to get the valid mac entries
379 	 * again as it may become zero in another thread and if is 0 then
380 	 * we need to reset "mac_cnt" to zero so that at zeroth index we
381 	 * add new entry
382 	 */
383 	valid_mac_entries = tdls_vdev_obj->valid_mac_entries;
384 	if (!valid_mac_entries)
385 		mac_cnt = 0;
386 
387 	/* If we have more than 8 peers within 30 mins. we will
388 	 *  stop tracking till the old entries are removed
389 	 */
390 	if (mac_cnt < WLAN_TDLS_CT_TABLE_SIZE) {
391 		qdf_mem_copy(mac_table[mac_cnt].mac_address.bytes,
392 		       mac_addr, QDF_MAC_ADDR_SIZE);
393 		tdls_vdev_obj->valid_mac_entries = mac_cnt+1;
394 		mac_table[mac_cnt].rx_packet_cnt = 1;
395 	}
396 
397 	qdf_spin_unlock_bh(&tdls_soc_obj->tdls_ct_spinlock);
398 	return;
399 }
400 
tdls_update_tx_pkt_cnt(struct wlan_objmgr_vdev * vdev,struct qdf_mac_addr * mac_addr)401 void tdls_update_tx_pkt_cnt(struct wlan_objmgr_vdev *vdev,
402 			    struct qdf_mac_addr *mac_addr)
403 {
404 	struct tdls_vdev_priv_obj *tdls_vdev_obj;
405 	struct tdls_soc_priv_obj *tdls_soc_obj;
406 	uint8_t mac_cnt;
407 	uint8_t valid_mac_entries;
408 	struct tdls_conn_tracker_mac_table *mac_table;
409 	struct wlan_objmgr_peer *bss_peer;
410 
411 	if (QDF_STATUS_SUCCESS != tdls_get_vdev_objects(vdev, &tdls_vdev_obj,
412 							&tdls_soc_obj))
413 		return;
414 
415 	if (!tdls_soc_obj->enable_tdls_connection_tracker)
416 		return;
417 
418 	/* Here we do without lock to ensure that in high throughput scenarios
419 	 * its fast and we quickly check the right mac entry and increment
420 	 * the pkt count. Here it may happen that
421 	 * "tdls_vdev_obj->valid_mac_entries", "tdls_vdev_obj->ct_peer_table"
422 	 * becomes zero in another thread but we are ok as this will not
423 	 * lead to any crash.
424 	 */
425 	mac_table = tdls_vdev_obj->ct_peer_table;
426 	valid_mac_entries = tdls_vdev_obj->valid_mac_entries;
427 
428 	for (mac_cnt = 0; mac_cnt < valid_mac_entries; mac_cnt++) {
429 		if (qdf_mem_cmp(mac_table[mac_cnt].mac_address.bytes,
430 		    mac_addr, QDF_MAC_ADDR_SIZE) == 0) {
431 			mac_table[mac_cnt].tx_packet_cnt++;
432 			return;
433 		}
434 	}
435 
436 	if (qdf_is_macaddr_group(mac_addr))
437 		return;
438 
439 	if (!qdf_mem_cmp(vdev->vdev_mlme.macaddr, mac_addr,
440 			 QDF_MAC_ADDR_SIZE))
441 		return;
442 	bss_peer = wlan_objmgr_vdev_try_get_bsspeer(vdev, WLAN_TDLS_NB_ID);
443 	if (bss_peer) {
444 		if (!qdf_mem_cmp(bss_peer->macaddr, mac_addr,
445 				 QDF_MAC_ADDR_SIZE)) {
446 			wlan_objmgr_peer_release_ref(bss_peer, WLAN_TDLS_NB_ID);
447 			return;
448 		}
449 		wlan_objmgr_peer_release_ref(bss_peer, WLAN_TDLS_NB_ID);
450 	}
451 
452 	qdf_spin_lock_bh(&tdls_soc_obj->tdls_ct_spinlock);
453 
454 	/* when we take the lock we need to get the valid mac entries
455 	 * again as it may become zero in another thread and if is 0 then
456 	 * we need to reset "mac_cnt" to zero so that at zeroth index we
457 	 * add new entry
458 	 */
459 	valid_mac_entries = tdls_vdev_obj->valid_mac_entries;
460 	if (!valid_mac_entries)
461 		mac_cnt = 0;
462 
463 	/* If we have more than 8 peers within 30 mins. we will
464 	 *  stop tracking till the old entries are removed
465 	 */
466 	if (mac_cnt < WLAN_TDLS_CT_TABLE_SIZE) {
467 		qdf_mem_copy(mac_table[mac_cnt].mac_address.bytes,
468 			mac_addr, QDF_MAC_ADDR_SIZE);
469 		mac_table[mac_cnt].tx_packet_cnt = 1;
470 		tdls_vdev_obj->valid_mac_entries++;
471 	}
472 
473 	qdf_spin_unlock_bh(&tdls_soc_obj->tdls_ct_spinlock);
474 	return;
475 }
476 
477 void
tdls_implicit_send_discovery_request(struct tdls_vdev_priv_obj * tdls_vdev_obj)478 tdls_implicit_send_discovery_request(struct tdls_vdev_priv_obj *tdls_vdev_obj)
479 {
480 	struct tdls_peer *curr_peer;
481 	struct tdls_peer *temp_peer;
482 	struct tdls_soc_priv_obj *tdls_psoc;
483 	struct tdls_osif_indication tdls_ind;
484 
485 	if (!tdls_vdev_obj) {
486 		tdls_notice("tdls_vdev_obj is NULL");
487 		return;
488 	}
489 
490 	tdls_psoc = wlan_vdev_get_tdls_soc_obj(tdls_vdev_obj->vdev);
491 
492 	if (!tdls_psoc) {
493 		tdls_notice("tdls_psoc_obj is NULL");
494 		return;
495 	}
496 
497 	curr_peer = tdls_vdev_obj->curr_candidate;
498 
499 	if (!curr_peer) {
500 		tdls_err("curr_peer is NULL");
501 		return;
502 	}
503 
504 	/* This function is called in mutex_lock */
505 	temp_peer = tdls_is_progress(tdls_vdev_obj, NULL, 0);
506 	if (temp_peer) {
507 		tdls_notice(QDF_MAC_ADDR_FMT " ongoing. pre_setup ignored",
508 			    QDF_MAC_ADDR_REF(temp_peer->peer_mac.bytes));
509 		goto done;
510 	}
511 
512 	if (TDLS_CAP_UNKNOWN != curr_peer->tdls_support)
513 		tdls_set_peer_link_status(curr_peer,
514 					  TDLS_LINK_DISCOVERING,
515 					  TDLS_LINK_SUCCESS);
516 
517 	qdf_mem_copy(tdls_ind.peer_mac, curr_peer->peer_mac.bytes,
518 			QDF_MAC_ADDR_SIZE);
519 
520 	tdls_ind.vdev = tdls_vdev_obj->vdev;
521 
522 	tdls_debug("Implicit TDLS, Send Discovery request event");
523 
524 	tdls_psoc->tdls_event_cb(tdls_psoc->tdls_evt_cb_data,
525 				 TDLS_EVENT_DISCOVERY_REQ, &tdls_ind);
526 
527 	if (!wlan_vdev_mlme_is_mlo_vdev(tdls_vdev_obj->vdev)) {
528 		tdls_vdev_obj->discovery_sent_cnt++;
529 		tdls_timer_restart(tdls_vdev_obj->vdev,
530 				   &tdls_vdev_obj->peer_discovery_timer,
531 				   tdls_vdev_obj->threshold_config.tx_period_t -
532 				   TDLS_DISCOVERY_TIMEOUT_ERE_UPDATE);
533 
534 		tdls_debug("discovery count %u timeout %u msec",
535 			   tdls_vdev_obj->discovery_sent_cnt,
536 			   tdls_vdev_obj->threshold_config.tx_period_t -
537 			   TDLS_DISCOVERY_TIMEOUT_ERE_UPDATE);
538 	}
539 done:
540 	tdls_vdev_obj->curr_candidate = NULL;
541 	tdls_vdev_obj->magic = 0;
542 	return;
543 }
544 
tdls_recv_discovery_resp(struct tdls_vdev_priv_obj * tdls_vdev,const uint8_t * mac)545 int tdls_recv_discovery_resp(struct tdls_vdev_priv_obj *tdls_vdev,
546 				   const uint8_t *mac)
547 {
548 	struct tdls_peer *curr_peer;
549 	struct tdls_soc_priv_obj *tdls_soc;
550 	struct tdls_osif_indication indication;
551 	struct tdls_config_params *tdls_cfg;
552 	int status = 0;
553 
554 	if (!tdls_vdev)
555 		return -EINVAL;
556 
557 	tdls_soc = wlan_vdev_get_tdls_soc_obj(tdls_vdev->vdev);
558 	if (!tdls_soc) {
559 		tdls_err("tdls soc is NULL");
560 		return -EINVAL;
561 	}
562 
563 	curr_peer = tdls_get_peer(tdls_vdev, mac);
564 	if (!curr_peer) {
565 		tdls_err("curr_peer is NULL");
566 		return -EINVAL;
567 	}
568 
569 	if (!wlan_vdev_mlme_is_mlo_vdev(tdls_vdev->vdev)) {
570 		if (tdls_vdev->discovery_sent_cnt)
571 			tdls_vdev->discovery_sent_cnt--;
572 
573 		if (tdls_vdev->discovery_sent_cnt == 0)
574 			qdf_mc_timer_stop(&tdls_vdev->peer_discovery_timer);
575 	}
576 
577 	tdls_debug("[TDLS] vdev:%d action:%d (%s) sent_count:%u from peer " QDF_MAC_ADDR_FMT
578 		   " link_status %d", wlan_vdev_get_id(tdls_vdev->vdev),
579 		   TDLS_DISCOVERY_RESPONSE,
580 		   "TDLS_DISCOVERY_RESPONSE",
581 		   tdls_vdev->discovery_sent_cnt,
582 		   QDF_MAC_ADDR_REF(curr_peer->peer_mac.bytes),
583 		   curr_peer->link_status);
584 
585 	/*
586 	 * Since peer link status bases on vdev and stream goes through
587 	 * vdev0 (assoc link) at start, rx/tx pkt count on vdev0, but
588 	 * it choices vdev1 as tdls link, the peer status does not change on
589 	 * vdev1 though it has been changed for vdev0 per the rx/tx pkt count.
590 	 */
591 	if (wlan_vdev_mlme_is_mlo_vdev(tdls_vdev->vdev) &&
592 	    curr_peer->link_status == TDLS_LINK_IDLE)
593 		tdls_set_peer_link_status(curr_peer, TDLS_LINK_DISCOVERING,
594 					  TDLS_LINK_SUCCESS);
595 
596 	tdls_cfg = &tdls_vdev->threshold_config;
597 	if (TDLS_LINK_DISCOVERING == curr_peer->link_status) {
598 		/* Since we are here, it means Throughput threshold is
599 		 * already met. Make sure RSSI threshold is also met
600 		 * before setting up TDLS link.
601 		 */
602 		if ((int32_t) curr_peer->rssi >
603 		    (int32_t) tdls_cfg->rssi_trigger_threshold) {
604 			tdls_set_peer_link_status(curr_peer,
605 						TDLS_LINK_DISCOVERED,
606 						TDLS_LINK_SUCCESS);
607 			tdls_debug("Rssi Threshold met: " QDF_MAC_ADDR_FMT
608 				" rssi = %d threshold= %d",
609 				QDF_MAC_ADDR_REF(curr_peer->peer_mac.bytes),
610 				curr_peer->rssi,
611 				tdls_cfg->rssi_trigger_threshold);
612 
613 			qdf_mem_copy(indication.peer_mac, mac,
614 					QDF_MAC_ADDR_SIZE);
615 
616 			indication.vdev = tdls_vdev->vdev;
617 
618 			tdls_soc->tdls_event_cb(tdls_soc->tdls_evt_cb_data,
619 						TDLS_EVENT_SETUP_REQ,
620 						&indication);
621 		} else {
622 			tdls_debug("Rssi Threshold not met: " QDF_MAC_ADDR_FMT
623 				" rssi = %d threshold = %d ",
624 				QDF_MAC_ADDR_REF(curr_peer->peer_mac.bytes),
625 				curr_peer->rssi,
626 				tdls_cfg->rssi_trigger_threshold);
627 
628 			tdls_set_peer_link_status(curr_peer,
629 						TDLS_LINK_IDLE,
630 						TDLS_LINK_UNSPECIFIED);
631 
632 			/* if RSSI threshold is not met then allow
633 			 * further discovery attempts by decrementing
634 			 * count for the last attempt
635 			 */
636 			if (curr_peer->discovery_attempt)
637 				curr_peer->discovery_attempt--;
638 		}
639 	}
640 
641 	curr_peer->tdls_support = TDLS_CAP_SUPPORTED;
642 
643 	return status;
644 }
645 
tdls_indicate_teardown(struct tdls_vdev_priv_obj * tdls_vdev,struct tdls_peer * curr_peer,uint16_t reason)646 void tdls_indicate_teardown(struct tdls_vdev_priv_obj *tdls_vdev,
647 			    struct tdls_peer *curr_peer,
648 			    uint16_t reason)
649 {
650 	struct tdls_soc_priv_obj *tdls_soc;
651 	struct tdls_osif_indication indication;
652 
653 	if (!tdls_vdev || !curr_peer) {
654 		tdls_err("tdls_vdev: %pK, curr_peer: %pK",
655 			 tdls_vdev, curr_peer);
656 		return;
657 	}
658 
659 	tdls_soc = wlan_vdev_get_tdls_soc_obj(tdls_vdev->vdev);
660 	if (!tdls_soc) {
661 		tdls_err("tdls_soc: %pK", tdls_soc);
662 		return;
663 	}
664 
665 	if (curr_peer->link_status != TDLS_LINK_CONNECTED) {
666 		tdls_err("link state %d peer:" QDF_MAC_ADDR_FMT,
667 			 curr_peer->link_status,
668 			 QDF_MAC_ADDR_REF(curr_peer->peer_mac.bytes));
669 		return;
670 	}
671 
672 	tdls_set_peer_link_status(curr_peer, TDLS_LINK_TEARING,
673 				  TDLS_LINK_UNSPECIFIED);
674 	tdls_notice("vdev:%d Teardown reason %d peer:" QDF_MAC_ADDR_FMT,
675 		    wlan_vdev_get_id(tdls_vdev->vdev), reason,
676 		    QDF_MAC_ADDR_REF(curr_peer->peer_mac.bytes));
677 
678 	if (tdls_soc->tdls_dp_vdev_update)
679 		tdls_soc->tdls_dp_vdev_update(
680 				&tdls_soc->soc,
681 				wlan_vdev_get_id(tdls_vdev->vdev),
682 				tdls_soc->tdls_update_dp_vdev_flags,
683 				false);
684 
685 	indication.reason = reason;
686 	indication.vdev = tdls_vdev->vdev;
687 	qdf_mem_copy(indication.peer_mac, curr_peer->peer_mac.bytes,
688 			QDF_MAC_ADDR_SIZE);
689 
690 	if (tdls_soc->tdls_event_cb)
691 		tdls_soc->tdls_event_cb(tdls_soc->tdls_evt_cb_data,
692 				     TDLS_EVENT_TEARDOWN_REQ, &indication);
693 }
694 
695 /**
696  * tdls_get_conn_info() - get the tdls connection information.
697  * @tdls_soc: tdls soc object
698  * @peer_mac: peer MAC address
699  *
700  * Function to check tdls sta index
701  *
702  * Return: tdls connection information
703  */
704 static struct tdls_conn_info *
tdls_get_conn_info(struct tdls_soc_priv_obj * tdls_soc,struct qdf_mac_addr * peer_mac)705 tdls_get_conn_info(struct tdls_soc_priv_obj *tdls_soc,
706 		   struct qdf_mac_addr *peer_mac)
707 {
708 	uint8_t sta_idx;
709 	/* check if there is available index for this new TDLS STA */
710 	for (sta_idx = 0; sta_idx < WLAN_TDLS_STA_MAX_NUM; sta_idx++) {
711 		if (!qdf_mem_cmp(
712 			    tdls_soc->tdls_conn_info[sta_idx].peer_mac.bytes,
713 			    peer_mac->bytes, QDF_MAC_ADDR_SIZE)) {
714 			tdls_debug("tdls peer exists idx %d " QDF_MAC_ADDR_FMT,
715 				   sta_idx,
716 				   QDF_MAC_ADDR_REF(peer_mac->bytes));
717 			tdls_soc->tdls_conn_info[sta_idx].index = sta_idx;
718 			return &tdls_soc->tdls_conn_info[sta_idx];
719 		}
720 	}
721 
722 	tdls_err("tdls peer does not exists");
723 	return NULL;
724 }
725 
726 static void
tdls_ct_process_idle_handler(struct wlan_objmgr_vdev * vdev,struct tdls_conn_info * tdls_info)727 tdls_ct_process_idle_handler(struct wlan_objmgr_vdev *vdev,
728 			     struct tdls_conn_info *tdls_info)
729 {
730 	struct tdls_peer *curr_peer;
731 	struct tdls_vdev_priv_obj *tdls_vdev_obj;
732 	struct tdls_soc_priv_obj *tdls_soc_obj;
733 
734 	if (QDF_STATUS_SUCCESS != tdls_get_vdev_objects(vdev, &tdls_vdev_obj,
735 						   &tdls_soc_obj))
736 		return;
737 
738 	if (!tdls_info->valid_entry) {
739 		tdls_err("peer doesn't exists");
740 		return;
741 	}
742 
743 	curr_peer = tdls_find_peer(tdls_vdev_obj,
744 		(u8 *) &tdls_info->peer_mac.bytes[0]);
745 
746 	if (!curr_peer) {
747 		tdls_err("Invalid tdls idle timer expired");
748 		return;
749 	}
750 
751 	tdls_debug(QDF_MAC_ADDR_FMT
752 		" tx_pkt: %d, rx_pkt: %d, idle_packet_n: %d",
753 		QDF_MAC_ADDR_REF(curr_peer->peer_mac.bytes),
754 		curr_peer->tx_pkt,
755 		curr_peer->rx_pkt,
756 		tdls_vdev_obj->threshold_config.idle_packet_n);
757 
758 	/* Check tx/rx statistics on this tdls link for recent activities and
759 	 * then decide whether to tear down the link or keep it.
760 	 */
761 	if ((curr_peer->tx_pkt >=
762 	     tdls_vdev_obj->threshold_config.idle_packet_n) ||
763 	    (curr_peer->rx_pkt >=
764 	     tdls_vdev_obj->threshold_config.idle_packet_n)) {
765 		/* this tdls link got back to normal, so keep it */
766 		tdls_debug("tdls link to " QDF_MAC_ADDR_FMT
767 			 " back to normal, will stay",
768 			  QDF_MAC_ADDR_REF(curr_peer->peer_mac.bytes));
769 	} else {
770 		/* this tdls link needs to get torn down */
771 		tdls_notice("trigger tdls link to "QDF_MAC_ADDR_FMT" down",
772 			    QDF_MAC_ADDR_REF(curr_peer->peer_mac.bytes));
773 		tdls_indicate_teardown(tdls_vdev_obj,
774 					curr_peer,
775 					TDLS_TEARDOWN_PEER_UNSPEC_REASON);
776 	}
777 
778 	return;
779 }
780 
tdls_ct_idle_handler(void * user_data)781 void tdls_ct_idle_handler(void *user_data)
782 {
783 	struct wlan_objmgr_vdev *vdev;
784 	struct tdls_conn_info *tdls_info;
785 	struct tdls_soc_priv_obj *tdls_soc_obj;
786 	uint32_t idx;
787 
788 	tdls_info = (struct tdls_conn_info *)user_data;
789 	if (!tdls_info)
790 		return;
791 
792 	idx = tdls_info->index;
793 	if (idx == INVALID_TDLS_PEER_INDEX || idx >= WLAN_TDLS_STA_MAX_NUM) {
794 		tdls_debug("invalid peer index %d" QDF_MAC_ADDR_FMT, idx,
795 			  QDF_MAC_ADDR_REF(tdls_info->peer_mac.bytes));
796 		return;
797 	}
798 
799 	tdls_soc_obj = qdf_container_of(tdls_info, struct tdls_soc_priv_obj,
800 					tdls_conn_info[idx]);
801 
802 	vdev = tdls_get_vdev(tdls_soc_obj->soc, WLAN_TDLS_NB_ID);
803 	if (!vdev) {
804 		tdls_err("Unable to fetch the vdev");
805 		return;
806 	}
807 
808 	tdls_ct_process_idle_handler(vdev, tdls_info);
809 	wlan_objmgr_vdev_release_ref(vdev,
810 				     WLAN_TDLS_NB_ID);
811 }
812 
813 /**
814  * tdls_ct_process_idle_and_discovery() - process the traffic data
815  * @curr_peer: tdls peer needs to be examined
816  * @tdls_vdev_obj: tdls vdev object
817  * @tdls_soc_obj: tdls soc object
818  *
819  * Function to check the peer traffic data in idle link and  tdls
820  * discovering link
821  *
822  * Return: None
823  */
824 static void
tdls_ct_process_idle_and_discovery(struct tdls_peer * curr_peer,struct tdls_vdev_priv_obj * tdls_vdev_obj,struct tdls_soc_priv_obj * tdls_soc_obj)825 tdls_ct_process_idle_and_discovery(struct tdls_peer *curr_peer,
826 				   struct tdls_vdev_priv_obj *tdls_vdev_obj,
827 				   struct tdls_soc_priv_obj *tdls_soc_obj)
828 {
829 	uint16_t valid_peers;
830 
831 	valid_peers = tdls_soc_obj->connected_peer_count;
832 
833 	if ((curr_peer->tx_pkt + curr_peer->rx_pkt) >=
834 	     tdls_vdev_obj->threshold_config.tx_packet_n) {
835 		if (WLAN_TDLS_STA_MAX_NUM > valid_peers) {
836 			tdls_notice("Tput trigger TDLS pre-setup");
837 			tdls_vdev_obj->curr_candidate = curr_peer;
838 			tdls_implicit_send_discovery_request(tdls_vdev_obj);
839 		} else {
840 			tdls_notice("Maximum peers connected already! %d",
841 				 valid_peers);
842 		}
843 	}
844 }
845 
846 /**
847  * tdls_ct_process_connected_link() - process the traffic
848  * @curr_peer: tdls peer needs to be examined
849  * @tdls_vdev: tdls vdev
850  * @tdls_soc: tdls soc context
851  *
852  * Function to check the peer traffic data in active STA
853  * session
854  *
855  * Return: None
856  */
tdls_ct_process_connected_link(struct tdls_peer * curr_peer,struct tdls_vdev_priv_obj * tdls_vdev,struct tdls_soc_priv_obj * tdls_soc)857 static void tdls_ct_process_connected_link(
858 				struct tdls_peer *curr_peer,
859 				struct tdls_vdev_priv_obj *tdls_vdev,
860 				struct tdls_soc_priv_obj *tdls_soc)
861 {
862 	/* Don't trigger low rssi tear down here since FW will do it */
863 	/* Only teardown based on non zero idle packet threshold, to address
864 	 * a use case where this threshold does not get consider for TEAR DOWN
865 	 */
866 	if ((0 != tdls_vdev->threshold_config.idle_packet_n) &&
867 	    ((curr_peer->tx_pkt <
868 	      tdls_vdev->threshold_config.idle_packet_n) &&
869 	     (curr_peer->rx_pkt <
870 	      tdls_vdev->threshold_config.idle_packet_n))) {
871 		if (!curr_peer->is_peer_idle_timer_initialised) {
872 			struct tdls_conn_info *tdls_info;
873 			tdls_info = tdls_get_conn_info(tdls_soc,
874 						       &curr_peer->peer_mac);
875 			qdf_mc_timer_init(&curr_peer->peer_idle_timer,
876 					  QDF_TIMER_TYPE_SW,
877 					  tdls_ct_idle_handler,
878 					  (void *)tdls_info);
879 			curr_peer->is_peer_idle_timer_initialised = true;
880 		}
881 		if (QDF_TIMER_STATE_RUNNING !=
882 		    curr_peer->peer_idle_timer.state) {
883 			tdls_warn("Tx/Rx Idle timer start: "
884 				QDF_MAC_ADDR_FMT "!",
885 				QDF_MAC_ADDR_REF(curr_peer->peer_mac.bytes));
886 			tdls_timer_restart(tdls_vdev->vdev,
887 				&curr_peer->peer_idle_timer,
888 				tdls_vdev->threshold_config.idle_timeout_t);
889 		}
890 	} else if (QDF_TIMER_STATE_RUNNING ==
891 		   curr_peer->peer_idle_timer.state) {
892 		tdls_warn("Tx/Rx Idle timer stop: " QDF_MAC_ADDR_FMT "!",
893 			 QDF_MAC_ADDR_REF(curr_peer->peer_mac.bytes));
894 		qdf_mc_timer_stop(&curr_peer->peer_idle_timer);
895 	}
896 }
897 
898 /**
899  * tdls_ct_process_cap_supported() - process TDLS supported peer.
900  * @curr_peer: tdls peer needs to be examined
901  * @tdls_vdev: tdls vdev context
902  * @tdls_soc_obj: tdls soc context
903  *
904  * Function to check the peer traffic data  for tdls supported peer
905  *
906  * Return: None
907  */
908 static void
tdls_ct_process_cap_supported(struct tdls_peer * curr_peer,struct tdls_vdev_priv_obj * tdls_vdev,struct tdls_soc_priv_obj * tdls_soc_obj)909 tdls_ct_process_cap_supported(struct tdls_peer *curr_peer,
910 			      struct tdls_vdev_priv_obj *tdls_vdev,
911 			      struct tdls_soc_priv_obj *tdls_soc_obj)
912 {
913 	if (curr_peer->rx_pkt || curr_peer->tx_pkt)
914 		tdls_debug(QDF_MAC_ADDR_FMT "link_status %d tdls_support %d tx %d rx %d rssi %d vdev %d",
915 			   QDF_MAC_ADDR_REF(curr_peer->peer_mac.bytes),
916 			   curr_peer->link_status, curr_peer->tdls_support,
917 			   curr_peer->tx_pkt, curr_peer->rx_pkt,
918 			   curr_peer->rssi, wlan_vdev_get_id(tdls_vdev->vdev));
919 
920 	switch (curr_peer->link_status) {
921 	case TDLS_LINK_IDLE:
922 	case TDLS_LINK_DISCOVERING:
923 		if (!curr_peer->is_forced_peer &&
924 		    TDLS_IS_EXTERNAL_CONTROL_ENABLED(
925 			tdls_soc_obj->tdls_configs.tdls_feature_flags))
926 			break;
927 
928 		tdls_ct_process_idle_and_discovery(curr_peer, tdls_vdev,
929 						   tdls_soc_obj);
930 		break;
931 	case TDLS_LINK_CONNECTED:
932 		tdls_ct_process_connected_link(curr_peer, tdls_vdev,
933 					       tdls_soc_obj);
934 		break;
935 	default:
936 		break;
937 	}
938 }
939 
940 /**
941  * tdls_ct_process_cap_unknown() - process unknown peer
942  * @curr_peer: tdls peer needs to be examined
943  * @tdls_vdev: tdls vdev object
944  * @tdls_soc: tdls soc object
945  *
946  * Function check the peer traffic data , when tdls capability is unknown
947  *
948  * Return: None
949  */
tdls_ct_process_cap_unknown(struct tdls_peer * curr_peer,struct tdls_vdev_priv_obj * tdls_vdev,struct tdls_soc_priv_obj * tdls_soc)950 static void tdls_ct_process_cap_unknown(struct tdls_peer *curr_peer,
951 					struct tdls_vdev_priv_obj *tdls_vdev,
952 					struct tdls_soc_priv_obj *tdls_soc)
953 {
954 	if (!curr_peer->is_forced_peer &&
955 	    TDLS_IS_EXTERNAL_CONTROL_ENABLED(
956 				tdls_soc->tdls_configs.tdls_feature_flags))
957 		return;
958 
959 	if (curr_peer->rx_pkt || curr_peer->tx_pkt)
960 		tdls_debug(QDF_MAC_ADDR_FMT " link_status %d tdls_support %d tx %d rx %d vdev %d",
961 			   QDF_MAC_ADDR_REF(curr_peer->peer_mac.bytes),
962 			   curr_peer->link_status, curr_peer->tdls_support,
963 			   curr_peer->tx_pkt, curr_peer->rx_pkt,
964 			   wlan_vdev_get_id(tdls_vdev->vdev));
965 
966 	if (TDLS_IS_LINK_CONNECTED(curr_peer))
967 		return;
968 
969 	if ((curr_peer->tx_pkt + curr_peer->rx_pkt) >=
970 	     tdls_vdev->threshold_config.tx_packet_n) {
971 		/*
972 		 * Ignore discovery attempt if External Control is enabled, that
973 		 * is, peer is forced. In that case, continue discovery attempt
974 		 * regardless attempt count
975 		 */
976 		tdls_debug("TDLS UNKNOWN pre discover ");
977 		if (curr_peer->is_forced_peer ||
978 		    curr_peer->discovery_attempt <
979 		    tdls_vdev->threshold_config.discovery_tries_n) {
980 			tdls_debug("TDLS UNKNOWN discover num_attempts:%d num_left:%d forced_peer:%d",
981 				   curr_peer->discovery_attempt,
982 				   tdls_vdev->threshold_config.discovery_tries_n,
983 				   curr_peer->is_forced_peer);
984 			tdls_vdev->curr_candidate = curr_peer;
985 			tdls_implicit_send_discovery_request(tdls_vdev);
986 
987 			return;
988 		}
989 
990 		if (curr_peer->link_status != TDLS_LINK_CONNECTING) {
991 			curr_peer->tdls_support = TDLS_CAP_NOT_SUPPORTED;
992 			tdls_set_peer_link_status(curr_peer, TDLS_LINK_IDLE,
993 						  TDLS_LINK_NOT_SUPPORTED);
994 		}
995 	}
996 }
997 
998 /**
999  * tdls_ct_process_peers() - process the peer
1000  * @curr_peer: tdls peer needs to be examined
1001  * @tdls_vdev_obj: tdls vdev object
1002  * @tdls_soc_obj: tdls soc object
1003  *
1004  * This function check the peer capability and process the metadata from
1005  * the peer
1006  *
1007  * Return: None
1008  */
tdls_ct_process_peers(struct tdls_peer * curr_peer,struct tdls_vdev_priv_obj * tdls_vdev_obj,struct tdls_soc_priv_obj * tdls_soc_obj)1009 static void tdls_ct_process_peers(struct tdls_peer *curr_peer,
1010 				  struct tdls_vdev_priv_obj *tdls_vdev_obj,
1011 				  struct tdls_soc_priv_obj *tdls_soc_obj)
1012 {
1013 	switch (curr_peer->tdls_support) {
1014 	case TDLS_CAP_SUPPORTED:
1015 		tdls_ct_process_cap_supported(curr_peer, tdls_vdev_obj,
1016 						       tdls_soc_obj);
1017 		break;
1018 
1019 	case TDLS_CAP_UNKNOWN:
1020 		tdls_ct_process_cap_unknown(curr_peer, tdls_vdev_obj,
1021 						     tdls_soc_obj);
1022 		break;
1023 	default:
1024 		break;
1025 	}
1026 
1027 }
1028 
tdls_ct_process_handler(struct wlan_objmgr_vdev * vdev)1029 static void tdls_ct_process_handler(struct wlan_objmgr_vdev *vdev)
1030 {
1031 	int i;
1032 	qdf_list_t *head;
1033 	qdf_list_node_t *list_node;
1034 	struct tdls_peer *curr_peer;
1035 	QDF_STATUS status;
1036 	struct tdls_vdev_priv_obj *tdls_vdev_obj;
1037 	struct tdls_soc_priv_obj *tdls_soc_obj;
1038 
1039 	status = tdls_get_vdev_objects(vdev, &tdls_vdev_obj, &tdls_soc_obj);
1040 	if (QDF_IS_STATUS_ERROR(status))
1041 		return;
1042 
1043 	/* If any concurrency is detected */
1044 	if (!tdls_soc_obj->enable_tdls_connection_tracker) {
1045 		tdls_notice("Connection tracker is disabled");
1046 		return;
1047 	}
1048 
1049 	/* Update tx rx traffic sample in tdls data structures */
1050 	tdls_ct_sampling_tx_rx(tdls_vdev_obj, tdls_soc_obj);
1051 
1052 	for (i = 0; i < WLAN_TDLS_PEER_LIST_SIZE; i++) {
1053 		head = &tdls_vdev_obj->peer_list[i];
1054 		status = qdf_list_peek_front(head, &list_node);
1055 		while (QDF_IS_STATUS_SUCCESS(status)) {
1056 			curr_peer = qdf_container_of(list_node,
1057 						struct tdls_peer, node);
1058 			tdls_ct_process_peers(curr_peer, tdls_vdev_obj,
1059 					      tdls_soc_obj);
1060 			curr_peer->tx_pkt = 0;
1061 			curr_peer->rx_pkt = 0;
1062 			status = qdf_list_peek_next(head,
1063 						    list_node, &list_node);
1064 		}
1065 	}
1066 
1067 	tdls_timer_restart(tdls_vdev_obj->vdev,
1068 			   &tdls_vdev_obj->peer_update_timer,
1069 			   tdls_vdev_obj->threshold_config.tx_period_t);
1070 
1071 }
1072 
tdls_ct_handler(void * user_data)1073 void tdls_ct_handler(void *user_data)
1074 {
1075 	struct wlan_objmgr_vdev *vdev;
1076 	struct wlan_objmgr_vdev *link_vdev;
1077 	QDF_STATUS status;
1078 
1079 	if (!user_data)
1080 		return;
1081 
1082 	vdev = (struct wlan_objmgr_vdev *)user_data;
1083 	if (!vdev)
1084 		return;
1085 
1086 	link_vdev = tdls_mlo_get_tdls_link_vdev(vdev);
1087 	if (link_vdev) {
1088 		status = wlan_objmgr_vdev_try_get_ref(link_vdev,
1089 						      WLAN_TDLS_NB_ID);
1090 		if (QDF_IS_STATUS_SUCCESS(status)) {
1091 			tdls_ct_process_handler(link_vdev);
1092 			wlan_objmgr_vdev_release_ref(link_vdev,
1093 						     WLAN_TDLS_NB_ID);
1094 		}
1095 	} else {
1096 		tdls_ct_process_handler(vdev);
1097 	}
1098 }
1099 
tdls_set_tdls_offchannel(struct tdls_soc_priv_obj * tdls_soc,int offchannel)1100 int tdls_set_tdls_offchannel(struct tdls_soc_priv_obj *tdls_soc,
1101 			     int offchannel)
1102 {
1103 	uint32_t tdls_feature_flags;
1104 
1105 	tdls_feature_flags = tdls_soc->tdls_configs.tdls_feature_flags;
1106 
1107 	if (TDLS_IS_OFF_CHANNEL_ENABLED(tdls_feature_flags) &&
1108 	   (TDLS_SUPPORT_EXP_TRIG_ONLY == tdls_soc->tdls_current_mode ||
1109 	    TDLS_SUPPORT_IMP_MODE == tdls_soc->tdls_current_mode ||
1110 	    TDLS_SUPPORT_EXT_CONTROL == tdls_soc->tdls_current_mode)) {
1111 		if (offchannel < TDLS_PREFERRED_OFF_CHANNEL_NUM_MIN ||
1112 			offchannel > TDLS_PREFERRED_OFF_CHANNEL_NUM_MAX) {
1113 			tdls_err("Invalid tdls off channel %u", offchannel);
1114 			return -EINVAL;
1115 			}
1116 	} else {
1117 		tdls_err("Either TDLS or TDLS Off-channel is not enabled");
1118 		return -ENOTSUPP;
1119 	}
1120 	tdls_notice("change tdls off channel from %d to %d",
1121 		   tdls_soc->tdls_off_channel, offchannel);
1122 	tdls_soc->tdls_off_channel = offchannel;
1123 	return 0;
1124 }
1125 
tdls_set_tdls_secoffchanneloffset(struct tdls_soc_priv_obj * tdls_soc,int offchanoffset)1126 int tdls_set_tdls_secoffchanneloffset(struct tdls_soc_priv_obj *tdls_soc,
1127 				int offchanoffset)
1128 {
1129 	uint32_t tdls_feature_flags;
1130 
1131 	tdls_feature_flags = tdls_soc->tdls_configs.tdls_feature_flags;
1132 
1133 	if (!TDLS_IS_OFF_CHANNEL_ENABLED(tdls_feature_flags) ||
1134 	    TDLS_SUPPORT_SUSPENDED >= tdls_soc->tdls_current_mode) {
1135 		tdls_err("Either TDLS or TDLS Off-channel is not enabled");
1136 		return  -ENOTSUPP;
1137 	}
1138 
1139 	tdls_soc->tdls_channel_offset = BW_INVALID;
1140 
1141 	switch (offchanoffset) {
1142 	case TDLS_SEC_OFFCHAN_OFFSET_0:
1143 		tdls_soc->tdls_channel_offset = BW20;
1144 		break;
1145 	case TDLS_SEC_OFFCHAN_OFFSET_40PLUS:
1146 		tdls_soc->tdls_channel_offset = BW40_HIGH_PRIMARY;
1147 		break;
1148 	case TDLS_SEC_OFFCHAN_OFFSET_40MINUS:
1149 		tdls_soc->tdls_channel_offset = BW40_LOW_PRIMARY;
1150 		break;
1151 	case TDLS_SEC_OFFCHAN_OFFSET_80:
1152 		tdls_soc->tdls_channel_offset = BW80;
1153 		break;
1154 	case TDLS_SEC_OFFCHAN_OFFSET_160:
1155 		tdls_soc->tdls_channel_offset = BWALL;
1156 		break;
1157 	default:
1158 		tdls_err("Invalid tdls secondary off channel offset %d",
1159 			offchanoffset);
1160 		return -EINVAL;
1161 	} /* end switch */
1162 
1163 	tdls_notice("change tdls secondary off channel offset to 0x%x",
1164 		    tdls_soc->tdls_channel_offset);
1165 	return 0;
1166 }
1167 
1168 static inline void
tdls_update_opclass(struct wlan_objmgr_psoc * psoc,struct tdls_channel_switch_params * params)1169 tdls_update_opclass(struct wlan_objmgr_psoc *psoc,
1170 		    struct tdls_channel_switch_params *params)
1171 {
1172 	params->oper_class = tdls_find_opclass(psoc, params->tdls_off_ch,
1173 					       params->tdls_off_ch_bw_offset);
1174 	if (params->oper_class)
1175 		return;
1176 
1177 	if (params->tdls_off_ch_bw_offset == BW40_HIGH_PRIMARY)
1178 		params->oper_class = tdls_find_opclass(psoc,
1179 						       params->tdls_off_ch,
1180 						       BW40_LOW_PRIMARY);
1181 	else if (params->tdls_off_ch_bw_offset == BW40_LOW_PRIMARY)
1182 		params->oper_class = tdls_find_opclass(psoc,
1183 						       params->tdls_off_ch,
1184 						       BW40_HIGH_PRIMARY);
1185 }
1186 
1187 #ifdef WLAN_FEATURE_TDLS_CONCURRENCIES
1188 static inline QDF_STATUS
tdls_update_peer_off_channel_list(struct wlan_objmgr_pdev * pdev,struct tdls_soc_priv_obj * tdls_soc,struct wlan_objmgr_vdev * vdev,struct tdls_peer * peer,struct tdls_channel_switch_params * params)1189 tdls_update_peer_off_channel_list(struct wlan_objmgr_pdev *pdev,
1190 				  struct tdls_soc_priv_obj *tdls_soc,
1191 				  struct wlan_objmgr_vdev *vdev,
1192 				  struct tdls_peer *peer,
1193 				  struct tdls_channel_switch_params *params)
1194 {
1195 	struct wlan_objmgr_psoc *psoc = wlan_pdev_get_psoc(pdev);
1196 	struct tdls_peer_update_state *peer_info;
1197 	struct tdls_ch_params *off_channels = params->allowed_off_channels;
1198 	uint16_t i;
1199 	qdf_freq_t freq, peer_freq;
1200 
1201 	if (!wlan_psoc_nif_fw_ext2_cap_get(psoc,
1202 					   WLAN_TDLS_CONCURRENCIES_SUPPORT)) {
1203 		tdls_debug("TDLS Concurrencies FW cap is not supported");
1204 		return QDF_STATUS_SUCCESS;
1205 	}
1206 
1207 	if (!policy_mgr_get_allowed_tdls_offchannel_freq(psoc, vdev, &freq)) {
1208 		tdls_debug("off channel not allowed for current concurrency");
1209 		return QDF_STATUS_E_NOSUPPORT;
1210 	}
1211 
1212 	/*
1213 	 * Overwrite the preferred off channel freq in case of concurrency
1214 	 */
1215 	if (freq) {
1216 		params->tdls_off_ch = wlan_reg_freq_to_chan(pdev, freq);
1217 		params->tdls_off_chan_freq = freq;
1218 
1219 		/*
1220 		 * tdls_off_ch_bw_offset is already filled in the caller
1221 		 */
1222 		if (tdls_soc->tdls_off_channel &&
1223 		    tdls_soc->tdls_channel_offset != BW_INVALID) {
1224 			tdls_update_opclass(psoc, params);
1225 		} else if (peer->off_channel_capable &&
1226 			   peer->pref_off_chan_freq) {
1227 			params->oper_class =
1228 				tdls_get_opclass_from_bandwidth(
1229 					vdev, params->tdls_off_chan_freq,
1230 					peer->pref_off_chan_width,
1231 					&params->tdls_off_ch_bw_offset);
1232 		}
1233 	}
1234 
1235 	peer_info = qdf_mem_malloc(sizeof(*peer_info));
1236 	if (!peer_info)
1237 		return QDF_STATUS_E_NOMEM;
1238 
1239 	tdls_extract_peer_state_param(peer_info, peer);
1240 	params->num_off_channels = 0;
1241 
1242 	/*
1243 	 * If TDLS concurrency is supported and freq == 0,
1244 	 * then allow all the 5GHz and 6GHz peer supported frequencies for
1245 	 * off-channel operation. If particular frequency is provided based on
1246 	 * concurrency combination then only allow that channel for off-channel.
1247 	 */
1248 	for (i = 0; i < peer_info->peer_cap.peer_chanlen; i++) {
1249 		peer_freq = peer_info->peer_cap.peer_chan[i].ch_freq;
1250 		if ((!freq || freq == peer_freq) &&
1251 		    (!wlan_reg_is_24ghz_ch_freq(peer_freq) ||
1252 		     (wlan_reg_is_6ghz_chan_freq(peer_freq) &&
1253 		      tdls_is_6g_freq_allowed(vdev, peer_freq)))) {
1254 			off_channels[params->num_off_channels] =
1255 					peer_info->peer_cap.peer_chan[i];
1256 			tdls_debug("allowd_chan:%d idx:%d",
1257 				   off_channels[params->num_off_channels].ch_freq,
1258 				   params->num_off_channels);
1259 			params->num_off_channels++;
1260 		}
1261 	}
1262 	tdls_debug("Num allowed off channels:%d freq:%u",
1263 		   params->num_off_channels, freq);
1264 	qdf_mem_free(peer_info);
1265 
1266 	return QDF_STATUS_SUCCESS;
1267 }
1268 #else
1269 static inline QDF_STATUS
tdls_update_peer_off_channel_list(struct wlan_objmgr_pdev * pdev,struct tdls_soc_priv_obj * tdls_soc,struct wlan_objmgr_vdev * vdev,struct tdls_peer * peer,struct tdls_channel_switch_params * params)1270 tdls_update_peer_off_channel_list(struct wlan_objmgr_pdev *pdev,
1271 				  struct tdls_soc_priv_obj *tdls_soc,
1272 				  struct wlan_objmgr_vdev *vdev,
1273 				  struct tdls_peer *peer,
1274 				  struct tdls_channel_switch_params *params)
1275 {
1276 	return QDF_STATUS_SUCCESS;
1277 }
1278 #endif
1279 
tdls_set_tdls_offchannelmode(struct wlan_objmgr_vdev * vdev,int offchanmode)1280 int tdls_set_tdls_offchannelmode(struct wlan_objmgr_vdev *vdev,
1281 				 int offchanmode)
1282 {
1283 	struct tdls_peer *conn_peer = NULL;
1284 	struct tdls_channel_switch_params *chan_switch_params;
1285 	QDF_STATUS status = QDF_STATUS_E_FAILURE;
1286 	int ret_value = 0;
1287 	struct tdls_vdev_priv_obj *tdls_vdev;
1288 	struct tdls_soc_priv_obj *tdls_soc;
1289 	uint32_t tdls_feature_flags;
1290 	struct wlan_objmgr_pdev *pdev = wlan_vdev_get_pdev(vdev);
1291 
1292 	status = tdls_get_vdev_objects(vdev, &tdls_vdev, &tdls_soc);
1293 
1294 	if (status != QDF_STATUS_SUCCESS)
1295 		return -EINVAL;
1296 
1297 
1298 	if (offchanmode < ENABLE_CHANSWITCH ||
1299 	    offchanmode > DISABLE_ACTIVE_CHANSWITCH) {
1300 		tdls_err("Invalid tdls off channel mode %d", offchanmode);
1301 		return -EINVAL;
1302 	}
1303 
1304 	if (wlan_vdev_is_up(vdev) != QDF_STATUS_SUCCESS) {
1305 		tdls_err("tdls off channel req in not associated state %d",
1306 			offchanmode);
1307 		return -EPERM;
1308 	}
1309 
1310 	tdls_feature_flags = tdls_soc->tdls_configs.tdls_feature_flags;
1311 	if (!TDLS_IS_OFF_CHANNEL_ENABLED(tdls_feature_flags) ||
1312 	    TDLS_SUPPORT_SUSPENDED >= tdls_soc->tdls_current_mode) {
1313 		tdls_err("Either TDLS or TDLS Off-channel is not enabled");
1314 		return  -ENOTSUPP;
1315 	}
1316 
1317 	conn_peer = tdls_find_first_connected_peer(tdls_vdev);
1318 	if (!conn_peer) {
1319 		tdls_debug("No TDLS Connected Peer");
1320 		return -EPERM;
1321 	}
1322 
1323 	tdls_notice("TDLS Channel Switch in off_chan_mode=%d tdls_off_channel %d offchanoffset %d",
1324 		    offchanmode, tdls_soc->tdls_off_channel,
1325 		    tdls_soc->tdls_channel_offset);
1326 
1327 	chan_switch_params = qdf_mem_malloc(sizeof(*chan_switch_params));
1328 	if (!chan_switch_params)
1329 		return -ENOMEM;
1330 
1331 	switch (offchanmode) {
1332 	case ENABLE_CHANSWITCH:
1333 		if (tdls_soc->tdls_off_channel &&
1334 		    tdls_soc->tdls_channel_offset != BW_INVALID) {
1335 			chan_switch_params->tdls_off_ch =
1336 					tdls_soc->tdls_off_channel;
1337 			chan_switch_params->tdls_off_ch_bw_offset =
1338 					tdls_soc->tdls_channel_offset;
1339 			tdls_update_opclass(wlan_pdev_get_psoc(pdev),
1340 					    chan_switch_params);
1341 		} else if (conn_peer->off_channel_capable &&
1342 			   conn_peer->pref_off_chan_freq) {
1343 			chan_switch_params->tdls_off_ch =
1344 				wlan_reg_freq_to_chan(pdev,
1345 						 conn_peer->pref_off_chan_freq);
1346 			chan_switch_params->oper_class =
1347 				tdls_get_opclass_from_bandwidth(
1348 				vdev, conn_peer->pref_off_chan_freq,
1349 				conn_peer->pref_off_chan_width,
1350 				&chan_switch_params->tdls_off_ch_bw_offset);
1351 			chan_switch_params->tdls_off_chan_freq =
1352 						 conn_peer->pref_off_chan_freq;
1353 		} else {
1354 			tdls_err("TDLS off-channel parameters are not set yet!!!");
1355 			qdf_mem_free(chan_switch_params);
1356 			return -EINVAL;
1357 
1358 		}
1359 
1360 		/*
1361 		 * Retain the connected peer preferred off-channel frequency
1362 		 * and opclass that was calculated during update peer caps and
1363 		 * don't overwrite it based on concurrency in
1364 		 * tdls_update_peer_off_channel_list().
1365 		 */
1366 		conn_peer->pref_off_chan_freq =
1367 			wlan_reg_chan_opclass_to_freq(
1368 					chan_switch_params->tdls_off_ch,
1369 					chan_switch_params->oper_class, false);
1370 		conn_peer->op_class_for_pref_off_chan =
1371 				chan_switch_params->oper_class;
1372 
1373 		/*
1374 		 * Don't enable TDLS off channel if concurrency is not allowed
1375 		 */
1376 		status = tdls_update_peer_off_channel_list(pdev, tdls_soc, vdev,
1377 							   conn_peer,
1378 							   chan_switch_params);
1379 		if (QDF_IS_STATUS_ERROR(status)) {
1380 			qdf_mem_free(chan_switch_params);
1381 			return -EINVAL;
1382 		}
1383 
1384 		break;
1385 	case DISABLE_CHANSWITCH:
1386 	case DISABLE_ACTIVE_CHANSWITCH:
1387 		chan_switch_params->tdls_off_ch = 0;
1388 		chan_switch_params->tdls_off_ch_bw_offset = 0;
1389 		chan_switch_params->oper_class = 0;
1390 		break;
1391 	default:
1392 		tdls_err("Incorrect Parameters mode: %d tdls_off_channel: %d offchanoffset: %d",
1393 			 offchanmode, tdls_soc->tdls_off_channel,
1394 			 tdls_soc->tdls_channel_offset);
1395 		qdf_mem_free(chan_switch_params);
1396 		return -EINVAL;
1397 	} /* end switch */
1398 
1399 	chan_switch_params->vdev_id = tdls_vdev->session_id;
1400 	chan_switch_params->tdls_sw_mode = offchanmode;
1401 	chan_switch_params->is_responder = conn_peer->is_responder;
1402 	qdf_mem_copy(&chan_switch_params->peer_mac_addr,
1403 		     &conn_peer->peer_mac.bytes, QDF_MAC_ADDR_SIZE);
1404 	tdls_notice("Peer " QDF_MAC_ADDR_FMT " vdevId: %d, off channel: %d, offset: %d, num_allowed_off_chan:%d mode: %d, is_responder: %d",
1405 		    QDF_MAC_ADDR_REF(chan_switch_params->peer_mac_addr),
1406 		    chan_switch_params->vdev_id,
1407 		    chan_switch_params->tdls_off_ch,
1408 		    chan_switch_params->tdls_off_ch_bw_offset,
1409 		    chan_switch_params->num_off_channels,
1410 		    chan_switch_params->tdls_sw_mode,
1411 		    chan_switch_params->is_responder);
1412 
1413 	status = tgt_tdls_set_offchan_mode(tdls_soc->soc, chan_switch_params);
1414 	if (QDF_IS_STATUS_ERROR(status)) {
1415 		qdf_mem_free(chan_switch_params);
1416 		tdls_err("Failed to send channel switch request to wmi");
1417 		return -EINVAL;
1418 	}
1419 
1420 	tdls_soc->tdls_fw_off_chan_mode = offchanmode;
1421 	qdf_mem_free(chan_switch_params);
1422 
1423 	return ret_value;
1424 }
1425 
tdls_delete_all_tdls_peers_flush_cb(struct scheduler_msg * msg)1426 static QDF_STATUS tdls_delete_all_tdls_peers_flush_cb(struct scheduler_msg *msg)
1427 {
1428 	if (msg && msg->bodyptr) {
1429 		qdf_mem_free(msg->bodyptr);
1430 		msg->bodyptr = NULL;
1431 	}
1432 
1433 	return QDF_STATUS_SUCCESS;
1434 }
1435 /**
1436  * tdls_delete_all_tdls_peers(): send request to delete tdls peers
1437  * @vdev: vdev object
1438  * @tdls_soc: tdls soc object
1439  *
1440  * This function sends request to lim to delete tdls peers
1441  *
1442  * Return: QDF_STATUS
1443  */
tdls_delete_all_tdls_peers(struct wlan_objmgr_vdev * vdev,struct tdls_soc_priv_obj * tdls_soc)1444 QDF_STATUS tdls_delete_all_tdls_peers(struct wlan_objmgr_vdev *vdev,
1445 					  struct tdls_soc_priv_obj *tdls_soc)
1446 {
1447 	struct wlan_objmgr_peer *peer;
1448 	struct tdls_del_all_tdls_peers *del_msg;
1449 	struct scheduler_msg msg = {0};
1450 	QDF_STATUS status;
1451 
1452 	peer = wlan_objmgr_vdev_try_get_bsspeer(vdev, WLAN_TDLS_SB_ID);
1453 	if (!peer) {
1454 		tdls_err("bss peer is null");
1455 		return QDF_STATUS_E_FAILURE;
1456 	}
1457 
1458 	del_msg = qdf_mem_malloc(sizeof(*del_msg));
1459 	if (!del_msg) {
1460 		wlan_objmgr_peer_release_ref(peer, WLAN_TDLS_SB_ID);
1461 		return QDF_STATUS_E_FAILURE;
1462 	}
1463 
1464 	qdf_mem_copy(del_msg->bssid.bytes,
1465 		     wlan_peer_get_macaddr(peer), QDF_MAC_ADDR_SIZE);
1466 
1467 	wlan_objmgr_peer_release_ref(peer, WLAN_TDLS_SB_ID);
1468 
1469 	del_msg->msg_type = tdls_soc->tdls_del_all_peers;
1470 	del_msg->msg_len = (uint16_t) sizeof(*del_msg);
1471 
1472 	/* Send the request to PE. */
1473 	qdf_mem_zero(&msg, sizeof(msg));
1474 
1475 	tdls_debug("sending delete all peers req to PE ");
1476 
1477 	msg.type = del_msg->msg_type;
1478 	msg.bodyptr = del_msg;
1479 	msg.flush_callback = tdls_delete_all_tdls_peers_flush_cb;
1480 
1481 	status = scheduler_post_message(QDF_MODULE_ID_TDLS,
1482 					QDF_MODULE_ID_PE,
1483 					QDF_MODULE_ID_PE, &msg);
1484 	if (QDF_IS_STATUS_ERROR(status)) {
1485 		tdls_err("post delete all peer req failed, status %d", status);
1486 		qdf_mem_free(del_msg);
1487 	}
1488 
1489 	return status;
1490 }
1491 
tdls_disable_offchan_and_teardown_links(struct wlan_objmgr_vdev * vdev)1492 void tdls_disable_offchan_and_teardown_links(
1493 				struct wlan_objmgr_vdev *vdev)
1494 {
1495 	uint16_t connected_tdls_peers = 0;
1496 	uint8_t staidx;
1497 	struct tdls_peer *curr_peer = NULL;
1498 	struct tdls_vdev_priv_obj *tdls_vdev;
1499 	struct tdls_soc_priv_obj *tdls_soc;
1500 	QDF_STATUS status;
1501 	uint8_t vdev_id;
1502 	bool tdls_in_progress = false;
1503 	bool is_mlo_vdev;
1504 
1505 	is_mlo_vdev = wlan_vdev_mlme_is_mlo_vdev(vdev);
1506 	if (is_mlo_vdev) {
1507 		tdls_debug("try to set vdev %d to unforce",
1508 			   wlan_vdev_get_id(vdev));
1509 		tdls_set_link_unforce(vdev);
1510 	}
1511 
1512 	status = tdls_get_vdev_objects(vdev, &tdls_vdev, &tdls_soc);
1513 	if (QDF_STATUS_SUCCESS != status) {
1514 		tdls_err("tdls objects are NULL ");
1515 		return;
1516 	}
1517 
1518 	if (TDLS_SUPPORT_SUSPENDED >= tdls_soc->tdls_current_mode) {
1519 		tdls_debug("TDLS mode %d is disabled OR not suspended now",
1520 			   tdls_soc->tdls_current_mode);
1521 		return;
1522 	}
1523 
1524 	connected_tdls_peers = tdls_soc->connected_peer_count;
1525 	if (tdls_is_progress(tdls_vdev, NULL, 0))
1526 		tdls_in_progress = true;
1527 
1528 	if (!(connected_tdls_peers || tdls_in_progress)) {
1529 		vdev_id = vdev->vdev_objmgr.vdev_id;
1530 		tdls_debug("No TDLS connected/progress peers to delete Disable tdls for vdev id %d, "
1531 			   "FW as second interface is coming up", vdev_id);
1532 		tdls_send_update_to_fw(tdls_vdev, tdls_soc, true, true, false,
1533 				       vdev_id);
1534 		return;
1535 	}
1536 
1537 	/* TDLS is not supported in case of concurrency.
1538 	 * Disable TDLS Offchannel in FW to avoid more
1539 	 * than two concurrent channels and generate TDLS
1540 	 * teardown indication to supplicant.
1541 	 * Below function Finds the first connected peer and
1542 	 * disables TDLS offchannel for that peer.
1543 	 * FW enables TDLS offchannel only when there is
1544 	 * one TDLS peer. When there are more than one TDLS peer,
1545 	 * there will not be TDLS offchannel in FW.
1546 	 * So to avoid sending multiple request to FW, for now,
1547 	 * just invoke offchannel mode functions only once
1548 	 */
1549 	tdls_set_tdls_offchannel(tdls_soc,
1550 				tdls_soc->tdls_configs.tdls_pre_off_chan_num);
1551 	tdls_set_tdls_secoffchanneloffset(tdls_soc,
1552 			TDLS_SEC_OFFCHAN_OFFSET_40PLUS);
1553 	tdls_set_tdls_offchannelmode(vdev, DISABLE_ACTIVE_CHANSWITCH);
1554 
1555 	/* Send Msg to PE for deleting all the TDLS peers */
1556 	tdls_delete_all_tdls_peers(vdev, tdls_soc);
1557 
1558 	for (staidx = 0; staidx < tdls_soc->max_num_tdls_sta; staidx++) {
1559 		if (!tdls_soc->tdls_conn_info[staidx].valid_entry)
1560 			continue;
1561 
1562 		curr_peer = tdls_find_all_peer(tdls_soc,
1563 			tdls_soc->tdls_conn_info[staidx].peer_mac.bytes);
1564 		if (!curr_peer)
1565 			continue;
1566 
1567 		tdls_notice("indicate TDLS teardown "QDF_MAC_ADDR_FMT,
1568 			    QDF_MAC_ADDR_REF(curr_peer->peer_mac.bytes));
1569 
1570 		/* Indicate teardown to supplicant */
1571 		tdls_indicate_teardown(tdls_vdev, curr_peer,
1572 				       TDLS_TEARDOWN_PEER_UNSPEC_REASON);
1573 
1574 		tdls_decrement_peer_count(vdev, tdls_soc);
1575 
1576 		/*
1577 		 * Del Sta happened already as part of tdls_delete_all_tdls_peers
1578 		 * Hence clear tdls vdev data structure.
1579 		 */
1580 		tdls_reset_peer(tdls_vdev, curr_peer->peer_mac.bytes);
1581 
1582 		tdls_soc->tdls_conn_info[staidx].valid_entry = false;
1583 		tdls_soc->tdls_conn_info[staidx].session_id = 255;
1584 		tdls_soc->tdls_conn_info[staidx].index =
1585 						INVALID_TDLS_PEER_INDEX;
1586 
1587 		qdf_mem_zero(&tdls_soc->tdls_conn_info[staidx].peer_mac,
1588 			     sizeof(struct qdf_mac_addr));
1589 	}
1590 }
1591 
tdls_teardown_connections(struct tdls_link_teardown * tdls_teardown)1592 void tdls_teardown_connections(struct tdls_link_teardown *tdls_teardown)
1593 {
1594 	struct tdls_vdev_priv_obj *tdls_vdev_obj;
1595 	struct wlan_objmgr_vdev *tdls_vdev;
1596 
1597 	/* Get the tdls specific vdev and clear the links */
1598 	tdls_vdev = tdls_get_vdev(tdls_teardown->psoc, WLAN_TDLS_SB_ID);
1599 	if (!tdls_vdev) {
1600 		tdls_err("Unable get the vdev");
1601 		goto fail_vdev;
1602 	}
1603 
1604 	tdls_vdev_obj = wlan_vdev_get_tdls_vdev_obj(tdls_vdev);
1605 	if (!tdls_vdev_obj) {
1606 		tdls_err("vdev priv is NULL");
1607 		goto fail_tdls_vdev;
1608 	}
1609 
1610 	tdls_debug("tdls teardown connections");
1611 	wlan_vdev_mlme_feat_ext2_cap_clear(tdls_vdev,
1612 					   WLAN_VDEV_FEXT2_MLO_STA_TDLS);
1613 
1614 	tdls_disable_offchan_and_teardown_links(tdls_vdev);
1615 	qdf_event_set(&tdls_vdev_obj->tdls_teardown_comp);
1616 fail_tdls_vdev:
1617 	wlan_objmgr_vdev_release_ref(tdls_vdev, WLAN_TDLS_SB_ID);
1618 fail_vdev:
1619 	wlan_objmgr_psoc_release_ref(tdls_teardown->psoc, WLAN_TDLS_SB_ID);
1620 	qdf_mem_free(tdls_teardown);
1621 }
1622