xref: /wlan-dirver/qca-wifi-host-cmn/umac/mlo_mgr/src/wlan_mlo_mgr_main.c (revision 06d0b5348967845f004ebe7c2348bf8f467ad2f9)
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(uint8_t *peer_addr)
293 {
294 	qdf_list_t *ml_list;
295 	struct wlan_mlo_dev_context *mld_cur, *mld_next;
296 	struct wlan_mlo_peer_list *mlo_peer_list;
297 	bool ret_status = false;
298 	struct mlo_mgr_context *g_mlo_ctx = wlan_objmgr_get_mlo_ctx();
299 
300 	if (!g_mlo_ctx || !peer_addr ||
301 	    qdf_is_macaddr_zero((struct qdf_mac_addr *)peer_addr))
302 		return ret_status;
303 
304 	ml_link_lock_acquire(g_mlo_ctx);
305 	ml_list = &g_mlo_ctx->ml_dev_list;
306 	if (!qdf_list_size(ml_list))
307 		goto g_ml_ref;
308 
309 	mld_cur = mlo_list_peek_head(ml_list);
310 	while (mld_cur) {
311 		mlo_dev_lock_acquire(mld_cur);
312 		if (qdf_is_macaddr_equal(&mld_cur->mld_addr,
313 					 (struct qdf_mac_addr *)peer_addr)) {
314 			mlo_dev_lock_release(mld_cur);
315 			mlo_err("MLD ID %d exists with mac " QDF_MAC_ADDR_FMT,
316 				mld_cur->mld_id, QDF_MAC_ADDR_REF(peer_addr));
317 			ret_status = true;
318 			goto g_ml_ref;
319 		}
320 
321 		/* Check the peer list for a MAC address match */
322 		mlo_peer_list = &mld_cur->mlo_peer_list;
323 		ml_peerlist_lock_acquire(mlo_peer_list);
324 		if (mlo_get_mlpeer(mld_cur, (struct qdf_mac_addr *)peer_addr)) {
325 			ml_peerlist_lock_release(mlo_peer_list);
326 			mlo_dev_lock_release(mld_cur);
327 			mlo_err("MLD ID %d ML Peer exists with mac " QDF_MAC_ADDR_FMT,
328 				mld_cur->mld_id, QDF_MAC_ADDR_REF(peer_addr));
329 			ret_status = true;
330 			goto g_ml_ref;
331 		}
332 		ml_peerlist_lock_release(mlo_peer_list);
333 
334 		mld_next = mlo_get_next_mld_ctx(ml_list, mld_cur);
335 		mlo_dev_lock_release(mld_cur);
336 		mld_cur = mld_next;
337 	}
338 
339 g_ml_ref:
340 	ml_link_lock_release(g_mlo_ctx);
341 	return ret_status;
342 }
343 #endif
344 
345 static QDF_STATUS mlo_ap_ctx_deinit(struct wlan_mlo_dev_context *ml_dev)
346 {
347 	wlan_mlo_vdev_aid_mgr_deinit(ml_dev);
348 	mlo_ap_lock_destroy(ml_dev->ap_ctx);
349 	qdf_mem_free(ml_dev->ap_ctx);
350 	ml_dev->ap_ctx = NULL;
351 
352 	return QDF_STATUS_SUCCESS;
353 }
354 
355 static QDF_STATUS mlo_ap_ctx_init(struct wlan_mlo_dev_context *ml_dev)
356 {
357 	struct wlan_mlo_ap *ap_ctx;
358 
359 	ap_ctx = qdf_mem_malloc(sizeof(*ap_ctx));
360 	if (!ap_ctx) {
361 		mlo_err("MLO AP ctx alloc failure");
362 		return QDF_STATUS_E_NOMEM;
363 	}
364 
365 	ml_dev->ap_ctx = ap_ctx;
366 	mlo_ap_lock_create(ml_dev->ap_ctx);
367 	if (wlan_mlo_vdev_aid_mgr_init(ml_dev) != QDF_STATUS_SUCCESS) {
368 		mlo_ap_ctx_deinit(ml_dev);
369 		return QDF_STATUS_E_NOMEM;
370 	}
371 
372 	return QDF_STATUS_SUCCESS;
373 }
374 
375 #ifdef CONFIG_AP_PLATFORM
376 static inline
377 QDF_STATUS wlan_mlo_check_grp_id(uint8_t ref_id,
378 				 struct wlan_objmgr_vdev *vdev)
379 {
380 	struct wlan_objmgr_psoc *psoc;
381 	uint8_t grp_id = 0;
382 
383 	psoc = wlan_vdev_get_psoc(vdev);
384 	if (!mlo_psoc_get_grp_id(psoc, &grp_id)) {
385 		mlo_err("Unable to get mlo group id");
386 		return QDF_STATUS_E_FAILURE;
387 	}
388 
389 	if (grp_id != ref_id) {
390 		mlo_err("Error : MLD VAP Configuration with different WSI/MLD Groups");
391 		return QDF_STATUS_E_FAILURE;
392 	}
393 
394 	return QDF_STATUS_SUCCESS;
395 }
396 
397 static inline
398 QDF_STATUS wlan_mlo_pdev_check(struct wlan_objmgr_pdev *ref_pdev,
399 			       struct wlan_objmgr_vdev *vdev)
400 {
401 	struct wlan_objmgr_pdev *pdev;
402 	struct wlan_objmgr_psoc *psoc;
403 	uint8_t grp_id = 0;
404 
405 	pdev = wlan_vdev_get_pdev(vdev);
406 
407 	psoc = wlan_pdev_get_psoc(ref_pdev);
408 	if (!mlo_psoc_get_grp_id(psoc, &grp_id)) {
409 		mlo_err("Unable to get the MLO Group ID for the vdev");
410 		return QDF_STATUS_E_FAILURE;
411 	}
412 
413 	if (mlo_check_all_pdev_state(psoc, grp_id, MLO_LINK_SETUP_DONE)) {
414 		mlo_err("Pdev link is not in ready state, initial link setup failed");
415 		return QDF_STATUS_E_FAILURE;
416 	}
417 
418 	if (ref_pdev == pdev) {
419 		mlo_err("MLD vdev for this pdev already found, investigate config");
420 		return QDF_STATUS_E_FAILURE;
421 	}
422 
423 	if (wlan_mlo_check_grp_id(grp_id, vdev))
424 		return QDF_STATUS_E_FAILURE;
425 
426 	return QDF_STATUS_SUCCESS;
427 }
428 
429 static inline
430 QDF_STATUS mlo_dev_config_check(struct wlan_mlo_dev_context *ml_dev,
431 				struct wlan_objmgr_vdev *vdev)
432 {
433 	return QDF_STATUS_SUCCESS;
434 }
435 
436 #else
437 static inline
438 QDF_STATUS mlo_dev_config_check(struct wlan_mlo_dev_context *ml_dev,
439 				struct wlan_objmgr_vdev *vdev)
440 {
441 	enum QDF_OPMODE opmode = wlan_vdev_mlme_get_opmode(vdev);
442 
443 	if (wlan_mlo_check_valid_config(ml_dev, wlan_vdev_get_pdev(vdev),
444 					opmode) != QDF_STATUS_SUCCESS)
445 		return QDF_STATUS_E_FAILURE;
446 
447 	return QDF_STATUS_SUCCESS;
448 }
449 
450 static inline
451 QDF_STATUS wlan_mlo_pdev_check(struct wlan_objmgr_pdev *ref_pdev,
452 			       struct wlan_objmgr_vdev *vdev)
453 {
454 	return QDF_STATUS_SUCCESS;
455 }
456 #endif
457 
458 QDF_STATUS wlan_mlo_check_valid_config(struct wlan_mlo_dev_context *ml_dev,
459 				       struct wlan_objmgr_pdev *pdev,
460 				       enum QDF_OPMODE opmode)
461 {
462 	uint32_t id = 0;
463 	struct wlan_objmgr_vdev *vdev;
464 
465 	if (!ml_dev)
466 		return QDF_STATUS_E_FAILURE;
467 
468 	if (!pdev)
469 		return QDF_STATUS_E_FAILURE;
470 
471 	mlo_dev_lock_acquire(ml_dev);
472 	while (id < WLAN_UMAC_MLO_MAX_VDEVS) {
473 		vdev = ml_dev->wlan_vdev_list[id];
474 		if (vdev) {
475 			if (wlan_mlo_pdev_check(pdev, vdev)) {
476 				mlo_dev_lock_release(ml_dev);
477 				return QDF_STATUS_E_FAILURE;
478 			}
479 
480 			if (wlan_vdev_mlme_get_opmode(vdev) != opmode) {
481 				mlo_err("Invalid opmode %d type found expected %d, investigate config",
482 					wlan_vdev_mlme_get_opmode(vdev),
483 					opmode);
484 				mlo_dev_lock_release(ml_dev);
485 				return QDF_STATUS_E_FAILURE;
486 			}
487 		}
488 		id++;
489 	}
490 
491 	mlo_dev_lock_release(ml_dev);
492 	return QDF_STATUS_SUCCESS;
493 }
494 
495 /**
496  * mlo_t2lm_ctx_init() - API to initialize the t2lm context with the default
497  * values.
498  * @ml_dev: Pointer to ML Dev context
499  * @vdev: Pointer to vdev structure
500  *
501  * Return: None
502  */
503 static inline void mlo_t2lm_ctx_init(struct wlan_mlo_dev_context *ml_dev,
504 				     struct wlan_objmgr_vdev *vdev)
505 {
506 	struct wlan_t2lm_info *t2lm;
507 
508 	t2lm = &ml_dev->t2lm_ctx.established_t2lm.t2lm;
509 
510 	qdf_mem_zero(&ml_dev->t2lm_ctx, sizeof(struct wlan_t2lm_context));
511 
512 	t2lm->direction = WLAN_T2LM_BIDI_DIRECTION;
513 	t2lm->default_link_mapping = 1;
514 
515 	wlan_mlo_t2lm_timer_init(vdev);
516 }
517 
518 static QDF_STATUS mlo_dev_ctx_init(struct wlan_objmgr_vdev *vdev)
519 {
520 	struct wlan_mlo_dev_context *ml_dev;
521 	QDF_STATUS status = QDF_STATUS_SUCCESS;
522 	struct qdf_mac_addr *mld_addr;
523 	struct mlo_mgr_context *g_mlo_ctx = wlan_objmgr_get_mlo_ctx();
524 	uint8_t id = 0;
525 
526 	mld_addr = (struct qdf_mac_addr *)wlan_vdev_mlme_get_mldaddr(vdev);
527 	ml_dev = wlan_mlo_get_mld_ctx_by_mldaddr(mld_addr);
528 
529 	if (ml_dev) {
530 		if (mlo_dev_config_check(ml_dev, vdev) != QDF_STATUS_SUCCESS)
531 			return QDF_STATUS_E_FAILURE;
532 
533 		mlo_dev_lock_acquire(ml_dev);
534 		while (id < WLAN_UMAC_MLO_MAX_VDEVS) {
535 			if (ml_dev->wlan_vdev_list[id]) {
536 				id++;
537 				continue;
538 			}
539 
540 			ml_dev->wlan_vdev_list[id] = vdev;
541 			ml_dev->wlan_vdev_count++;
542 			vdev->mlo_dev_ctx = ml_dev;
543 
544 			if (wlan_vdev_mlme_get_opmode(vdev) == QDF_SAP_MODE)
545 				wlan_mlo_vdev_alloc_aid_mgr(ml_dev, vdev);
546 
547 			break;
548 		}
549 		mlo_dev_lock_release(ml_dev);
550 		return QDF_STATUS_SUCCESS;
551 	}
552 
553 	/* Create a new ML dev context */
554 	ml_dev = qdf_mem_malloc(sizeof(*ml_dev));
555 	if (!ml_dev) {
556 		mlo_err("Failed to allocate memory for ML dev");
557 		return QDF_STATUS_E_NOMEM;
558 	}
559 
560 	qdf_copy_macaddr(&ml_dev->mld_addr, mld_addr);
561 	ml_dev->wlan_vdev_list[0] = vdev;
562 	ml_dev->wlan_vdev_count++;
563 	vdev->mlo_dev_ctx = ml_dev;
564 
565 	mlo_dev_lock_create(ml_dev);
566 	tsf_recalculation_lock_create(ml_dev);
567 	if (wlan_vdev_mlme_get_opmode(vdev) == QDF_STA_MODE) {
568 		ml_dev->sta_ctx = qdf_mem_malloc(sizeof(struct wlan_mlo_sta));
569 		if (!ml_dev->sta_ctx) {
570 			tsf_recalculation_lock_destroy(ml_dev);
571 			mlo_dev_lock_destroy(ml_dev);
572 			qdf_mem_free(ml_dev);
573 			return QDF_STATUS_E_NOMEM;
574 		}
575 		copied_conn_req_lock_create(ml_dev->sta_ctx);
576 	} else if (wlan_vdev_mlme_get_opmode(vdev) == QDF_SAP_MODE) {
577 		if (mlo_ap_ctx_init(ml_dev) != QDF_STATUS_SUCCESS) {
578 			tsf_recalculation_lock_destroy(ml_dev);
579 			mlo_dev_lock_destroy(ml_dev);
580 			qdf_mem_free(ml_dev);
581 			mlo_err("Failed to allocate memory for ap ctx");
582 			return QDF_STATUS_E_NOMEM;
583 		}
584 	}
585 
586 	mlo_dev_mlpeer_list_init(ml_dev);
587 
588 	ml_link_lock_acquire(g_mlo_ctx);
589 	if (qdf_list_size(&g_mlo_ctx->ml_dev_list) < WLAN_UMAC_MLO_MAX_DEV)
590 		qdf_list_insert_back(&g_mlo_ctx->ml_dev_list, &ml_dev->node);
591 	ml_link_lock_release(g_mlo_ctx);
592 
593 	mlo_t2lm_ctx_init(ml_dev, vdev);
594 
595 	return status;
596 }
597 
598 /**
599  * mlo_t2lm_ctx_deinit() - API to deinitialize the t2lm context with the default
600  * values.
601  * @vdev: Pointer to vdev structure
602  *
603  * Return: None
604  */
605 static inline void mlo_t2lm_ctx_deinit(struct wlan_objmgr_vdev *vdev)
606 {
607 	wlan_mlo_t2lm_timer_deinit(vdev);
608 }
609 
610 static QDF_STATUS mlo_dev_ctx_deinit(struct wlan_objmgr_vdev *vdev)
611 {
612 	struct wlan_mlo_dev_context *ml_dev;
613 	QDF_STATUS status = QDF_STATUS_SUCCESS;
614 	struct qdf_mac_addr *mld_addr;
615 	struct mlo_mgr_context *g_mlo_ctx = wlan_objmgr_get_mlo_ctx();
616 	uint8_t id = 0;
617 	struct wlan_cm_connect_req *connect_req;
618 
619 	mld_addr = (struct qdf_mac_addr *)wlan_vdev_mlme_get_mldaddr(vdev);
620 	ml_dev = wlan_mlo_get_mld_ctx_by_mldaddr(mld_addr);
621 	if (!ml_dev) {
622 		mlo_err("Failed to get MLD dev context by mld addr "QDF_MAC_ADDR_FMT,
623 			QDF_MAC_ADDR_REF(mld_addr->bytes));
624 		if (!vdev->mlo_dev_ctx) {
625 			mlo_err("Failed to get MLD dev context from vdev");
626 			return QDF_STATUS_SUCCESS;
627 		}
628 		ml_dev = vdev->mlo_dev_ctx;
629 	}
630 
631 	mlo_debug("deleting vdev from MLD device ctx "QDF_MAC_ADDR_FMT,
632 		  QDF_MAC_ADDR_REF(mld_addr->bytes));
633 	mlo_dev_lock_acquire(ml_dev);
634 	while (id < WLAN_UMAC_MLO_MAX_VDEVS) {
635 		if (ml_dev->wlan_vdev_list[id] == vdev) {
636 			if (wlan_vdev_mlme_get_opmode(vdev) ==
637 							QDF_SAP_MODE)
638 				wlan_mlo_vdev_free_aid_mgr(ml_dev,
639 							   vdev);
640 			ml_dev->wlan_vdev_list[id] = NULL;
641 			ml_dev->wlan_vdev_count--;
642 			vdev->mlo_dev_ctx = NULL;
643 			break;
644 		}
645 		id++;
646 	}
647 	mlo_dev_lock_release(ml_dev);
648 
649 	ml_link_lock_acquire(g_mlo_ctx);
650 	if (!ml_dev->wlan_vdev_count) {
651 		if (ml_dev->ap_ctx)
652 			mlo_ap_ctx_deinit(ml_dev);
653 
654 		mlo_dev_mlpeer_list_deinit(ml_dev);
655 		qdf_list_remove_node(&g_mlo_ctx->ml_dev_list,
656 				     &ml_dev->node);
657 		if (wlan_vdev_mlme_get_opmode(vdev) == QDF_STA_MODE) {
658 			connect_req = ml_dev->sta_ctx->connect_req;
659 			if (connect_req) {
660 				if (connect_req->scan_ie.ptr) {
661 					qdf_mem_free(connect_req->scan_ie.ptr);
662 					connect_req->scan_ie.ptr = NULL;
663 				}
664 
665 				if (connect_req->assoc_ie.ptr) {
666 					qdf_mem_free(connect_req->assoc_ie.ptr);
667 					connect_req->assoc_ie.ptr = NULL;
668 				}
669 				qdf_mem_free(ml_dev->sta_ctx->connect_req);
670 			}
671 
672 			if (ml_dev->sta_ctx->disconn_req)
673 				qdf_mem_free(ml_dev->sta_ctx->disconn_req);
674 
675 			if (ml_dev->sta_ctx->assoc_rsp.ptr)
676 				qdf_mem_free(ml_dev->sta_ctx->assoc_rsp.ptr);
677 
678 			copied_conn_req_lock_destroy(ml_dev->sta_ctx);
679 
680 			qdf_mem_free(ml_dev->sta_ctx);
681 		}
682 		else if (wlan_vdev_mlme_get_opmode(vdev) == QDF_SAP_MODE)
683 			qdf_mem_free(ml_dev->ap_ctx);
684 
685 		mlo_t2lm_ctx_deinit(vdev);
686 		tsf_recalculation_lock_destroy(ml_dev);
687 		mlo_dev_lock_destroy(ml_dev);
688 		qdf_mem_free(ml_dev);
689 	}
690 	ml_link_lock_release(g_mlo_ctx);
691 	return status;
692 }
693 
694 QDF_STATUS wlan_mlo_mgr_vdev_created_notification(struct wlan_objmgr_vdev *vdev,
695 						  void *arg_list)
696 {
697 	QDF_STATUS status = QDF_STATUS_SUCCESS;
698 	struct qdf_mac_addr *mld_addr;
699 
700 	mld_addr = (struct qdf_mac_addr *)wlan_vdev_mlme_get_mldaddr(vdev);
701 	if (qdf_is_macaddr_zero(mld_addr)) {
702 		/* It's not a ML interface*/
703 		return QDF_STATUS_SUCCESS;
704 	}
705 	mlo_debug("MLD addr" QDF_MAC_ADDR_FMT,
706 		  QDF_MAC_ADDR_REF(mld_addr->bytes));
707 	status = mlo_dev_ctx_init(vdev);
708 
709 	return status;
710 }
711 
712 QDF_STATUS wlan_mlo_mgr_vdev_destroyed_notification(struct wlan_objmgr_vdev *vdev,
713 						    void *arg_list)
714 {
715 	QDF_STATUS status = QDF_STATUS_SUCCESS;
716 	struct qdf_mac_addr *mld_addr;
717 
718 	mld_addr = (struct qdf_mac_addr *)wlan_vdev_mlme_get_mldaddr(vdev);
719 	if (qdf_is_macaddr_zero(mld_addr)) {
720 		/* It's not a ML interface*/
721 		return QDF_STATUS_SUCCESS;
722 	}
723 	mlo_debug("MLD addr" QDF_MAC_ADDR_FMT,
724 		  QDF_MAC_ADDR_REF(mld_addr->bytes));
725 
726 	status = mlo_dev_ctx_deinit(vdev);
727 
728 	return status;
729 }
730 
731 QDF_STATUS wlan_mlo_mgr_update_mld_addr(struct qdf_mac_addr *old_mac,
732 					struct qdf_mac_addr *new_mac)
733 {
734 	struct wlan_mlo_dev_context *ml_dev;
735 
736 	ml_dev = wlan_mlo_get_mld_ctx_by_mldaddr(old_mac);
737 	if (!ml_dev) {
738 		mlo_err("ML dev context not found for MLD:" QDF_MAC_ADDR_FMT,
739 			QDF_MAC_ADDR_REF(old_mac->bytes));
740 		return QDF_STATUS_E_INVAL;
741 	}
742 	mlo_dev_lock_acquire(ml_dev);
743 	qdf_copy_macaddr(&ml_dev->mld_addr, new_mac);
744 	mlo_dev_lock_release(ml_dev);
745 
746 	return QDF_STATUS_SUCCESS;
747 }
748