xref: /wlan-driver/qca-wifi-host-cmn/umac/mlo_mgr/src/wlan_mlo_mgr_main.c (revision 5113495b16420b49004c444715d2daae2066e7dc)
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