xref: /wlan-driver/qcacld-3.0/components/tdls/core/src/wlan_tdls_peer.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_peer.c
22  *
23  * TDLS peer basic operations
24  */
25 #include "wlan_tdls_main.h"
26 #include "wlan_tdls_peer.h"
27 #include <wlan_reg_services_api.h>
28 #include <wlan_utility.h>
29 #include <wlan_policy_mgr_api.h>
30 #include "wlan_reg_ucfg_api.h"
31 #include <host_diag_core_event.h>
32 #include "wlan_policy_mgr_api.h"
33 
calculate_hash_key(const uint8_t * macaddr)34 static uint8_t calculate_hash_key(const uint8_t *macaddr)
35 {
36 	uint8_t i, key;
37 
38 	for (i = 0, key = 0; i < 6; i++)
39 		key ^= macaddr[i];
40 
41 	return key % WLAN_TDLS_PEER_LIST_SIZE;
42 }
43 
tdls_find_peer(struct tdls_vdev_priv_obj * vdev_obj,const uint8_t * macaddr)44 struct tdls_peer *tdls_find_peer(struct tdls_vdev_priv_obj *vdev_obj,
45 				 const uint8_t *macaddr)
46 {
47 	uint8_t key;
48 	QDF_STATUS status;
49 	struct tdls_peer *peer;
50 	qdf_list_t *head;
51 	qdf_list_node_t *p_node;
52 
53 	key = calculate_hash_key(macaddr);
54 	head = &vdev_obj->peer_list[key];
55 
56 	status = qdf_list_peek_front(head, &p_node);
57 	while (QDF_IS_STATUS_SUCCESS(status)) {
58 		peer = qdf_container_of(p_node, struct tdls_peer, node);
59 		if (WLAN_ADDR_EQ(&peer->peer_mac, macaddr)
60 		    == QDF_STATUS_SUCCESS) {
61 			return peer;
62 		}
63 		status = qdf_list_peek_next(head, p_node, &p_node);
64 	}
65 
66 	tdls_debug("no tdls peer " QDF_MAC_ADDR_FMT,
67 		   QDF_MAC_ADDR_REF(macaddr));
68 	return NULL;
69 }
70 
71 /**
72  * tdls_find_peer_handler() - helper function for tdls_find_all_peer
73  * @psoc: soc object
74  * @obj: vdev object
75  * @arg: used to keep search peer parameters
76  *
77  * Return: None.
78  */
79 static void
tdls_find_peer_handler(struct wlan_objmgr_psoc * psoc,void * obj,void * arg)80 tdls_find_peer_handler(struct wlan_objmgr_psoc *psoc, void *obj, void *arg)
81 {
82 	struct wlan_objmgr_vdev *vdev = obj;
83 	struct tdls_search_peer_param *tdls_param = arg;
84 	struct tdls_vdev_priv_obj *vdev_obj;
85 
86 	if (tdls_param->peer)
87 		return;
88 
89 	if (!vdev) {
90 		tdls_err("invalid vdev");
91 		return;
92 	}
93 
94 	if (wlan_vdev_mlme_get_opmode(vdev) != QDF_STA_MODE &&
95 	    wlan_vdev_mlme_get_opmode(vdev) != QDF_P2P_CLIENT_MODE)
96 		return;
97 
98 	vdev_obj = wlan_objmgr_vdev_get_comp_private_obj(vdev,
99 							 WLAN_UMAC_COMP_TDLS);
100 	if (!vdev_obj)
101 		return;
102 
103 	tdls_param->peer = tdls_find_peer(vdev_obj, tdls_param->macaddr);
104 }
105 
106 struct tdls_peer *
tdls_find_all_peer(struct tdls_soc_priv_obj * soc_obj,const uint8_t * macaddr)107 tdls_find_all_peer(struct tdls_soc_priv_obj *soc_obj, const uint8_t *macaddr)
108 {
109 	struct tdls_search_peer_param tdls_search_param;
110 	struct wlan_objmgr_psoc *psoc;
111 
112 	if (!soc_obj) {
113 		tdls_err("tdls soc object is NULL");
114 		return NULL;
115 	}
116 
117 	psoc = soc_obj->soc;
118 	if (!psoc) {
119 		tdls_err("psoc is NULL");
120 		return NULL;
121 	}
122 	tdls_search_param.macaddr = macaddr;
123 	tdls_search_param.peer = NULL;
124 
125 	wlan_objmgr_iterate_obj_list(psoc, WLAN_VDEV_OP,
126 				     tdls_find_peer_handler,
127 				     &tdls_search_param, 0, WLAN_TDLS_NB_ID);
128 
129 	return tdls_search_param.peer;
130 }
131 
tdls_find_opclass(struct wlan_objmgr_psoc * psoc,uint8_t channel,uint8_t bw_offset)132 uint8_t tdls_find_opclass(struct wlan_objmgr_psoc *psoc, uint8_t channel,
133 				 uint8_t bw_offset)
134 {
135 	char country[REG_ALPHA2_LEN + 1];
136 	QDF_STATUS status;
137 
138 	if (!psoc) {
139 		tdls_err("psoc is NULL");
140 		return 0;
141 	}
142 
143 	status = wlan_reg_read_default_country(psoc, country);
144 	if (QDF_IS_STATUS_ERROR(status))
145 		return 0;
146 
147 	return wlan_reg_dmn_get_opclass_from_channel(country, channel,
148 						     bw_offset);
149 }
150 
151 #ifdef WLAN_FEATURE_11AX
tdls_get_offchan_freq(struct wlan_objmgr_vdev * vdev,struct tdls_soc_priv_obj * soc_obj)152 qdf_freq_t tdls_get_offchan_freq(struct wlan_objmgr_vdev *vdev,
153 				 struct tdls_soc_priv_obj *soc_obj)
154 {
155 	struct wlan_objmgr_pdev *pdev = wlan_vdev_get_pdev(vdev);
156 	qdf_freq_t pref_freq, pref_6g_freq;
157 	uint8_t pref_non6g_ch;
158 
159 	if (!pdev) {
160 		tdls_err("pdev is NULL");
161 		return 0;
162 	}
163 
164 	pref_6g_freq = soc_obj->tdls_configs.tdls_pre_off_chan_freq_6g;
165 	pref_non6g_ch = soc_obj->tdls_configs.tdls_pre_off_chan_num;
166 
167 	/*
168 	 * Fill preferred offchannel frequency here. If TDLS on 6 GHz is
169 	 * allowed then fill pref 6 GHz frequency
170 	 * Otherwise, fill 5 GHz preferred frequency
171 	 */
172 	if (pref_6g_freq && tdls_is_6g_freq_allowed(vdev, pref_6g_freq))
173 		pref_freq = pref_6g_freq;
174 	else
175 		pref_freq = wlan_reg_legacy_chan_to_freq(pdev, pref_non6g_ch);
176 
177 	return pref_freq;
178 }
179 
180 #else
tdls_get_offchan_freq(struct wlan_objmgr_vdev * vdev,struct tdls_soc_priv_obj * soc_obj)181 qdf_freq_t tdls_get_offchan_freq(struct wlan_objmgr_vdev *vdev,
182 				 struct tdls_soc_priv_obj *soc_obj)
183 {
184 	struct wlan_objmgr_pdev *pdev = wlan_vdev_get_pdev(vdev);
185 	uint32_t pref_leg_chan = soc_obj->tdls_configs.tdls_pre_off_chan_num;
186 
187 	if (!pdev) {
188 		tdls_err("pdev is NULL");
189 		return 0;
190 	}
191 
192 	return wlan_reg_legacy_chan_to_freq(pdev, pref_leg_chan);
193 }
194 #endif
195 
tdls_get_offchan_bw(struct tdls_soc_priv_obj * soc_obj,qdf_freq_t off_chan_freq)196 uint32_t tdls_get_offchan_bw(struct tdls_soc_priv_obj *soc_obj,
197 			     qdf_freq_t off_chan_freq)
198 {
199 	uint32_t pre_off_chan_bw;
200 
201 	if (wlan_reg_is_5ghz_ch_freq(off_chan_freq) &&
202 	    CHECK_BIT(soc_obj->tdls_configs.tdls_pre_off_chan_bw,
203 		      BW_160_OFFSET_BIT))
204 		pre_off_chan_bw = soc_obj->tdls_configs.tdls_pre_off_chan_bw &
205 						~(1 << BW_160_OFFSET_BIT);
206 	else
207 		pre_off_chan_bw = soc_obj->tdls_configs.tdls_pre_off_chan_bw;
208 
209 	return pre_off_chan_bw;
210 }
211 
tdls_fill_pref_off_chan_info(struct tdls_vdev_priv_obj * vdev_obj,struct tdls_soc_priv_obj * soc_obj,struct tdls_peer * peer)212 static void tdls_fill_pref_off_chan_info(struct tdls_vdev_priv_obj *vdev_obj,
213 					 struct tdls_soc_priv_obj *soc_obj,
214 					 struct tdls_peer *peer)
215 {
216 	peer->pref_off_chan_freq = tdls_get_offchan_freq(vdev_obj->vdev,
217 							 soc_obj);
218 	peer->pref_off_chan_width = tdls_get_offchan_bw(soc_obj,
219 						      peer->pref_off_chan_freq);
220 	tdls_debug("Pref off channel freq %d chan width %d",
221 		   peer->pref_off_chan_freq, peer->pref_off_chan_width);
222 }
223 
224 static QDF_STATUS
tdls_remove_first_idle_peer(qdf_list_t * head)225 tdls_remove_first_idle_peer(qdf_list_t *head) {
226 	QDF_STATUS status;
227 	qdf_list_node_t *p_node;
228 	struct tdls_peer *peer;
229 
230 	status = qdf_list_peek_front(head, &p_node);
231 	while (QDF_IS_STATUS_SUCCESS(status)) {
232 		peer = qdf_container_of(p_node, struct tdls_peer, node);
233 		if (peer && peer->link_status == TDLS_LINK_IDLE) {
234 			if (peer->is_peer_idle_timer_initialised) {
235 				tdls_debug(QDF_MAC_ADDR_FMT
236 					": destroy  idle timer ",
237 					QDF_MAC_ADDR_REF(
238 					peer->peer_mac.bytes));
239 				qdf_mc_timer_stop(&peer->peer_idle_timer);
240 				qdf_mc_timer_destroy(&peer->peer_idle_timer);
241 			}
242 
243 			tdls_debug(QDF_MAC_ADDR_FMT ": free peer",
244 				   QDF_MAC_ADDR_REF(peer->peer_mac.bytes));
245 			qdf_list_remove_node(head, p_node);
246 			qdf_mem_free(peer);
247 
248 			return status;
249 		}
250 		status = qdf_list_peek_next(head, p_node, &p_node);
251 	}
252 
253 	return QDF_STATUS_E_INVAL;
254 }
255 
256 /**
257  * tdls_add_peer() - add TDLS peer in TDLS vdev object
258  * @vdev_obj: TDLS vdev object
259  * @macaddr: MAC address of peer
260  *
261  * Allocate memory for the new peer, and add it to hash table.
262  *
263  * Return: new added TDLS peer, NULL if failed.
264  */
tdls_add_peer(struct tdls_vdev_priv_obj * vdev_obj,const uint8_t * macaddr)265 static struct tdls_peer *tdls_add_peer(struct tdls_vdev_priv_obj *vdev_obj,
266 				       const uint8_t *macaddr)
267 {
268 	struct tdls_peer *peer;
269 	struct tdls_soc_priv_obj *soc_obj;
270 	uint8_t key = 0;
271 	qdf_list_t *head;
272 	uint8_t reg_bw_offset;
273 
274 	peer = qdf_mem_malloc(sizeof(*peer));
275 	if (!peer)
276 		return NULL;
277 
278 	soc_obj = wlan_vdev_get_tdls_soc_obj(vdev_obj->vdev);
279 	if (!soc_obj) {
280 		tdls_err("NULL tdls soc object");
281 		return NULL;
282 	}
283 
284 	key = calculate_hash_key(macaddr);
285 	head = &vdev_obj->peer_list[key];
286 
287 	qdf_mem_copy(&peer->peer_mac, macaddr, sizeof(peer->peer_mac));
288 	peer->vdev_priv = vdev_obj;
289 
290 	tdls_fill_pref_off_chan_info(vdev_obj, soc_obj, peer);
291 	peer->op_class_for_pref_off_chan =
292 		tdls_get_opclass_from_bandwidth(
293 				vdev_obj->vdev, peer->pref_off_chan_freq,
294 				peer->pref_off_chan_width,
295 				&reg_bw_offset);
296 
297 	peer->valid_entry = false;
298 
299 	if (qdf_list_size(head) >= qdf_list_max_size(head)) {
300 		if (QDF_IS_STATUS_ERROR(tdls_remove_first_idle_peer(head))) {
301 			tdls_err("list size exceed max and remove idle peer failed, key %d",
302 				 key);
303 			qdf_mem_free(peer);
304 			return NULL;
305 		}
306 	}
307 
308 	qdf_list_insert_back(head, &peer->node);
309 
310 	tdls_debug("add tdls peer: " QDF_MAC_ADDR_FMT,
311 		   QDF_MAC_ADDR_REF(macaddr));
312 	return peer;
313 }
314 
tdls_get_peer(struct tdls_vdev_priv_obj * vdev_obj,const uint8_t * macaddr)315 struct tdls_peer *tdls_get_peer(struct tdls_vdev_priv_obj *vdev_obj,
316 				const uint8_t *macaddr)
317 {
318 	struct tdls_peer *peer;
319 
320 	peer = tdls_find_peer(vdev_obj, macaddr);
321 	if (!peer)
322 		peer = tdls_add_peer(vdev_obj, macaddr);
323 
324 	return peer;
325 }
326 
327 static struct tdls_peer *
tdls_find_progress_peer_in_list(qdf_list_t * head,const uint8_t * macaddr,uint8_t skip_self)328 tdls_find_progress_peer_in_list(qdf_list_t *head,
329 				const uint8_t *macaddr, uint8_t skip_self)
330 {
331 	QDF_STATUS status;
332 	struct tdls_peer *peer;
333 	qdf_list_node_t *p_node;
334 
335 	status = qdf_list_peek_front(head, &p_node);
336 	while (QDF_IS_STATUS_SUCCESS(status)) {
337 		peer = qdf_container_of(p_node, struct tdls_peer, node);
338 		if (skip_self && macaddr &&
339 		    WLAN_ADDR_EQ(&peer->peer_mac, macaddr)
340 		    == QDF_STATUS_SUCCESS) {
341 			status = qdf_list_peek_next(head, p_node, &p_node);
342 			continue;
343 		} else if (TDLS_LINK_CONNECTING == peer->link_status) {
344 			tdls_debug(QDF_MAC_ADDR_FMT " TDLS_LINK_CONNECTING",
345 				   QDF_MAC_ADDR_REF(peer->peer_mac.bytes));
346 			return peer;
347 		}
348 		status = qdf_list_peek_next(head, p_node, &p_node);
349 	}
350 
351 	return NULL;
352 }
353 
354 /**
355  * tdls_find_progress_peer() - find the peer with ongoing TDLS progress
356  *                             on present vdev
357  * @vdev_obj: TDLS vdev object
358  * @macaddr: MAC address of peer, if NULL check for all the peer list
359  * @skip_self: If true, skip this macaddr. Otherwise, check all the peer list.
360  *             if macaddr is NULL, this argument is ignored, and check for all
361  *             the peer list.
362  *
363  * Return: Pointer to tdls_peer if TDLS is ongoing. Otherwise return NULL.
364  */
365 static struct tdls_peer *
tdls_find_progress_peer(struct tdls_vdev_priv_obj * vdev_obj,const uint8_t * macaddr,uint8_t skip_self)366 tdls_find_progress_peer(struct tdls_vdev_priv_obj *vdev_obj,
367 			const uint8_t *macaddr, uint8_t skip_self)
368 {
369 	uint8_t i;
370 	struct tdls_peer *peer;
371 	qdf_list_t *head;
372 
373 	if (!vdev_obj) {
374 		tdls_err("invalid tdls vdev object");
375 		return NULL;
376 	}
377 
378 	for (i = 0; i < WLAN_TDLS_PEER_LIST_SIZE; i++) {
379 		head = &vdev_obj->peer_list[i];
380 
381 		peer = tdls_find_progress_peer_in_list(head, macaddr,
382 						       skip_self);
383 		if (peer)
384 			return peer;
385 	}
386 
387 	return NULL;
388 }
389 
390 /**
391  * tdls_find_progress_peer_handler() - helper function for tdls_is_progress
392  * @psoc: soc object
393  * @obj: vdev object
394  * @arg: used to keep search peer parameters
395  *
396  * Return: None.
397  */
398 static void
tdls_find_progress_peer_handler(struct wlan_objmgr_psoc * psoc,void * obj,void * arg)399 tdls_find_progress_peer_handler(struct wlan_objmgr_psoc *psoc,
400 				void *obj, void *arg)
401 {
402 	struct wlan_objmgr_vdev *vdev = obj;
403 	struct tdls_search_progress_param *tdls_progress = arg;
404 	struct tdls_vdev_priv_obj *vdev_obj;
405 
406 	if (tdls_progress->peer)
407 		return;
408 
409 	if (!vdev) {
410 		tdls_err("invalid vdev");
411 		return;
412 	}
413 
414 	if (wlan_vdev_mlme_get_opmode(vdev) != QDF_STA_MODE &&
415 	    wlan_vdev_mlme_get_opmode(vdev) != QDF_P2P_CLIENT_MODE)
416 		return;
417 
418 	vdev_obj = wlan_objmgr_vdev_get_comp_private_obj(vdev,
419 							 WLAN_UMAC_COMP_TDLS);
420 
421 	tdls_progress->peer = tdls_find_progress_peer(vdev_obj,
422 						      tdls_progress->macaddr,
423 						      tdls_progress->skip_self);
424 }
425 
tdls_is_progress(struct tdls_vdev_priv_obj * vdev_obj,const uint8_t * macaddr,uint8_t skip_self)426 struct tdls_peer *tdls_is_progress(struct tdls_vdev_priv_obj *vdev_obj,
427 				   const uint8_t *macaddr, uint8_t skip_self)
428 {
429 	struct tdls_search_progress_param tdls_progress;
430 	struct wlan_objmgr_psoc *psoc;
431 
432 	if (!vdev_obj) {
433 		tdls_err("invalid tdls vdev object");
434 		return NULL;
435 	}
436 
437 	psoc = wlan_vdev_get_psoc(vdev_obj->vdev);
438 	if (!psoc) {
439 		tdls_err("invalid psoc");
440 		return NULL;
441 	}
442 	tdls_progress.macaddr = macaddr;
443 	tdls_progress.skip_self = skip_self;
444 	tdls_progress.peer = NULL;
445 
446 	wlan_objmgr_iterate_obj_list(psoc, WLAN_VDEV_OP,
447 				     tdls_find_progress_peer_handler,
448 				     &tdls_progress, 0, WLAN_TDLS_NB_ID);
449 
450 	return tdls_progress.peer;
451 }
452 
453 struct tdls_peer *
tdls_find_first_connected_peer(struct tdls_vdev_priv_obj * vdev_obj)454 tdls_find_first_connected_peer(struct tdls_vdev_priv_obj *vdev_obj)
455 {
456 	uint16_t i;
457 	struct tdls_peer *peer;
458 	qdf_list_t *head;
459 	qdf_list_node_t *p_node;
460 	QDF_STATUS status;
461 
462 	if (!vdev_obj) {
463 		tdls_err("invalid tdls vdev object");
464 		return NULL;
465 	}
466 
467 	for (i = 0; i < WLAN_TDLS_PEER_LIST_SIZE; i++) {
468 		head = &vdev_obj->peer_list[i];
469 
470 		status = qdf_list_peek_front(head, &p_node);
471 		while (QDF_IS_STATUS_SUCCESS(status)) {
472 			peer = qdf_container_of(p_node, struct tdls_peer, node);
473 
474 			if (peer && TDLS_LINK_CONNECTED == peer->link_status) {
475 				tdls_debug(QDF_MAC_ADDR_FMT
476 					   " TDLS_LINK_CONNECTED",
477 					   QDF_MAC_ADDR_REF(
478 						   peer->peer_mac.bytes));
479 				return peer;
480 			}
481 			status = qdf_list_peek_next(head, p_node, &p_node);
482 		}
483 	}
484 
485 	return NULL;
486 }
487 
488 /**
489  * tdls_determine_channel_opclass() - determine channel and opclass
490  * @soc_obj: TDLS soc object
491  * @vdev_obj: TDLS vdev object
492  * @peer: TDLS peer
493  * @channel: pointer to channel
494  * @opclass: pointer to opclass
495  *
496  * Function determines the channel and operating class
497  *
498  * Return: None.
499  */
tdls_determine_channel_opclass(struct tdls_soc_priv_obj * soc_obj,struct tdls_vdev_priv_obj * vdev_obj,struct tdls_peer * peer,uint32_t * channel,uint32_t * opclass)500 static void tdls_determine_channel_opclass(struct tdls_soc_priv_obj *soc_obj,
501 					   struct tdls_vdev_priv_obj *vdev_obj,
502 					   struct tdls_peer *peer,
503 					   uint32_t *channel, uint32_t *opclass)
504 {
505 	uint32_t vdev_id;
506 	enum QDF_OPMODE opmode;
507 	struct wlan_objmgr_pdev *pdev = NULL;
508 	struct wlan_objmgr_psoc *psoc = NULL;
509 	enum policy_mgr_con_mode mode;
510 	/*
511 	 * If tdls offchannel is not enabled then we provide base channel
512 	 * and in that case pass opclass as 0 since opclass is mainly needed
513 	 * for offchannel cases.
514 	 */
515 	if (!(TDLS_IS_OFF_CHANNEL_ENABLED(
516 		      soc_obj->tdls_configs.tdls_feature_flags)) ||
517 	      soc_obj->tdls_fw_off_chan_mode != ENABLE_CHANSWITCH) {
518 		vdev_id = wlan_vdev_get_id(vdev_obj->vdev);
519 		opmode = wlan_vdev_mlme_get_opmode(vdev_obj->vdev);
520 		pdev = wlan_vdev_get_pdev(vdev_obj->vdev);
521 		psoc = wlan_pdev_get_psoc(pdev);
522 
523 		mode = policy_mgr_qdf_opmode_to_pm_con_mode(psoc, opmode,
524 							    vdev_id);
525 		*channel = wlan_reg_freq_to_chan(pdev, policy_mgr_get_channel(
526 						 soc_obj->soc,
527 						 mode,
528 						 &vdev_id));
529 		*opclass = 0;
530 	} else {
531 		*channel = wlan_reg_freq_to_chan(pdev,
532 						 peer->pref_off_chan_freq);
533 		*opclass = peer->op_class_for_pref_off_chan;
534 	}
535 	tdls_debug("channel:%d opclass:%d", *channel, *opclass);
536 }
537 
538 /**
539  * tdls_get_wifi_hal_state() - get TDLS wifi hal state on current peer
540  * @peer: TDLS peer
541  * @state: output parameter to store the TDLS wifi hal state
542  * @reason: output parameter to store the reason of the current peer
543  *
544  * Return: None.
545  */
tdls_get_wifi_hal_state(struct tdls_peer * peer,uint32_t * state,int32_t * reason)546 static void tdls_get_wifi_hal_state(struct tdls_peer *peer, uint32_t *state,
547 				    int32_t *reason)
548 {
549 	struct wlan_objmgr_vdev *vdev;
550 	struct tdls_soc_priv_obj *soc_obj;
551 
552 	vdev = peer->vdev_priv->vdev;
553 	soc_obj = wlan_vdev_get_tdls_soc_obj(vdev);
554 	if (!soc_obj) {
555 		tdls_err("can't get tdls object");
556 		return;
557 	}
558 
559 	*reason = peer->reason;
560 
561 	switch (peer->link_status) {
562 	case TDLS_LINK_IDLE:
563 	case TDLS_LINK_DISCOVERED:
564 	case TDLS_LINK_DISCOVERING:
565 	case TDLS_LINK_CONNECTING:
566 		*state = QCA_WIFI_HAL_TDLS_S_ENABLED;
567 		break;
568 	case TDLS_LINK_CONNECTED:
569 		if ((TDLS_IS_OFF_CHANNEL_ENABLED(
570 			     soc_obj->tdls_configs.tdls_feature_flags)) &&
571 		     (soc_obj->tdls_fw_off_chan_mode == ENABLE_CHANSWITCH))
572 			*state = QCA_WIFI_HAL_TDLS_S_ESTABLISHED_OFF_CHANNEL;
573 		else
574 			*state = QCA_WIFI_HAL_TDLS_S_ENABLED;
575 		break;
576 	case TDLS_LINK_TEARING:
577 		*state = QCA_WIFI_HAL_TDLS_S_DROPPED;
578 		break;
579 	}
580 }
581 
582 #ifdef WLAN_FEATURE_TDLS_CONCURRENCIES
583 /**
584  * tdls_get_allowed_off_channel_for_concurrency() - Get allowed off-channel
585  * frequency based on current concurrency. Return 0 if all frequencies are
586  * allowed
587  * @pdev: Pointer to PDEV object
588  * @vdev: Pointer to vdev object
589  *
590  * Return: Frequency
591  */
592 static inline qdf_freq_t
tdls_get_allowed_off_channel_for_concurrency(struct wlan_objmgr_pdev * pdev,struct wlan_objmgr_vdev * vdev)593 tdls_get_allowed_off_channel_for_concurrency(struct wlan_objmgr_pdev *pdev,
594 					     struct wlan_objmgr_vdev *vdev)
595 {
596 	struct wlan_objmgr_psoc *psoc = wlan_pdev_get_psoc(pdev);
597 	qdf_freq_t freq = 0;
598 
599 	if (!psoc)
600 		return 0;
601 
602 	if (!wlan_psoc_nif_fw_ext2_cap_get(psoc,
603 					   WLAN_TDLS_CONCURRENCIES_SUPPORT))
604 		return 0;
605 
606 	if (!policy_mgr_get_allowed_tdls_offchannel_freq(psoc, vdev, &freq)) {
607 		tdls_debug("off channel not allowed for current concurrency");
608 		return 0;
609 	}
610 
611 	return freq;
612 }
613 #else
614 static inline qdf_freq_t
tdls_get_allowed_off_channel_for_concurrency(struct wlan_objmgr_pdev * pdev,struct wlan_objmgr_vdev * vdev)615 tdls_get_allowed_off_channel_for_concurrency(struct wlan_objmgr_pdev *pdev,
616 					     struct wlan_objmgr_vdev *vdev)
617 {
618 	return 0;
619 }
620 #endif
621 
622 /**
623  * tdls_extract_peer_state_param() - extract peer update params from TDLS peer
624  * @peer_param: output peer update params
625  * @peer: TDLS peer
626  *
627  * This is used when enable TDLS link
628  *
629  * Return: None.
630  */
tdls_extract_peer_state_param(struct tdls_peer_update_state * peer_param,struct tdls_peer * peer)631 void tdls_extract_peer_state_param(struct tdls_peer_update_state *peer_param,
632 				   struct tdls_peer *peer)
633 {
634 	uint16_t i, num;
635 	struct tdls_vdev_priv_obj *vdev_obj;
636 	struct tdls_soc_priv_obj *soc_obj;
637 	enum channel_state ch_state;
638 	struct wlan_objmgr_pdev *pdev;
639 	uint32_t cur_band;
640 	qdf_freq_t ch_freq, allowed_freq;
641 	uint32_t tx_power = 0;
642 
643 	vdev_obj = peer->vdev_priv;
644 	soc_obj = wlan_vdev_get_tdls_soc_obj(vdev_obj->vdev);
645 	pdev = wlan_vdev_get_pdev(vdev_obj->vdev);
646 	if (!soc_obj || !pdev) {
647 		tdls_err("soc_obj: %pK, pdev: %pK", soc_obj, pdev);
648 		return;
649 	}
650 
651 	qdf_mem_zero(peer_param, sizeof(*peer_param));
652 	peer_param->vdev_id = wlan_vdev_get_id(vdev_obj->vdev);
653 
654 	qdf_mem_copy(peer_param->peer_macaddr,
655 		     peer->peer_mac.bytes, QDF_MAC_ADDR_SIZE);
656 	peer_param->peer_state = TDLS_PEER_STATE_CONNECTED;
657 	peer_param->peer_cap.is_peer_responder = peer->is_responder;
658 	peer_param->peer_cap.peer_uapsd_queue = peer->uapsd_queues;
659 	peer_param->peer_cap.peer_max_sp = peer->max_sp;
660 	peer_param->peer_cap.peer_buff_sta_support = peer->buf_sta_capable;
661 	peer_param->peer_cap.peer_off_chan_support =
662 		peer->off_channel_capable;
663 	peer_param->peer_cap.peer_curr_operclass = 0;
664 	peer_param->peer_cap.self_curr_operclass =
665 			peer->op_class_for_pref_off_chan;
666 	peer_param->peer_cap.pref_off_channum = wlan_reg_freq_to_chan(pdev,
667 						      peer->pref_off_chan_freq);
668 	peer_param->peer_cap.pref_off_chan_bandwidth =
669 						peer->pref_off_chan_width;
670 	peer_param->peer_cap.opclass_for_prefoffchan =
671 		peer->op_class_for_pref_off_chan;
672 	peer_param->peer_cap.pref_offchan_freq = peer->pref_off_chan_freq;
673 
674 	if (QDF_STATUS_SUCCESS != ucfg_reg_get_band(pdev, &cur_band)) {
675 		tdls_err("not able get the current frequency band");
676 		return;
677 	}
678 
679 	if (BIT(REG_BAND_2G) == cur_band) {
680 		tdls_err("sending the offchannel value as 0 as only 2g is supported");
681 		peer_param->peer_cap.pref_off_channum = 0;
682 		peer_param->peer_cap.opclass_for_prefoffchan = 0;
683 		peer_param->peer_cap.pref_offchan_freq = 0;
684 	}
685 
686 	ch_freq = peer->pref_off_chan_freq;
687 	if (wlan_reg_is_dfs_for_freq(pdev, ch_freq)) {
688 		/*
689 		 * If pref_off_chan_freq is DFS frequency, that means it is 5Ghz
690 		 * case. So, reset to default 5 GHz frequency
691 		 */
692 		tdls_err("Resetting TDLS off-channel from %d to %d",
693 			 peer_param->peer_cap.pref_off_channum,
694 			 WLAN_TDLS_PREFERRED_OFF_CHANNEL_NUM_DEF);
695 		peer_param->peer_cap.pref_off_channum =
696 			WLAN_TDLS_PREFERRED_OFF_CHANNEL_NUM_DEF;
697 		peer_param->peer_cap.pref_offchan_freq =
698 			WLAN_TDLS_PREFERRED_OFF_CHANNEL_FRQ_DEF;
699 	}
700 
701 	num = 0;
702 	allowed_freq =
703 		tdls_get_allowed_off_channel_for_concurrency(pdev,
704 							     vdev_obj->vdev);
705 	tdls_debug("allowed freq:%u", allowed_freq);
706 
707 	for (i = 0; i < peer->supported_channels_len; i++) {
708 		ch_freq = peer->supported_chan_freq[i];
709 		if (allowed_freq && allowed_freq != ch_freq)
710 			continue;
711 
712 		ch_state = wlan_reg_get_channel_state_for_pwrmode(
713 							pdev, ch_freq,
714 							REG_CURRENT_PWR_MODE);
715 
716 		if (CHANNEL_STATE_INVALID != ch_state &&
717 		    !wlan_reg_is_dfs_for_freq(pdev, ch_freq) &&
718 		    !wlan_reg_is_dsrc_freq(ch_freq)) {
719 			peer_param->peer_cap.peer_chan[num].ch_freq = ch_freq;
720 			if (!wlan_reg_is_6ghz_chan_freq(ch_freq)) {
721 				tx_power =
722 				wlan_reg_get_channel_reg_power_for_freq(pdev,
723 								       ch_freq);
724 			} else {
725 				tx_power =
726 				tdls_get_6g_pwr_for_power_type(vdev_obj->vdev,
727 							       ch_freq,
728 							       REG_CLI_DEF_VLP);
729 			}
730 			peer_param->peer_cap.peer_chan[num].pwr = tx_power;
731 			peer_param->peer_cap.peer_chan[num].dfs_set = false;
732 			peer_param->peer_cap.peer_chanlen++;
733 			num++;
734 		}
735 	}
736 
737 	peer_param->peer_cap.peer_oper_classlen =
738 		peer->supported_oper_classes_len;
739 	for (i = 0; i < peer->supported_oper_classes_len; i++)
740 		peer_param->peer_cap.peer_oper_class[i] =
741 			peer->supported_oper_classes[i];
742 }
743 
744 #ifdef TDLS_WOW_ENABLED
745 /**
746  * tdls_prevent_suspend(): Prevent suspend for TDLS
747  * @tdls_soc: TDLS soc object
748  *
749  * Acquire wake lock and prevent suspend for TDLS
750  *
751  * Return None
752  */
tdls_prevent_suspend(struct tdls_soc_priv_obj * tdls_soc)753 static void tdls_prevent_suspend(struct tdls_soc_priv_obj *tdls_soc)
754 {
755 	if (tdls_soc->is_prevent_suspend)
756 		return;
757 
758 	qdf_wake_lock_acquire(&tdls_soc->wake_lock,
759 			      WIFI_POWER_EVENT_WAKELOCK_TDLS);
760 	qdf_runtime_pm_prevent_suspend(&tdls_soc->runtime_lock);
761 	tdls_soc->is_prevent_suspend = true;
762 	tdls_debug("Acquire WIFI_POWER_EVENT_WAKELOCK_TDLS");
763 }
764 
765 /**
766  * tdls_allow_suspend(): Allow suspend for TDLS
767  * @tdls_soc: TDLS soc object
768  *
769  * Release wake lock and allow suspend for TDLS
770  *
771  * Return None
772  */
tdls_allow_suspend(struct tdls_soc_priv_obj * tdls_soc)773 static void tdls_allow_suspend(struct tdls_soc_priv_obj *tdls_soc)
774 {
775 	if (!tdls_soc->is_prevent_suspend)
776 		return;
777 
778 	qdf_wake_lock_release(&tdls_soc->wake_lock,
779 			      WIFI_POWER_EVENT_WAKELOCK_TDLS);
780 	qdf_runtime_pm_allow_suspend(&tdls_soc->runtime_lock);
781 	tdls_soc->is_prevent_suspend = false;
782 	tdls_debug("Release WIFI_POWER_EVENT_WAKELOCK_TDLS");
783 }
784 
785 /**
786  * tdls_update_pmo_status() - Update PMO status by TDLS status
787  * @tdls_vdev: TDLS vdev object
788  * @old_status: old link status
789  * @new_status: new link status
790  *
791  * Return: None.
792  */
tdls_update_pmo_status(struct tdls_vdev_priv_obj * tdls_vdev,enum tdls_link_state old_status,enum tdls_link_state new_status)793 static void tdls_update_pmo_status(struct tdls_vdev_priv_obj *tdls_vdev,
794 				   enum tdls_link_state old_status,
795 				   enum tdls_link_state new_status)
796 {
797 	struct tdls_soc_priv_obj *tdls_soc;
798 
799 	tdls_soc = wlan_vdev_get_tdls_soc_obj(tdls_vdev->vdev);
800 	if (!tdls_soc) {
801 		tdls_err("NULL psoc object");
802 		return;
803 	}
804 
805 	if (tdls_soc->is_drv_supported)
806 		return;
807 
808 	if ((old_status < TDLS_LINK_CONNECTING) &&
809 	    (new_status == TDLS_LINK_CONNECTING))
810 		tdls_prevent_suspend(tdls_soc);
811 
812 	if ((old_status > TDLS_LINK_IDLE) &&
813 	    (new_status == TDLS_LINK_IDLE) &&
814 	    (!tdls_soc->connected_peer_count) &&
815 	    (!tdls_is_progress(tdls_vdev, NULL, 0)))
816 		tdls_allow_suspend(tdls_soc);
817 }
818 #else
tdls_update_pmo_status(struct tdls_vdev_priv_obj * tdls_vdev,enum tdls_link_state old_status,enum tdls_link_state new_status)819 static void tdls_update_pmo_status(struct tdls_vdev_priv_obj *tdls_vdev,
820 				   enum tdls_link_state old_status,
821 				   enum tdls_link_state new_status)
822 {
823 }
824 #endif
825 
tdls_set_link_status(struct tdls_vdev_priv_obj * vdev_obj,const uint8_t * mac,enum tdls_link_state link_status,enum tdls_link_state_reason link_reason)826 void tdls_set_link_status(struct tdls_vdev_priv_obj *vdev_obj,
827 			  const uint8_t *mac,
828 			  enum tdls_link_state link_status,
829 			  enum tdls_link_state_reason link_reason)
830 {
831 	uint32_t state = 0;
832 	int32_t res = 0;
833 	uint32_t op_class = 0;
834 	uint32_t channel = 0;
835 	struct tdls_peer *peer;
836 	struct tdls_soc_priv_obj *soc_obj;
837 	enum tdls_link_state old_status;
838 
839 	peer = tdls_find_peer(vdev_obj, mac);
840 	if (!peer) {
841 		tdls_err("peer is NULL, can't set link status %d, reason %d",
842 			 link_status, link_reason);
843 		return;
844 	}
845 
846 	old_status = peer->link_status;
847 	peer->link_status = link_status;
848 	tdls_update_pmo_status(vdev_obj, old_status, link_status);
849 
850 	if (link_status >= TDLS_LINK_DISCOVERED)
851 		peer->discovery_attempt = 0;
852 
853 	if (peer->is_forced_peer && peer->state_change_notification) {
854 		peer->reason = link_reason;
855 
856 		soc_obj = wlan_vdev_get_tdls_soc_obj(vdev_obj->vdev);
857 		if (!soc_obj) {
858 			tdls_err("NULL psoc object");
859 			return;
860 		}
861 
862 		tdls_determine_channel_opclass(soc_obj, vdev_obj,
863 					       peer, &channel, &op_class);
864 		tdls_get_wifi_hal_state(peer, &state, &res);
865 		peer->state_change_notification(mac, op_class, channel,
866 						state, res, soc_obj->soc);
867 	}
868 }
869 
870 static inline char *
tdls_link_status_str(enum tdls_link_state link_status)871 tdls_link_status_str(enum tdls_link_state link_status)
872 {
873 	switch (link_status) {
874 	CASE_RETURN_STRING(TDLS_LINK_IDLE);
875 	CASE_RETURN_STRING(TDLS_LINK_DISCOVERING);
876 	CASE_RETURN_STRING(TDLS_LINK_DISCOVERED);
877 	CASE_RETURN_STRING(TDLS_LINK_CONNECTING);
878 	CASE_RETURN_STRING(TDLS_LINK_CONNECTED);
879 	CASE_RETURN_STRING(TDLS_LINK_TEARING);
880 	default:
881 		return "UNKNOWN";
882 	}
883 }
884 
tdls_set_peer_link_status(struct tdls_peer * peer,enum tdls_link_state link_status,enum tdls_link_state_reason link_reason)885 void tdls_set_peer_link_status(struct tdls_peer *peer,
886 			       enum tdls_link_state link_status,
887 			       enum tdls_link_state_reason link_reason)
888 {
889 	uint32_t state = 0;
890 	int32_t res = 0;
891 	uint32_t op_class = 0;
892 	uint32_t channel = 0;
893 	struct tdls_soc_priv_obj *soc_obj;
894 	struct tdls_vdev_priv_obj *vdev_obj;
895 	enum tdls_link_state old_status;
896 
897 	vdev_obj = peer->vdev_priv;
898 
899 	old_status = peer->link_status;
900 	peer->link_status = link_status;
901 	tdls_debug("vdev:%d new state: %s old state:%s reason %d peer:" QDF_MAC_ADDR_FMT,
902 		   wlan_vdev_get_id(vdev_obj->vdev),
903 		   tdls_link_status_str(link_status),
904 		   tdls_link_status_str(old_status), link_reason,
905 		   QDF_MAC_ADDR_REF(peer->peer_mac.bytes));
906 	tdls_update_pmo_status(vdev_obj, old_status, link_status);
907 
908 	if (link_status >= TDLS_LINK_DISCOVERED)
909 		peer->discovery_attempt = 0;
910 
911 	if (peer->is_forced_peer && peer->state_change_notification) {
912 		peer->reason = link_reason;
913 
914 		soc_obj = wlan_vdev_get_tdls_soc_obj(vdev_obj->vdev);
915 		if (!soc_obj) {
916 			tdls_err("NULL psoc object");
917 			return;
918 		}
919 
920 		tdls_determine_channel_opclass(soc_obj, vdev_obj,
921 					       peer, &channel, &op_class);
922 		tdls_get_wifi_hal_state(peer, &state, &res);
923 		peer->state_change_notification(peer->peer_mac.bytes,
924 						op_class, channel, state,
925 						res, soc_obj->soc);
926 	}
927 }
928 
929 static void
tdls_fill_peer_pref_offchan_bw(struct tdls_peer * peer,uint16_t bw)930 tdls_fill_peer_pref_offchan_bw(struct tdls_peer *peer,
931 			       uint16_t bw)
932 {
933 	if (bw < BW_160_MHZ)
934 		peer->pref_off_chan_width &= ~(1 << BW_160_OFFSET_BIT);
935 
936 	if (bw < BW_80_MHZ)
937 		peer->pref_off_chan_width &= ~(1 << BW_80_OFFSET_BIT);
938 
939 	if (bw < BW_40_MHZ)
940 		peer->pref_off_chan_width &= ~(1 << BW_40_OFFSET_BIT);
941 }
942 
tdls_update_off_chan_peer_caps(struct tdls_vdev_priv_obj * vdev_obj,struct tdls_soc_priv_obj * soc_obj,struct tdls_peer * peer)943 static void tdls_update_off_chan_peer_caps(struct tdls_vdev_priv_obj *vdev_obj,
944 					   struct tdls_soc_priv_obj *soc_obj,
945 					   struct tdls_peer *peer)
946 {
947 	struct wlan_objmgr_pdev *pdev = wlan_vdev_get_pdev(vdev_obj->vdev);
948 	qdf_freq_t ini_pref_6g_freq, ini_pref_non6g_freq, peer_freq;
949 	enum channel_enum peer_chan;
950 	qdf_freq_t peer_5g_freq = 0, peer_6g_freq = 0;
951 	bool is_6g_support = false;
952 	bool peer_6g_supportd = false;
953 	bool peer_5g_supportd = false;
954 	uint8_t i;
955 	uint16_t temp_bw, max_pref_width, peer_supportd_max_bw = 0;
956 	uint8_t reg_bw_offset;
957 
958 	if (!pdev) {
959 		tdls_err("pdev is NULL");
960 		return;
961 	}
962 
963 	/*
964 	 * Update Pref Offcahnnel BW such that:
965 	 * 1. If 6 GHz is supported then select the ini preferred 6 GHz channel
966 	 *    frequency.
967 	 * 2. If 6 GHz is supported and peer doesn't support the ini preferred
968 	 *    channel frequency then select the very first 6 GHz channel which
969 	 *    peer supports as prefferd offchannel.
970 	 * 3. If peer doesn't support 6 GHz, then select ini preferred 5 GHz
971 	 *    off channel frequency, given that peer should also support it
972 	 * 4. If peer doesn support 6 GHz and also doesn't support ini preferred
973 	 *    5 GHz offcahnnel, then select the very first 5 GHz channel it
974 	 *    supports.
975 	 */
976 	ini_pref_6g_freq = soc_obj->tdls_configs.tdls_pre_off_chan_freq_6g;
977 	ini_pref_non6g_freq = wlan_reg_legacy_chan_to_freq(pdev,
978 				soc_obj->tdls_configs.tdls_pre_off_chan_num);
979 
980 	if (ini_pref_6g_freq == peer->pref_off_chan_freq)
981 		is_6g_support = true;
982 
983 	for (i = 0; i < peer->supported_channels_len; i++) {
984 		peer_freq = peer->supported_chan_freq[i];
985 		peer_chan = wlan_reg_get_chan_enum_for_freq(peer_freq);
986 
987 		if (!wlan_reg_is_freq_idx_enabled(pdev, peer_chan,
988 						  REG_CLI_DEF_VLP))
989 			continue;
990 
991 		if (peer->pref_off_chan_freq == peer_freq)
992 			break;
993 
994 		if (ini_pref_non6g_freq == peer_freq) {
995 			peer_5g_supportd = true;
996 			peer_5g_freq = ini_pref_non6g_freq;
997 		}
998 		if (!peer_5g_supportd &&
999 		    wlan_reg_is_5ghz_ch_freq(peer_freq)) {
1000 			peer_5g_freq = peer_freq;
1001 			peer_5g_supportd = true;
1002 		}
1003 		if (!peer_6g_supportd &&
1004 		    wlan_reg_is_6ghz_chan_freq(peer_freq)) {
1005 			peer_6g_freq = peer_freq;
1006 			peer_6g_supportd = true;
1007 		}
1008 	}
1009 
1010 	if (peer->pref_off_chan_freq == peer->supported_chan_freq[i])
1011 		goto bw_check;
1012 
1013 	if (is_6g_support && peer_6g_freq)
1014 		peer->pref_off_chan_freq = peer_6g_freq;
1015 	else if (peer_5g_freq)
1016 		peer->pref_off_chan_freq = peer_5g_freq;
1017 	else
1018 		peer->pref_off_chan_freq = 0;
1019 
1020 bw_check:
1021 	max_pref_width = wlan_reg_get_max_chwidth(pdev,
1022 						  peer->pref_off_chan_freq);
1023 	for (i = 0; i < peer->supported_oper_classes_len; i++) {
1024 		temp_bw = wlan_reg_get_op_class_width(pdev,
1025 						peer->supported_oper_classes[i],
1026 						false);
1027 		if (temp_bw > peer_supportd_max_bw)
1028 			peer_supportd_max_bw = temp_bw;
1029 	}
1030 
1031 	peer_supportd_max_bw = (peer_supportd_max_bw > max_pref_width) ?
1032 				max_pref_width : peer_supportd_max_bw;
1033 	if (wlan_reg_is_6ghz_chan_freq(peer->pref_off_chan_freq) &&
1034 	    peer_supportd_max_bw < BW_160_MHZ)
1035 		tdls_fill_peer_pref_offchan_bw(peer, peer_supportd_max_bw);
1036 	else if (wlan_reg_is_5ghz_ch_freq(peer->pref_off_chan_freq) &&
1037 		 peer_supportd_max_bw < BW_80_MHZ)
1038 		tdls_fill_peer_pref_offchan_bw(peer, peer_supportd_max_bw);
1039 
1040 	if (wlan_reg_is_5ghz_ch_freq(peer->pref_off_chan_freq) &&
1041 	    CHECK_BIT(peer->pref_off_chan_width, BW_160_OFFSET_BIT))
1042 		peer->pref_off_chan_width &= ~(1 << BW_160_OFFSET_BIT);
1043 
1044 	peer->op_class_for_pref_off_chan =
1045 		tdls_get_opclass_from_bandwidth(
1046 				vdev_obj->vdev, peer->pref_off_chan_freq,
1047 				peer->pref_off_chan_width,
1048 				&reg_bw_offset);
1049 
1050 	tdls_debug("Updated preff offchannel freq %d width %d opclass %d",
1051 		   peer->pref_off_chan_freq, peer->pref_off_chan_width,
1052 		   peer->op_class_for_pref_off_chan);
1053 }
1054 
tdls_set_peer_caps(struct tdls_vdev_priv_obj * vdev_obj,const uint8_t * macaddr,struct tdls_update_peer_params * req_info)1055 void tdls_set_peer_caps(struct tdls_vdev_priv_obj *vdev_obj,
1056 			const uint8_t *macaddr,
1057 			struct tdls_update_peer_params  *req_info)
1058 {
1059 	uint8_t is_buffer_sta = 0;
1060 	uint8_t is_off_channel_supported = 0;
1061 	uint8_t is_qos_wmm_sta = 0;
1062 	struct tdls_soc_priv_obj *soc_obj;
1063 	struct tdls_peer *curr_peer;
1064 	uint32_t feature;
1065 
1066 	soc_obj = wlan_vdev_get_tdls_soc_obj(vdev_obj->vdev);
1067 	if (!soc_obj) {
1068 		tdls_err("NULL psoc object");
1069 		return;
1070 	}
1071 
1072 	curr_peer = tdls_find_peer(vdev_obj, macaddr);
1073 	if (!curr_peer) {
1074 		tdls_err("NULL tdls peer");
1075 		return;
1076 	}
1077 
1078 	feature = soc_obj->tdls_configs.tdls_feature_flags;
1079 	if ((1 << 4) & req_info->extn_capability[3])
1080 		is_buffer_sta = 1;
1081 
1082 	if ((1 << 6) & req_info->extn_capability[3])
1083 		is_off_channel_supported = 1;
1084 
1085 	if (TDLS_IS_WMM_ENABLED(feature) && req_info->is_qos_wmm_sta)
1086 		is_qos_wmm_sta = 1;
1087 
1088 	curr_peer->uapsd_queues = req_info->uapsd_queues;
1089 	curr_peer->max_sp = req_info->max_sp;
1090 	curr_peer->buf_sta_capable = is_buffer_sta;
1091 	curr_peer->off_channel_capable = is_off_channel_supported;
1092 
1093 	qdf_mem_copy(curr_peer->supported_chan_freq,
1094 		     req_info->supported_chan_freq,
1095 		     sizeof(qdf_freq_t) * req_info->supported_channels_len);
1096 
1097 	curr_peer->supported_channels_len = req_info->supported_channels_len;
1098 
1099 	qdf_mem_copy(curr_peer->supported_oper_classes,
1100 		     req_info->supported_oper_classes,
1101 		     req_info->supported_oper_classes_len);
1102 
1103 	curr_peer->supported_oper_classes_len =
1104 		req_info->supported_oper_classes_len;
1105 
1106 	curr_peer->qos = is_qos_wmm_sta;
1107 
1108 	tdls_update_off_chan_peer_caps(vdev_obj, soc_obj, curr_peer);
1109 }
1110 
tdls_set_valid(struct tdls_vdev_priv_obj * vdev_obj,const uint8_t * macaddr)1111 QDF_STATUS tdls_set_valid(struct tdls_vdev_priv_obj *vdev_obj,
1112 			   const uint8_t *macaddr)
1113 {
1114 	struct tdls_peer *peer;
1115 
1116 	peer = tdls_find_peer(vdev_obj, macaddr);
1117 	if (!peer) {
1118 		tdls_err("peer is NULL");
1119 		return QDF_STATUS_E_FAILURE;
1120 	}
1121 
1122 	peer->valid_entry = true;
1123 
1124 	return QDF_STATUS_SUCCESS;
1125 }
1126 
tdls_set_force_peer(struct tdls_vdev_priv_obj * vdev_obj,const uint8_t * macaddr,bool forcepeer)1127 QDF_STATUS tdls_set_force_peer(struct tdls_vdev_priv_obj *vdev_obj,
1128 			       const uint8_t *macaddr, bool forcepeer)
1129 {
1130 	struct tdls_peer *peer;
1131 
1132 	peer = tdls_find_peer(vdev_obj, macaddr);
1133 	if (!peer) {
1134 		tdls_err("peer is NULL");
1135 		return QDF_STATUS_E_FAILURE;
1136 	}
1137 	peer->is_forced_peer = forcepeer;
1138 
1139 	return QDF_STATUS_SUCCESS;
1140 }
1141 
tdls_set_callback(struct tdls_peer * peer,tdls_state_change_callback callback)1142 QDF_STATUS tdls_set_callback(struct tdls_peer *peer,
1143 			     tdls_state_change_callback callback)
1144 {
1145 	if (!peer) {
1146 		tdls_err("peer is NULL");
1147 		return QDF_STATUS_E_FAILURE;
1148 	}
1149 	peer->state_change_notification = callback;
1150 
1151 	return QDF_STATUS_SUCCESS;
1152 }
1153 
tdls_set_extctrl_param(struct tdls_peer * peer,qdf_freq_t ch_freq,uint32_t max_latency,uint32_t op_class,uint32_t min_bandwidth)1154 QDF_STATUS tdls_set_extctrl_param(struct tdls_peer *peer, qdf_freq_t ch_freq,
1155 				  uint32_t max_latency, uint32_t op_class,
1156 				  uint32_t min_bandwidth)
1157 {
1158 	if (!peer) {
1159 		tdls_err("peer is NULL");
1160 		return QDF_STATUS_E_FAILURE;
1161 	}
1162 	peer->op_class_for_pref_off_chan = (uint8_t)op_class;
1163 	peer->pref_off_chan_freq = ch_freq;
1164 
1165 	return QDF_STATUS_SUCCESS;
1166 }
1167 
tdls_reset_peer(struct tdls_vdev_priv_obj * vdev_obj,const uint8_t * macaddr)1168 QDF_STATUS tdls_reset_peer(struct tdls_vdev_priv_obj *vdev_obj,
1169 			   const uint8_t *macaddr)
1170 {
1171 	struct tdls_soc_priv_obj *soc_obj;
1172 	struct tdls_peer *curr_peer;
1173 	struct tdls_user_config *config;
1174 	uint8_t reg_bw_offset;
1175 
1176 	soc_obj = wlan_vdev_get_tdls_soc_obj(vdev_obj->vdev);
1177 	if (!soc_obj) {
1178 		tdls_err("NULL psoc object");
1179 		return QDF_STATUS_E_FAILURE;
1180 	}
1181 
1182 	curr_peer = tdls_find_peer(vdev_obj, macaddr);
1183 	if (!curr_peer) {
1184 		tdls_err("NULL tdls peer");
1185 		return QDF_STATUS_E_FAILURE;
1186 	}
1187 
1188 	if (!curr_peer->is_forced_peer) {
1189 		config = &soc_obj->tdls_configs;
1190 		tdls_fill_pref_off_chan_info(vdev_obj, soc_obj, curr_peer);
1191 		curr_peer->op_class_for_pref_off_chan =
1192 			tdls_get_opclass_from_bandwidth(
1193 				vdev_obj->vdev, curr_peer->pref_off_chan_freq,
1194 				curr_peer->pref_off_chan_width,
1195 				&reg_bw_offset);
1196 	}
1197 
1198 	if (curr_peer->is_peer_idle_timer_initialised) {
1199 		tdls_debug(QDF_MAC_ADDR_FMT ": destroy  idle timer ",
1200 			   QDF_MAC_ADDR_REF(curr_peer->peer_mac.bytes));
1201 		qdf_mc_timer_stop(&curr_peer->peer_idle_timer);
1202 		qdf_mc_timer_destroy(&curr_peer->peer_idle_timer);
1203 		curr_peer->is_peer_idle_timer_initialised = false;
1204 	}
1205 
1206 	tdls_set_peer_link_status(curr_peer, TDLS_LINK_IDLE,
1207 				  TDLS_LINK_UNSPECIFIED);
1208 	curr_peer->valid_entry = false;
1209 
1210 	return QDF_STATUS_SUCCESS;
1211 }
1212 
tdls_peer_idle_timers_destroy(struct tdls_vdev_priv_obj * vdev_obj)1213 void tdls_peer_idle_timers_destroy(struct tdls_vdev_priv_obj *vdev_obj)
1214 {
1215 	uint16_t i;
1216 	struct tdls_peer *peer;
1217 	qdf_list_t *head;
1218 	qdf_list_node_t *p_node;
1219 	QDF_STATUS status;
1220 
1221 	if (!vdev_obj) {
1222 		tdls_err("NULL tdls vdev object");
1223 		return;
1224 	}
1225 
1226 	for (i = 0; i < WLAN_TDLS_PEER_LIST_SIZE; i++) {
1227 		head = &vdev_obj->peer_list[i];
1228 
1229 		status = qdf_list_peek_front(head, &p_node);
1230 		while (QDF_IS_STATUS_SUCCESS(status)) {
1231 			peer = qdf_container_of(p_node, struct tdls_peer, node);
1232 			if (peer && peer->is_peer_idle_timer_initialised) {
1233 				tdls_debug(QDF_MAC_ADDR_FMT
1234 					   ": destroy  idle timer ",
1235 					   QDF_MAC_ADDR_REF(
1236 						   peer->peer_mac.bytes));
1237 				qdf_mc_timer_stop(&peer->peer_idle_timer);
1238 				qdf_mc_timer_destroy(&peer->peer_idle_timer);
1239 			}
1240 			status = qdf_list_peek_next(head, p_node, &p_node);
1241 		}
1242 	}
1243 }
1244 
tdls_free_peer_list(struct tdls_vdev_priv_obj * vdev_obj)1245 void tdls_free_peer_list(struct tdls_vdev_priv_obj *vdev_obj)
1246 {
1247 	uint16_t i;
1248 	struct tdls_peer *peer;
1249 	qdf_list_t *head;
1250 	qdf_list_node_t *p_node;
1251 
1252 	if (!vdev_obj) {
1253 		tdls_err("NULL tdls vdev object");
1254 		return;
1255 	}
1256 
1257 	for (i = 0; i < WLAN_TDLS_PEER_LIST_SIZE; i++) {
1258 		head = &vdev_obj->peer_list[i];
1259 
1260 		while (QDF_IS_STATUS_SUCCESS(
1261 			       qdf_list_remove_front(head, &p_node))) {
1262 			peer = qdf_container_of(p_node, struct tdls_peer, node);
1263 			qdf_mem_free(peer);
1264 		}
1265 		qdf_list_destroy(head);
1266 	}
1267 }
1268