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