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 ®_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 ®_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 ®_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