xref: /wlan-dirver/qca-wifi-host-cmn/umac/mlo_mgr/src/wlan_mlo_mgr_main.c (revision 70a19e16789e308182f63b15c75decec7bf0b342)
1 /*
2  * Copyright (c) 2021, The Linux Foundation. All rights reserved.
3  * Copyright (c) 2021-2023 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 
34 static void mlo_global_ctx_deinit(void)
35 {
36 	struct mlo_mgr_context *mlo_mgr_ctx = wlan_objmgr_get_mlo_ctx();
37 
38 	if (!mlo_mgr_ctx)
39 		return;
40 
41 	if (qdf_list_empty(&mlo_mgr_ctx->ml_dev_list))
42 		mlo_err("ML dev list is not empty");
43 
44 	mlo_setup_deinit();
45 	mlo_msgq_free();
46 	ml_peerid_lock_destroy(mlo_mgr_ctx);
47 	ml_link_lock_destroy(mlo_mgr_ctx);
48 	ml_aid_lock_destroy(mlo_mgr_ctx);
49 	qdf_list_destroy(&mlo_mgr_ctx->ml_dev_list);
50 
51 	qdf_mem_free(mlo_mgr_ctx);
52 	wlan_objmgr_set_mlo_ctx(NULL);
53 }
54 
55 static void mlo_global_ctx_init(void)
56 {
57 	struct mlo_mgr_context *mlo_mgr_ctx;
58 
59 	/* If it is already created, ignore */
60 	if (wlan_objmgr_get_mlo_ctx()) {
61 		mlo_err("Global object is already created");
62 		return;
63 	}
64 
65 	/* Allocation of memory for Global object */
66 	mlo_mgr_ctx = (struct mlo_mgr_context *)
67 			qdf_mem_malloc(sizeof(*mlo_mgr_ctx));
68 	if (!mlo_mgr_ctx)
69 		return;
70 
71 	wlan_objmgr_set_mlo_ctx(mlo_mgr_ctx);
72 
73 	qdf_list_create(&mlo_mgr_ctx->ml_dev_list, WLAN_UMAC_MLO_MAX_DEV);
74 	mlo_mgr_ctx->max_mlo_peer_id = MAX_MLO_PEER_ID;
75 	ml_peerid_lock_create(mlo_mgr_ctx);
76 	ml_link_lock_create(mlo_mgr_ctx);
77 	ml_aid_lock_create(mlo_mgr_ctx);
78 	mlo_mgr_ctx->mlo_is_force_primary_umac = 0;
79 	mlo_msgq_init();
80 }
81 
82 QDF_STATUS wlan_mlo_mgr_psoc_enable(struct wlan_objmgr_psoc *psoc)
83 {
84 	struct wlan_lmac_if_mlo_tx_ops *mlo_tx_ops;
85 
86 	if (!psoc) {
87 		mlo_err("psoc is null");
88 		return QDF_STATUS_E_NULL_VALUE;
89 	}
90 
91 	mlo_tx_ops = target_if_mlo_get_tx_ops(psoc);
92 	if (!mlo_tx_ops) {
93 		mlo_err("tx_ops is null!");
94 		return QDF_STATUS_E_NULL_VALUE;
95 	}
96 
97 	if (!mlo_tx_ops->register_events) {
98 		mlo_err("register_events function is null!");
99 		return QDF_STATUS_E_NULL_VALUE;
100 	}
101 
102 	return mlo_tx_ops->register_events(psoc);
103 }
104 
105 QDF_STATUS wlan_mlo_mgr_psoc_disable(struct wlan_objmgr_psoc *psoc)
106 {
107 	struct wlan_lmac_if_mlo_tx_ops *mlo_tx_ops;
108 
109 	if (!psoc) {
110 		mlo_err("psoc is null");
111 		return QDF_STATUS_E_NULL_VALUE;
112 	}
113 
114 	mlo_tx_ops = target_if_mlo_get_tx_ops(psoc);
115 	if (!mlo_tx_ops) {
116 		mlo_err("tx_ops is null!");
117 		return QDF_STATUS_E_NULL_VALUE;
118 	}
119 
120 	if (!mlo_tx_ops->unregister_events) {
121 		mlo_err("unregister_events function is null!");
122 		return QDF_STATUS_E_NULL_VALUE;
123 	}
124 
125 	return mlo_tx_ops->unregister_events(psoc);
126 }
127 
128 QDF_STATUS wlan_mlo_mgr_init(void)
129 {
130 	QDF_STATUS status;
131 
132 	mlo_global_ctx_init();
133 
134 	status = wlan_objmgr_register_vdev_create_handler(
135 		WLAN_UMAC_COMP_MLO_MGR,
136 		wlan_mlo_mgr_vdev_created_notification, NULL);
137 	if (QDF_IS_STATUS_ERROR(status)) {
138 		mlo_err("Failed to register vdev create handler");
139 		return QDF_STATUS_E_FAILURE;
140 	}
141 
142 	status = wlan_objmgr_register_vdev_destroy_handler(WLAN_UMAC_COMP_MLO_MGR,
143 		wlan_mlo_mgr_vdev_destroyed_notification, NULL);
144 	if (QDF_IS_STATUS_SUCCESS(status)) {
145 		mlo_debug("MLO vdev create and delete handler registered with objmgr");
146 		return QDF_STATUS_SUCCESS;
147 	}
148 	wlan_objmgr_unregister_vdev_create_handler(WLAN_UMAC_COMP_MLO_MGR,
149 				wlan_mlo_mgr_vdev_created_notification, NULL);
150 
151 	return status;
152 }
153 
154 QDF_STATUS wlan_mlo_mgr_deinit(void)
155 {
156 	QDF_STATUS status;
157 	struct mlo_mgr_context *mlo_mgr_ctx = wlan_objmgr_get_mlo_ctx();
158 
159 	if (!mlo_mgr_ctx) {
160 		mlo_err("MLO global object is not allocated");
161 		return QDF_STATUS_E_FAILURE;
162 	}
163 
164 	mlo_global_ctx_deinit();
165 
166 	status = wlan_objmgr_unregister_vdev_create_handler(
167 		WLAN_UMAC_COMP_MLO_MGR,
168 		wlan_mlo_mgr_vdev_created_notification, NULL);
169 	if (status != QDF_STATUS_SUCCESS)
170 		mlo_err("Failed to unregister vdev create handler");
171 
172 	status = wlan_objmgr_unregister_vdev_destroy_handler(
173 			WLAN_UMAC_COMP_MLO_MGR,
174 			wlan_mlo_mgr_vdev_destroyed_notification, NULL);
175 	if (status != QDF_STATUS_SUCCESS)
176 		mlo_err("Failed to unregister vdev delete handler");
177 
178 	return status;
179 }
180 
181 static inline struct wlan_mlo_dev_context *mlo_list_peek_head(
182 					qdf_list_t *ml_list)
183 {
184 	struct wlan_mlo_dev_context *mld_ctx;
185 	qdf_list_node_t *ml_node = NULL;
186 
187 	/* This API is invoked with lock acquired, do not add log prints */
188 	if (qdf_list_peek_front(ml_list, &ml_node) != QDF_STATUS_SUCCESS)
189 		return NULL;
190 
191 	mld_ctx = qdf_container_of(ml_node, struct wlan_mlo_dev_context,
192 				   node);
193 
194 	return mld_ctx;
195 }
196 
197 static inline
198 struct wlan_mlo_dev_context *mlo_get_next_mld_ctx(qdf_list_t *ml_list,
199 					struct wlan_mlo_dev_context *mld_cur)
200 {
201 	struct wlan_mlo_dev_context *mld_next;
202 	qdf_list_node_t *node = &mld_cur->node;
203 	qdf_list_node_t *next_node = NULL;
204 
205 	/* This API is invoked with lock acquired, do not add log prints */
206 	if (!node)
207 		return NULL;
208 
209 	if (qdf_list_peek_next(ml_list, node, &next_node) !=
210 						QDF_STATUS_SUCCESS)
211 		return NULL;
212 
213 	mld_next = qdf_container_of(next_node, struct wlan_mlo_dev_context,
214 				    node);
215 	return mld_next;
216 }
217 
218 uint8_t wlan_mlo_get_sta_mld_ctx_count(void)
219 {
220 	struct wlan_mlo_dev_context *mld_cur;
221 	struct wlan_mlo_dev_context *mld_next;
222 	qdf_list_t *ml_list;
223 	struct mlo_mgr_context *mlo_mgr_ctx = wlan_objmgr_get_mlo_ctx();
224 	uint8_t count = 0;
225 
226 	if (!mlo_mgr_ctx)
227 		return count;
228 
229 	ml_link_lock_acquire(mlo_mgr_ctx);
230 	ml_list = &mlo_mgr_ctx->ml_dev_list;
231 	/* Get first mld context */
232 	mld_cur = mlo_list_peek_head(ml_list);
233 
234 	while (mld_cur) {
235 		/* get next mld node */
236 		if (mld_cur->sta_ctx)
237 			count++;
238 		mld_next = mlo_get_next_mld_ctx(ml_list, mld_cur);
239 		mld_cur = mld_next;
240 	}
241 	ml_link_lock_release(mlo_mgr_ctx);
242 
243 	return count;
244 }
245 
246 struct wlan_mlo_dev_context
247 *wlan_mlo_get_mld_ctx_by_mldaddr(struct qdf_mac_addr *mldaddr)
248 {
249 	struct wlan_mlo_dev_context *mld_cur;
250 	struct wlan_mlo_dev_context *mld_next;
251 	qdf_list_t *ml_list;
252 	struct mlo_mgr_context *mlo_mgr_ctx = wlan_objmgr_get_mlo_ctx();
253 
254 	if (!mlo_mgr_ctx)
255 		return NULL;
256 
257 	ml_link_lock_acquire(mlo_mgr_ctx);
258 	ml_list = &mlo_mgr_ctx->ml_dev_list;
259 	/* Get first mld context */
260 	mld_cur = mlo_list_peek_head(ml_list);
261 	/**
262 	 * Iterate through ml list, till ml mldaddr matches with
263 	 * entry of list
264 	 */
265 	while (mld_cur) {
266 		if (QDF_IS_STATUS_SUCCESS(WLAN_ADDR_EQ(&mld_cur->mld_addr,
267 					  mldaddr))) {
268 			ml_link_lock_release(mlo_mgr_ctx);
269 			return mld_cur;
270 		}
271 		/* get next mld node */
272 		mld_next = mlo_get_next_mld_ctx(ml_list, mld_cur);
273 		mld_cur = mld_next;
274 	}
275 	ml_link_lock_release(mlo_mgr_ctx);
276 
277 	return NULL;
278 }
279 
280 bool wlan_mlo_is_mld_ctx_exist(struct qdf_mac_addr *mldaddr)
281 {
282 	struct wlan_mlo_dev_context *mld_ctx = NULL;
283 
284 	mld_ctx = wlan_mlo_get_mld_ctx_by_mldaddr(mldaddr);
285 	if (mld_ctx)
286 		return true;
287 
288 	return false;
289 }
290 
291 #ifdef WLAN_FEATURE_11BE_MLO
292 bool mlo_mgr_ml_peer_exist_on_diff_ml_ctx(uint8_t *peer_addr,
293 					  uint8_t *peer_vdev_id)
294 {
295 	qdf_list_t *ml_list;
296 	uint32_t idx, count;
297 	struct wlan_mlo_dev_context *mld_cur, *mld_next;
298 	struct wlan_mlo_peer_list *mlo_peer_list;
299 	struct wlan_objmgr_vdev *vdev;
300 	bool ret_status = false, same_ml_ctx = false;
301 	struct mlo_mgr_context *g_mlo_ctx = wlan_objmgr_get_mlo_ctx();
302 
303 	if (!g_mlo_ctx || !peer_addr ||
304 	    qdf_is_macaddr_zero((struct qdf_mac_addr *)peer_addr))
305 		return ret_status;
306 
307 	ml_link_lock_acquire(g_mlo_ctx);
308 	ml_list = &g_mlo_ctx->ml_dev_list;
309 	if (!qdf_list_size(ml_list))
310 		goto g_ml_ref;
311 
312 	mld_cur = mlo_list_peek_head(ml_list);
313 	while (mld_cur) {
314 		mlo_dev_lock_acquire(mld_cur);
315 		if (qdf_is_macaddr_equal(&mld_cur->mld_addr,
316 					 (struct qdf_mac_addr *)peer_addr)) {
317 			/* For self peer, the address passed will match the
318 			 * MLD address of its own ML dev context, so allow
319 			 * peer creation in this scenario as both are in
320 			 * same ML dev context.
321 			 */
322 			if (peer_vdev_id) {
323 				count = QDF_ARRAY_SIZE(mld_cur->wlan_vdev_list);
324 				for (idx = 0; idx < count; idx++) {
325 					vdev = mld_cur->wlan_vdev_list[idx];
326 					if (!vdev)
327 						continue;
328 					if (*peer_vdev_id ==
329 					    wlan_vdev_get_id(vdev)) {
330 						same_ml_ctx = true;
331 						break;
332 					}
333 				}
334 			}
335 			mlo_dev_lock_release(mld_cur);
336 			mlo_err("MLD ID %d exists with mac " QDF_MAC_ADDR_FMT,
337 				mld_cur->mld_id, QDF_MAC_ADDR_REF(peer_addr));
338 			ret_status = true;
339 			goto check_same_ml_ctx;
340 		}
341 
342 		/* Check the peer list for a MAC address match */
343 		mlo_peer_list = &mld_cur->mlo_peer_list;
344 		ml_peerlist_lock_acquire(mlo_peer_list);
345 		if (mlo_get_mlpeer(mld_cur, (struct qdf_mac_addr *)peer_addr)) {
346 			/* If peer_vdev_id is NULL, then API will treat any
347 			 * match as happening on another dev context
348 			 */
349 			if (peer_vdev_id) {
350 				count = QDF_ARRAY_SIZE(mld_cur->wlan_vdev_list);
351 				for (idx = 0; idx < count; idx++) {
352 					vdev = mld_cur->wlan_vdev_list[idx];
353 					if (!vdev)
354 						continue;
355 					if (*peer_vdev_id ==
356 					    wlan_vdev_get_id(vdev)) {
357 						same_ml_ctx = true;
358 						break;
359 					}
360 				}
361 			}
362 			ml_peerlist_lock_release(mlo_peer_list);
363 			mlo_dev_lock_release(mld_cur);
364 			mlo_err("MLD ID %d ML Peer exists with mac " QDF_MAC_ADDR_FMT,
365 				mld_cur->mld_id, QDF_MAC_ADDR_REF(peer_addr));
366 			ret_status = true;
367 			goto check_same_ml_ctx;
368 		}
369 		ml_peerlist_lock_release(mlo_peer_list);
370 
371 		mld_next = mlo_get_next_mld_ctx(ml_list, mld_cur);
372 		mlo_dev_lock_release(mld_cur);
373 		mld_cur = mld_next;
374 	}
375 
376 check_same_ml_ctx:
377 	if (same_ml_ctx)
378 		ret_status = false;
379 
380 g_ml_ref:
381 	ml_link_lock_release(g_mlo_ctx);
382 	return ret_status;
383 }
384 #endif
385 
386 static QDF_STATUS mlo_ap_ctx_deinit(struct wlan_mlo_dev_context *ml_dev)
387 {
388 	wlan_mlo_vdev_aid_mgr_deinit(ml_dev);
389 	mlo_ap_lock_destroy(ml_dev->ap_ctx);
390 	qdf_mem_free(ml_dev->ap_ctx);
391 	ml_dev->ap_ctx = NULL;
392 
393 	return QDF_STATUS_SUCCESS;
394 }
395 
396 static QDF_STATUS mlo_ap_ctx_init(struct wlan_mlo_dev_context *ml_dev)
397 {
398 	struct wlan_mlo_ap *ap_ctx;
399 
400 	ap_ctx = qdf_mem_malloc(sizeof(*ap_ctx));
401 	if (!ap_ctx) {
402 		mlo_err("MLO AP ctx alloc failure");
403 		return QDF_STATUS_E_NOMEM;
404 	}
405 
406 	ml_dev->ap_ctx = ap_ctx;
407 	mlo_ap_lock_create(ml_dev->ap_ctx);
408 	if (wlan_mlo_vdev_aid_mgr_init(ml_dev) != QDF_STATUS_SUCCESS) {
409 		mlo_ap_ctx_deinit(ml_dev);
410 		return QDF_STATUS_E_NOMEM;
411 	}
412 
413 	return QDF_STATUS_SUCCESS;
414 }
415 
416 #ifdef CONFIG_AP_PLATFORM
417 static inline
418 QDF_STATUS wlan_mlo_check_grp_id(uint8_t ref_id,
419 				 struct wlan_objmgr_vdev *vdev)
420 {
421 	struct wlan_objmgr_psoc *psoc;
422 	uint8_t grp_id = 0;
423 
424 	psoc = wlan_vdev_get_psoc(vdev);
425 	if (!mlo_psoc_get_grp_id(psoc, &grp_id)) {
426 		mlo_err("Unable to get mlo group id");
427 		return QDF_STATUS_E_FAILURE;
428 	}
429 
430 	if (grp_id != ref_id) {
431 		mlo_err("Error : MLD VAP Configuration with different WSI/MLD Groups");
432 		return QDF_STATUS_E_FAILURE;
433 	}
434 
435 	return QDF_STATUS_SUCCESS;
436 }
437 
438 static inline
439 QDF_STATUS wlan_mlo_pdev_check(struct wlan_objmgr_pdev *ref_pdev,
440 			       struct wlan_objmgr_vdev *vdev)
441 {
442 	struct wlan_objmgr_pdev *pdev;
443 	struct wlan_objmgr_psoc *psoc;
444 	uint8_t grp_id = 0;
445 
446 	pdev = wlan_vdev_get_pdev(vdev);
447 
448 	psoc = wlan_pdev_get_psoc(ref_pdev);
449 	if (!mlo_psoc_get_grp_id(psoc, &grp_id)) {
450 		mlo_err("Unable to get the MLO Group ID for the vdev");
451 		return QDF_STATUS_E_FAILURE;
452 	}
453 
454 	if (mlo_check_all_pdev_state(psoc, grp_id, MLO_LINK_SETUP_DONE)) {
455 		mlo_err("Pdev link is not in ready state, initial link setup failed");
456 		return QDF_STATUS_E_FAILURE;
457 	}
458 
459 	if (ref_pdev == pdev) {
460 		mlo_err("MLD vdev for this pdev already found, investigate config");
461 		return QDF_STATUS_E_FAILURE;
462 	}
463 
464 	if (wlan_mlo_check_grp_id(grp_id, vdev))
465 		return QDF_STATUS_E_FAILURE;
466 
467 	return QDF_STATUS_SUCCESS;
468 }
469 
470 static inline
471 QDF_STATUS mlo_dev_config_check(struct wlan_mlo_dev_context *ml_dev,
472 				struct wlan_objmgr_vdev *vdev)
473 {
474 	return QDF_STATUS_SUCCESS;
475 }
476 
477 #else
478 static inline
479 QDF_STATUS mlo_dev_config_check(struct wlan_mlo_dev_context *ml_dev,
480 				struct wlan_objmgr_vdev *vdev)
481 {
482 	enum QDF_OPMODE opmode = wlan_vdev_mlme_get_opmode(vdev);
483 
484 	if (wlan_mlo_check_valid_config(ml_dev, wlan_vdev_get_pdev(vdev),
485 					opmode) != QDF_STATUS_SUCCESS)
486 		return QDF_STATUS_E_FAILURE;
487 
488 	return QDF_STATUS_SUCCESS;
489 }
490 
491 static inline
492 QDF_STATUS wlan_mlo_pdev_check(struct wlan_objmgr_pdev *ref_pdev,
493 			       struct wlan_objmgr_vdev *vdev)
494 {
495 	return QDF_STATUS_SUCCESS;
496 }
497 #endif
498 
499 QDF_STATUS wlan_mlo_check_valid_config(struct wlan_mlo_dev_context *ml_dev,
500 				       struct wlan_objmgr_pdev *pdev,
501 				       enum QDF_OPMODE opmode)
502 {
503 	uint32_t id = 0;
504 	struct wlan_objmgr_vdev *vdev;
505 
506 	if (!ml_dev)
507 		return QDF_STATUS_E_FAILURE;
508 
509 	if (!pdev)
510 		return QDF_STATUS_E_FAILURE;
511 
512 	mlo_dev_lock_acquire(ml_dev);
513 	while (id < WLAN_UMAC_MLO_MAX_VDEVS) {
514 		vdev = ml_dev->wlan_vdev_list[id];
515 		if (vdev) {
516 			if (wlan_mlo_pdev_check(pdev, vdev)) {
517 				mlo_dev_lock_release(ml_dev);
518 				return QDF_STATUS_E_FAILURE;
519 			}
520 
521 			if (wlan_vdev_mlme_get_opmode(vdev) != opmode) {
522 				mlo_err("Invalid opmode %d type found expected %d, investigate config",
523 					wlan_vdev_mlme_get_opmode(vdev),
524 					opmode);
525 				mlo_dev_lock_release(ml_dev);
526 				return QDF_STATUS_E_FAILURE;
527 			}
528 		}
529 		id++;
530 	}
531 
532 	mlo_dev_lock_release(ml_dev);
533 	return QDF_STATUS_SUCCESS;
534 }
535 
536 /**
537  * mlo_t2lm_ctx_init() - API to initialize the t2lm context with the default
538  * values.
539  * @ml_dev: Pointer to ML Dev context
540  * @vdev: Pointer to vdev structure
541  *
542  * Return: None
543  */
544 static inline void mlo_t2lm_ctx_init(struct wlan_mlo_dev_context *ml_dev,
545 				     struct wlan_objmgr_vdev *vdev)
546 {
547 	struct wlan_t2lm_info *t2lm;
548 
549 	t2lm = &ml_dev->t2lm_ctx.established_t2lm.t2lm;
550 
551 	qdf_mem_zero(&ml_dev->t2lm_ctx, sizeof(struct wlan_t2lm_context));
552 
553 	t2lm->direction = WLAN_T2LM_BIDI_DIRECTION;
554 	t2lm->default_link_mapping = 1;
555 
556 	wlan_mlo_t2lm_timer_init(vdev);
557 }
558 
559 static QDF_STATUS mlo_dev_ctx_init(struct wlan_objmgr_vdev *vdev)
560 {
561 	struct wlan_mlo_dev_context *ml_dev;
562 	QDF_STATUS status = QDF_STATUS_SUCCESS;
563 	struct qdf_mac_addr *mld_addr;
564 	struct mlo_mgr_context *g_mlo_ctx = wlan_objmgr_get_mlo_ctx();
565 	uint8_t id = 0;
566 
567 	mld_addr = (struct qdf_mac_addr *)wlan_vdev_mlme_get_mldaddr(vdev);
568 	ml_dev = wlan_mlo_get_mld_ctx_by_mldaddr(mld_addr);
569 
570 	if (ml_dev) {
571 		if (mlo_dev_config_check(ml_dev, vdev) != QDF_STATUS_SUCCESS)
572 			return QDF_STATUS_E_FAILURE;
573 
574 		mlo_dev_lock_acquire(ml_dev);
575 		while (id < WLAN_UMAC_MLO_MAX_VDEVS) {
576 			if (ml_dev->wlan_vdev_list[id]) {
577 				id++;
578 				continue;
579 			}
580 
581 			ml_dev->wlan_vdev_list[id] = vdev;
582 			ml_dev->wlan_vdev_count++;
583 			vdev->mlo_dev_ctx = ml_dev;
584 
585 			if (wlan_vdev_mlme_get_opmode(vdev) == QDF_SAP_MODE)
586 				wlan_mlo_vdev_alloc_aid_mgr(ml_dev, vdev);
587 
588 			break;
589 		}
590 		mlo_dev_lock_release(ml_dev);
591 		return QDF_STATUS_SUCCESS;
592 	}
593 
594 	/* Create a new ML dev context */
595 	ml_dev = qdf_mem_malloc(sizeof(*ml_dev));
596 	if (!ml_dev) {
597 		mlo_err("Failed to allocate memory for ML dev");
598 		return QDF_STATUS_E_NOMEM;
599 	}
600 
601 	qdf_copy_macaddr(&ml_dev->mld_addr, mld_addr);
602 	ml_dev->wlan_vdev_list[0] = vdev;
603 	ml_dev->wlan_vdev_count++;
604 	vdev->mlo_dev_ctx = ml_dev;
605 
606 	mlo_dev_lock_create(ml_dev);
607 	tsf_recalculation_lock_create(ml_dev);
608 	if (wlan_vdev_mlme_get_opmode(vdev) == QDF_STA_MODE) {
609 		ml_dev->sta_ctx = qdf_mem_malloc(sizeof(struct wlan_mlo_sta));
610 		if (!ml_dev->sta_ctx) {
611 			tsf_recalculation_lock_destroy(ml_dev);
612 			mlo_dev_lock_destroy(ml_dev);
613 			qdf_mem_free(ml_dev);
614 			return QDF_STATUS_E_NOMEM;
615 		}
616 		copied_conn_req_lock_create(ml_dev->sta_ctx);
617 	} else if (wlan_vdev_mlme_get_opmode(vdev) == QDF_SAP_MODE) {
618 		if (mlo_ap_ctx_init(ml_dev) != QDF_STATUS_SUCCESS) {
619 			tsf_recalculation_lock_destroy(ml_dev);
620 			mlo_dev_lock_destroy(ml_dev);
621 			qdf_mem_free(ml_dev);
622 			mlo_err("Failed to allocate memory for ap ctx");
623 			return QDF_STATUS_E_NOMEM;
624 		}
625 	}
626 
627 	mlo_dev_mlpeer_list_init(ml_dev);
628 
629 	ml_link_lock_acquire(g_mlo_ctx);
630 	if (qdf_list_size(&g_mlo_ctx->ml_dev_list) < WLAN_UMAC_MLO_MAX_DEV)
631 		qdf_list_insert_back(&g_mlo_ctx->ml_dev_list, &ml_dev->node);
632 	ml_link_lock_release(g_mlo_ctx);
633 
634 	mlo_t2lm_ctx_init(ml_dev, vdev);
635 
636 	return status;
637 }
638 
639 /**
640  * mlo_t2lm_ctx_deinit() - API to deinitialize the t2lm context with the default
641  * values.
642  * @vdev: Pointer to vdev structure
643  *
644  * Return: None
645  */
646 static inline void mlo_t2lm_ctx_deinit(struct wlan_objmgr_vdev *vdev)
647 {
648 	wlan_mlo_t2lm_timer_deinit(vdev);
649 }
650 
651 static QDF_STATUS mlo_dev_ctx_deinit(struct wlan_objmgr_vdev *vdev)
652 {
653 	struct wlan_mlo_dev_context *ml_dev;
654 	QDF_STATUS status = QDF_STATUS_SUCCESS;
655 	struct qdf_mac_addr *mld_addr;
656 	struct mlo_mgr_context *g_mlo_ctx = wlan_objmgr_get_mlo_ctx();
657 	uint8_t id = 0;
658 	struct wlan_cm_connect_req *connect_req;
659 
660 	mld_addr = (struct qdf_mac_addr *)wlan_vdev_mlme_get_mldaddr(vdev);
661 	ml_dev = wlan_mlo_get_mld_ctx_by_mldaddr(mld_addr);
662 	if (!ml_dev) {
663 		mlo_err("Failed to get MLD dev context by mld addr "QDF_MAC_ADDR_FMT,
664 			QDF_MAC_ADDR_REF(mld_addr->bytes));
665 		if (!vdev->mlo_dev_ctx) {
666 			mlo_err("Failed to get MLD dev context from vdev");
667 			return QDF_STATUS_SUCCESS;
668 		}
669 		ml_dev = vdev->mlo_dev_ctx;
670 	}
671 
672 	mlo_debug("deleting vdev from MLD device ctx "QDF_MAC_ADDR_FMT,
673 		  QDF_MAC_ADDR_REF(mld_addr->bytes));
674 	mlo_dev_lock_acquire(ml_dev);
675 	while (id < WLAN_UMAC_MLO_MAX_VDEVS) {
676 		if (ml_dev->wlan_vdev_list[id] == vdev) {
677 			if (wlan_vdev_mlme_get_opmode(vdev) ==
678 							QDF_SAP_MODE)
679 				wlan_mlo_vdev_free_aid_mgr(ml_dev,
680 							   vdev);
681 			ml_dev->wlan_vdev_list[id] = NULL;
682 			ml_dev->wlan_vdev_count--;
683 			vdev->mlo_dev_ctx = NULL;
684 			break;
685 		}
686 		id++;
687 	}
688 	mlo_dev_lock_release(ml_dev);
689 
690 	ml_link_lock_acquire(g_mlo_ctx);
691 	if (!ml_dev->wlan_vdev_count) {
692 		if (ml_dev->ap_ctx)
693 			mlo_ap_ctx_deinit(ml_dev);
694 
695 		mlo_dev_mlpeer_list_deinit(ml_dev);
696 		qdf_list_remove_node(&g_mlo_ctx->ml_dev_list,
697 				     &ml_dev->node);
698 		if (wlan_vdev_mlme_get_opmode(vdev) == QDF_STA_MODE) {
699 			connect_req = ml_dev->sta_ctx->connect_req;
700 			if (connect_req) {
701 				if (connect_req->scan_ie.ptr) {
702 					qdf_mem_free(connect_req->scan_ie.ptr);
703 					connect_req->scan_ie.ptr = NULL;
704 				}
705 
706 				if (connect_req->assoc_ie.ptr) {
707 					qdf_mem_free(connect_req->assoc_ie.ptr);
708 					connect_req->assoc_ie.ptr = NULL;
709 				}
710 				qdf_mem_free(ml_dev->sta_ctx->connect_req);
711 			}
712 
713 			if (ml_dev->sta_ctx->disconn_req)
714 				qdf_mem_free(ml_dev->sta_ctx->disconn_req);
715 
716 			if (ml_dev->sta_ctx->assoc_rsp.ptr)
717 				qdf_mem_free(ml_dev->sta_ctx->assoc_rsp.ptr);
718 
719 			copied_conn_req_lock_destroy(ml_dev->sta_ctx);
720 
721 			qdf_mem_free(ml_dev->sta_ctx);
722 		}
723 		else if (wlan_vdev_mlme_get_opmode(vdev) == QDF_SAP_MODE)
724 			qdf_mem_free(ml_dev->ap_ctx);
725 
726 		mlo_t2lm_ctx_deinit(vdev);
727 		tsf_recalculation_lock_destroy(ml_dev);
728 		mlo_dev_lock_destroy(ml_dev);
729 		qdf_mem_free(ml_dev);
730 	}
731 	ml_link_lock_release(g_mlo_ctx);
732 	return status;
733 }
734 
735 QDF_STATUS wlan_mlo_mgr_vdev_created_notification(struct wlan_objmgr_vdev *vdev,
736 						  void *arg_list)
737 {
738 	QDF_STATUS status = QDF_STATUS_SUCCESS;
739 	struct qdf_mac_addr *mld_addr;
740 
741 	mld_addr = (struct qdf_mac_addr *)wlan_vdev_mlme_get_mldaddr(vdev);
742 	if (qdf_is_macaddr_zero(mld_addr)) {
743 		/* It's not a ML interface*/
744 		return QDF_STATUS_SUCCESS;
745 	}
746 	mlo_debug("MLD addr" QDF_MAC_ADDR_FMT,
747 		  QDF_MAC_ADDR_REF(mld_addr->bytes));
748 	status = mlo_dev_ctx_init(vdev);
749 
750 	return status;
751 }
752 
753 QDF_STATUS wlan_mlo_mgr_vdev_destroyed_notification(struct wlan_objmgr_vdev *vdev,
754 						    void *arg_list)
755 {
756 	QDF_STATUS status = QDF_STATUS_SUCCESS;
757 	struct qdf_mac_addr *mld_addr;
758 
759 	mld_addr = (struct qdf_mac_addr *)wlan_vdev_mlme_get_mldaddr(vdev);
760 	if (qdf_is_macaddr_zero(mld_addr)) {
761 		/* It's not a ML interface*/
762 		return QDF_STATUS_SUCCESS;
763 	}
764 	mlo_debug("MLD addr" QDF_MAC_ADDR_FMT,
765 		  QDF_MAC_ADDR_REF(mld_addr->bytes));
766 
767 	status = mlo_dev_ctx_deinit(vdev);
768 
769 	return status;
770 }
771 
772 QDF_STATUS wlan_mlo_mgr_update_mld_addr(struct qdf_mac_addr *old_mac,
773 					struct qdf_mac_addr *new_mac)
774 {
775 	struct wlan_mlo_dev_context *ml_dev;
776 
777 	ml_dev = wlan_mlo_get_mld_ctx_by_mldaddr(old_mac);
778 	if (!ml_dev) {
779 		mlo_err("ML dev context not found for MLD:" QDF_MAC_ADDR_FMT,
780 			QDF_MAC_ADDR_REF(old_mac->bytes));
781 		return QDF_STATUS_E_INVAL;
782 	}
783 	mlo_dev_lock_acquire(ml_dev);
784 	qdf_copy_macaddr(&ml_dev->mld_addr, new_mac);
785 	mlo_dev_lock_release(ml_dev);
786 
787 	return QDF_STATUS_SUCCESS;
788 }
789