xref: /wlan-dirver/qca-wifi-host-cmn/umac/mlo_mgr/src/wlan_mlo_mgr_main.c (revision 5db38f17138c409346f0ba0d72e13640f35d04b5)
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 struct wlan_mlo_dev_context *wlan_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 struct wlan_mlo_dev_context *wlan_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 = wlan_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 = wlan_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 = wlan_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 = wlan_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 = wlan_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 = wlan_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 
385 #define WLAN_HDD_MGMT_FRAME_DA_OFFSET 4
386 #define WLAN_HDD_MGMT_FRAME_SA_OFFSET (WLAN_HDD_MGMT_FRAME_DA_OFFSET + 6)
387 #define WLAN_HDD_MGMT_FRAME_BSSID_OFFSET (WLAN_HDD_MGMT_FRAME_SA_OFFSET + 6)
388 #define WLAN_HDD_MGMT_FRAME_ACTION_CATEGORY_OFFSET \
389 				(WLAN_HDD_MGMT_FRAME_BSSID_OFFSET + 6 + 2)
390 #define WLAN_HDD_MGMT_FRAME_ACTION_TYPE_OFFSET \
391 				(WLAN_HDD_MGMT_FRAME_ACTION_CATEGORY_OFFSET + 1)
392 #define WLAN_HDD_ACTION_FRAME_CATEGORY_PUBLIC 0x04
393 
394 /*
395  * Typical 802.11 Action Frame Format
396  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-
397  * | FC | DUR |  DA  |   SA  | BSSID |Seq.|Cat.|Act|   Elements   | FCS |
398  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-
399  *    2    2     6       6       6     2    1    1   Variable Len    4
400  */
401 void wlan_mlo_update_action_frame_from_user(struct wlan_objmgr_vdev *vdev,
402 					    uint8_t *frame,
403 					    uint32_t frame_len)
404 {
405 	struct wlan_objmgr_peer *peer;
406 	uint8_t *da, *sa, *bssid;
407 
408 	if (!wlan_vdev_mlme_is_mlo_vdev(vdev) ||
409 	    (wlan_vdev_mlme_get_opmode(vdev) != QDF_STA_MODE))
410 		return;
411 
412 	if (frame_len <= WLAN_HDD_MGMT_FRAME_ACTION_TYPE_OFFSET) {
413 		mlo_debug("Not a valid Action frame len: %d", frame_len);
414 		return;
415 	}
416 
417 	/* Translate address only for action frames
418 	 * which are not of public category.
419 	 * Reference: 802.11-2012, Subclause: 8.5
420 	 */
421 
422 	if (frame[WLAN_HDD_MGMT_FRAME_ACTION_CATEGORY_OFFSET] ==
423 				WLAN_HDD_ACTION_FRAME_CATEGORY_PUBLIC)
424 		return;
425 
426 	da = frame + WLAN_HDD_MGMT_FRAME_DA_OFFSET;
427 	sa = frame + WLAN_HDD_MGMT_FRAME_SA_OFFSET;
428 	bssid = frame + WLAN_HDD_MGMT_FRAME_BSSID_OFFSET;
429 
430 	peer = wlan_objmgr_vdev_try_get_bsspeer(vdev, WLAN_MLO_MGR_ID);
431 	if (!peer) {
432 		mlo_debug("Peer not found");
433 		return;
434 	}
435 
436 	mlo_debug("Change MLD addr to link addr for non-Public action frame");
437 	/* DA = VDEV's BSS peer's link address.
438 	 * SA = VDEV's link address.
439 	 * BSSID = VDEV's BSS peer's link address.
440 	 */
441 
442 	qdf_ether_addr_copy(da, wlan_peer_get_macaddr(peer));
443 	qdf_ether_addr_copy(sa, wlan_vdev_mlme_get_macaddr(vdev));
444 	qdf_ether_addr_copy(bssid, wlan_peer_get_macaddr(peer));
445 
446 	wlan_objmgr_peer_release_ref(peer, WLAN_MLO_MGR_ID);
447 }
448 
449 void wlan_mlo_update_action_frame_to_user(struct wlan_objmgr_vdev *vdev,
450 					  uint8_t *frame,
451 					  uint32_t frame_len)
452 {
453 	struct wlan_objmgr_peer *peer;
454 	uint8_t *da, *sa, *bssid;
455 
456 	if (!wlan_vdev_mlme_is_mlo_vdev(vdev) ||
457 	    (wlan_vdev_mlme_get_opmode(vdev) != QDF_STA_MODE))
458 		return;
459 
460 	if (frame_len <= WLAN_HDD_MGMT_FRAME_ACTION_TYPE_OFFSET) {
461 		mlo_debug("Not a valid Action frame len: %d", frame_len);
462 		return;
463 	}
464 
465 	/* Translate address only for action frames
466 	 * which are not of public category.
467 	 * Reference: 802.11-2012, Subclause: 8.5
468 	 */
469 
470 	if (frame[WLAN_HDD_MGMT_FRAME_ACTION_CATEGORY_OFFSET] ==
471 				WLAN_HDD_ACTION_FRAME_CATEGORY_PUBLIC)
472 		return;
473 
474 	da = frame + WLAN_HDD_MGMT_FRAME_DA_OFFSET;
475 	sa = frame + WLAN_HDD_MGMT_FRAME_SA_OFFSET;
476 	bssid = frame + WLAN_HDD_MGMT_FRAME_BSSID_OFFSET;
477 
478 	peer = wlan_objmgr_vdev_try_get_bsspeer(vdev, WLAN_MLO_MGR_ID);
479 	if (!peer) {
480 		mlo_debug("Peer not found");
481 		return;
482 	}
483 
484 	mlo_debug("Change link addr to MLD addr for non-Public action frame");
485 	/* DA = VDEV's MLD address.
486 	 * SA = VDEV's BSS peer's MLD address.
487 	 * BSSID = VDEV's BSS peer's MLD address.
488 	 */
489 
490 	qdf_ether_addr_copy(da, wlan_vdev_mlme_get_mldaddr(vdev));
491 	qdf_ether_addr_copy(sa, wlan_peer_mlme_get_mldaddr(peer));
492 	qdf_ether_addr_copy(bssid, wlan_peer_mlme_get_mldaddr(peer));
493 
494 	wlan_objmgr_peer_release_ref(peer, WLAN_MLO_MGR_ID);
495 }
496 #endif
497 
498 static QDF_STATUS mlo_ap_ctx_deinit(struct wlan_mlo_dev_context *ml_dev)
499 {
500 	wlan_mlo_vdev_aid_mgr_deinit(ml_dev);
501 	mlo_ap_lock_destroy(ml_dev->ap_ctx);
502 	qdf_mem_free(ml_dev->ap_ctx);
503 	ml_dev->ap_ctx = NULL;
504 
505 	return QDF_STATUS_SUCCESS;
506 }
507 
508 static QDF_STATUS mlo_ap_ctx_init(struct wlan_mlo_dev_context *ml_dev)
509 {
510 	struct wlan_mlo_ap *ap_ctx;
511 
512 	ap_ctx = qdf_mem_malloc(sizeof(*ap_ctx));
513 	if (!ap_ctx) {
514 		mlo_err("MLO AP ctx alloc failure");
515 		return QDF_STATUS_E_NOMEM;
516 	}
517 
518 	ml_dev->ap_ctx = ap_ctx;
519 	mlo_ap_lock_create(ml_dev->ap_ctx);
520 	if (wlan_mlo_vdev_aid_mgr_init(ml_dev) != QDF_STATUS_SUCCESS) {
521 		mlo_ap_ctx_deinit(ml_dev);
522 		return QDF_STATUS_E_NOMEM;
523 	}
524 
525 	return QDF_STATUS_SUCCESS;
526 }
527 
528 #ifdef CONFIG_AP_PLATFORM
529 static inline
530 QDF_STATUS wlan_mlo_check_grp_id(uint8_t ref_id,
531 				 struct wlan_objmgr_vdev *vdev)
532 {
533 	struct wlan_objmgr_psoc *psoc;
534 	uint8_t grp_id = 0;
535 
536 	psoc = wlan_vdev_get_psoc(vdev);
537 	if (!mlo_psoc_get_grp_id(psoc, &grp_id)) {
538 		mlo_err("Unable to get mlo group id");
539 		return QDF_STATUS_E_FAILURE;
540 	}
541 
542 	if (grp_id != ref_id) {
543 		mlo_err("Error : MLD VAP Configuration with different WSI/MLD Groups");
544 		return QDF_STATUS_E_FAILURE;
545 	}
546 
547 	return QDF_STATUS_SUCCESS;
548 }
549 
550 static inline
551 QDF_STATUS wlan_mlo_pdev_check(struct wlan_objmgr_pdev *ref_pdev,
552 			       struct wlan_objmgr_vdev *vdev)
553 {
554 	struct wlan_objmgr_pdev *pdev;
555 	struct wlan_objmgr_psoc *psoc;
556 	uint8_t grp_id = 0;
557 
558 	pdev = wlan_vdev_get_pdev(vdev);
559 
560 	psoc = wlan_pdev_get_psoc(ref_pdev);
561 	if (!mlo_psoc_get_grp_id(psoc, &grp_id)) {
562 		mlo_err("Unable to get the MLO Group ID for the vdev");
563 		return QDF_STATUS_E_FAILURE;
564 	}
565 
566 	if (mlo_check_all_pdev_state(psoc, grp_id, MLO_LINK_SETUP_DONE)) {
567 		mlo_err("Pdev link is not in ready state, initial link setup failed");
568 		return QDF_STATUS_E_FAILURE;
569 	}
570 
571 	if (ref_pdev == pdev) {
572 		mlo_err("MLD vdev for this pdev already found, investigate config");
573 		return QDF_STATUS_E_FAILURE;
574 	}
575 
576 	if (wlan_mlo_check_grp_id(grp_id, vdev))
577 		return QDF_STATUS_E_FAILURE;
578 
579 	return QDF_STATUS_SUCCESS;
580 }
581 
582 static inline
583 QDF_STATUS mlo_dev_config_check(struct wlan_mlo_dev_context *ml_dev,
584 				struct wlan_objmgr_vdev *vdev)
585 {
586 	return QDF_STATUS_SUCCESS;
587 }
588 
589 #else
590 static inline
591 QDF_STATUS mlo_dev_config_check(struct wlan_mlo_dev_context *ml_dev,
592 				struct wlan_objmgr_vdev *vdev)
593 {
594 	enum QDF_OPMODE opmode = wlan_vdev_mlme_get_opmode(vdev);
595 
596 	if (wlan_mlo_check_valid_config(ml_dev, wlan_vdev_get_pdev(vdev),
597 					opmode) != QDF_STATUS_SUCCESS)
598 		return QDF_STATUS_E_FAILURE;
599 
600 	return QDF_STATUS_SUCCESS;
601 }
602 
603 static inline
604 QDF_STATUS wlan_mlo_pdev_check(struct wlan_objmgr_pdev *ref_pdev,
605 			       struct wlan_objmgr_vdev *vdev)
606 {
607 	return QDF_STATUS_SUCCESS;
608 }
609 #endif
610 
611 QDF_STATUS wlan_mlo_check_valid_config(struct wlan_mlo_dev_context *ml_dev,
612 				       struct wlan_objmgr_pdev *pdev,
613 				       enum QDF_OPMODE opmode)
614 {
615 	uint32_t id = 0;
616 	struct wlan_objmgr_vdev *vdev;
617 
618 	if (!ml_dev)
619 		return QDF_STATUS_E_FAILURE;
620 
621 	if (!pdev)
622 		return QDF_STATUS_E_FAILURE;
623 
624 	mlo_dev_lock_acquire(ml_dev);
625 	while (id < WLAN_UMAC_MLO_MAX_VDEVS) {
626 		vdev = ml_dev->wlan_vdev_list[id];
627 		if (vdev) {
628 			if (wlan_mlo_pdev_check(pdev, vdev)) {
629 				mlo_dev_lock_release(ml_dev);
630 				return QDF_STATUS_E_FAILURE;
631 			}
632 
633 			if (wlan_vdev_mlme_get_opmode(vdev) != opmode) {
634 				mlo_err("Invalid opmode %d type found expected %d, investigate config",
635 					wlan_vdev_mlme_get_opmode(vdev),
636 					opmode);
637 				mlo_dev_lock_release(ml_dev);
638 				return QDF_STATUS_E_FAILURE;
639 			}
640 		}
641 		id++;
642 	}
643 
644 	mlo_dev_lock_release(ml_dev);
645 	return QDF_STATUS_SUCCESS;
646 }
647 
648 /**
649  * mlo_t2lm_ctx_init() - API to initialize the t2lm context with the default
650  * values.
651  * @ml_dev: Pointer to ML Dev context
652  * @vdev: Pointer to vdev structure
653  *
654  * Return: None
655  */
656 static inline void mlo_t2lm_ctx_init(struct wlan_mlo_dev_context *ml_dev,
657 				     struct wlan_objmgr_vdev *vdev)
658 {
659 	struct wlan_t2lm_info *t2lm;
660 
661 	t2lm = &ml_dev->t2lm_ctx.established_t2lm.t2lm;
662 
663 	qdf_mem_zero(&ml_dev->t2lm_ctx, sizeof(struct wlan_t2lm_context));
664 
665 	t2lm->direction = WLAN_T2LM_BIDI_DIRECTION;
666 	t2lm->default_link_mapping = 1;
667 	t2lm->link_mapping_size = 0;
668 
669 	wlan_mlo_t2lm_timer_init(vdev);
670 }
671 
672 /**
673  * mlo_epcs_ctx_init() - API to initialize the epcs context with the
674  * default values.
675  * @ml_dev: Pointer to ML Dev context
676  *
677  * Return: None
678  */
679 static inline void mlo_epcs_ctx_init(struct wlan_mlo_dev_context *ml_dev)
680 {
681 	struct wlan_epcs_context *epcs_ctx;
682 
683 	epcs_ctx = &ml_dev->epcs_ctx;
684 	qdf_mem_zero(epcs_ctx, sizeof(struct wlan_epcs_context));
685 }
686 
687 static QDF_STATUS mlo_dev_ctx_init(struct wlan_objmgr_vdev *vdev)
688 {
689 	struct wlan_mlo_dev_context *ml_dev;
690 	QDF_STATUS status = QDF_STATUS_SUCCESS;
691 	struct qdf_mac_addr *mld_addr;
692 	struct mlo_mgr_context *g_mlo_ctx = wlan_objmgr_get_mlo_ctx();
693 	uint8_t id = 0;
694 
695 	mld_addr = (struct qdf_mac_addr *)wlan_vdev_mlme_get_mldaddr(vdev);
696 	ml_dev = wlan_mlo_get_mld_ctx_by_mldaddr(mld_addr);
697 
698 	if (ml_dev) {
699 		if (mlo_dev_config_check(ml_dev, vdev) != QDF_STATUS_SUCCESS)
700 			return QDF_STATUS_E_FAILURE;
701 
702 		mlo_dev_lock_acquire(ml_dev);
703 		while (id < WLAN_UMAC_MLO_MAX_VDEVS) {
704 			if (ml_dev->wlan_vdev_list[id]) {
705 				id++;
706 				continue;
707 			}
708 
709 			ml_dev->wlan_vdev_list[id] = vdev;
710 			ml_dev->wlan_vdev_count++;
711 			vdev->mlo_dev_ctx = ml_dev;
712 
713 			if (wlan_vdev_mlme_get_opmode(vdev) == QDF_SAP_MODE)
714 				wlan_mlo_vdev_alloc_aid_mgr(ml_dev, vdev);
715 
716 			break;
717 		}
718 		mlo_dev_lock_release(ml_dev);
719 		return QDF_STATUS_SUCCESS;
720 	}
721 
722 	/* Create a new ML dev context */
723 	ml_dev = qdf_mem_malloc(sizeof(*ml_dev));
724 	if (!ml_dev) {
725 		mlo_err("Failed to allocate memory for ML dev");
726 		return QDF_STATUS_E_NOMEM;
727 	}
728 
729 	qdf_copy_macaddr(&ml_dev->mld_addr, mld_addr);
730 	ml_dev->wlan_vdev_list[0] = vdev;
731 	ml_dev->wlan_vdev_count++;
732 	vdev->mlo_dev_ctx = ml_dev;
733 
734 	mlo_dev_lock_create(ml_dev);
735 	tsf_recalculation_lock_create(ml_dev);
736 	if (wlan_vdev_mlme_get_opmode(vdev) == QDF_STA_MODE) {
737 		ml_dev->sta_ctx = qdf_mem_malloc(sizeof(struct wlan_mlo_sta));
738 		if (!ml_dev->sta_ctx) {
739 			tsf_recalculation_lock_destroy(ml_dev);
740 			mlo_dev_lock_destroy(ml_dev);
741 			qdf_mem_free(ml_dev);
742 			return QDF_STATUS_E_NOMEM;
743 		}
744 		copied_conn_req_lock_create(ml_dev->sta_ctx);
745 	} else if (wlan_vdev_mlme_get_opmode(vdev) == QDF_SAP_MODE) {
746 		if (mlo_ap_ctx_init(ml_dev) != QDF_STATUS_SUCCESS) {
747 			tsf_recalculation_lock_destroy(ml_dev);
748 			mlo_dev_lock_destroy(ml_dev);
749 			qdf_mem_free(ml_dev);
750 			mlo_err("Failed to allocate memory for ap ctx");
751 			return QDF_STATUS_E_NOMEM;
752 		}
753 	}
754 
755 	mlo_dev_mlpeer_list_init(ml_dev);
756 
757 	ml_link_lock_acquire(g_mlo_ctx);
758 	if (qdf_list_size(&g_mlo_ctx->ml_dev_list) < WLAN_UMAC_MLO_MAX_DEV)
759 		qdf_list_insert_back(&g_mlo_ctx->ml_dev_list, &ml_dev->node);
760 	ml_link_lock_release(g_mlo_ctx);
761 
762 	mlo_t2lm_ctx_init(ml_dev, vdev);
763 	mlo_epcs_ctx_init(ml_dev);
764 
765 	return status;
766 }
767 
768 /**
769  * mlo_t2lm_ctx_deinit() - API to deinitialize the t2lm context with the default
770  * values.
771  * @vdev: Pointer to vdev structure
772  *
773  * Return: None
774  */
775 static inline void mlo_t2lm_ctx_deinit(struct wlan_objmgr_vdev *vdev)
776 {
777 	wlan_mlo_t2lm_timer_deinit(vdev);
778 }
779 
780 static QDF_STATUS mlo_dev_ctx_deinit(struct wlan_objmgr_vdev *vdev)
781 {
782 	struct wlan_mlo_dev_context *ml_dev;
783 	QDF_STATUS status = QDF_STATUS_SUCCESS;
784 	struct qdf_mac_addr *mld_addr;
785 	struct mlo_mgr_context *g_mlo_ctx = wlan_objmgr_get_mlo_ctx();
786 	uint8_t id = 0;
787 	struct wlan_cm_connect_req *connect_req;
788 
789 	mld_addr = (struct qdf_mac_addr *)wlan_vdev_mlme_get_mldaddr(vdev);
790 	ml_dev = wlan_mlo_get_mld_ctx_by_mldaddr(mld_addr);
791 	if (!ml_dev) {
792 		mlo_err("Failed to get MLD dev context by mld addr "QDF_MAC_ADDR_FMT,
793 			QDF_MAC_ADDR_REF(mld_addr->bytes));
794 		if (!vdev->mlo_dev_ctx) {
795 			mlo_err("Failed to get MLD dev context from vdev");
796 			return QDF_STATUS_SUCCESS;
797 		}
798 		ml_dev = vdev->mlo_dev_ctx;
799 	}
800 
801 	mlo_debug("deleting vdev from MLD device ctx "QDF_MAC_ADDR_FMT,
802 		  QDF_MAC_ADDR_REF(mld_addr->bytes));
803 	mlo_dev_lock_acquire(ml_dev);
804 	while (id < WLAN_UMAC_MLO_MAX_VDEVS) {
805 		if (ml_dev->wlan_vdev_list[id] == vdev) {
806 			if (wlan_vdev_mlme_get_opmode(vdev) ==
807 							QDF_SAP_MODE)
808 				wlan_mlo_vdev_free_aid_mgr(ml_dev,
809 							   vdev);
810 			ml_dev->wlan_vdev_list[id] = NULL;
811 			ml_dev->wlan_vdev_count--;
812 			vdev->mlo_dev_ctx = NULL;
813 			break;
814 		}
815 		id++;
816 	}
817 	mlo_dev_lock_release(ml_dev);
818 
819 	ml_link_lock_acquire(g_mlo_ctx);
820 	if (!ml_dev->wlan_vdev_count) {
821 		if (ml_dev->ap_ctx)
822 			mlo_ap_ctx_deinit(ml_dev);
823 
824 		mlo_dev_mlpeer_list_deinit(ml_dev);
825 		qdf_list_remove_node(&g_mlo_ctx->ml_dev_list,
826 				     &ml_dev->node);
827 		if (wlan_vdev_mlme_get_opmode(vdev) == QDF_STA_MODE) {
828 			connect_req = ml_dev->sta_ctx->connect_req;
829 			if (connect_req) {
830 				if (connect_req->scan_ie.ptr) {
831 					qdf_mem_free(connect_req->scan_ie.ptr);
832 					connect_req->scan_ie.ptr = NULL;
833 				}
834 
835 				if (connect_req->assoc_ie.ptr) {
836 					qdf_mem_free(connect_req->assoc_ie.ptr);
837 					connect_req->assoc_ie.ptr = NULL;
838 				}
839 				qdf_mem_free(ml_dev->sta_ctx->connect_req);
840 			}
841 
842 			if (ml_dev->sta_ctx->disconn_req)
843 				qdf_mem_free(ml_dev->sta_ctx->disconn_req);
844 
845 			if (ml_dev->sta_ctx->assoc_rsp.ptr)
846 				qdf_mem_free(ml_dev->sta_ctx->assoc_rsp.ptr);
847 
848 			copied_conn_req_lock_destroy(ml_dev->sta_ctx);
849 
850 			qdf_mem_free(ml_dev->sta_ctx);
851 		}
852 		else if (wlan_vdev_mlme_get_opmode(vdev) == QDF_SAP_MODE)
853 			qdf_mem_free(ml_dev->ap_ctx);
854 
855 		mlo_t2lm_ctx_deinit(vdev);
856 		tsf_recalculation_lock_destroy(ml_dev);
857 		mlo_dev_lock_destroy(ml_dev);
858 		qdf_mem_free(ml_dev);
859 	}
860 	ml_link_lock_release(g_mlo_ctx);
861 	return status;
862 }
863 
864 QDF_STATUS wlan_mlo_mgr_vdev_created_notification(struct wlan_objmgr_vdev *vdev,
865 						  void *arg_list)
866 {
867 	QDF_STATUS status = QDF_STATUS_SUCCESS;
868 	struct qdf_mac_addr *mld_addr;
869 
870 	mld_addr = (struct qdf_mac_addr *)wlan_vdev_mlme_get_mldaddr(vdev);
871 	if (qdf_is_macaddr_zero(mld_addr)) {
872 		/* It's not a ML interface*/
873 		return QDF_STATUS_SUCCESS;
874 	}
875 	mlo_debug("MLD addr" QDF_MAC_ADDR_FMT,
876 		  QDF_MAC_ADDR_REF(mld_addr->bytes));
877 	status = mlo_dev_ctx_init(vdev);
878 
879 	wlan_vdev_set_link_id(vdev, WLAN_LINK_ID_INVALID);
880 
881 	return status;
882 }
883 
884 QDF_STATUS wlan_mlo_mgr_vdev_destroyed_notification(struct wlan_objmgr_vdev *vdev,
885 						    void *arg_list)
886 {
887 	QDF_STATUS status = QDF_STATUS_SUCCESS;
888 	struct qdf_mac_addr *mld_addr;
889 
890 	mld_addr = (struct qdf_mac_addr *)wlan_vdev_mlme_get_mldaddr(vdev);
891 	if (qdf_is_macaddr_zero(mld_addr)) {
892 		/* It's not a ML interface*/
893 		return QDF_STATUS_SUCCESS;
894 	}
895 	mlo_debug("MLD addr" QDF_MAC_ADDR_FMT,
896 		  QDF_MAC_ADDR_REF(mld_addr->bytes));
897 
898 	status = mlo_dev_ctx_deinit(vdev);
899 
900 	return status;
901 }
902 
903 QDF_STATUS wlan_mlo_mgr_update_mld_addr(struct qdf_mac_addr *old_mac,
904 					struct qdf_mac_addr *new_mac)
905 {
906 	struct wlan_mlo_dev_context *ml_dev;
907 
908 	ml_dev = wlan_mlo_get_mld_ctx_by_mldaddr(old_mac);
909 	if (!ml_dev) {
910 		mlo_err("ML dev context not found for MLD:" QDF_MAC_ADDR_FMT,
911 			QDF_MAC_ADDR_REF(old_mac->bytes));
912 		return QDF_STATUS_E_INVAL;
913 	}
914 	mlo_dev_lock_acquire(ml_dev);
915 	qdf_copy_macaddr(&ml_dev->mld_addr, new_mac);
916 	mlo_dev_lock_release(ml_dev);
917 
918 	return QDF_STATUS_SUCCESS;
919 }
920