1 /*
2 * Copyright (c) 2021, The Linux Foundation. All rights reserved.
3 * Copyright (c) 2021-2024 Qualcomm Innovation Center, Inc. All rights reserved.
4 *
5 * Permission to use, copy, modify, and/or distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
8 *
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 */
17
18 /*
19 * DOC: contains MLO manager init/deinit api's
20 */
21 #include "wlan_cmn.h"
22 #include <wlan_objmgr_cmn.h>
23 #include <wlan_objmgr_global_obj.h>
24 #include "wlan_mlo_mgr_cmn.h"
25 #include "wlan_mlo_mgr_main.h"
26 #include <wlan_mlo_mgr_ap.h>
27 #include <wlan_mlo_mgr_peer.h>
28 #include <wlan_mlo_mgr_setup.h>
29 #include <wlan_cm_public_struct.h>
30 #include "wlan_mlo_mgr_msgq.h"
31 #include <target_if_mlo_mgr.h>
32 #include <wlan_mlo_t2lm.h>
33 #include <wlan_cm_api.h>
34 #include <wlan_mlo_mgr_public_api.h>
35 #include "cdp_txrx_cmn.h"
36
37 #ifdef WLAN_WSI_STATS_SUPPORT
38 /*
39 * wlan_mlo_wsi_get_num_psocs() - Get the number of attached PSOCs
40 * @psoc: Pointer to psoc
41 * @arg: Pointer to variable to store count
42 * @index: Index for iteration function
43 */
wlan_mlo_wsi_get_num_psocs(struct wlan_objmgr_psoc * psoc,void * arg,uint8_t index)44 static void wlan_mlo_wsi_get_num_psocs(struct wlan_objmgr_psoc *psoc,
45 void *arg, uint8_t index)
46 {
47 /* If arg is NULL then skip increment */
48 if (!arg)
49 return;
50
51 (*(uint32_t *)arg)++;
52 }
53
mlo_wsi_link_info_deinit(struct mlo_mgr_context * mlo_mgr)54 static void mlo_wsi_link_info_deinit(struct mlo_mgr_context *mlo_mgr)
55 {
56 if (!mlo_mgr)
57 return;
58
59 if (mlo_mgr->wsi_info) {
60 qdf_mem_free(mlo_mgr->wsi_info);
61 mlo_mgr->wsi_info = NULL;
62 }
63 }
64
65 #ifdef WLAN_MLO_MULTI_CHIP
mlo_wsi_link_info_update_soc(struct wlan_objmgr_psoc * psoc,uint8_t grp_id)66 void mlo_wsi_link_info_update_soc(struct wlan_objmgr_psoc *psoc,
67 uint8_t grp_id)
68 {
69 struct mlo_mgr_context *mlo_ctx = wlan_objmgr_get_mlo_ctx();
70 struct mlo_wsi_psoc_grp *mlo_grp_info;
71 uint8_t i, j;
72
73 if (!mlo_ctx) {
74 mlo_err("Invalid mlo_mgr_ctx");
75 return;
76 }
77
78 mlo_grp_info = &mlo_ctx->wsi_info->mlo_psoc_grp[grp_id];
79 if (!mlo_grp_info) {
80 mlo_err("mlo_grp_info is invalid for ix %d", i);
81 return;
82 }
83
84 mlo_ctx->wsi_info->num_psoc++;
85
86 /* Set the PSOC order for the MLO group */
87 for (j = 0; j < WLAN_OBJMGR_MAX_DEVICES; j++) {
88 if (mlo_grp_info->psoc_order[j] == MLO_WSI_PSOC_ID_MAX) {
89 mlo_grp_info->psoc_order[j] = wlan_psoc_get_id(psoc);
90 mlo_grp_info->num_psoc++;
91 break;
92 }
93 }
94 }
95 #endif
96
97 static void
mlo_wsi_link_info_setup_mlo_grps(struct mlo_mgr_context * mlo_mgr)98 mlo_wsi_link_info_setup_mlo_grps(struct mlo_mgr_context *mlo_mgr)
99 {
100 struct mlo_wsi_psoc_grp *mlo_grp_info;
101 uint8_t i, j;
102
103 if (!mlo_mgr) {
104 mlo_err("Invalid mlo_mgr");
105 return;
106 }
107
108 if (!mlo_mgr->wsi_info) {
109 mlo_err("Invalid wsi_info");
110 return;
111 }
112
113 wlan_objmgr_iterate_psoc_list(wlan_mlo_wsi_get_num_psocs,
114 &mlo_mgr->wsi_info->num_psoc,
115 WLAN_MLO_MGR_ID);
116 if (!mlo_mgr->wsi_info->num_psoc)
117 mlo_info("Could not find active PSOCs");
118
119 for (i = 0; i < MLO_WSI_MAX_MLO_GRPS; i++) {
120 mlo_grp_info =
121 &mlo_mgr->wsi_info->mlo_psoc_grp[i];
122 if (!mlo_grp_info) {
123 mlo_err("mlo_grp_info is invalid for ix %d", i);
124 continue;
125 }
126
127 /* Set the PSOC order for the MLO group */
128 for (j = 0; j < WLAN_OBJMGR_MAX_DEVICES; j++) {
129 /*
130 * NOTE: Inclusion of more MLO groups will require
131 * changes to this block where rvalue will need
132 * to be checked against the group they need to
133 * be assigned to.
134 */
135 if (j < mlo_mgr->wsi_info->num_psoc) {
136 mlo_grp_info->psoc_order[j] = j;
137 mlo_grp_info->num_psoc++;
138 } else {
139 mlo_grp_info->psoc_order[j] =
140 MLO_WSI_PSOC_ID_MAX;
141 }
142 mlo_err("PSOC order %d, index %d",
143 mlo_grp_info->psoc_order[j], j);
144 }
145 }
146 }
147
mlo_wsi_link_info_init(struct mlo_mgr_context * mlo_mgr)148 static void mlo_wsi_link_info_init(struct mlo_mgr_context *mlo_mgr)
149 {
150 uint8_t i;
151
152 if (!mlo_mgr)
153 return;
154
155 /* Initialize the mlo_wsi_link_info structure */
156 mlo_mgr->wsi_info = qdf_mem_malloc(
157 sizeof(struct mlo_wsi_info));
158 if (!mlo_mgr->wsi_info) {
159 mlo_err("Could not allocate memory for wsi_link_info");
160 return;
161 }
162
163 /* Initialize the MLO group context in the WSI stats */
164 for (i = 0; i < MLO_WSI_MAX_MLO_GRPS; i++)
165 mlo_wsi_link_info_setup_mlo_grps(mlo_mgr);
166 }
167 #else
mlo_wsi_link_info_init(struct mlo_mgr_context * mlo_mgr)168 static void mlo_wsi_link_info_init(struct mlo_mgr_context *mlo_mgr)
169 {
170 }
171
mlo_wsi_link_info_deinit(struct mlo_mgr_context * mlo_mgr)172 static void mlo_wsi_link_info_deinit(struct mlo_mgr_context *mlo_mgr)
173 {
174 }
175 #endif
176
mlo_global_ctx_deinit(void)177 static void mlo_global_ctx_deinit(void)
178 {
179 struct mlo_mgr_context *mlo_mgr_ctx = wlan_objmgr_get_mlo_ctx();
180
181 if (!mlo_mgr_ctx)
182 return;
183
184 if (qdf_list_empty(&mlo_mgr_ctx->ml_dev_list))
185 mlo_debug("ML dev list is not empty");
186
187 /* Deallocation of the WSI link information */
188 mlo_wsi_link_info_deinit(mlo_mgr_ctx);
189
190 mlo_setup_deinit();
191 mlo_msgq_free();
192 ml_peerid_lock_destroy(mlo_mgr_ctx);
193 ml_link_lock_destroy(mlo_mgr_ctx);
194 ml_aid_lock_destroy(mlo_mgr_ctx);
195 qdf_list_destroy(&mlo_mgr_ctx->ml_dev_list);
196
197 qdf_mem_free(mlo_mgr_ctx);
198 wlan_objmgr_set_mlo_ctx(NULL);
199 }
200
mlo_global_ctx_init(void)201 static void mlo_global_ctx_init(void)
202 {
203 struct mlo_mgr_context *mlo_mgr_ctx;
204
205 /* If it is already created, ignore */
206 if (wlan_objmgr_get_mlo_ctx()) {
207 mlo_err("Global object is already created");
208 return;
209 }
210
211 /* Allocation of memory for Global object */
212 mlo_mgr_ctx = (struct mlo_mgr_context *)
213 qdf_mem_malloc(sizeof(*mlo_mgr_ctx));
214 if (!mlo_mgr_ctx)
215 return;
216
217 wlan_objmgr_set_mlo_ctx(mlo_mgr_ctx);
218
219 qdf_list_create(&mlo_mgr_ctx->ml_dev_list, WLAN_UMAC_MLO_MAX_DEV);
220 mlo_mgr_ctx->max_mlo_peer_id = MAX_MLO_PEER_ID;
221 mlo_mgr_ctx->last_mlo_peer_id = 0;
222 ml_peerid_lock_create(mlo_mgr_ctx);
223 ml_link_lock_create(mlo_mgr_ctx);
224 ml_aid_lock_create(mlo_mgr_ctx);
225 mlo_mgr_ctx->mlo_is_force_primary_umac = 0;
226 mlo_mgr_ctx->force_non_assoc_prim_umac = 0;
227 mlo_msgq_init();
228
229 /* Allocation of the WSI link information */
230 mlo_wsi_link_info_init(mlo_mgr_ctx);
231 }
232
233 /**
234 * wlan_mlo_check_psoc_capable() - Check if psoc is mlo capable
235 * @psoc: psoc pointer
236 *
237 * API to check if psoc is mlo capable
238 *
239 * Return: bool, true if capable else false
240 */
241 #ifdef WLAN_MLO_MULTI_CHIP
wlan_mlo_check_psoc_capable(struct wlan_objmgr_psoc * psoc)242 static bool wlan_mlo_check_psoc_capable(struct wlan_objmgr_psoc *psoc)
243 {
244 return wlan_mlo_get_psoc_capable(psoc);
245 }
246 #else
wlan_mlo_check_psoc_capable(struct wlan_objmgr_psoc * psoc)247 static bool wlan_mlo_check_psoc_capable(struct wlan_objmgr_psoc *psoc)
248 {
249 return true;
250 }
251 #endif
252
wlan_mlo_mgr_psoc_enable(struct wlan_objmgr_psoc * psoc)253 QDF_STATUS wlan_mlo_mgr_psoc_enable(struct wlan_objmgr_psoc *psoc)
254 {
255 struct wlan_lmac_if_mlo_tx_ops *mlo_tx_ops;
256
257 if (!psoc) {
258 mlo_err("psoc is null");
259 return QDF_STATUS_E_NULL_VALUE;
260 }
261
262 if (!wlan_mlo_check_psoc_capable(psoc))
263 return QDF_STATUS_SUCCESS;
264
265 mlo_tx_ops = target_if_mlo_get_tx_ops(psoc);
266 if (!mlo_tx_ops) {
267 mlo_err("tx_ops is null!");
268 return QDF_STATUS_E_NULL_VALUE;
269 }
270
271 if (!mlo_tx_ops->register_events) {
272 mlo_err("register_events function is null!");
273 return QDF_STATUS_E_NULL_VALUE;
274 }
275
276 return mlo_tx_ops->register_events(psoc);
277 }
278
wlan_mlo_mgr_psoc_disable(struct wlan_objmgr_psoc * psoc)279 QDF_STATUS wlan_mlo_mgr_psoc_disable(struct wlan_objmgr_psoc *psoc)
280 {
281 struct wlan_lmac_if_mlo_tx_ops *mlo_tx_ops;
282
283 if (!psoc) {
284 mlo_err("psoc is null");
285 return QDF_STATUS_E_NULL_VALUE;
286 }
287
288 mlo_tx_ops = target_if_mlo_get_tx_ops(psoc);
289 if (!mlo_tx_ops) {
290 mlo_err("tx_ops is null!");
291 return QDF_STATUS_E_NULL_VALUE;
292 }
293
294 if (!mlo_tx_ops->unregister_events) {
295 mlo_err("unregister_events function is null!");
296 return QDF_STATUS_E_NULL_VALUE;
297 }
298
299 return mlo_tx_ops->unregister_events(psoc);
300 }
301
302 #ifdef WLAN_FEATURE_11BE_MLO_ADV_FEATURE
303 QDF_STATUS
mlo_mgr_register_link_switch_notifier(enum wlan_umac_comp_id comp_id,mlo_mgr_link_switch_notifier_cb cb)304 mlo_mgr_register_link_switch_notifier(enum wlan_umac_comp_id comp_id,
305 mlo_mgr_link_switch_notifier_cb cb)
306 {
307 struct mlo_mgr_context *g_mlo_mgr_ctx = wlan_objmgr_get_mlo_ctx();
308
309 if (!g_mlo_mgr_ctx) {
310 mlo_err("global mlo mgr not initialized");
311 return QDF_STATUS_E_INVAL;
312 }
313
314 if (!cb || comp_id >= WLAN_UMAC_COMP_ID_MAX) {
315 mlo_err("Invalid component");
316 QDF_ASSERT(0);
317 return QDF_STATUS_E_INVAL;
318 }
319
320 if (g_mlo_mgr_ctx->lswitch_notifier[comp_id].in_use)
321 return QDF_STATUS_E_ALREADY;
322
323 g_mlo_mgr_ctx->lswitch_notifier[comp_id].in_use = true;
324 g_mlo_mgr_ctx->lswitch_notifier[comp_id].cb = cb;
325 return QDF_STATUS_SUCCESS;
326 }
327
328 QDF_STATUS
mlo_mgr_unregister_link_switch_notifier(enum wlan_umac_comp_id comp_id)329 mlo_mgr_unregister_link_switch_notifier(enum wlan_umac_comp_id comp_id)
330 {
331 struct mlo_mgr_context *g_mlo_mgr_ctx = wlan_objmgr_get_mlo_ctx();
332
333 if (!g_mlo_mgr_ctx) {
334 mlo_err("global mlo mgr not initialized");
335 return QDF_STATUS_E_INVAL;
336 }
337
338 if (comp_id >= WLAN_UMAC_COMP_ID_MAX) {
339 mlo_err("Invalid component");
340 QDF_ASSERT(0);
341 return QDF_STATUS_E_INVAL;
342 }
343
344 if (!g_mlo_mgr_ctx->lswitch_notifier[comp_id].in_use)
345 return QDF_STATUS_E_INVAL;
346
347 g_mlo_mgr_ctx->lswitch_notifier[comp_id].in_use = false;
348 g_mlo_mgr_ctx->lswitch_notifier[comp_id].cb = NULL;
349 return QDF_STATUS_SUCCESS;
350 }
351
mlo_mgr_init_link_switch_notifier(void)352 static QDF_STATUS mlo_mgr_init_link_switch_notifier(void)
353 {
354 int i;
355 struct mlo_mgr_context *g_mlo_mgr_ctx = wlan_objmgr_get_mlo_ctx();
356
357 if (!g_mlo_mgr_ctx)
358 return QDF_STATUS_E_INVAL;
359
360 for (i = 0; i < WLAN_UMAC_COMP_ID_MAX; i++) {
361 g_mlo_mgr_ctx->lswitch_notifier[i].in_use = false;
362 g_mlo_mgr_ctx->lswitch_notifier[i].cb = NULL;
363 }
364
365 return QDF_STATUS_SUCCESS;
366 }
367 #else
mlo_mgr_init_link_switch_notifier(void)368 static inline QDF_STATUS mlo_mgr_init_link_switch_notifier(void)
369 {
370 return QDF_STATUS_E_NOSUPPORT;
371 }
372 #endif /* WLAN_FEATURE_11BE_MLO_ADV_FEATURE */
373
wlan_mlo_mgr_init(void)374 QDF_STATUS wlan_mlo_mgr_init(void)
375 {
376 QDF_STATUS status;
377
378 mlo_global_ctx_init();
379
380 status = wlan_objmgr_register_vdev_create_handler(
381 WLAN_UMAC_COMP_MLO_MGR,
382 wlan_mlo_mgr_vdev_created_notification, NULL);
383 if (QDF_IS_STATUS_ERROR(status)) {
384 mlo_err("Failed to register vdev create handler");
385 return QDF_STATUS_E_FAILURE;
386 }
387
388 status = wlan_objmgr_register_vdev_destroy_handler(WLAN_UMAC_COMP_MLO_MGR,
389 wlan_mlo_mgr_vdev_destroyed_notification, NULL);
390 if (QDF_IS_STATUS_ERROR(status)) {
391 mlo_debug("Failed to register VDEV destroy handler");
392 wlan_objmgr_unregister_vdev_create_handler(WLAN_UMAC_COMP_MLO_MGR,
393 wlan_mlo_mgr_vdev_created_notification, NULL);
394 return status;
395 }
396
397 status = mlo_mgr_init_link_switch_notifier();
398 if (QDF_IS_STATUS_SUCCESS(status)) {
399 status = mlo_mgr_register_link_switch_notifier(WLAN_UMAC_COMP_MLO_MGR,
400 mlo_mgr_link_switch_notification);
401 return status;
402 }
403 if (status == QDF_STATUS_E_NOSUPPORT)
404 status = QDF_STATUS_SUCCESS;
405
406 return status;
407 }
408
wlan_mlo_mgr_deinit(void)409 QDF_STATUS wlan_mlo_mgr_deinit(void)
410 {
411 QDF_STATUS status;
412 struct mlo_mgr_context *mlo_mgr_ctx = wlan_objmgr_get_mlo_ctx();
413
414 if (!mlo_mgr_ctx) {
415 mlo_err("MLO global object is not allocated");
416 return QDF_STATUS_E_FAILURE;
417 }
418
419 wlan_mlo_mgr_unregister_link_switch_notifier(WLAN_UMAC_COMP_MLO_MGR);
420
421 mlo_global_ctx_deinit();
422
423 status = wlan_objmgr_unregister_vdev_create_handler(
424 WLAN_UMAC_COMP_MLO_MGR,
425 wlan_mlo_mgr_vdev_created_notification, NULL);
426 if (status != QDF_STATUS_SUCCESS)
427 mlo_err("Failed to unregister vdev create handler");
428
429 status = wlan_objmgr_unregister_vdev_destroy_handler(
430 WLAN_UMAC_COMP_MLO_MGR,
431 wlan_mlo_mgr_vdev_destroyed_notification, NULL);
432 if (status != QDF_STATUS_SUCCESS)
433 mlo_err("Failed to unregister vdev delete handler");
434
435 return status;
436 }
437
wlan_mlo_list_peek_head(qdf_list_t * ml_list)438 struct wlan_mlo_dev_context *wlan_mlo_list_peek_head(
439 qdf_list_t *ml_list)
440 {
441 struct wlan_mlo_dev_context *mld_ctx;
442 qdf_list_node_t *ml_node = NULL;
443
444 /* This API is invoked with lock acquired, do not add log prints */
445 if (qdf_list_peek_front(ml_list, &ml_node) != QDF_STATUS_SUCCESS)
446 return NULL;
447
448 mld_ctx = qdf_container_of(ml_node, struct wlan_mlo_dev_context,
449 node);
450
451 return mld_ctx;
452 }
453
wlan_mlo_get_next_mld_ctx(qdf_list_t * ml_list,struct wlan_mlo_dev_context * mld_cur)454 struct wlan_mlo_dev_context *wlan_mlo_get_next_mld_ctx(qdf_list_t *ml_list,
455 struct wlan_mlo_dev_context *mld_cur)
456 {
457 struct wlan_mlo_dev_context *mld_next;
458 qdf_list_node_t *node = &mld_cur->node;
459 qdf_list_node_t *next_node = NULL;
460
461 /* This API is invoked with lock acquired, do not add log prints */
462 if (!node)
463 return NULL;
464
465 if (qdf_list_peek_next(ml_list, node, &next_node) !=
466 QDF_STATUS_SUCCESS)
467 return NULL;
468
469 mld_next = qdf_container_of(next_node, struct wlan_mlo_dev_context,
470 node);
471 return mld_next;
472 }
473
wlan_mlo_get_sta_mld_ctx_count(void)474 uint8_t wlan_mlo_get_sta_mld_ctx_count(void)
475 {
476 struct wlan_mlo_dev_context *mld_cur;
477 struct wlan_mlo_dev_context *mld_next;
478 qdf_list_t *ml_list;
479 struct mlo_mgr_context *mlo_mgr_ctx = wlan_objmgr_get_mlo_ctx();
480 uint8_t count = 0;
481
482 if (!mlo_mgr_ctx)
483 return count;
484
485 ml_link_lock_acquire(mlo_mgr_ctx);
486 ml_list = &mlo_mgr_ctx->ml_dev_list;
487 /* Get first mld context */
488 mld_cur = wlan_mlo_list_peek_head(ml_list);
489
490 while (mld_cur) {
491 /* get next mld node */
492 if (mld_cur->sta_ctx)
493 count++;
494 mld_next = wlan_mlo_get_next_mld_ctx(ml_list, mld_cur);
495 mld_cur = mld_next;
496 }
497 ml_link_lock_release(mlo_mgr_ctx);
498
499 return count;
500 }
501
502 struct wlan_mlo_dev_context
wlan_mlo_get_mld_ctx_by_mldaddr(struct qdf_mac_addr * mldaddr)503 *wlan_mlo_get_mld_ctx_by_mldaddr(struct qdf_mac_addr *mldaddr)
504 {
505 struct wlan_mlo_dev_context *mld_cur;
506 struct wlan_mlo_dev_context *mld_next;
507 qdf_list_t *ml_list;
508 struct mlo_mgr_context *mlo_mgr_ctx = wlan_objmgr_get_mlo_ctx();
509
510 if (!mlo_mgr_ctx)
511 return NULL;
512
513 ml_link_lock_acquire(mlo_mgr_ctx);
514 ml_list = &mlo_mgr_ctx->ml_dev_list;
515 /* Get first mld context */
516 mld_cur = wlan_mlo_list_peek_head(ml_list);
517 /**
518 * Iterate through ml list, till ml mldaddr matches with
519 * entry of list
520 */
521 while (mld_cur) {
522 if (QDF_IS_STATUS_SUCCESS(WLAN_ADDR_EQ(&mld_cur->mld_addr,
523 mldaddr))) {
524 ml_link_lock_release(mlo_mgr_ctx);
525 return mld_cur;
526 }
527 /* get next mld node */
528 mld_next = wlan_mlo_get_next_mld_ctx(ml_list, mld_cur);
529 mld_cur = mld_next;
530 }
531 ml_link_lock_release(mlo_mgr_ctx);
532
533 return NULL;
534 }
535
wlan_mlo_is_mld_ctx_exist(struct qdf_mac_addr * mldaddr)536 bool wlan_mlo_is_mld_ctx_exist(struct qdf_mac_addr *mldaddr)
537 {
538 struct wlan_mlo_dev_context *mld_ctx = NULL;
539
540 mld_ctx = wlan_mlo_get_mld_ctx_by_mldaddr(mldaddr);
541 if (mld_ctx)
542 return true;
543
544 return false;
545 }
546
547 #ifdef WLAN_MLO_MULTI_CHIP
mlo_mgr_is_mld_has_active_link(bool * is_active)548 QDF_STATUS mlo_mgr_is_mld_has_active_link(bool *is_active)
549 {
550 qdf_list_t *ml_list;
551 uint32_t idx, count;
552 struct wlan_mlo_dev_context *mld_cur, *mld_next;
553 struct wlan_objmgr_vdev *vdev;
554 struct mlo_mgr_context *g_mlo_ctx = wlan_objmgr_get_mlo_ctx();
555 QDF_STATUS status;
556
557 if (!g_mlo_ctx || !is_active)
558 return QDF_STATUS_E_FAILURE;
559
560 ml_link_lock_acquire(g_mlo_ctx);
561 ml_list = &g_mlo_ctx->ml_dev_list;
562 if (!qdf_list_size(ml_list)) {
563 ml_link_lock_release(g_mlo_ctx);
564 return QDF_STATUS_E_FAILURE;
565 }
566
567 *is_active = false;
568 mld_cur = wlan_mlo_list_peek_head(ml_list);
569 while (mld_cur) {
570 mlo_dev_lock_acquire(mld_cur);
571 count = QDF_ARRAY_SIZE(mld_cur->wlan_vdev_list);
572 for (idx = 0; idx < count; idx++) {
573 vdev = mld_cur->wlan_vdev_list[idx];
574 if (!vdev)
575 continue;
576
577 status = wlan_vdev_mlme_is_init_state(vdev);
578 if (QDF_STATUS_SUCCESS == status)
579 continue;
580
581 qdf_err("VDEV [vdev_id %u, pdev_id %u, psoc_id %u, state %u] is still active",
582 wlan_vdev_get_id(vdev),
583 wlan_objmgr_pdev_get_pdev_id(wlan_vdev_get_pdev(vdev)),
584 wlan_vdev_get_psoc_id(vdev),
585 wlan_vdev_mlme_get_state(vdev));
586 *is_active = true;
587 mlo_dev_lock_release(mld_cur);
588 ml_link_lock_release(g_mlo_ctx);
589 return QDF_STATUS_SUCCESS;
590 }
591 mld_next = wlan_mlo_get_next_mld_ctx(ml_list, mld_cur);
592 mlo_dev_lock_release(mld_cur);
593 mld_cur = mld_next;
594 }
595 ml_link_lock_release(g_mlo_ctx);
596
597 return QDF_STATUS_SUCCESS;
598 }
599
600 qdf_export_symbol(mlo_mgr_is_mld_has_active_link);
601 #endif
602
603 #ifdef WLAN_FEATURE_11BE_MLO
mlo_mgr_ml_peer_exist_on_diff_ml_ctx(uint8_t * peer_addr,uint8_t * peer_vdev_id)604 bool mlo_mgr_ml_peer_exist_on_diff_ml_ctx(uint8_t *peer_addr,
605 uint8_t *peer_vdev_id)
606 {
607 qdf_list_t *ml_list;
608 uint32_t idx, count;
609 struct wlan_mlo_dev_context *mld_cur, *mld_next;
610 struct wlan_mlo_peer_list *mlo_peer_list;
611 struct wlan_objmgr_vdev *vdev;
612 bool ret_status = false, same_ml_ctx = false;
613 struct mlo_mgr_context *g_mlo_ctx = wlan_objmgr_get_mlo_ctx();
614
615 if (!g_mlo_ctx || !peer_addr ||
616 qdf_is_macaddr_zero((struct qdf_mac_addr *)peer_addr))
617 return ret_status;
618
619 ml_link_lock_acquire(g_mlo_ctx);
620 ml_list = &g_mlo_ctx->ml_dev_list;
621 if (!qdf_list_size(ml_list))
622 goto g_ml_ref;
623
624 mld_cur = wlan_mlo_list_peek_head(ml_list);
625 while (mld_cur) {
626 mlo_dev_lock_acquire(mld_cur);
627 if (qdf_is_macaddr_equal(&mld_cur->mld_addr,
628 (struct qdf_mac_addr *)peer_addr)) {
629 /* For self peer, the address passed will match the
630 * MLD address of its own ML dev context, so allow
631 * peer creation in this scenario as both are in
632 * same ML dev context.
633 */
634 if (peer_vdev_id) {
635 count = QDF_ARRAY_SIZE(mld_cur->wlan_vdev_list);
636 for (idx = 0; idx < count; idx++) {
637 vdev = mld_cur->wlan_vdev_list[idx];
638 if (!vdev)
639 continue;
640 if (*peer_vdev_id ==
641 wlan_vdev_get_id(vdev)) {
642 same_ml_ctx = true;
643 break;
644 }
645 }
646 }
647 mlo_dev_lock_release(mld_cur);
648 mlo_err("MLD ID %d exists with mac " QDF_MAC_ADDR_FMT,
649 mld_cur->mld_id, QDF_MAC_ADDR_REF(peer_addr));
650 ret_status = true;
651 goto check_same_ml_ctx;
652 }
653
654 /* Check the peer list for a MAC address match */
655 mlo_peer_list = &mld_cur->mlo_peer_list;
656 ml_peerlist_lock_acquire(mlo_peer_list);
657 if (mlo_get_mlpeer(mld_cur, (struct qdf_mac_addr *)peer_addr)) {
658 /* If peer_vdev_id is NULL, then API will treat any
659 * match as happening on another dev context
660 */
661 if (peer_vdev_id) {
662 count = QDF_ARRAY_SIZE(mld_cur->wlan_vdev_list);
663 for (idx = 0; idx < count; idx++) {
664 vdev = mld_cur->wlan_vdev_list[idx];
665 if (!vdev)
666 continue;
667 if (*peer_vdev_id ==
668 wlan_vdev_get_id(vdev)) {
669 same_ml_ctx = true;
670 break;
671 }
672 }
673 }
674 ml_peerlist_lock_release(mlo_peer_list);
675 mlo_dev_lock_release(mld_cur);
676 mlo_err("MLD ID %d ML Peer exists with mac " QDF_MAC_ADDR_FMT,
677 mld_cur->mld_id, QDF_MAC_ADDR_REF(peer_addr));
678 ret_status = true;
679 goto check_same_ml_ctx;
680 }
681 ml_peerlist_lock_release(mlo_peer_list);
682
683 mld_next = wlan_mlo_get_next_mld_ctx(ml_list, mld_cur);
684 mlo_dev_lock_release(mld_cur);
685 mld_cur = mld_next;
686 }
687
688 check_same_ml_ctx:
689 if (same_ml_ctx)
690 ret_status = false;
691
692 g_ml_ref:
693 ml_link_lock_release(g_mlo_ctx);
694 return ret_status;
695 }
696
697 #define WLAN_HDD_MGMT_FRAME_DA_OFFSET 4
698 #define WLAN_HDD_MGMT_FRAME_SA_OFFSET (WLAN_HDD_MGMT_FRAME_DA_OFFSET + 6)
699 #define WLAN_HDD_MGMT_FRAME_BSSID_OFFSET (WLAN_HDD_MGMT_FRAME_SA_OFFSET + 6)
700 #define WLAN_HDD_MGMT_FRAME_ACTION_CATEGORY_OFFSET \
701 (WLAN_HDD_MGMT_FRAME_BSSID_OFFSET + 6 + 2)
702 #define WLAN_HDD_MGMT_FRAME_ACTION_TYPE_OFFSET \
703 (WLAN_HDD_MGMT_FRAME_ACTION_CATEGORY_OFFSET + 1)
704 #define WLAN_HDD_ACTION_FRAME_CATEGORY_PUBLIC 0x04
705
706 /*
707 * Typical 802.11 Action Frame Format
708 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-
709 * | FC | DUR | DA | SA | BSSID |Seq.|Cat.|Act| Elements | FCS |
710 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-
711 * 2 2 6 6 6 2 1 1 Variable Len 4
712 */
wlan_mlo_update_action_frame_from_user(struct wlan_objmgr_vdev * vdev,uint8_t * frame,uint32_t frame_len)713 void wlan_mlo_update_action_frame_from_user(struct wlan_objmgr_vdev *vdev,
714 uint8_t *frame,
715 uint32_t frame_len)
716 {
717 struct wlan_objmgr_peer *peer;
718 uint8_t *da, *sa, *bssid;
719
720 if (!wlan_vdev_mlme_is_mlo_vdev(vdev) ||
721 (wlan_vdev_mlme_get_opmode(vdev) != QDF_STA_MODE))
722 return;
723
724 if (frame_len <= WLAN_HDD_MGMT_FRAME_ACTION_TYPE_OFFSET) {
725 mlo_debug("Not a valid Action frame len: %d", frame_len);
726 return;
727 }
728
729 /* Translate address only for action frames
730 * which are not of public category.
731 * Reference: 802.11-2012, Subclause: 8.5
732 */
733
734 if (frame[WLAN_HDD_MGMT_FRAME_ACTION_CATEGORY_OFFSET] ==
735 WLAN_HDD_ACTION_FRAME_CATEGORY_PUBLIC)
736 return;
737
738 da = frame + WLAN_HDD_MGMT_FRAME_DA_OFFSET;
739 sa = frame + WLAN_HDD_MGMT_FRAME_SA_OFFSET;
740 bssid = frame + WLAN_HDD_MGMT_FRAME_BSSID_OFFSET;
741
742 peer = wlan_objmgr_vdev_try_get_bsspeer(vdev, WLAN_MLO_MGR_ID);
743 if (!peer) {
744 mlo_debug("Peer not found");
745 return;
746 }
747
748 mlo_debug("Change MLD addr to link addr for non-Public action frame");
749 /* DA = VDEV's BSS peer's link address.
750 * SA = VDEV's link address.
751 * BSSID = VDEV's BSS peer's link address.
752 */
753
754 qdf_ether_addr_copy(da, wlan_peer_get_macaddr(peer));
755 qdf_ether_addr_copy(sa, wlan_vdev_mlme_get_macaddr(vdev));
756 qdf_ether_addr_copy(bssid, wlan_peer_get_macaddr(peer));
757
758 wlan_objmgr_peer_release_ref(peer, WLAN_MLO_MGR_ID);
759 }
760
wlan_mlo_update_action_frame_to_user(struct wlan_objmgr_vdev * vdev,uint8_t * frame,uint32_t frame_len)761 void wlan_mlo_update_action_frame_to_user(struct wlan_objmgr_vdev *vdev,
762 uint8_t *frame,
763 uint32_t frame_len)
764 {
765 struct wlan_objmgr_peer *peer;
766 uint8_t *da, *sa, *bssid;
767
768 if (!wlan_vdev_mlme_is_mlo_vdev(vdev) ||
769 (wlan_vdev_mlme_get_opmode(vdev) != QDF_STA_MODE))
770 return;
771
772 if (frame_len <= WLAN_HDD_MGMT_FRAME_ACTION_TYPE_OFFSET) {
773 mlo_debug("Not a valid Action frame len: %d", frame_len);
774 return;
775 }
776
777 /* Translate address only for action frames
778 * which are not of public category.
779 * Reference: 802.11-2012, Subclause: 8.5
780 */
781
782 if (frame[WLAN_HDD_MGMT_FRAME_ACTION_CATEGORY_OFFSET] ==
783 WLAN_HDD_ACTION_FRAME_CATEGORY_PUBLIC)
784 return;
785
786 da = frame + WLAN_HDD_MGMT_FRAME_DA_OFFSET;
787 sa = frame + WLAN_HDD_MGMT_FRAME_SA_OFFSET;
788 bssid = frame + WLAN_HDD_MGMT_FRAME_BSSID_OFFSET;
789
790 peer = wlan_objmgr_vdev_try_get_bsspeer(vdev, WLAN_MLO_MGR_ID);
791 if (!peer) {
792 mlo_debug("Peer not found");
793 return;
794 }
795
796 mlo_debug("Change link addr to MLD addr for non-Public action frame");
797 /* DA = VDEV's MLD address.
798 * SA = VDEV's BSS peer's MLD address.
799 * BSSID = VDEV's BSS peer's MLD address.
800 */
801
802 qdf_ether_addr_copy(da, wlan_vdev_mlme_get_mldaddr(vdev));
803 qdf_ether_addr_copy(sa, wlan_peer_mlme_get_mldaddr(peer));
804 qdf_ether_addr_copy(bssid, wlan_peer_mlme_get_mldaddr(peer));
805
806 wlan_objmgr_peer_release_ref(peer, WLAN_MLO_MGR_ID);
807 }
808 #endif
809
mlo_ap_ctx_deinit(struct wlan_mlo_dev_context * ml_dev)810 static QDF_STATUS mlo_ap_ctx_deinit(struct wlan_mlo_dev_context *ml_dev)
811 {
812 wlan_mlo_vdev_aid_mgr_deinit(ml_dev);
813 mlo_ap_lock_destroy(ml_dev->ap_ctx);
814 qdf_mem_free(ml_dev->ap_ctx);
815 ml_dev->ap_ctx = NULL;
816
817 return QDF_STATUS_SUCCESS;
818 }
819
mlo_ap_ctx_init(struct wlan_mlo_dev_context * ml_dev)820 static QDF_STATUS mlo_ap_ctx_init(struct wlan_mlo_dev_context *ml_dev)
821 {
822 struct wlan_mlo_ap *ap_ctx;
823
824 ap_ctx = qdf_mem_malloc(sizeof(*ap_ctx));
825 if (!ap_ctx) {
826 mlo_err("MLO AP ctx alloc failure");
827 return QDF_STATUS_E_NOMEM;
828 }
829
830 ml_dev->ap_ctx = ap_ctx;
831 mlo_ap_lock_create(ml_dev->ap_ctx);
832 if (wlan_mlo_vdev_aid_mgr_init(ml_dev) != QDF_STATUS_SUCCESS) {
833 mlo_ap_ctx_deinit(ml_dev);
834 return QDF_STATUS_E_NOMEM;
835 }
836
837 return QDF_STATUS_SUCCESS;
838 }
839
840 #ifdef CONFIG_AP_PLATFORM
841 static inline
wlan_mlo_check_grp_id(uint8_t ref_id,struct wlan_objmgr_vdev * vdev)842 QDF_STATUS wlan_mlo_check_grp_id(uint8_t ref_id,
843 struct wlan_objmgr_vdev *vdev)
844 {
845 struct wlan_objmgr_psoc *psoc;
846 uint8_t grp_id = 0;
847
848 psoc = wlan_vdev_get_psoc(vdev);
849 if (!mlo_psoc_get_grp_id(psoc, &grp_id)) {
850 mlo_err("Unable to get mlo group id");
851 return QDF_STATUS_E_FAILURE;
852 }
853
854 if (grp_id != ref_id) {
855 mlo_err("Error : MLD VAP Configuration with different WSI/MLD Groups");
856 return QDF_STATUS_E_FAILURE;
857 }
858
859 return QDF_STATUS_SUCCESS;
860 }
861
862 static inline
wlan_mlo_pdev_check(struct wlan_objmgr_pdev * ref_pdev,struct wlan_objmgr_vdev * vdev)863 QDF_STATUS wlan_mlo_pdev_check(struct wlan_objmgr_pdev *ref_pdev,
864 struct wlan_objmgr_vdev *vdev)
865 {
866 struct wlan_objmgr_pdev *pdev;
867 struct wlan_objmgr_psoc *psoc;
868 uint8_t grp_id = 0;
869
870 pdev = wlan_vdev_get_pdev(vdev);
871
872 psoc = wlan_pdev_get_psoc(ref_pdev);
873 if (!mlo_psoc_get_grp_id(psoc, &grp_id)) {
874 mlo_err("Unable to get the MLO Group ID for the vdev");
875 return QDF_STATUS_E_FAILURE;
876 }
877
878 if (mlo_check_all_pdev_state(psoc, grp_id, MLO_LINK_SETUP_DONE)) {
879 mlo_err("Pdev link is not in ready state, initial link setup failed");
880 return QDF_STATUS_E_FAILURE;
881 }
882
883 if (ref_pdev == pdev) {
884 mlo_err("MLD vdev for this pdev already found, investigate config");
885 return QDF_STATUS_E_FAILURE;
886 }
887
888 if (wlan_mlo_check_grp_id(grp_id, vdev))
889 return QDF_STATUS_E_FAILURE;
890
891 return QDF_STATUS_SUCCESS;
892 }
893
894 static inline
mlo_dev_config_check(struct wlan_mlo_dev_context * ml_dev,struct wlan_objmgr_vdev * vdev)895 QDF_STATUS mlo_dev_config_check(struct wlan_mlo_dev_context *ml_dev,
896 struct wlan_objmgr_vdev *vdev)
897 {
898 return QDF_STATUS_SUCCESS;
899 }
900
901 #else
902 static inline
mlo_dev_config_check(struct wlan_mlo_dev_context * ml_dev,struct wlan_objmgr_vdev * vdev)903 QDF_STATUS mlo_dev_config_check(struct wlan_mlo_dev_context *ml_dev,
904 struct wlan_objmgr_vdev *vdev)
905 {
906 enum QDF_OPMODE opmode = wlan_vdev_mlme_get_opmode(vdev);
907
908 if (wlan_mlo_check_valid_config(ml_dev, wlan_vdev_get_pdev(vdev),
909 opmode) != QDF_STATUS_SUCCESS)
910 return QDF_STATUS_E_FAILURE;
911
912 return QDF_STATUS_SUCCESS;
913 }
914
915 static inline
wlan_mlo_pdev_check(struct wlan_objmgr_pdev * ref_pdev,struct wlan_objmgr_vdev * vdev)916 QDF_STATUS wlan_mlo_pdev_check(struct wlan_objmgr_pdev *ref_pdev,
917 struct wlan_objmgr_vdev *vdev)
918 {
919 return QDF_STATUS_SUCCESS;
920 }
921 #endif
922
wlan_mlo_check_valid_config(struct wlan_mlo_dev_context * ml_dev,struct wlan_objmgr_pdev * pdev,enum QDF_OPMODE opmode)923 QDF_STATUS wlan_mlo_check_valid_config(struct wlan_mlo_dev_context *ml_dev,
924 struct wlan_objmgr_pdev *pdev,
925 enum QDF_OPMODE opmode)
926 {
927 uint32_t id = 0;
928 struct wlan_objmgr_vdev *vdev;
929
930 if (!ml_dev)
931 return QDF_STATUS_E_FAILURE;
932
933 if (!pdev)
934 return QDF_STATUS_E_FAILURE;
935
936 mlo_dev_lock_acquire(ml_dev);
937 while (id < WLAN_UMAC_MLO_MAX_VDEVS) {
938 vdev = ml_dev->wlan_vdev_list[id];
939 if (vdev) {
940 if (wlan_mlo_pdev_check(pdev, vdev)) {
941 mlo_dev_lock_release(ml_dev);
942 return QDF_STATUS_E_FAILURE;
943 }
944
945 if (wlan_vdev_mlme_get_opmode(vdev) != opmode) {
946 mlo_err("Invalid opmode %d type found expected %d, investigate config",
947 wlan_vdev_mlme_get_opmode(vdev),
948 opmode);
949 mlo_dev_lock_release(ml_dev);
950 return QDF_STATUS_E_FAILURE;
951 }
952 }
953 id++;
954 }
955
956 mlo_dev_lock_release(ml_dev);
957 return QDF_STATUS_SUCCESS;
958 }
959
960 /**
961 * mlo_t2lm_ctx_init() - API to initialize the t2lm context with the default
962 * values.
963 * @ml_dev: Pointer to ML Dev context
964 * @vdev: Pointer to vdev structure
965 *
966 * Return: None
967 */
mlo_t2lm_ctx_init(struct wlan_mlo_dev_context * ml_dev,struct wlan_objmgr_vdev * vdev)968 static inline void mlo_t2lm_ctx_init(struct wlan_mlo_dev_context *ml_dev,
969 struct wlan_objmgr_vdev *vdev)
970 {
971 struct wlan_t2lm_info *t2lm;
972
973 t2lm = &ml_dev->t2lm_ctx.established_t2lm.t2lm;
974
975 qdf_mem_zero(&ml_dev->t2lm_ctx, sizeof(struct wlan_t2lm_context));
976
977 t2lm->direction = WLAN_T2LM_BIDI_DIRECTION;
978 t2lm->default_link_mapping = 1;
979 t2lm->link_mapping_size = 0;
980
981 wlan_mlo_t2lm_timer_init(vdev);
982 wlan_mlo_t2lm_register_link_update_notify_handler(ml_dev);
983 }
984
985 /**
986 * mlo_epcs_ctx_init() - API to initialize the epcs context with the
987 * default values.
988 * @ml_dev: Pointer to ML Dev context
989 *
990 * Return: None
991 */
mlo_epcs_ctx_init(struct wlan_mlo_dev_context * ml_dev)992 static inline void mlo_epcs_ctx_init(struct wlan_mlo_dev_context *ml_dev)
993 {
994 struct wlan_epcs_context *epcs_ctx;
995
996 epcs_ctx = &ml_dev->epcs_ctx;
997 qdf_mem_zero(epcs_ctx, sizeof(struct wlan_epcs_context));
998 epcs_dev_lock_create(epcs_ctx);
999 }
1000
1001 #ifdef QCA_SUPPORT_PRIMARY_LINK_MIGRATE
1002 /**
1003 * mlo_ptqm_migration_init() - API to initialize ptqm migration timer
1004 * @ml_dev: Pointer to ML Dev context
1005 *
1006 * Return: None
1007 */
mlo_ptqm_migration_init(struct wlan_mlo_dev_context * ml_dev)1008 static inline void mlo_ptqm_migration_init(struct wlan_mlo_dev_context *ml_dev)
1009 {
1010 qdf_timer_init(NULL, &ml_dev->ptqm_migrate_timer,
1011 mlo_mlme_ptqm_migrate_timer_cb, (void *)(ml_dev),
1012 QDF_TIMER_TYPE_WAKE_APPS);
1013 }
1014 #else
mlo_ptqm_migration_init(struct wlan_mlo_dev_context * ml_dev)1015 static inline void mlo_ptqm_migration_init(struct wlan_mlo_dev_context *ml_dev)
1016 { }
1017 #endif
1018
1019 #if defined(WLAN_FEATURE_11BE_MLO) && defined(WLAN_MLO_MULTI_CHIP)
1020 static QDF_STATUS
mlo_add_to_bridge_vdev_list(struct wlan_objmgr_vdev * vdev)1021 mlo_add_to_bridge_vdev_list(struct wlan_objmgr_vdev *vdev)
1022 {
1023 struct wlan_mlo_dev_context *ml_dev;
1024 struct qdf_mac_addr *mld_addr;
1025 uint8_t id = 0;
1026
1027 if (!vdev)
1028 return QDF_STATUS_E_FAILURE;
1029
1030 mld_addr = (struct qdf_mac_addr *)wlan_vdev_mlme_get_mldaddr(vdev);
1031 ml_dev = wlan_mlo_get_mld_ctx_by_mldaddr(mld_addr);
1032
1033 if (ml_dev) {
1034 mlo_dev_lock_acquire(ml_dev);
1035 while (id < WLAN_UMAC_MLO_MAX_BRIDGE_VDEVS) {
1036 if (ml_dev->wlan_bridge_vdev_list[id]) {
1037 id++;
1038 continue;
1039 }
1040
1041 ml_dev->wlan_bridge_vdev_list[id] = vdev;
1042 ml_dev->wlan_bridge_vdev_count++;
1043 vdev->mlo_dev_ctx = ml_dev;
1044 break;
1045 }
1046 mlo_dev_lock_release(ml_dev);
1047
1048 if (id == WLAN_UMAC_MLO_MAX_BRIDGE_VDEVS)
1049 return QDF_STATUS_E_FAILURE;
1050
1051 return QDF_STATUS_SUCCESS;
1052 }
1053
1054 return QDF_STATUS_E_FAILURE;
1055 }
1056
1057 static QDF_STATUS
mld_delete_from_bridge_vdev_list(struct wlan_objmgr_vdev * vdev)1058 mld_delete_from_bridge_vdev_list(struct wlan_objmgr_vdev *vdev)
1059 {
1060 struct wlan_mlo_dev_context *ml_dev;
1061 struct qdf_mac_addr *mld_addr;
1062 uint8_t id = 0;
1063
1064 if (!vdev)
1065 return QDF_STATUS_E_FAILURE;
1066
1067 mld_addr = (struct qdf_mac_addr *)wlan_vdev_mlme_get_mldaddr(vdev);
1068 ml_dev = wlan_mlo_get_mld_ctx_by_mldaddr(mld_addr);
1069
1070 if (ml_dev) {
1071 mlo_dev_lock_acquire(ml_dev);
1072 while (id < WLAN_UMAC_MLO_MAX_BRIDGE_VDEVS) {
1073 if (ml_dev->wlan_bridge_vdev_list[id] == vdev) {
1074 vdev->mlo_dev_ctx = NULL;
1075 ml_dev->wlan_bridge_vdev_list[id] = NULL;
1076 ml_dev->wlan_bridge_vdev_count--;
1077 break;
1078 }
1079 id++;
1080 }
1081 mlo_dev_lock_release(ml_dev);
1082 return QDF_STATUS_SUCCESS;
1083 }
1084
1085 return QDF_STATUS_E_FAILURE;
1086 }
1087 #else
1088 static QDF_STATUS
mlo_add_to_bridge_vdev_list(struct wlan_objmgr_vdev * vdev)1089 mlo_add_to_bridge_vdev_list(struct wlan_objmgr_vdev *vdev)
1090 {
1091 return QDF_STATUS_SUCCESS;
1092 }
1093
1094 static QDF_STATUS
mld_delete_from_bridge_vdev_list(struct wlan_objmgr_vdev * vdev)1095 mld_delete_from_bridge_vdev_list(struct wlan_objmgr_vdev *vdev)
1096 {
1097 return QDF_STATUS_SUCCESS;
1098 }
1099 #endif
1100
mlo_dev_ctx_init(struct wlan_objmgr_vdev * vdev)1101 static QDF_STATUS mlo_dev_ctx_init(struct wlan_objmgr_vdev *vdev)
1102 {
1103 struct wlan_mlo_dev_context *ml_dev;
1104 QDF_STATUS status = QDF_STATUS_SUCCESS;
1105 struct qdf_mac_addr *mld_addr;
1106 struct mlo_mgr_context *g_mlo_ctx = wlan_objmgr_get_mlo_ctx();
1107 uint8_t id = 0;
1108 struct wlan_objmgr_psoc *psoc = NULL;
1109
1110 if (wlan_vdev_mlme_is_mlo_bridge_vdev(vdev)) {
1111 status = mlo_add_to_bridge_vdev_list(vdev);
1112 if (!QDF_IS_STATUS_SUCCESS(status))
1113 mlo_err("Failed to init bridge vap ctx");
1114 return status;
1115 }
1116
1117 mld_addr = (struct qdf_mac_addr *)wlan_vdev_mlme_get_mldaddr(vdev);
1118 ml_dev = wlan_mlo_get_mld_ctx_by_mldaddr(mld_addr);
1119 psoc = wlan_vdev_get_psoc(vdev);
1120
1121 if (!psoc) {
1122 mlo_err("Failed to get psoc");
1123 return QDF_STATUS_E_FAILURE;
1124 }
1125
1126 if (ml_dev) {
1127 if (mlo_dev_config_check(ml_dev, vdev) != QDF_STATUS_SUCCESS)
1128 return QDF_STATUS_E_FAILURE;
1129
1130 mlo_dev_lock_acquire(ml_dev);
1131 while (id < WLAN_UMAC_MLO_MAX_VDEVS) {
1132 if (ml_dev->wlan_vdev_list[id]) {
1133 id++;
1134 continue;
1135 }
1136
1137 ml_dev->wlan_vdev_list[id] = vdev;
1138 ml_dev->wlan_vdev_count++;
1139 vdev->mlo_dev_ctx = ml_dev;
1140
1141 if (wlan_vdev_mlme_get_opmode(vdev) == QDF_SAP_MODE)
1142 wlan_mlo_vdev_alloc_aid_mgr(ml_dev, vdev);
1143
1144 break;
1145 }
1146 mlo_dev_lock_release(ml_dev);
1147 return QDF_STATUS_SUCCESS;
1148 }
1149
1150 if (qdf_list_size(&g_mlo_ctx->ml_dev_list) >= WLAN_UMAC_MLO_MAX_DEV) {
1151 mlo_err("No more MLD allowed");
1152 return QDF_STATUS_E_RESOURCES;
1153 }
1154
1155 /* Create a new ML dev context */
1156 ml_dev = qdf_mem_malloc(sizeof(*ml_dev));
1157 if (!ml_dev) {
1158 mlo_err("Failed to allocate memory for ML dev");
1159 return QDF_STATUS_E_NOMEM;
1160 }
1161
1162 qdf_copy_macaddr(&ml_dev->mld_addr, mld_addr);
1163 ml_dev->wlan_vdev_list[0] = vdev;
1164 ml_dev->wlan_vdev_count++;
1165 vdev->mlo_dev_ctx = ml_dev;
1166
1167 mlo_dev_lock_create(ml_dev);
1168 tsf_recalculation_lock_create(ml_dev);
1169 if (wlan_vdev_mlme_get_opmode(vdev) == QDF_STA_MODE) {
1170 ml_dev->sta_ctx = qdf_mem_malloc(sizeof(struct wlan_mlo_sta));
1171 if (!ml_dev->sta_ctx) {
1172 tsf_recalculation_lock_destroy(ml_dev);
1173 mlo_dev_lock_destroy(ml_dev);
1174 qdf_mem_free(ml_dev);
1175 return QDF_STATUS_E_NOMEM;
1176 }
1177 copied_conn_req_lock_create(ml_dev->sta_ctx);
1178 #if defined(WLAN_FEATURE_11BE_MLO) && defined(WLAN_MLO_MULTI_CHIP)
1179 ml_dev->bridge_sta_ctx = qdf_mem_malloc(sizeof(struct wlan_mlo_bridge_sta));
1180 if (!ml_dev->bridge_sta_ctx) {
1181 tsf_recalculation_lock_destroy(ml_dev);
1182 mlo_dev_lock_destroy(ml_dev);
1183 qdf_mem_free(ml_dev->sta_ctx);
1184 qdf_mem_free(ml_dev);
1185 return QDF_STATUS_E_NOMEM;
1186 }
1187 #endif
1188 } else if (wlan_vdev_mlme_get_opmode(vdev) == QDF_SAP_MODE) {
1189 if (mlo_ap_ctx_init(ml_dev) != QDF_STATUS_SUCCESS) {
1190 tsf_recalculation_lock_destroy(ml_dev);
1191 mlo_dev_lock_destroy(ml_dev);
1192 qdf_mem_free(ml_dev);
1193 mlo_err("Failed to allocate memory for ap ctx");
1194 return QDF_STATUS_E_NOMEM;
1195 }
1196 }
1197
1198 /* Create DP MLO Device Context */
1199 if (cdp_mlo_dev_ctxt_create(wlan_psoc_get_dp_handle(psoc),
1200 (uint8_t *)mld_addr) !=
1201 QDF_STATUS_SUCCESS) {
1202 tsf_recalculation_lock_destroy(ml_dev);
1203 if (wlan_vdev_mlme_get_opmode(vdev) == QDF_STA_MODE) {
1204 qdf_mem_free(ml_dev->sta_ctx);
1205 #if defined(WLAN_FEATURE_11BE_MLO) && defined(WLAN_MLO_MULTI_CHIP)
1206 qdf_mem_free(ml_dev->bridge_sta_ctx);
1207 #endif
1208 } else if (wlan_vdev_mlme_get_opmode(vdev) == QDF_SAP_MODE) {
1209 mlo_ap_ctx_deinit(ml_dev);
1210 }
1211 mlo_dev_lock_destroy(ml_dev);
1212 qdf_mem_free(ml_dev);
1213 mlo_err("Failed to create DP MLO Dev ctxt");
1214 return QDF_STATUS_E_NOMEM;
1215 }
1216
1217 ml_dev->mlo_max_recom_simult_links =
1218 WLAN_UMAC_MLO_RECOM_MAX_SIMULT_LINKS_DEFAULT;
1219
1220 mlo_dev_mlpeer_list_init(ml_dev);
1221
1222 ml_link_lock_acquire(g_mlo_ctx);
1223 if (qdf_list_size(&g_mlo_ctx->ml_dev_list) < WLAN_UMAC_MLO_MAX_DEV)
1224 qdf_list_insert_back(&g_mlo_ctx->ml_dev_list, &ml_dev->node);
1225 ml_link_lock_release(g_mlo_ctx);
1226
1227 mlo_t2lm_ctx_init(ml_dev, vdev);
1228 mlo_epcs_ctx_init(ml_dev);
1229 mlo_ptqm_migration_init(ml_dev);
1230 mlo_mgr_link_switch_init(psoc, ml_dev);
1231
1232 return status;
1233 }
1234
1235 #ifdef QCA_SUPPORT_PRIMARY_LINK_MIGRATE
1236 /**
1237 * mlo_ptqm_migration_deinit() - API to deinitialize ptqm migration timer
1238 * @ml_dev: Pointer to ML Dev context
1239 *
1240 * Return: None
1241 */
mlo_ptqm_migration_deinit(struct wlan_mlo_dev_context * ml_dev)1242 static inline void mlo_ptqm_migration_deinit(
1243 struct wlan_mlo_dev_context *ml_dev)
1244 {
1245 qdf_timer_free(&ml_dev->ptqm_migrate_timer);
1246 }
1247 #else
mlo_ptqm_migration_deinit(struct wlan_mlo_dev_context * ml_dev)1248 static inline void mlo_ptqm_migration_deinit(
1249 struct wlan_mlo_dev_context *ml_dev)
1250 { }
1251 #endif
1252
1253 /**
1254 * mlo_t2lm_ctx_deinit() - API to deinitialize the t2lm context with the default
1255 * values.
1256 * @vdev: Pointer to vdev structure
1257 * @ml_dev: Pointer to mlo dev context
1258 *
1259 * Return: None
1260 */
mlo_t2lm_ctx_deinit(struct wlan_objmgr_vdev * vdev,struct wlan_mlo_dev_context * ml_dev)1261 static inline void mlo_t2lm_ctx_deinit(struct wlan_objmgr_vdev *vdev,
1262 struct wlan_mlo_dev_context *ml_dev)
1263 {
1264 wlan_mlo_t2lm_timer_deinit(vdev);
1265 wlan_unregister_t2lm_link_update_notify_handler(
1266 ml_dev, ml_dev->t2lm_ctx.link_update_callback_index);
1267 }
1268
1269 /**
1270 * mlo_epcs_ctx_deinit() - API to deinitialize the epcs context with the default
1271 * values.
1272 * @mlo_dev_ctx: MLO dev context pointer
1273 *
1274 * Return: None
1275 */
mlo_epcs_ctx_deinit(struct wlan_mlo_dev_context * mlo_dev_ctx)1276 static inline void mlo_epcs_ctx_deinit(struct wlan_mlo_dev_context *mlo_dev_ctx)
1277 {
1278 epcs_dev_lock_destroy(&mlo_dev_ctx->epcs_ctx);
1279 }
1280
1281 #ifdef WLAN_FEATURE_ROAM_OFFLOAD
ml_free_copied_reassoc_rsp(struct wlan_mlo_sta * sta_ctx)1282 static void ml_free_copied_reassoc_rsp(struct wlan_mlo_sta *sta_ctx)
1283 {
1284 wlan_cm_free_connect_resp(sta_ctx->copied_reassoc_rsp);
1285 }
1286 #else
ml_free_copied_reassoc_rsp(struct wlan_mlo_sta * sta_ctx)1287 static void ml_free_copied_reassoc_rsp(struct wlan_mlo_sta *sta_ctx)
1288 {
1289 return;
1290 }
1291 #endif
1292
mlo_dev_ctx_deinit(struct wlan_objmgr_vdev * vdev)1293 static QDF_STATUS mlo_dev_ctx_deinit(struct wlan_objmgr_vdev *vdev)
1294 {
1295 struct wlan_mlo_dev_context *ml_dev;
1296 QDF_STATUS status = QDF_STATUS_SUCCESS;
1297 struct qdf_mac_addr *mld_addr;
1298 struct mlo_mgr_context *g_mlo_ctx = wlan_objmgr_get_mlo_ctx();
1299 uint8_t id = 0;
1300 struct wlan_cm_connect_req *connect_req;
1301 struct wlan_objmgr_psoc *psoc = NULL;
1302
1303 mld_addr = (struct qdf_mac_addr *)wlan_vdev_mlme_get_mldaddr(vdev);
1304 ml_dev = wlan_mlo_get_mld_ctx_by_mldaddr(mld_addr);
1305 psoc = wlan_vdev_get_psoc(vdev);
1306
1307 if (!psoc) {
1308 mlo_err("Failed to get psoc");
1309 return QDF_STATUS_E_FAILURE;
1310 }
1311
1312 if (!ml_dev) {
1313 mlo_err("Failed to get MLD dev context by mld addr "QDF_MAC_ADDR_FMT,
1314 QDF_MAC_ADDR_REF(mld_addr->bytes));
1315 if (!vdev->mlo_dev_ctx) {
1316 mlo_err("Failed to get MLD dev context from vdev");
1317 return QDF_STATUS_SUCCESS;
1318 }
1319 ml_dev = vdev->mlo_dev_ctx;
1320 }
1321
1322 mlo_debug("deleting vdev from MLD device ctx "QDF_MAC_ADDR_FMT,
1323 QDF_MAC_ADDR_REF(mld_addr->bytes));
1324
1325 mlo_dev_lock_acquire(ml_dev);
1326 while (id < WLAN_UMAC_MLO_MAX_VDEVS) {
1327 if (ml_dev->wlan_vdev_list[id] == vdev) {
1328 if (wlan_vdev_mlme_get_opmode(vdev) ==
1329 QDF_SAP_MODE)
1330 wlan_mlo_vdev_free_aid_mgr(ml_dev,
1331 vdev);
1332 ml_dev->wlan_vdev_list[id] = NULL;
1333 ml_dev->wlan_vdev_count--;
1334 vdev->mlo_dev_ctx = NULL;
1335 break;
1336 }
1337 id++;
1338 }
1339 mlo_dev_lock_release(ml_dev);
1340
1341 if (wlan_vdev_mlme_is_mlo_bridge_vdev(vdev)) {
1342 status = mld_delete_from_bridge_vdev_list(vdev);
1343 if (!QDF_IS_STATUS_SUCCESS(status))
1344 mlo_err("Failed to deinit bridge vap ctx");
1345 }
1346
1347 ml_link_lock_acquire(g_mlo_ctx);
1348 if (!ml_dev->wlan_vdev_count && !ml_dev->wlan_bridge_vdev_count) {
1349 if (ml_dev->ap_ctx)
1350 mlo_ap_ctx_deinit(ml_dev);
1351
1352 mlo_dev_mlpeer_list_deinit(ml_dev);
1353 qdf_list_remove_node(&g_mlo_ctx->ml_dev_list,
1354 &ml_dev->node);
1355 if (wlan_vdev_mlme_get_opmode(vdev) == QDF_STA_MODE) {
1356 connect_req = ml_dev->sta_ctx->connect_req;
1357 wlan_cm_free_connect_req(connect_req);
1358
1359 if (ml_dev->sta_ctx->disconn_req)
1360 qdf_mem_free(ml_dev->sta_ctx->disconn_req);
1361
1362 if (ml_dev->sta_ctx->assoc_rsp.ptr)
1363 qdf_mem_free(ml_dev->sta_ctx->assoc_rsp.ptr);
1364
1365 ml_free_copied_reassoc_rsp(ml_dev->sta_ctx);
1366
1367 copied_conn_req_lock_destroy(ml_dev->sta_ctx);
1368
1369 qdf_mem_free(ml_dev->sta_ctx);
1370 #if defined(WLAN_FEATURE_11BE_MLO) && defined(WLAN_MLO_MULTI_CHIP)
1371 qdf_mem_free(ml_dev->bridge_sta_ctx);
1372 #endif
1373 }
1374 else if (wlan_vdev_mlme_get_opmode(vdev) == QDF_SAP_MODE)
1375 qdf_mem_free(ml_dev->ap_ctx);
1376
1377 mlo_ptqm_migration_deinit(ml_dev);
1378 mlo_mgr_link_switch_deinit(ml_dev);
1379 mlo_t2lm_ctx_deinit(vdev, ml_dev);
1380 mlo_epcs_ctx_deinit(ml_dev);
1381
1382 /* Destroy DP MLO Device Context */
1383 if (cdp_mlo_dev_ctxt_destroy(wlan_psoc_get_dp_handle(psoc),
1384 (uint8_t *)mld_addr) !=
1385 QDF_STATUS_SUCCESS) {
1386 mlo_err("Failed to destroy DP MLO Dev ctxt");
1387 QDF_BUG(0);
1388 }
1389
1390 tsf_recalculation_lock_destroy(ml_dev);
1391 mlo_dev_lock_destroy(ml_dev);
1392 qdf_mem_free(ml_dev);
1393 }
1394 ml_link_lock_release(g_mlo_ctx);
1395 return status;
1396 }
1397
wlan_mlo_mgr_vdev_created_notification(struct wlan_objmgr_vdev * vdev,void * arg_list)1398 QDF_STATUS wlan_mlo_mgr_vdev_created_notification(struct wlan_objmgr_vdev *vdev,
1399 void *arg_list)
1400 {
1401 QDF_STATUS status = QDF_STATUS_SUCCESS;
1402 struct qdf_mac_addr *mld_addr;
1403
1404 mld_addr = (struct qdf_mac_addr *)wlan_vdev_mlme_get_mldaddr(vdev);
1405 if (qdf_is_macaddr_zero(mld_addr)) {
1406 /* It's not a ML interface*/
1407 return QDF_STATUS_SUCCESS;
1408 }
1409 mlo_debug("MLD addr" QDF_MAC_ADDR_FMT,
1410 QDF_MAC_ADDR_REF(mld_addr->bytes));
1411 status = mlo_dev_ctx_init(vdev);
1412
1413 wlan_vdev_set_link_id(vdev, WLAN_LINK_ID_INVALID);
1414
1415 return status;
1416 }
1417
wlan_mlo_mgr_vdev_destroyed_notification(struct wlan_objmgr_vdev * vdev,void * arg_list)1418 QDF_STATUS wlan_mlo_mgr_vdev_destroyed_notification(struct wlan_objmgr_vdev *vdev,
1419 void *arg_list)
1420 {
1421 QDF_STATUS status = QDF_STATUS_SUCCESS;
1422 struct qdf_mac_addr *mld_addr;
1423
1424 mld_addr = (struct qdf_mac_addr *)wlan_vdev_mlme_get_mldaddr(vdev);
1425 if (qdf_is_macaddr_zero(mld_addr)) {
1426 /* It's not a ML interface*/
1427 return QDF_STATUS_SUCCESS;
1428 }
1429 mlo_debug("MLD addr" QDF_MAC_ADDR_FMT,
1430 QDF_MAC_ADDR_REF(mld_addr->bytes));
1431
1432 status = mlo_dev_ctx_deinit(vdev);
1433
1434 return status;
1435 }
1436
wlan_mlo_mgr_update_mld_addr(struct qdf_mac_addr * old_mac,struct qdf_mac_addr * new_mac)1437 QDF_STATUS wlan_mlo_mgr_update_mld_addr(struct qdf_mac_addr *old_mac,
1438 struct qdf_mac_addr *new_mac)
1439 {
1440 struct wlan_mlo_dev_context *ml_dev;
1441
1442 ml_dev = wlan_mlo_get_mld_ctx_by_mldaddr(old_mac);
1443 if (!ml_dev) {
1444 mlo_err("ML dev context not found for MLD:" QDF_MAC_ADDR_FMT,
1445 QDF_MAC_ADDR_REF(old_mac->bytes));
1446 return QDF_STATUS_E_INVAL;
1447 }
1448 mlo_dev_lock_acquire(ml_dev);
1449 qdf_copy_macaddr(&ml_dev->mld_addr, new_mac);
1450 mlo_dev_lock_release(ml_dev);
1451
1452 return QDF_STATUS_SUCCESS;
1453 }
1454
wlan_mlo_mgr_mld_vdev_attach(struct wlan_objmgr_vdev * vdev,struct qdf_mac_addr * mld_addr)1455 QDF_STATUS wlan_mlo_mgr_mld_vdev_attach(struct wlan_objmgr_vdev *vdev,
1456 struct qdf_mac_addr *mld_addr)
1457 {
1458 QDF_STATUS status = QDF_STATUS_SUCCESS;
1459 struct wlan_objmgr_psoc *psoc = NULL;
1460
1461 psoc = wlan_vdev_get_psoc(vdev);
1462 if (!psoc) {
1463 mlo_err("Failed to get psoc");
1464 return QDF_STATUS_E_FAILURE;
1465 }
1466
1467 wlan_vdev_obj_lock(vdev);
1468 wlan_vdev_mlme_set_mldaddr(vdev, (uint8_t *)&mld_addr->bytes[0]);
1469 wlan_vdev_obj_unlock(vdev);
1470
1471 status = mlo_dev_ctx_init(vdev);
1472
1473 if (cdp_mlo_dev_ctxt_attach(wlan_psoc_get_dp_handle(psoc),
1474 wlan_vdev_get_id(vdev),
1475 (uint8_t *)mld_addr)
1476 != QDF_STATUS_SUCCESS) {
1477 mlo_err("Failed to attach DP vdev (" QDF_MAC_ADDR_FMT ") to"
1478 " MLO Dev ctxt (" QDF_MAC_ADDR_FMT ")",
1479 QDF_MAC_ADDR_REF(wlan_vdev_mlme_get_macaddr(vdev)),
1480 QDF_MAC_ADDR_REF(mld_addr->bytes));
1481 }
1482 return status;
1483 }
1484
wlan_mlo_mgr_mld_vdev_detach(struct wlan_objmgr_vdev * vdev)1485 QDF_STATUS wlan_mlo_mgr_mld_vdev_detach(struct wlan_objmgr_vdev *vdev)
1486 {
1487 QDF_STATUS status = QDF_STATUS_SUCCESS;
1488 struct qdf_mac_addr *mld_addr;
1489 struct wlan_objmgr_psoc *psoc = NULL;
1490
1491 psoc = wlan_vdev_get_psoc(vdev);
1492 if (!psoc) {
1493 mlo_err("Failed to get psoc");
1494 return QDF_STATUS_E_FAILURE;
1495 }
1496
1497 status = mlo_dev_ctx_deinit(vdev);
1498
1499 /* Detach DP vdev from DP MLO Device Context */
1500 mld_addr = (struct qdf_mac_addr *)wlan_vdev_mlme_get_mldaddr(vdev);
1501
1502 if (cdp_mlo_dev_ctxt_detach(wlan_psoc_get_dp_handle(psoc),
1503 wlan_vdev_get_id(vdev),
1504 (uint8_t *)mld_addr)
1505 != QDF_STATUS_SUCCESS) {
1506 mlo_err("Failed to detach DP vdev (" QDF_MAC_ADDR_FMT ") from"
1507 " MLO Dev ctxt (" QDF_MAC_ADDR_FMT ")",
1508 QDF_MAC_ADDR_REF(wlan_vdev_mlme_get_macaddr(vdev)),
1509 QDF_MAC_ADDR_REF(mld_addr->bytes));
1510 }
1511
1512 wlan_vdev_obj_lock(vdev);
1513 wlan_vdev_mlme_reset_mldaddr(vdev);
1514 wlan_vdev_mlme_op_flags_clear(vdev, WLAN_VDEV_OP_MLO_REMOVE_LINK_VDEV);
1515 wlan_vdev_obj_unlock(vdev);
1516
1517 return status;
1518 }
1519