xref: /wlan-dirver/qca-wifi-host-cmn/umac/mlo_mgr/src/wlan_mlo_mgr_peer.c (revision c94e9f1b4dba1e1866da3000c3b5c6f159493f07)
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 #include "wlan_mlo_mgr_main.h"
19 #include "qdf_module.h"
20 #include "qdf_types.h"
21 #include "wlan_cmn.h"
22 #include "wlan_mlo_mgr_msgq.h"
23 #include "wlan_objmgr_peer_obj.h"
24 #include "wlan_mlo_mgr_peer.h"
25 #include "wlan_mlo_mgr_ap.h"
26 #include "wlan_crypto_global_api.h"
27 #include "wlan_mlo_mgr_setup.h"
28 #include "wlan_utility.h"
29 #include "wlan_mlo_epcs.h"
30 
31 static void mlo_partner_peer_create_post(struct wlan_mlo_dev_context *ml_dev,
32 					 struct wlan_objmgr_vdev *vdev_link,
33 					 struct wlan_mlo_peer_context *ml_peer,
34 					 qdf_nbuf_t frm_buf,
35 					 struct mlo_partner_info *ml_info)
36 {
37 	struct peer_create_notif_s peer_create;
38 	QDF_STATUS status;
39 	uint8_t i;
40 	uint8_t link_id;
41 
42 	if (wlan_objmgr_vdev_try_get_ref(vdev_link, WLAN_MLO_MGR_ID) ==
43 							QDF_STATUS_SUCCESS) {
44 		peer_create.vdev_link = vdev_link;
45 	} else {
46 		mlo_err("VDEV is not in created state");
47 		return;
48 	}
49 
50 	wlan_mlo_peer_get_ref(ml_peer);
51 	peer_create.ml_peer = ml_peer;
52 	link_id = wlan_vdev_get_link_id(vdev_link);
53 	for (i = 0; i < ml_info->num_partner_links; i++) {
54 		if (link_id != ml_info->partner_link_info[i].link_id)
55 			continue;
56 
57 		qdf_copy_macaddr(&peer_create.addr,
58 				 &ml_info->partner_link_info[i].link_addr);
59 		break;
60 	}
61 
62 	status = mlo_peer_create_get_frm_buf(ml_peer, &peer_create, frm_buf);
63 
64 	if (QDF_IS_STATUS_ERROR(status)) {
65 		wlan_mlo_peer_release_ref(ml_peer);
66 		wlan_objmgr_vdev_release_ref(vdev_link, WLAN_MLO_MGR_ID);
67 		mlo_err("nbuf clone is failed");
68 		return;
69 	}
70 
71 	status = mlo_msgq_post(MLO_PEER_CREATE, ml_dev, &peer_create);
72 	if (status != QDF_STATUS_SUCCESS) {
73 		qdf_nbuf_free(frm_buf);
74 		wlan_mlo_peer_release_ref(ml_peer);
75 		wlan_objmgr_vdev_release_ref(vdev_link, WLAN_MLO_MGR_ID);
76 	}
77 }
78 
79 static void mlo_partner_peer_reassoc_post(struct wlan_mlo_dev_context *ml_dev,
80 					  struct wlan_objmgr_vdev *vdev_link,
81 					  struct wlan_mlo_peer_context *ml_peer,
82 					  qdf_nbuf_t frm_buf,
83 					  struct mlo_partner_info *ml_info)
84 {
85 	struct peer_create_notif_s peer_create;
86 	QDF_STATUS status;
87 	uint8_t i;
88 	uint8_t link_id;
89 
90 	if (wlan_objmgr_vdev_try_get_ref(vdev_link, WLAN_MLO_MGR_ID) ==
91 							QDF_STATUS_SUCCESS) {
92 		peer_create.vdev_link = vdev_link;
93 	} else {
94 		mlo_err("VDEV is not in created state");
95 		return;
96 	}
97 
98 	wlan_mlo_peer_get_ref(ml_peer);
99 	peer_create.ml_peer = ml_peer;
100 	link_id = wlan_vdev_get_link_id(vdev_link);
101 	for (i = 0; i < ml_info->num_partner_links; i++) {
102 		if (link_id != ml_info->partner_link_info[i].link_id)
103 			continue;
104 
105 		qdf_copy_macaddr(&peer_create.addr,
106 				 &ml_info->partner_link_info[i].link_addr);
107 		break;
108 	}
109 
110 	status = mlo_peer_create_get_frm_buf(ml_peer, &peer_create, frm_buf);
111 
112 	if (QDF_IS_STATUS_ERROR(status)) {
113 		wlan_mlo_peer_release_ref(ml_peer);
114 		wlan_objmgr_vdev_release_ref(vdev_link, WLAN_MLO_MGR_ID);
115 		mlo_err("nbuf clone is failed");
116 		return;
117 	}
118 
119 	status = mlo_msgq_post(MLO_PEER_REASSOC, ml_dev, &peer_create);
120 	if (status != QDF_STATUS_SUCCESS) {
121 		qdf_nbuf_free(frm_buf);
122 		wlan_mlo_peer_release_ref(ml_peer);
123 		wlan_objmgr_vdev_release_ref(vdev_link, WLAN_MLO_MGR_ID);
124 	}
125 }
126 
127 static void mlo_link_peer_assoc_notify(struct wlan_mlo_dev_context *ml_dev,
128 				       struct wlan_objmgr_peer *peer)
129 {
130 	struct peer_assoc_notify_s peer_assoc;
131 	QDF_STATUS status;
132 
133 	peer_assoc.peer = peer;
134 	status = mlo_msgq_post(MLO_PEER_ASSOC, ml_dev, &peer_assoc);
135 	if (status != QDF_STATUS_SUCCESS)
136 		wlan_objmgr_peer_release_ref(peer, WLAN_MLO_MGR_ID);
137 }
138 
139 static void mlo_link_peer_send_assoc_fail(struct wlan_mlo_dev_context *ml_dev,
140 					  struct wlan_objmgr_peer *peer)
141 {
142 	struct peer_assoc_fail_notify_s peer_assoc_fail;
143 	QDF_STATUS status;
144 
145 	peer_assoc_fail.peer = peer;
146 	status = mlo_msgq_post(MLO_PEER_ASSOC_FAIL, ml_dev, &peer_assoc_fail);
147 	if (status != QDF_STATUS_SUCCESS)
148 		wlan_objmgr_peer_release_ref(peer, WLAN_MLO_MGR_ID);
149 }
150 
151 static void mlo_link_peer_disconnect_notify(struct wlan_mlo_dev_context *ml_dev,
152 					    struct wlan_objmgr_peer *peer)
153 {
154 	struct peer_discon_notify_s peer_disconn;
155 	QDF_STATUS status;
156 	struct wlan_objmgr_vdev *vdev;
157 	enum QDF_OPMODE opmode;
158 
159 	vdev = wlan_peer_get_vdev(peer);
160 	opmode = wlan_vdev_mlme_get_opmode(vdev);
161 
162 	if (opmode == QDF_SAP_MODE) {
163 		peer_disconn.peer = peer;
164 		status = mlo_msgq_post(MLO_PEER_DISCONNECT, ml_dev,
165 				       &peer_disconn);
166 		if (status != QDF_STATUS_SUCCESS)
167 			wlan_objmgr_peer_release_ref(peer, WLAN_MLO_MGR_ID);
168 	} else {
169 		wlan_objmgr_peer_release_ref(peer, WLAN_MLO_MGR_ID);
170 	}
171 }
172 
173 static void mlo_link_peer_deauth_init(struct wlan_mlo_dev_context *ml_dev,
174 				      struct wlan_objmgr_peer *peer,
175 				      uint8_t is_disassoc)
176 {
177 	struct peer_deauth_notify_s peer_deauth;
178 	QDF_STATUS status;
179 
180 	peer_deauth.peer = peer;
181 	peer_deauth.is_disassoc = is_disassoc;
182 	status = mlo_msgq_post(MLO_PEER_DEAUTH, ml_dev, &peer_deauth);
183 	if (status != QDF_STATUS_SUCCESS)
184 		wlan_objmgr_peer_release_ref(peer, WLAN_MLO_MGR_ID);
185 }
186 
187 #ifdef UMAC_MLO_AUTH_DEFER
188 static void mlo_peer_process_pending_auth(struct wlan_mlo_dev_context *ml_dev,
189 					  struct wlan_mlo_peer_context *ml_peer)
190 {
191 	struct peer_auth_process_notif_s peer_auth;
192 	struct mlpeer_auth_params *recv_auth;
193 	uint8_t i;
194 	QDF_STATUS status;
195 
196 	for (i = 0; i < MAX_MLO_LINK_PEERS; i++) {
197 		mlo_peer_lock_acquire(ml_peer);
198 		recv_auth = ml_peer->pending_auth[i];
199 		if (!recv_auth) {
200 			mlo_peer_lock_release(ml_peer);
201 			continue;
202 		}
203 		peer_auth.auth_params = recv_auth;
204 		ml_peer->pending_auth[i] = NULL;
205 
206 		mlo_peer_lock_release(ml_peer);
207 
208 		status = mlo_msgq_post(MLO_PEER_PENDING_AUTH, ml_dev,
209 				       &peer_auth);
210 		if (QDF_IS_STATUS_ERROR(status))
211 			mlo_peer_free_auth_param(peer_auth.auth_params);
212 	}
213 }
214 #else
215 static void mlo_peer_process_pending_auth(struct wlan_mlo_dev_context *ml_dev,
216 					  struct wlan_mlo_peer_context *ml_peer)
217 {
218 }
219 #endif
220 
221 QDF_STATUS
222 wlan_mlo_peer_is_disconnect_progress(struct wlan_mlo_peer_context *ml_peer)
223 {
224 	QDF_STATUS status;
225 
226 	if (!ml_peer)
227 		return QDF_STATUS_E_FAILURE;
228 
229 	mlo_peer_lock_acquire(ml_peer);
230 
231 	if (ml_peer->mlpeer_state == ML_PEER_DISCONN_INITIATED)
232 		status = QDF_STATUS_SUCCESS;
233 	else
234 		status = QDF_STATUS_E_FAILURE;
235 
236 	mlo_peer_lock_release(ml_peer);
237 
238 	return status;
239 }
240 
241 QDF_STATUS wlan_mlo_peer_is_assoc_done(struct wlan_mlo_peer_context *ml_peer)
242 {
243 	QDF_STATUS status;
244 
245 	if (!ml_peer)
246 		return QDF_STATUS_E_FAILURE;
247 
248 	mlo_peer_lock_acquire(ml_peer);
249 
250 	if (ml_peer->mlpeer_state == ML_PEER_ASSOC_DONE)
251 		status = QDF_STATUS_SUCCESS;
252 	else
253 		status = QDF_STATUS_E_FAILURE;
254 
255 	mlo_peer_lock_release(ml_peer);
256 
257 	return status;
258 }
259 
260 qdf_export_symbol(wlan_mlo_peer_is_assoc_done);
261 
262 struct wlan_objmgr_peer *wlan_mlo_peer_get_assoc_peer(
263 					struct wlan_mlo_peer_context *ml_peer)
264 {
265 	struct wlan_mlo_link_peer_entry *peer_entry;
266 	struct wlan_objmgr_peer *assoc_peer = NULL;
267 
268 	if (!ml_peer)
269 		return NULL;
270 
271 	mlo_peer_lock_acquire(ml_peer);
272 
273 	peer_entry = &ml_peer->peer_list[0];
274 
275 	if (peer_entry->link_peer)
276 		assoc_peer = peer_entry->link_peer;
277 
278 	mlo_peer_lock_release(ml_peer);
279 
280 	return assoc_peer;
281 }
282 
283 qdf_export_symbol(wlan_mlo_peer_get_assoc_peer);
284 
285 struct wlan_objmgr_peer *wlan_mlo_peer_get_bridge_peer(
286 					struct wlan_mlo_peer_context *ml_peer)
287 {
288 	struct wlan_mlo_link_peer_entry *peer_entry = NULL;
289 	struct wlan_objmgr_peer *bridge_peer = NULL;
290 	struct wlan_objmgr_peer *link_peer = NULL;
291 	int i = 0;
292 
293 	if (!ml_peer)
294 		return NULL;
295 
296 	mlo_peer_lock_acquire(ml_peer);
297 
298 	for (i = 0; i < MAX_MLO_LINK_PEERS; i++) {
299 		peer_entry = &ml_peer->peer_list[i];
300 		if (!peer_entry)
301 			continue;
302 
303 		link_peer = peer_entry->link_peer;
304 		if (!link_peer)
305 			continue;
306 
307 		if (wlan_peer_get_peer_type(link_peer) ==
308 		    WLAN_PEER_MLO_BRIDGE) {
309 			if (peer_entry->is_primary)
310 				bridge_peer = link_peer;
311 			else
312 				mlo_err("Bridge peer is not primary");
313 
314 			break;
315 		}
316 	}
317 	mlo_peer_lock_release(ml_peer);
318 
319 	return bridge_peer;
320 }
321 
322 qdf_export_symbol(wlan_mlo_peer_get_bridge_peer);
323 
324 struct wlan_objmgr_vdev *
325 wlan_mlo_peer_get_primary_link_vdev(struct wlan_mlo_peer_context *ml_peer)
326 {
327 	struct wlan_mlo_link_peer_entry *peer_entry = NULL;
328 	struct wlan_objmgr_peer *link_peer;
329 	struct wlan_objmgr_vdev *link_vdev;
330 	uint8_t i;
331 
332 	if (!ml_peer) {
333 		mlo_err("ml_peer is null");
334 		return NULL;
335 	}
336 	mlo_peer_lock_acquire(ml_peer);
337 
338 	if ((ml_peer->mlpeer_state != ML_PEER_CREATED) &&
339 	    (ml_peer->mlpeer_state != ML_PEER_ASSOC_DONE)) {
340 		mlo_peer_lock_release(ml_peer);
341 		mlo_err("ml_peer is not created and association is not done");
342 		return NULL;
343 	}
344 
345 	for (i = 0; i < MAX_MLO_LINK_PEERS; i++) {
346 		peer_entry = &ml_peer->peer_list[i];
347 		link_peer = peer_entry->link_peer;
348 		if (!link_peer)
349 			continue;
350 
351 		if (peer_entry->is_primary) {
352 			link_vdev = wlan_peer_get_vdev(link_peer);
353 			if (!link_vdev) {
354 				mlo_peer_lock_release(ml_peer);
355 				mlo_err("link vdev not found");
356 				return NULL;
357 			}
358 			if (wlan_objmgr_vdev_try_get_ref(link_vdev, WLAN_MLO_MGR_ID) !=
359 					QDF_STATUS_SUCCESS) {
360 				mlo_peer_lock_release(ml_peer);
361 				mlo_err("taking ref failed");
362 				return NULL;
363 			}
364 			mlo_peer_lock_release(ml_peer);
365 			return link_vdev;
366 		}
367 	}
368 	mlo_peer_lock_release(ml_peer);
369 	mlo_err("None of the peer is designated as primary");
370 
371 	return NULL;
372 }
373 
374 bool mlo_peer_is_assoc_peer(struct wlan_mlo_peer_context *ml_peer,
375 			    struct wlan_objmgr_peer *peer)
376 {
377 	struct wlan_mlo_link_peer_entry *peer_entry;
378 	bool is_assoc_peer = false;
379 
380 	if (!ml_peer || !peer)
381 		return is_assoc_peer;
382 
383 	peer_entry = &ml_peer->peer_list[0];
384 
385 	if (peer_entry->link_peer == peer)
386 		is_assoc_peer = true;
387 
388 	return is_assoc_peer;
389 }
390 
391 bool wlan_mlo_peer_is_assoc_peer(struct wlan_mlo_peer_context *ml_peer,
392 				 struct wlan_objmgr_peer *peer)
393 {
394 	bool is_assoc_peer = false;
395 
396 	if (!ml_peer || !peer)
397 		return is_assoc_peer;
398 
399 	mlo_peer_lock_acquire(ml_peer);
400 
401 	is_assoc_peer = mlo_peer_is_assoc_peer(ml_peer, peer);
402 
403 	mlo_peer_lock_release(ml_peer);
404 
405 	return is_assoc_peer;
406 }
407 
408 bool wlan_mlo_peer_is_link_peer(struct wlan_mlo_peer_context *ml_peer,
409 				struct wlan_objmgr_peer *peer)
410 {
411 	struct wlan_mlo_link_peer_entry *peer_entry;
412 	bool is_link_peer = false;
413 	uint16_t i;
414 
415 	if (!ml_peer || !peer)
416 		return is_link_peer;
417 
418 	mlo_peer_lock_acquire(ml_peer);
419 
420 	for (i = 0; i < MAX_MLO_LINK_PEERS; i++) {
421 		peer_entry = &ml_peer->peer_list[i];
422 		if (!peer_entry->link_peer)
423 			continue;
424 
425 		if (peer == peer_entry->link_peer) {
426 			is_link_peer = true;
427 			break;
428 		}
429 	}
430 
431 	mlo_peer_lock_release(ml_peer);
432 
433 	return is_link_peer;
434 }
435 
436 void wlan_mlo_partner_peer_assoc_post(struct wlan_objmgr_peer *assoc_peer)
437 {
438 	struct wlan_mlo_dev_context *ml_dev;
439 	struct wlan_mlo_peer_context *ml_peer;
440 	struct wlan_objmgr_peer *link_peer;
441 	struct wlan_objmgr_peer *link_peers[MAX_MLO_LINK_PEERS];
442 	struct wlan_mlo_link_peer_entry *peer_entry;
443 	uint16_t i;
444 
445 	ml_peer = assoc_peer->mlo_peer_ctx;
446 	if (!ml_peer)
447 		return;
448 
449 	mlo_peer_lock_acquire(ml_peer);
450 
451 	if (ml_peer->mlpeer_state != ML_PEER_CREATED) {
452 		mlo_peer_lock_release(ml_peer);
453 		return;
454 	}
455 
456 	ml_peer->mlpeer_state = ML_PEER_ASSOC_DONE;
457 	ml_dev = ml_peer->ml_dev;
458 
459 	for (i = 0; i < MAX_MLO_LINK_PEERS; i++) {
460 		link_peers[i] = NULL;
461 		peer_entry = &ml_peer->peer_list[i];
462 
463 		if (!peer_entry->link_peer)
464 			continue;
465 
466 		if (peer_entry->link_peer == assoc_peer)
467 			continue;
468 
469 		link_peer = peer_entry->link_peer;
470 
471 		if (wlan_objmgr_peer_try_get_ref(link_peer, WLAN_MLO_MGR_ID) !=
472 						 QDF_STATUS_SUCCESS)
473 			continue;
474 
475 		link_peers[i] = link_peer;
476 	}
477 	wlan_mlo_peer_wsi_link_add(ml_peer);
478 	mlo_peer_lock_release(ml_peer);
479 
480 	for (i = 0; i < MAX_MLO_LINK_PEERS; i++) {
481 		if (!link_peers[i])
482 			continue;
483 
484 		/* Prepare and queue message */
485 		mlo_link_peer_assoc_notify(ml_dev, link_peers[i]);
486 	}
487 }
488 
489 void wlan_mlo_link_peer_assoc_set(struct wlan_objmgr_peer *peer, bool is_sent)
490 {
491 	struct wlan_mlo_peer_context *ml_peer;
492 	struct wlan_mlo_link_peer_entry *peer_entry;
493 	uint16_t i;
494 
495 	ml_peer = peer->mlo_peer_ctx;
496 	if (!ml_peer)
497 		return;
498 
499 	mlo_peer_lock_acquire(ml_peer);
500 
501 	for (i = 0; i < MAX_MLO_LINK_PEERS; i++) {
502 		peer_entry = &ml_peer->peer_list[i];
503 
504 		if (!peer_entry->link_peer)
505 			continue;
506 
507 		if (peer_entry->link_peer == peer) {
508 			peer_entry->peer_assoc_sent = is_sent;
509 			break;
510 		}
511 	}
512 	mlo_peer_lock_release(ml_peer);
513 }
514 
515 qdf_export_symbol(wlan_mlo_link_peer_assoc_set);
516 
517 void wlan_mlo_peer_get_del_hw_bitmap(struct wlan_objmgr_peer *peer,
518 				     uint32_t *hw_link_id_bitmap)
519 {
520 	struct wlan_mlo_peer_context *ml_peer;
521 	struct wlan_mlo_link_peer_entry *peer_entry;
522 	uint16_t i;
523 
524 	ml_peer = peer->mlo_peer_ctx;
525 	if (!ml_peer)
526 		return;
527 
528 	mlo_peer_lock_acquire(ml_peer);
529 
530 	for (i = 0; i < MAX_MLO_LINK_PEERS; i++) {
531 		peer_entry = &ml_peer->peer_list[i];
532 
533 		if (!peer_entry->link_peer)
534 			continue;
535 
536 		if (peer_entry->link_peer == peer) {
537 			/* Peer assoc is not sent, no need to send bitmap */
538 			if (!peer_entry->peer_assoc_sent)
539 				break;
540 
541 			continue;
542 		}
543 		if (!peer_entry->peer_assoc_sent)
544 			*hw_link_id_bitmap |= 1 << peer_entry->hw_link_id;
545 	}
546 	mlo_peer_lock_release(ml_peer);
547 }
548 
549 qdf_export_symbol(wlan_mlo_peer_get_del_hw_bitmap);
550 
551 void
552 wlan_mlo_peer_deauth_init(struct wlan_mlo_peer_context *ml_peer,
553 			  struct wlan_objmgr_peer *src_peer,
554 			  uint8_t is_disassoc)
555 {
556 	struct wlan_mlo_dev_context *ml_dev;
557 	struct wlan_objmgr_peer *link_peer;
558 	struct wlan_objmgr_peer *link_peers[MAX_MLO_LINK_PEERS];
559 	struct wlan_mlo_link_peer_entry *peer_entry;
560 	uint16_t i;
561 	uint8_t deauth_sent = 0;
562 
563 	if (!ml_peer)
564 		return;
565 
566 	mlo_peer_lock_acquire(ml_peer);
567 
568 	if (ml_peer->mlpeer_state == ML_PEER_DISCONN_INITIATED) {
569 		mlo_peer_lock_release(ml_peer);
570 		return;
571 	}
572 
573 	ml_dev = ml_peer->ml_dev;
574 
575 	for (i = 0; i < MAX_MLO_LINK_PEERS; i++) {
576 		link_peers[i] = NULL;
577 		peer_entry = &ml_peer->peer_list[i];
578 		if (!peer_entry->link_peer)
579 			continue;
580 
581 		link_peer = peer_entry->link_peer;
582 
583 		if (wlan_objmgr_peer_try_get_ref(link_peer, WLAN_MLO_MGR_ID) !=
584 						QDF_STATUS_SUCCESS)
585 			continue;
586 
587 		link_peers[i] = link_peer;
588 	}
589 
590 	ml_peer->mlpeer_state = ML_PEER_DISCONN_INITIATED;
591 
592 	mlo_peer_lock_release(ml_peer);
593 
594 	for (i = 0; i < MAX_MLO_LINK_PEERS; i++) {
595 		if (!link_peers[i])
596 			continue;
597 
598 		/* Prepare and queue message */
599 		/* skip sending deauth on src peer */
600 		if ((deauth_sent) ||
601 		    (src_peer && (src_peer == link_peers[i]))) {
602 			mlo_link_peer_disconnect_notify(ml_dev, link_peers[i]);
603 		} else {
604 			mlo_link_peer_deauth_init(ml_dev, link_peers[i],
605 						  is_disassoc);
606 			deauth_sent = 1;
607 		}
608 	}
609 }
610 
611 qdf_export_symbol(wlan_mlo_peer_deauth_init);
612 
613 void wlan_mlo_peer_delete(struct wlan_mlo_peer_context *ml_peer)
614 {
615 	struct wlan_mlo_dev_context *ml_dev;
616 	struct wlan_objmgr_peer *link_peer;
617 	struct wlan_objmgr_peer *link_peers[MAX_MLO_LINK_PEERS];
618 	struct wlan_mlo_link_peer_entry *peer_entry;
619 	uint16_t i;
620 
621 	if (!ml_peer)
622 		return;
623 
624 	mlo_peer_lock_acquire(ml_peer);
625 
626 	if (ml_peer->mlpeer_state == ML_PEER_DISCONN_INITIATED) {
627 		mlo_peer_lock_release(ml_peer);
628 		return;
629 	}
630 
631 	ml_dev = ml_peer->ml_dev;
632 
633 	for (i = 0; i < MAX_MLO_LINK_PEERS; i++) {
634 		link_peers[i] = NULL;
635 		peer_entry = &ml_peer->peer_list[i];
636 		if (!peer_entry->link_peer)
637 			continue;
638 
639 		link_peer = peer_entry->link_peer;
640 
641 		if (wlan_objmgr_peer_try_get_ref(link_peer, WLAN_MLO_MGR_ID) !=
642 						QDF_STATUS_SUCCESS)
643 			continue;
644 
645 		link_peers[i] = link_peer;
646 	}
647 
648 	ml_peer->mlpeer_state = ML_PEER_DISCONN_INITIATED;
649 
650 	mlo_peer_lock_release(ml_peer);
651 
652 	for (i = 0; i < MAX_MLO_LINK_PEERS; i++) {
653 		if (!link_peers[i])
654 			continue;
655 
656 		mlo_link_peer_disconnect_notify(ml_dev, link_peers[i]);
657 	}
658 }
659 
660 void
661 wlan_mlo_partner_peer_create_failed_notify(
662 				struct wlan_mlo_peer_context *ml_peer)
663 {
664 	struct wlan_mlo_dev_context *ml_dev;
665 	struct wlan_objmgr_peer *link_peer;
666 	struct wlan_objmgr_peer *link_peers[MAX_MLO_LINK_PEERS];
667 	struct wlan_mlo_link_peer_entry *peer_entry;
668 	uint16_t i;
669 
670 	if (!ml_peer)
671 		return;
672 
673 	mlo_peer_lock_acquire(ml_peer);
674 
675 	if (ml_peer->mlpeer_state == ML_PEER_DISCONN_INITIATED) {
676 		mlo_peer_lock_release(ml_peer);
677 		return;
678 	}
679 
680 	ml_peer->mlpeer_state = ML_PEER_DISCONN_INITIATED;
681 	ml_dev = ml_peer->ml_dev;
682 
683 	for (i = 0; i < MAX_MLO_LINK_PEERS; i++) {
684 		link_peers[i] = NULL;
685 		peer_entry = &ml_peer->peer_list[i];
686 		if (!peer_entry->link_peer)
687 			continue;
688 
689 		link_peer = peer_entry->link_peer;
690 		if (wlan_objmgr_peer_try_get_ref(link_peer, WLAN_MLO_MGR_ID) !=
691 						QDF_STATUS_SUCCESS)
692 			continue;
693 
694 		link_peers[i] = link_peer;
695 	}
696 	mlo_peer_lock_release(ml_peer);
697 
698 	for (i = 0; i < MAX_MLO_LINK_PEERS; i++) {
699 		if (!link_peers[i])
700 			continue;
701 
702 		/* Prepare and queue message */
703 		if (i == 0)
704 			mlo_link_peer_send_assoc_fail(ml_dev, link_peers[i]);
705 		else
706 			mlo_link_peer_disconnect_notify(ml_dev, link_peers[i]);
707 	}
708 }
709 
710 void wlan_mlo_partner_peer_disconnect_notify(struct wlan_objmgr_peer *src_peer)
711 {
712 	struct wlan_mlo_dev_context *ml_dev;
713 	struct wlan_mlo_peer_context *ml_peer;
714 	struct wlan_objmgr_peer *link_peer;
715 	struct wlan_objmgr_peer *link_peers[MAX_MLO_LINK_PEERS];
716 	struct wlan_mlo_link_peer_entry *peer_entry;
717 	struct wlan_objmgr_vdev *vdev = NULL;
718 	uint16_t i;
719 
720 	ml_peer = src_peer->mlo_peer_ctx;
721 	if (!ml_peer)
722 		return;
723 
724 	vdev = wlan_peer_get_vdev(src_peer);
725 	if (!vdev)
726 		return;
727 
728 	/* Do not change peer state to disconnect initiated for
729 	 * link switch case, this can lead to not sending deauth frame
730 	 * incase of actual disconnect and AP might drop the next connect
731 	 * request as it might think STA is still in connected state.
732 	 */
733 	if (wlan_vdev_mlme_is_mlo_link_switch_in_progress(vdev))
734 		return;
735 
736 	mlo_peer_lock_acquire(ml_peer);
737 
738 	if (ml_peer->mlpeer_state == ML_PEER_DISCONN_INITIATED) {
739 		mlo_peer_lock_release(ml_peer);
740 		return;
741 	}
742 
743 	wlan_mlo_peer_wsi_link_delete(ml_peer);
744 
745 	ml_peer->mlpeer_state = ML_PEER_DISCONN_INITIATED;
746 
747 	if (wlan_vdev_mlme_get_opmode(vdev) == QDF_STA_MODE) {
748 		mlo_peer_lock_release(ml_peer);
749 		return;
750 	}
751 
752 	ml_dev = ml_peer->ml_dev;
753 	for (i = 0; i < MAX_MLO_LINK_PEERS; i++) {
754 		link_peers[i] = NULL;
755 		peer_entry = &ml_peer->peer_list[i];
756 		if (!peer_entry->link_peer) {
757 			mlo_debug("link peer is null");
758 			continue;
759 		}
760 
761 		if (peer_entry->link_peer == src_peer)
762 			continue;
763 
764 		link_peer = peer_entry->link_peer;
765 		if (wlan_objmgr_peer_try_get_ref(link_peer, WLAN_MLO_MGR_ID) !=
766 						QDF_STATUS_SUCCESS)
767 			continue;
768 
769 		link_peers[i] = link_peer;
770 	}
771 	mlo_peer_lock_release(ml_peer);
772 
773 	for (i = 0; i < MAX_MLO_LINK_PEERS; i++) {
774 		if (!link_peers[i])
775 			continue;
776 
777 		/* Prepare and queue message */
778 		mlo_link_peer_disconnect_notify(ml_dev, link_peers[i]);
779 	}
780 }
781 
782 qdf_export_symbol(wlan_mlo_partner_peer_disconnect_notify);
783 
784 static void mlo_peer_populate_link_peer(
785 			struct wlan_mlo_peer_context *ml_peer,
786 			struct wlan_objmgr_peer *link_peer)
787 {
788 	mlo_peer_lock_acquire(ml_peer);
789 	wlan_mlo_peer_get_ref(ml_peer);
790 	link_peer->mlo_peer_ctx = ml_peer;
791 	mlo_peer_lock_release(ml_peer);
792 }
793 
794 static void mlo_reset_link_peer(
795 			struct wlan_mlo_peer_context *ml_peer,
796 			struct wlan_objmgr_peer *link_peer)
797 {
798 	mlo_peer_lock_acquire(ml_peer);
799 	link_peer->mlo_peer_ctx = NULL;
800 	wlan_peer_clear_mlo(link_peer);
801 	mlo_peer_lock_release(ml_peer);
802 }
803 
804 static void mlo_peer_free(struct wlan_mlo_peer_context *ml_peer)
805 {
806 	struct wlan_mlo_dev_context *ml_dev;
807 
808 	ml_dev = ml_peer->ml_dev;
809 	if (!ml_dev) {
810 		mlo_err("ML DEV is NULL");
811 		return;
812 	}
813 
814 	mlo_debug("ML Peer " QDF_MAC_ADDR_FMT " is freed",
815 		  QDF_MAC_ADDR_REF(ml_peer->peer_mld_addr.bytes));
816 	mlo_peer_lock_destroy(ml_peer);
817 	epcs_dev_peer_lock_destroy(&ml_peer->epcs_info);
818 	mlo_ap_ml_ptqm_peerid_free(ml_dev, ml_peer->mlo_peer_id);
819 	mlo_ap_ml_peerid_free(ml_peer->mlo_peer_id);
820 	mlo_peer_free_aid(ml_dev, ml_peer);
821 	mlo_peer_free_primary_umac(ml_dev, ml_peer);
822 	qdf_mem_free(ml_peer);
823 }
824 
825 void mlo_peer_cleanup(struct wlan_mlo_peer_context *ml_peer)
826 {
827 	struct wlan_mlo_dev_context *ml_dev;
828 
829 	if (!ml_peer) {
830 		mlo_err("ML PEER is NULL");
831 		return;
832 	}
833 	ml_dev = ml_peer->ml_dev;
834 	if (!ml_dev) {
835 		mlo_err("ML DEV is NULL");
836 		return;
837 	}
838 
839 	mlo_dev_mlpeer_detach(ml_dev, ml_peer);
840 	/* If any Auth req is received during ML peer delete */
841 	mlo_peer_process_pending_auth(ml_dev, ml_peer);
842 	mlo_peer_free(ml_peer);
843 }
844 
845 static QDF_STATUS mlo_peer_attach_link_peer(
846 		struct wlan_mlo_peer_context *ml_peer,
847 		struct wlan_objmgr_peer *link_peer,
848 		qdf_nbuf_t frm_buf)
849 {
850 	struct wlan_mlo_link_peer_entry *peer_entry;
851 	QDF_STATUS status = QDF_STATUS_E_RESOURCES;
852 	struct wlan_objmgr_pdev *pdev;
853 	struct wlan_objmgr_vdev *vdev;
854 	uint16_t i;
855 
856 	if (!link_peer)
857 		return QDF_STATUS_E_FAILURE;
858 
859 	vdev = wlan_peer_get_vdev(link_peer);
860 	if (!vdev)
861 		return QDF_STATUS_E_FAILURE;
862 
863 	mlo_peer_lock_acquire(ml_peer);
864 
865 	if (ml_peer->mlpeer_state != ML_PEER_CREATED) {
866 		mlo_peer_lock_release(ml_peer);
867 		mlo_err("ML Peer " QDF_MAC_ADDR_FMT " is not in created state (state %d)",
868 			QDF_MAC_ADDR_REF(ml_peer->peer_mld_addr.bytes),
869 			ml_peer->mlpeer_state);
870 		return status;
871 	}
872 
873 	for (i = 0; i < MAX_MLO_LINK_PEERS; i++) {
874 		peer_entry = &ml_peer->peer_list[i];
875 		if (peer_entry->link_peer)
876 			continue;
877 
878 		if (wlan_objmgr_peer_try_get_ref(link_peer, WLAN_MLO_MGR_ID) !=
879 						QDF_STATUS_SUCCESS) {
880 			mlo_err("ML Peer " QDF_MAC_ADDR_FMT ", link peer " QDF_MAC_ADDR_FMT " is not in valid state",
881 				QDF_MAC_ADDR_REF(ml_peer->peer_mld_addr.bytes),
882 				QDF_MAC_ADDR_REF
883 					(wlan_peer_get_macaddr(link_peer)));
884 			break;
885 		}
886 		peer_entry->link_peer = link_peer;
887 		qdf_atomic_inc(&vdev->vdev_objmgr.wlan_ml_peer_count);
888 		qdf_copy_macaddr(&peer_entry->link_addr,
889 				 (struct qdf_mac_addr *)&link_peer->macaddr[0]);
890 
891 		peer_entry->link_ix = wlan_vdev_get_link_id(vdev);
892 		pdev = wlan_vdev_get_pdev(wlan_peer_get_vdev(link_peer));
893 		peer_entry->hw_link_id = wlan_mlo_get_pdev_hw_link_id(pdev);
894 		mlo_peer_assign_primary_umac(ml_peer, peer_entry);
895 		if (frm_buf)
896 			peer_entry->assoc_rsp_buf = frm_buf;
897 		else
898 			peer_entry->assoc_rsp_buf = NULL;
899 
900 		status = QDF_STATUS_SUCCESS;
901 		break;
902 	}
903 	if (QDF_IS_STATUS_SUCCESS(status))
904 		ml_peer->link_peer_cnt++;
905 
906 	mlo_peer_lock_release(ml_peer);
907 
908 	return status;
909 }
910 
911 qdf_nbuf_t mlo_peer_get_link_peer_assoc_resp_buf(
912 		struct wlan_mlo_peer_context *ml_peer,
913 		uint8_t link_ix)
914 {
915 	struct wlan_mlo_link_peer_entry *peer_entry;
916 	qdf_nbuf_t frm_buf = NULL;
917 	uint8_t i;
918 
919 	if (!ml_peer)
920 		return NULL;
921 
922 	if (link_ix > MAX_MLO_LINK_PEERS)
923 		return NULL;
924 
925 	mlo_peer_lock_acquire(ml_peer);
926 	if ((ml_peer->mlpeer_state != ML_PEER_CREATED) &&
927 	    (ml_peer->mlpeer_state != ML_PEER_ASSOC_DONE)) {
928 		mlo_peer_lock_release(ml_peer);
929 		return NULL;
930 	}
931 
932 	for (i = 0; i < MAX_MLO_LINK_PEERS; i++) {
933 		peer_entry = &ml_peer->peer_list[i];
934 
935 		if (!peer_entry->link_peer)
936 			continue;
937 
938 		if (peer_entry->link_ix == link_ix) {
939 			if (!peer_entry->assoc_rsp_buf)
940 				break;
941 
942 			frm_buf = qdf_nbuf_clone(peer_entry->assoc_rsp_buf);
943 			break;
944 		}
945 	}
946 	mlo_peer_lock_release(ml_peer);
947 
948 	return frm_buf;
949 }
950 
951 void wlan_mlo_peer_free_all_link_assoc_resp_buf(
952 			struct wlan_objmgr_peer *link_peer)
953 {
954 	struct wlan_mlo_link_peer_entry *peer_entry;
955 	struct wlan_mlo_peer_context *ml_peer;
956 	uint8_t i;
957 
958 	ml_peer = link_peer->mlo_peer_ctx;
959 	if (!ml_peer)
960 		return;
961 
962 	mlo_peer_lock_acquire(ml_peer);
963 
964 	for (i = 0; i < MAX_MLO_LINK_PEERS; i++) {
965 		peer_entry = &ml_peer->peer_list[i];
966 
967 		if (peer_entry->assoc_rsp_buf) {
968 			qdf_nbuf_free(peer_entry->assoc_rsp_buf);
969 			peer_entry->assoc_rsp_buf = NULL;
970 		}
971 	}
972 	mlo_peer_lock_release(ml_peer);
973 }
974 
975 static QDF_STATUS mlo_peer_detach_link_peer(
976 		struct wlan_mlo_peer_context *ml_peer,
977 		struct wlan_objmgr_peer *link_peer)
978 {
979 	struct wlan_mlo_link_peer_entry *peer_entry;
980 	QDF_STATUS status = QDF_STATUS_E_RESOURCES;
981 	uint16_t i;
982 	struct wlan_objmgr_vdev *vdev;
983 
984 	mlo_peer_lock_acquire(ml_peer);
985 
986 	for (i = 0; i < MAX_MLO_LINK_PEERS; i++) {
987 		peer_entry = &ml_peer->peer_list[i];
988 		if (!peer_entry->link_peer)
989 			continue;
990 
991 		if (peer_entry->link_peer != link_peer)
992 			continue;
993 
994 		if (peer_entry->assoc_rsp_buf) {
995 			qdf_nbuf_free(peer_entry->assoc_rsp_buf);
996 			peer_entry->assoc_rsp_buf = NULL;
997 		}
998 		vdev =  wlan_peer_get_vdev(link_peer);
999 		if (vdev) {
1000 			qdf_atomic_dec(&vdev->vdev_objmgr.wlan_ml_peer_count);
1001 		} else {
1002 			mlo_err("vdev is null for ml_peer: " QDF_MAC_ADDR_FMT
1003 				"mld mac addr: " QDF_MAC_ADDR_FMT,
1004 				QDF_MAC_ADDR_REF(link_peer->macaddr),
1005 				QDF_MAC_ADDR_REF(link_peer->mldaddr));
1006 			qdf_assert_always(vdev);
1007 		}
1008 		wlan_objmgr_peer_release_ref(link_peer, WLAN_MLO_MGR_ID);
1009 		peer_entry->link_peer = NULL;
1010 		ml_peer->link_peer_cnt--;
1011 		status = QDF_STATUS_SUCCESS;
1012 		break;
1013 	}
1014 	mlo_peer_lock_release(ml_peer);
1015 
1016 	return status;
1017 }
1018 #if defined (SAP_MULTI_LINK_EMULATION)
1019 /*Skip link vdev check. Second link does not have vdev*/
1020 static QDF_STATUS mlo_dev_get_link_vdevs(
1021 			struct wlan_objmgr_vdev *vdev,
1022 			struct wlan_mlo_dev_context *ml_dev,
1023 			struct mlo_partner_info *ml_info,
1024 			struct wlan_objmgr_vdev *link_vdevs[])
1025 {
1026 	return QDF_STATUS_SUCCESS;
1027 }
1028 #else
1029 static QDF_STATUS mlo_dev_get_link_vdevs(
1030 			struct wlan_objmgr_vdev *vdev,
1031 			struct wlan_mlo_dev_context *ml_dev,
1032 			struct mlo_partner_info *ml_info,
1033 			struct wlan_objmgr_vdev *link_vdevs[])
1034 {
1035 	uint16_t i, j;
1036 	struct wlan_objmgr_vdev *vdev_link;
1037 	uint8_t link_id;
1038 
1039 	if (!ml_dev) {
1040 		mlo_err("ml_dev is null");
1041 		return QDF_STATUS_E_INVAL;
1042 	}
1043 
1044 	if (!ml_info) {
1045 		mlo_err("ml_info is null");
1046 		return QDF_STATUS_E_INVAL;
1047 	}
1048 
1049 	mlo_debug("num_partner_links %d", ml_info->num_partner_links);
1050 	for (i = 0; i < ml_info->num_partner_links; i++) {
1051 		link_id = ml_info->partner_link_info[i].link_id;
1052 		vdev_link = mlo_get_vdev_by_link_id(vdev, link_id,
1053 						    WLAN_MLO_MGR_ID);
1054 		if (vdev_link) {
1055 			link_vdevs[i] = vdev_link;
1056 		} else {
1057 			/* release ref which were taken before failure */
1058 			for (j = 0; j < i; j++) {
1059 				vdev_link = link_vdevs[j];
1060 				if (!vdev_link)
1061 					continue;
1062 
1063 				wlan_objmgr_vdev_release_ref(vdev_link,
1064 							     WLAN_MLO_MGR_ID);
1065 			}
1066 			return QDF_STATUS_E_INVAL;
1067 		}
1068 	}
1069 
1070 	return QDF_STATUS_SUCCESS;
1071 }
1072 #endif
1073 
1074 static void mlo_dev_release_link_vdevs(
1075 			struct wlan_objmgr_vdev *link_vdevs[])
1076 {
1077 	uint16_t i;
1078 	struct wlan_objmgr_vdev *vdev_link;
1079 
1080 	for (i = 0; i < WLAN_UMAC_MLO_MAX_VDEVS; i++) {
1081 		vdev_link = link_vdevs[i];
1082 		if (!vdev_link)
1083 			continue;
1084 
1085 		wlan_objmgr_vdev_release_ref(vdev_link, WLAN_MLO_MGR_ID);
1086 	}
1087 }
1088 
1089 #ifdef WLAN_FEATURE_11BE
1090 static void
1091 wlan_mlo_peer_set_t2lm_enable_val(struct wlan_mlo_peer_context *ml_peer,
1092 				  struct mlo_partner_info *ml_info)
1093 {
1094 	ml_peer->t2lm_policy.t2lm_enable_val = ml_info->t2lm_enable_val;
1095 }
1096 
1097 static void
1098 wlan_mlo_peer_initialize_epcs_info(struct wlan_mlo_peer_context *ml_peer)
1099 {
1100 	ml_peer->epcs_info.state = EPCS_DOWN;
1101 	ml_peer->epcs_info.self_gen_dialog_token = 0;
1102 }
1103 
1104 #else
1105 static void
1106 wlan_mlo_peer_set_t2lm_enable_val(struct wlan_mlo_peer_context *ml_peer,
1107 				  struct mlo_partner_info *ml_info)
1108 {}
1109 
1110 static void
1111 wlan_mlo_peer_initialize_epcs_info(struct wlan_mlo_peer_context *ml_peer)
1112 {}
1113 #endif /* WLAN_FEATURE_11BE */
1114 
1115 #if defined(WLAN_FEATURE_11BE_MLO) && defined(WLAN_MLO_MULTI_CHIP)
1116 struct wlan_objmgr_vdev*
1117 mlo_get_link_vdev_from_psoc_id(struct wlan_mlo_dev_context *ml_dev,
1118 			       uint8_t psoc_id, bool get_bridge_vdev)
1119 {
1120 	uint8_t i;
1121 	uint16_t num_bridge_vdev = 0;
1122 	uint8_t max_vdevs = WLAN_UMAC_MLO_MAX_BRIDGE_VDEVS;
1123 	struct wlan_objmgr_vdev *link_vdev;
1124 	QDF_STATUS status;
1125 
1126 	if (WLAN_OBJMGR_MAX_DEVICES <= psoc_id)
1127 		return NULL;
1128 
1129 	if (!ml_dev)
1130 		return NULL;
1131 
1132 	/* if there are no bridge vdevs available,
1133 	 * fall back to actual link vdevs
1134 	 */
1135 	status = mlo_ap_get_bridge_vdev_count(ml_dev, &num_bridge_vdev);
1136 	if (!get_bridge_vdev || (status != QDF_STATUS_SUCCESS) ||
1137 	    !num_bridge_vdev)
1138 		max_vdevs = WLAN_UMAC_MLO_MAX_VDEVS;
1139 
1140 	for (i = 0; i < max_vdevs; i++) {
1141 		if (max_vdevs == WLAN_UMAC_MLO_MAX_BRIDGE_VDEVS)
1142 			link_vdev = ml_dev->wlan_bridge_vdev_list[i];
1143 		else
1144 			link_vdev = ml_dev->wlan_vdev_list[i];
1145 		if (!link_vdev)
1146 			continue;
1147 		if (psoc_id != wlan_vdev_get_psoc_id(link_vdev))
1148 			continue;
1149 		if (wlan_objmgr_vdev_try_get_ref(link_vdev, WLAN_MLO_MGR_ID) !=
1150 							QDF_STATUS_SUCCESS) {
1151 			mlo_err("VDEV is not in created state");
1152 			return NULL;
1153 		}
1154 		return link_vdev;
1155 	}
1156 
1157 	return NULL;
1158 }
1159 
1160 static
1161 QDF_STATUS mlo_bridge_peer_create_post(struct wlan_mlo_dev_context *ml_dev,
1162 				       struct wlan_mlo_peer_context *ml_peer,
1163 				       uint8_t psoc_id)
1164 {
1165 	struct peer_create_notif_s peer_create;
1166 	struct wlan_objmgr_vdev *vdev_link;
1167 	QDF_STATUS status;
1168 
1169 	/* Bridge peer not required */
1170 	if (psoc_id >= WLAN_OBJMGR_MAX_DEVICES)
1171 		return QDF_STATUS_SUCCESS;
1172 
1173 	vdev_link = mlo_get_link_vdev_from_psoc_id(ml_dev, psoc_id, true);
1174 
1175 	if (!vdev_link) {
1176 		mlo_err("VDEV derivation in unsuccessful for %u psoc",
1177 			psoc_id);
1178 		return QDF_STATUS_E_FAILURE;
1179 	}
1180 
1181 	peer_create.vdev_link = vdev_link;
1182 	wlan_mlo_peer_get_ref(ml_peer);
1183 	peer_create.ml_peer = ml_peer;
1184 
1185 	qdf_copy_macaddr(&peer_create.addr,
1186 			 &ml_peer->peer_mld_addr);
1187 
1188 	peer_create.frm_buf = NULL;
1189 
1190 	status = mlo_msgq_post(MLO_BRIDGE_PEER_CREATE, ml_dev, &peer_create);
1191 	if (status != QDF_STATUS_SUCCESS) {
1192 		wlan_mlo_peer_release_ref(ml_peer);
1193 		wlan_objmgr_vdev_release_ref(vdev_link, WLAN_MLO_MGR_ID);
1194 	}
1195 
1196 	return status;
1197 }
1198 
1199 static QDF_STATUS
1200 wlan_mlo_get_bridge_peer_psoc_id(struct wlan_objmgr_vdev *vdev,
1201 				 struct wlan_mlo_peer_context *ml_peer,
1202 				 struct wlan_objmgr_vdev *link_vdevs[],
1203 				 uint8_t num_partner_links,
1204 				 uint8_t *bridge_psoc_id)
1205 {
1206 	struct wlan_mlo_dev_context *ml_dev;
1207 	struct wlan_objmgr_vdev *ml_vdev;
1208 	uint8_t psoc_ids[WLAN_NUM_TWO_LINK_PSOC];
1209 	uint8_t comp_psoc_id, i, is_adjacent;
1210 	uint8_t bridge_peer_psoc_id = WLAN_OBJMGR_MAX_DEVICES;
1211 	uint16_t num_bridge_vdev = 0;
1212 	uint8_t max_vdevs = WLAN_UMAC_MLO_MAX_BRIDGE_VDEVS;
1213 	QDF_STATUS status;
1214 
1215 	if (wlan_vdev_mlme_get_opmode(vdev) != QDF_SAP_MODE)
1216 		return QDF_STATUS_SUCCESS;
1217 
1218 	/* Return from here for 3 link association */
1219 	if (WLAN_NUM_TWO_LINK_PSOC != num_partner_links)
1220 		return QDF_STATUS_SUCCESS;
1221 
1222 	ml_dev = vdev->mlo_dev_ctx;
1223 	if (!ml_dev)
1224 		return QDF_STATUS_E_FAILURE;
1225 
1226 	for (i = 0; i < WLAN_NUM_TWO_LINK_PSOC; i++)
1227 		psoc_ids[i] = wlan_vdev_get_psoc_id(link_vdevs[i]);
1228 
1229 	status = mlo_chip_adjacent(psoc_ids[0], psoc_ids[1],
1230 				   &is_adjacent);
1231 	if (QDF_STATUS_SUCCESS != status) {
1232 		mlo_err("Unable to get chip adjacency for " QDF_MAC_ADDR_FMT ", psoc_0 %u, psoc_1 %u",
1233 			QDF_MAC_ADDR_REF(ml_peer->peer_mld_addr.bytes),
1234 			psoc_ids[0], psoc_ids[1]);
1235 		return status;
1236 	}
1237 
1238 	if (is_adjacent)
1239 		return QDF_STATUS_SUCCESS;
1240 
1241 	/* if there are no bridge vdevs available,
1242 	 * fall back to actual link vdevs
1243 	 */
1244 	status = mlo_ap_get_bridge_vdev_count(ml_dev, &num_bridge_vdev);
1245 	if ((status != QDF_STATUS_SUCCESS) || !num_bridge_vdev) {
1246 		mlo_err_rl("Using actual vdev as bridge vdev");
1247 		max_vdevs = WLAN_UMAC_MLO_MAX_VDEVS;
1248 	}
1249 
1250 	for (i = 0; i < max_vdevs; i++) {
1251 		if (max_vdevs == WLAN_UMAC_MLO_MAX_BRIDGE_VDEVS)
1252 			ml_vdev = ml_dev->wlan_bridge_vdev_list[i];
1253 		else
1254 			ml_vdev = ml_dev->wlan_vdev_list[i];
1255 		if (!ml_vdev || (wlan_vdev_is_up(ml_vdev) != QDF_STATUS_SUCCESS))
1256 			continue;
1257 		comp_psoc_id = wlan_vdev_get_psoc_id(ml_vdev);
1258 		if ((comp_psoc_id != psoc_ids[0]) &&
1259 		    (comp_psoc_id != psoc_ids[1])) {
1260 			bridge_peer_psoc_id = comp_psoc_id;
1261 			break;
1262 		}
1263 	}
1264 
1265 	if (bridge_peer_psoc_id >= WLAN_OBJMGR_MAX_DEVICES) {
1266 		mlo_err("Invalid psoc or psoc not found for " QDF_MAC_ADDR_FMT " psoc %u",
1267 			ether_sprintf(ml_peer->peer_mld_addr.bytes),
1268 			bridge_peer_psoc_id);
1269 		return QDF_STATUS_E_FAILURE;
1270 	}
1271 
1272 	/* Check if derived psoc is adjecent to both links */
1273 	for (i = 0; i < WLAN_NUM_TWO_LINK_PSOC; i++) {
1274 		status = mlo_chip_adjacent(psoc_ids[i], bridge_peer_psoc_id,
1275 					   &is_adjacent);
1276 		if (QDF_STATUS_SUCCESS != status) {
1277 			mlo_err("Unable to get chip adjacency for " QDF_MAC_ADDR_FMT ", psoc_0 %u, psoc_1 %u",
1278 				QDF_MAC_ADDR_REF(ml_peer->peer_mld_addr.bytes),
1279 				psoc_ids[i], bridge_peer_psoc_id);
1280 			return status;
1281 		}
1282 		if (!is_adjacent) {
1283 			mlo_err("Derived psoc is not adjecent to one of the links for " QDF_MAC_ADDR_FMT ", psoc_0 %u, psoc_1 %u psoc_2 %u",
1284 				QDF_MAC_ADDR_REF(ml_peer->peer_mld_addr.bytes),
1285 				psoc_ids[0], psoc_ids[1], bridge_peer_psoc_id);
1286 			return QDF_STATUS_E_FAILURE;
1287 		}
1288 	}
1289 
1290 	/* Add vdev corresponds to bridge link to link_vdevs so
1291 	 * that primary UMAC derivation follows 3-link assoc.
1292 	 */
1293 	for (i = 0; i < WLAN_UMAC_MLO_MAX_VDEVS; i++) {
1294 		if (link_vdevs[i])
1295 			continue;
1296 
1297 		link_vdevs[i] = mlo_get_link_vdev_from_psoc_id(ml_dev,
1298 							       bridge_peer_psoc_id,
1299 							       true);
1300 		if (!link_vdevs[i])
1301 			return QDF_STATUS_E_FAILURE;
1302 
1303 		ml_peer->max_links++;
1304 		*bridge_psoc_id = bridge_peer_psoc_id;
1305 		break;
1306 	}
1307 
1308 	if (i == WLAN_UMAC_MLO_MAX_VDEVS) {
1309 		mlo_err("Unable to append bridge peer vdev to link vdev list");
1310 		return QDF_STATUS_E_FAILURE;
1311 	}
1312 
1313 	mlo_debug("%u is adjecent psoc for " QDF_MAC_ADDR_FMT " is_adjacent %u",
1314 		  bridge_peer_psoc_id,
1315 		  QDF_MAC_ADDR_REF(ml_peer->peer_mld_addr.bytes),
1316 		  is_adjacent);
1317 
1318 	return status;
1319 }
1320 #else
1321 static
1322 QDF_STATUS mlo_bridge_peer_create_post(struct wlan_mlo_dev_context *ml_dev,
1323 				       struct wlan_mlo_peer_context *ml_peer,
1324 				       uint8_t psoc_id)
1325 {
1326 	return QDF_STATUS_SUCCESS;
1327 }
1328 
1329 static QDF_STATUS
1330 wlan_mlo_get_bridge_peer_psoc_id(struct wlan_objmgr_vdev *vdev,
1331 				 struct wlan_mlo_peer_context *ml_peer,
1332 				 struct wlan_objmgr_vdev *link_vdevs[],
1333 				 uint8_t num_partner_links,
1334 				 uint8_t *bridge_psoc_id)
1335 {
1336 	return QDF_STATUS_SUCCESS;
1337 }
1338 #endif
1339 
1340 QDF_STATUS wlan_mlo_peer_asreq(struct wlan_objmgr_vdev *vdev,
1341 			       struct wlan_objmgr_peer *link_peer,
1342 			       struct mlo_partner_info *ml_info,
1343 			       qdf_nbuf_t frm_buf)
1344 {
1345 	struct wlan_mlo_dev_context *ml_dev;
1346 	struct wlan_mlo_peer_context *ml_peer = NULL;
1347 	struct wlan_objmgr_vdev *link_vdevs[WLAN_UMAC_MLO_MAX_VDEVS] = { NULL };
1348 	struct wlan_objmgr_vdev *vdev_link;
1349 	QDF_STATUS status;
1350 	uint16_t i;
1351 	uint16_t j;
1352 	uint16_t link_count;
1353 	struct wlan_mlo_link_peer_entry *peer_entry;
1354 	struct wlan_objmgr_peer *iter_peer;
1355 
1356 	/* get ML VDEV from VDEV */
1357 	ml_dev = vdev->mlo_dev_ctx;
1358 	if (!ml_dev) {
1359 		mlo_err("ML dev ctx is NULL");
1360 		return QDF_STATUS_E_NULL_VALUE;
1361 	}
1362 
1363 	ml_peer = link_peer->mlo_peer_ctx;
1364 	if (!ml_peer) {
1365 		mlo_err("MLD ID %d ML Peer " QDF_MAC_ADDR_FMT " ML peer is NULL",
1366 			ml_dev->mld_id,
1367 			QDF_MAC_ADDR_REF(link_peer->mldaddr));
1368 
1369 		return QDF_STATUS_E_FAILURE;
1370 	}
1371 
1372 	if (!wlan_mlo_peer_is_assoc_peer(ml_peer, link_peer)) {
1373 		mlo_err("MLD ID %d ML Peer " QDF_MAC_ADDR_FMT "Assoc req received on non-assoc peer" QDF_MAC_ADDR_FMT,
1374 			ml_dev->mld_id,
1375 			QDF_MAC_ADDR_REF(link_peer->mldaddr),
1376 			QDF_MAC_ADDR_REF(link_peer->macaddr));
1377 
1378 		return QDF_STATUS_E_FAILURE;
1379 	}
1380 
1381 	status = mlo_dev_get_link_vdevs(vdev, ml_dev,
1382 					ml_info, link_vdevs);
1383 	if (QDF_IS_STATUS_ERROR(status)) {
1384 		mlo_err("MLD ID %d ML Peer " QDF_MAC_ADDR_FMT " get link vdevs failed",
1385 			ml_dev->mld_id,
1386 			QDF_MAC_ADDR_REF(link_peer->mldaddr));
1387 		return QDF_STATUS_E_FAILURE;
1388 	}
1389 
1390 	/* If ML peer state is not in Assoc done state, drop REASSOC req */
1391 	if (ml_peer->mlpeer_state != ML_PEER_ASSOC_DONE) {
1392 		mlo_err("MLD ID %d ML Peer " QDF_MAC_ADDR_FMT " invalid state %d",
1393 			ml_dev->mld_id,
1394 			QDF_MAC_ADDR_REF(link_peer->mldaddr),
1395 			ml_peer->mlpeer_state);
1396 
1397 		mlo_dev_release_link_vdevs(link_vdevs);
1398 
1399 		return QDF_STATUS_E_FAILURE;
1400 	}
1401 
1402 	link_count = 0;
1403 	for (j = 0; j < ml_peer->max_links; j++) {
1404 		peer_entry = &ml_peer->peer_list[j];
1405 		iter_peer = peer_entry->link_peer;
1406 		if (!iter_peer)
1407 			continue;
1408 
1409 		if (wlan_peer_get_peer_type(iter_peer) ==
1410 						WLAN_PEER_MLO_BRIDGE) {
1411 			link_count++;
1412 			continue;
1413 		}
1414 
1415 		for (i = 0; i < WLAN_UMAC_MLO_MAX_VDEVS; i++) {
1416 			vdev_link = link_vdevs[i];
1417 			if (!vdev_link)
1418 				continue;
1419 
1420 			if (vdev_link != wlan_peer_get_vdev(iter_peer))
1421 				continue;
1422 
1423 			link_count++;
1424 			break;
1425 		}
1426 	}
1427 	if (link_count != ml_peer->link_peer_cnt) {
1428 		mlo_err("MLD ID %d ML Peer " QDF_MAC_ADDR_FMT " incorrect link peers",
1429 			ml_dev->mld_id,
1430 			QDF_MAC_ADDR_REF(link_peer->mldaddr));
1431 		mlo_dev_release_link_vdevs(link_vdevs);
1432 
1433 		return QDF_STATUS_E_INVAL;
1434 	}
1435 
1436 	/* Notify other vdevs about assoc req */
1437 	for (i = 0; i < WLAN_UMAC_MLO_MAX_VDEVS; i++) {
1438 		vdev_link = link_vdevs[i];
1439 		if (!vdev_link)
1440 			continue;
1441 
1442 		if (vdev_link == vdev)
1443 			continue;
1444 
1445 		mlo_partner_peer_reassoc_post(ml_dev, vdev_link,
1446 					      ml_peer, frm_buf, ml_info);
1447 	}
1448 
1449 	mlo_dev_release_link_vdevs(link_vdevs);
1450 
1451 	if (QDF_IS_STATUS_ERROR(wlan_mlo_validate_reassocreq(ml_peer))) {
1452 		mlo_info("MLD ID %d ML Peer " QDF_MAC_ADDR_FMT " reassoc proc is failed %pK",
1453 			 ml_dev->mld_id,
1454 			 QDF_MAC_ADDR_REF(ml_peer->peer_mld_addr.bytes),
1455 			 ml_peer);
1456 
1457 		return QDF_STATUS_E_FAILURE;
1458 	}
1459 
1460 	mlo_info("MLD ID %d ML Peer " QDF_MAC_ADDR_FMT " reassoc handled %pK",
1461 		 ml_dev->mld_id,
1462 		 QDF_MAC_ADDR_REF(ml_peer->peer_mld_addr.bytes),
1463 		 ml_peer);
1464 
1465 	return QDF_STATUS_SUCCESS;
1466 }
1467 #if defined (SAP_MULTI_LINK_EMULATION)
1468 static void
1469 set_assoc_peer_for_2link_sap(struct wlan_objmgr_peer *assoc_peer,
1470 			     struct wlan_mlo_peer_context *ml_peer)
1471 {
1472 	assoc_peer = ml_peer->peer_list[0].link_peer;
1473 	if (assoc_peer)
1474 		mlo_mlme_peer_assoc_resp(assoc_peer);
1475 }
1476 #else
1477 static void
1478 set_assoc_peer_for_2link_sap(struct wlan_objmgr_peer *assoc_peer,
1479 			     struct wlan_mlo_peer_context *ml_peer)
1480 {
1481 }
1482 #endif
1483 QDF_STATUS wlan_mlo_peer_create(struct wlan_objmgr_vdev *vdev,
1484 				struct wlan_objmgr_peer *link_peer,
1485 				struct mlo_partner_info *ml_info,
1486 				qdf_nbuf_t frm_buf,
1487 				uint16_t aid)
1488 {
1489 	struct wlan_mlo_dev_context *ml_dev;
1490 	struct wlan_mlo_peer_context *ml_peer = NULL;
1491 	struct wlan_objmgr_vdev *link_vdevs[WLAN_UMAC_MLO_MAX_VDEVS] = { NULL };
1492 	struct wlan_objmgr_vdev *tmp_link_vdevs[WLAN_UMAC_MLO_MAX_VDEVS] = { NULL };
1493 	struct wlan_objmgr_vdev *vdev_link;
1494 	QDF_STATUS status;
1495 	uint16_t i, j;
1496 	struct wlan_objmgr_peer *assoc_peer = NULL;
1497 	uint8_t bridge_peer_psoc_id = WLAN_OBJMGR_MAX_DEVICES;
1498 	bool is_ml_peer_attached = false;
1499 
1500 	/* get ML VDEV from VDEV */
1501 	ml_dev = vdev->mlo_dev_ctx;
1502 
1503 	if (!ml_dev) {
1504 		mlo_err("ML dev ctx is NULL");
1505 		return QDF_STATUS_E_NULL_VALUE;
1506 	}
1507 
1508 	/* Check resources of Partner VDEV */
1509 	if (wlan_vdev_mlme_get_opmode(vdev) == QDF_SAP_MODE) {
1510 		if (wlan_mlo_is_mld_ctx_exist(
1511 		    (struct qdf_mac_addr *)&link_peer->mldaddr[0])) {
1512 			mlo_err("MLD ID %d ML Peer " QDF_MAC_ADDR_FMT " is matching with one of the MLD address in the system",
1513 				ml_dev->mld_id,
1514 				QDF_MAC_ADDR_REF(link_peer->mldaddr));
1515 			return QDF_STATUS_E_FAILURE;
1516 		}
1517 		/* Limit max assoc links */
1518 		if (ml_info->num_partner_links > WLAN_UMAC_MLO_ASSOC_MAX_SUPPORTED_LINKS) {
1519 			mlo_err("MLD ID %d ML Peer " QDF_MAC_ADDR_FMT " exceeds MAX assoc limit of %d",
1520 				ml_dev->mld_id,
1521 				QDF_MAC_ADDR_REF(link_peer->mldaddr),
1522 				WLAN_UMAC_MLO_ASSOC_MAX_SUPPORTED_LINKS);
1523 			return QDF_STATUS_E_RESOURCES;
1524 		}
1525 
1526 		status = mlo_dev_get_link_vdevs(vdev, ml_dev,
1527 						ml_info, link_vdevs);
1528 		if (QDF_IS_STATUS_ERROR(status)) {
1529 			mlo_err("MLD ID %d ML Peer " QDF_MAC_ADDR_FMT " get link vdevs failed",
1530 				ml_dev->mld_id,
1531 				QDF_MAC_ADDR_REF(link_peer->mldaddr));
1532 			return QDF_STATUS_E_FAILURE;
1533 		}
1534 		for (i = 0; i < WLAN_UMAC_MLO_MAX_VDEVS; i++) {
1535 			vdev_link = link_vdevs[i];
1536 			if (!vdev_link) {
1537 				mlo_debug("vdev_link is null");
1538 				continue;
1539 			}
1540 
1541 			if (wlan_vdev_is_mlo_peer_create_allowed(vdev_link)
1542 					!= QDF_STATUS_SUCCESS) {
1543 				mlo_dev_release_link_vdevs(link_vdevs);
1544 
1545 				mlo_err("MLD ID %d ML Peer " QDF_MAC_ADDR_FMT " create not allowed on link vdev %d",
1546 					ml_dev->mld_id,
1547 					QDF_MAC_ADDR_REF
1548 						(link_peer->mldaddr),
1549 					wlan_vdev_get_id(vdev_link));
1550 				return QDF_STATUS_E_INVAL;
1551 			}
1552 		}
1553 
1554 		for (i = 0; i < WLAN_UMAC_MLO_MAX_VDEVS; i++) {
1555 			vdev_link = link_vdevs[i];
1556 			if (vdev_link && (vdev_link != vdev) &&
1557 			    (wlan_vdev_get_peer_count(vdev_link) >
1558 			     wlan_vdev_get_max_peer_count(vdev_link))) {
1559 				mlo_dev_release_link_vdevs(link_vdevs);
1560 				mlo_err("MLD ID %d ML Peer " QDF_MAC_ADDR_FMT " Max peer count reached on link vdev %d",
1561 					ml_dev->mld_id,
1562 					QDF_MAC_ADDR_REF
1563 						(link_peer->mldaddr),
1564 					wlan_vdev_get_id(vdev_link));
1565 				return QDF_STATUS_E_RESOURCES;
1566 			}
1567 		}
1568 	}
1569 	/* When roam to MLO AP, partner link vdev1 is updated first,
1570 	 * ml peer need be created and attached for partner link peer.
1571 	 *
1572 	 * When roam target AP and current AP have same MLD address, don't
1573 	 * delete old ML peer and re-create new one, just update different
1574 	 * info.
1575 	 */
1576 	if (wlan_vdev_mlme_get_opmode(vdev) == QDF_STA_MODE) {
1577 		ml_peer = wlan_mlo_get_mlpeer(ml_dev,
1578 				 (struct qdf_mac_addr *)&link_peer->mldaddr[0]);
1579 		if (ml_peer) {
1580 			mlo_debug("ML Peer " QDF_MAC_ADDR_FMT
1581 				" existed, state %d",
1582 				QDF_MAC_ADDR_REF(ml_peer->peer_mld_addr.bytes),
1583 				ml_peer->mlpeer_state);
1584 			ml_peer->mlpeer_state = ML_PEER_CREATED;
1585 			ml_peer->max_links = ml_info->num_partner_links;
1586 			wlan_mlo_peer_set_t2lm_enable_val(ml_peer, ml_info);
1587 			is_ml_peer_attached = true;
1588 		}
1589 	}
1590 	if (!ml_peer) {
1591 		/* Allocate MLO peer */
1592 		ml_peer = qdf_mem_malloc(sizeof(*ml_peer));
1593 		if (!ml_peer) {
1594 			mlo_err("MLD ID %d ML Peer " QDF_MAC_ADDR_FMT " mem alloc failed",
1595 				ml_dev->mld_id,
1596 				QDF_MAC_ADDR_REF(link_peer->mldaddr));
1597 			mlo_dev_release_link_vdevs(link_vdevs);
1598 			return QDF_STATUS_E_NOMEM;
1599 		}
1600 
1601 		qdf_atomic_init(&ml_peer->ref_cnt);
1602 		mlo_peer_lock_create(ml_peer);
1603 		ml_peer->ml_dev = ml_dev;
1604 		ml_peer->mlpeer_state = ML_PEER_CREATED;
1605 		ml_peer->max_links = ml_info->num_partner_links;
1606 		ml_peer->primary_umac_psoc_id = ML_PRIMARY_UMAC_ID_INVAL;
1607 		ml_peer->migrate_primary_umac_psoc_id =
1608 						ML_PRIMARY_UMAC_ID_INVAL;
1609 		ml_peer->primary_umac_migration_in_progress = false;
1610 
1611 		ml_peer->mlo_peer_id = mlo_ap_ml_peerid_alloc();
1612 		if (ml_peer->mlo_peer_id == MLO_INVALID_PEER_ID) {
1613 			mlo_err("MLD ID %d ML Peer " QDF_MAC_ADDR_FMT " invalid ml peer id",
1614 				ml_dev->mld_id,
1615 				QDF_MAC_ADDR_REF
1616 				(ml_peer->peer_mld_addr.bytes));
1617 			mlo_peer_free(ml_peer);
1618 			mlo_dev_release_link_vdevs(link_vdevs);
1619 			return QDF_STATUS_E_RESOURCES;
1620 		}
1621 
1622 		qdf_copy_macaddr((struct qdf_mac_addr *)&ml_peer->peer_mld_addr,
1623 				 (struct qdf_mac_addr *)&link_peer->mldaddr[0]);
1624 		wlan_mlo_peer_set_t2lm_enable_val(ml_peer, ml_info);
1625 		epcs_dev_peer_lock_create(&ml_peer->epcs_info);
1626 		wlan_mlo_peer_initialize_epcs_info(ml_peer);
1627 
1628 		/* Allocate AID */
1629 		if (wlan_vdev_mlme_get_opmode(vdev) == QDF_SAP_MODE) {
1630 			if (aid == (uint16_t)-1) {
1631 				status = mlo_peer_allocate_aid(ml_dev, ml_peer);
1632 				if (status != QDF_STATUS_SUCCESS) {
1633 					mlo_err("MLD ID %d ML Peer " QDF_MAC_ADDR_FMT " aid alloc failed",
1634 						ml_dev->mld_id,
1635 						QDF_MAC_ADDR_REF
1636 						(ml_peer->peer_mld_addr.bytes));
1637 					mlo_peer_free(ml_peer);
1638 					mlo_dev_release_link_vdevs(link_vdevs);
1639 					return status;
1640 				}
1641 			} else {
1642 				ml_peer->assoc_id = aid;
1643 			}
1644 		}
1645 	}
1646 
1647 	/* Populate Link peer pointer, peer MAC address,
1648 	 * MLD address. HW link ID, update ref count
1649 	 */
1650 	status = mlo_peer_attach_link_peer(ml_peer, link_peer, NULL);
1651 	if (QDF_IS_STATUS_ERROR(status)) {
1652 		mlo_err("MLD ID %d ML Peer " QDF_MAC_ADDR_FMT " link peer attach failed",
1653 			ml_dev->mld_id,
1654 			QDF_MAC_ADDR_REF
1655 			(ml_peer->peer_mld_addr.bytes));
1656 		/* If there is another link peer attached for this ML peer,
1657 		 * ml peer can't be detached and freed.
1658 		 */
1659 		if (is_ml_peer_attached && ml_peer->link_peer_cnt)
1660 			return status;
1661 		if (is_ml_peer_attached)
1662 			mlo_dev_mlpeer_detach(ml_dev, ml_peer);
1663 		mlo_peer_free(ml_peer);
1664 		mlo_dev_release_link_vdevs(link_vdevs);
1665 		return status;
1666 	}
1667 
1668 	if (wlan_vdev_mlme_get_opmode(vdev) == QDF_SAP_MODE) {
1669 		for (i = 0; i < WLAN_UMAC_MLO_MAX_VDEVS; i++) {
1670 			if (!link_vdevs[i]) {
1671 				mlo_debug("vdev_link is null");
1672 				continue;
1673 			}
1674 
1675 			if (wlan_objmgr_vdev_try_get_ref(link_vdevs[i], WLAN_MLO_MGR_ID) !=
1676 					QDF_STATUS_SUCCESS) {
1677 				mlo_err("VDEV is not in created state");
1678 				/* release ref which were taken before failure */
1679 				for (j = 0; j < i; j++) {
1680 					if (!link_vdevs[i])
1681 						continue;
1682 
1683 					wlan_objmgr_vdev_release_ref(link_vdevs[i],
1684 								     WLAN_MLO_MGR_ID);
1685 				}
1686 				mlo_reset_link_peer(ml_peer, link_peer);
1687 				mlo_peer_free(ml_peer);
1688 				mlo_dev_release_link_vdevs(link_vdevs);
1689 
1690 				return QDF_STATUS_E_FAILURE;
1691 			}
1692 			tmp_link_vdevs[i] = link_vdevs[i];
1693 		}
1694 
1695 		status = wlan_mlo_get_bridge_peer_psoc_id(vdev, ml_peer,
1696 							  tmp_link_vdevs,
1697 							  ml_info->num_partner_links,
1698 							  &bridge_peer_psoc_id);
1699 		if (QDF_STATUS_SUCCESS != status) {
1700 			mlo_err("MLD ID %d: Failed to derive bridge peer psoc id",
1701 				ml_dev->mld_id);
1702 			mlo_reset_link_peer(ml_peer, link_peer);
1703 			mlo_peer_free(ml_peer);
1704 			mlo_dev_release_link_vdevs(link_vdevs);
1705 			mlo_dev_release_link_vdevs(tmp_link_vdevs);
1706 			wlan_objmgr_peer_release_ref(link_peer,
1707 						     WLAN_MLO_MGR_ID);
1708 			return QDF_STATUS_E_FAILURE;
1709 		}
1710 	}
1711 
1712 	/* Allocate Primary UMAC */
1713 	mlo_peer_allocate_primary_umac(ml_dev, ml_peer, tmp_link_vdevs);
1714 
1715 	if (wlan_vdev_mlme_get_opmode(vdev) == QDF_SAP_MODE)
1716 		mlo_dev_release_link_vdevs(tmp_link_vdevs);
1717 
1718 	/* Store AID, MLO Peer pointer in link peer, take link peer ref count */
1719 	mlo_peer_populate_link_peer(ml_peer, link_peer);
1720 
1721 	mlo_peer_populate_nawds_params(ml_peer, ml_info);
1722 	mlo_peer_populate_mesh_params(ml_peer, ml_info);
1723 
1724 	if ((wlan_vdev_mlme_get_opmode(vdev) == QDF_SAP_MODE) ||
1725 		((wlan_vdev_mlme_get_opmode(vdev) == QDF_STA_MODE) &&
1726 			!is_ml_peer_attached)) {
1727 		/* Reject creation for AP mode, If ML peer is present with
1728 		 * MLD MAC address, For PSTA case, all MLD STAs are connected
1729 		 * to same MLD AP, it can have duplicate MLD address entries
1730 		 * for STA MLDs
1731 		 */
1732 		if ((wlan_vdev_mlme_get_opmode(vdev) == QDF_SAP_MODE) &&
1733 		    mlo_mgr_ml_peer_exist_on_diff_ml_ctx(&link_peer->mldaddr[0],
1734 							 NULL)) {
1735 			mlo_err("MLD ID %d ML Peer " QDF_MAC_ADDR_FMT " is exists, creation failed",
1736 				ml_dev->mld_id,
1737 				QDF_MAC_ADDR_REF(ml_peer->peer_mld_addr.bytes));
1738 			mlo_reset_link_peer(ml_peer, link_peer);
1739 			mlo_peer_free(ml_peer);
1740 			mlo_dev_release_link_vdevs(link_vdevs);
1741 			wlan_objmgr_peer_release_ref(link_peer,
1742 						     WLAN_MLO_MGR_ID);
1743 			return QDF_STATUS_E_EXISTS;
1744 		}
1745 
1746 		/* Attach MLO peer to ML Peer table */
1747 		status = mlo_dev_mlpeer_attach(ml_dev, ml_peer);
1748 		if (status != QDF_STATUS_SUCCESS) {
1749 			mlo_err("MLD ID %d ML Peer " QDF_MAC_ADDR_FMT " attach failed",
1750 				ml_dev->mld_id,
1751 				QDF_MAC_ADDR_REF(ml_peer->peer_mld_addr.bytes));
1752 			mlo_reset_link_peer(ml_peer, link_peer);
1753 			wlan_objmgr_peer_release_ref(link_peer,
1754 						     WLAN_MLO_MGR_ID);
1755 			mlo_peer_free(ml_peer);
1756 			mlo_dev_release_link_vdevs(link_vdevs);
1757 			return status;
1758 		}
1759 	}
1760 
1761 	wlan_mlo_peer_get_ref(ml_peer);
1762 
1763 	if (wlan_vdev_mlme_get_opmode(vdev) == QDF_SAP_MODE) {
1764 		/* Notify other vdevs about link peer creation */
1765 		for (i = 0; i < WLAN_UMAC_MLO_MAX_VDEVS; i++) {
1766 			vdev_link = link_vdevs[i];
1767 			if (!vdev_link)
1768 				continue;
1769 
1770 			if (vdev_link == vdev)
1771 				continue;
1772 
1773 			mlo_partner_peer_create_post(ml_dev, vdev_link,
1774 						     ml_peer, frm_buf, ml_info);
1775 		}
1776 		/* Create bridge peer */
1777 		status = mlo_bridge_peer_create_post(ml_dev, ml_peer,
1778 						     bridge_peer_psoc_id);
1779 		if (QDF_STATUS_SUCCESS != status) {
1780 			mlo_err("MLD ID %d: Bridge peer creation failed",
1781 				ml_dev->mld_id);
1782 			wlan_mlo_partner_peer_create_failed_notify(ml_peer);
1783 			mlo_dev_release_link_vdevs(link_vdevs);
1784 			wlan_mlo_peer_release_ref(ml_peer);
1785 			return QDF_STATUS_E_FAILURE;
1786 		}
1787 	}
1788 	mlo_dev_release_link_vdevs(link_vdevs);
1789 
1790 	if (ml_peer->mlpeer_state == ML_PEER_DISCONN_INITIATED) {
1791 		mlo_info("MLD ID %d ML Peer " QDF_MAC_ADDR_FMT " allocation failed",
1792 			 ml_dev->mld_id,
1793 			 QDF_MAC_ADDR_REF(ml_peer->peer_mld_addr.bytes));
1794 		wlan_mlo_peer_release_ref(ml_peer);
1795 		return QDF_STATUS_E_FAILURE;
1796 	}
1797 
1798 	mlo_info("MLD ID %d ML Peer " QDF_MAC_ADDR_FMT " allocated %pK",
1799 		 ml_dev->mld_id,
1800 		 QDF_MAC_ADDR_REF(ml_peer->peer_mld_addr.bytes),
1801 		 ml_peer);
1802 
1803 	/*
1804 	 * wlan_mlo_peer_create() is trigggered after getting peer
1805 	 * assoc confirm from FW. For single link MLO connection, it is
1806 	 * OK to trigger assoc response from here.
1807 	 */
1808 	if ((wlan_vdev_mlme_get_opmode(vdev) == QDF_SAP_MODE) &&
1809 	    (!wlan_mlo_peer_is_nawds(ml_peer))) {
1810 		if ((ml_peer->max_links == 1) &&
1811 		    (ml_peer->link_peer_cnt == 1)) {
1812 			assoc_peer = ml_peer->peer_list[0].link_peer;
1813 			if (assoc_peer)
1814 				mlo_mlme_peer_assoc_resp(assoc_peer);
1815 		} else {
1816 			set_assoc_peer_for_2link_sap(assoc_peer, ml_peer);
1817 		}
1818 	}
1819 
1820 
1821 	if (wlan_vdev_mlme_get_opmode(vdev) == QDF_STA_MODE)
1822 		wlan_clear_peer_level_tid_to_link_mapping(vdev);
1823 
1824 	wlan_mlo_peer_release_ref(ml_peer);
1825 
1826 	return QDF_STATUS_SUCCESS;
1827 }
1828 
1829 QDF_STATUS wlan_mlo_link_peer_attach(struct wlan_mlo_peer_context *ml_peer,
1830 				     struct wlan_objmgr_peer *peer,
1831 				     qdf_nbuf_t frm_buf)
1832 {
1833 	QDF_STATUS status;
1834 	struct wlan_objmgr_peer *assoc_peer;
1835 	struct wlan_objmgr_vdev *vdev = NULL;
1836 
1837 	if (!ml_peer)
1838 		return QDF_STATUS_E_FAILURE;
1839 
1840 	vdev = wlan_peer_get_vdev(peer);
1841 	if (!vdev)
1842 		return QDF_STATUS_E_FAILURE;
1843 
1844 	/* Populate Link peer pointer, peer MAC address,
1845 	 * MLD address. HW link ID, update ref count
1846 	 */
1847 	status = mlo_peer_attach_link_peer(ml_peer, peer, frm_buf);
1848 	if (QDF_IS_STATUS_ERROR(status))
1849 		return status;
1850 
1851 	/* Store AID, MLO Peer pointer in link peer, take link peer ref count */
1852 	mlo_peer_populate_link_peer(ml_peer, peer);
1853 
1854 	if (wlan_vdev_mlme_get_opmode(vdev) == QDF_SAP_MODE) {
1855 		if (ml_peer->max_links == ml_peer->link_peer_cnt) {
1856 			assoc_peer = ml_peer->peer_list[0].link_peer;
1857 			if (assoc_peer)
1858 				mlo_mlme_peer_assoc_resp(assoc_peer);
1859 		}
1860 	}
1861 
1862 	return status;
1863 }
1864 
1865 QDF_STATUS wlan_mlo_link_asresp_attach(struct wlan_mlo_peer_context *ml_peer,
1866 				       struct wlan_objmgr_peer *peer,
1867 				       qdf_nbuf_t frm_buf)
1868 {
1869 	uint16_t i;
1870 	struct wlan_mlo_link_peer_entry *peer_entry;
1871 
1872 	if (!ml_peer) {
1873 		mlo_err(" ml peer is NULL");
1874 		return QDF_STATUS_E_FAILURE;
1875 	}
1876 
1877 	if (!peer) {
1878 		ml_peer->link_asresp_cnt++;
1879 		mlo_err(" ml peer or link peer pointer is NULL");
1880 		return QDF_STATUS_E_FAILURE;
1881 	}
1882 	mlo_peer_lock_acquire(ml_peer);
1883 
1884 	for (i = 0; i < MAX_MLO_LINK_PEERS; i++) {
1885 		peer_entry = &ml_peer->peer_list[i];
1886 		if (!peer_entry->link_peer)
1887 			continue;
1888 
1889 		if (peer == peer_entry->link_peer) {
1890 			ml_peer->link_asresp_cnt++;
1891 			/* Free previous assoc resp buffer */
1892 			if (peer_entry->assoc_rsp_buf) {
1893 				qdf_nbuf_free(peer_entry->assoc_rsp_buf);
1894 				peer_entry->assoc_rsp_buf = NULL;
1895 			}
1896 
1897 			if (frm_buf)
1898 				peer_entry->assoc_rsp_buf = frm_buf;
1899 			else
1900 				peer_entry->assoc_rsp_buf = NULL;
1901 
1902 			break;
1903 		}
1904 	}
1905 
1906 	mlo_peer_lock_release(ml_peer);
1907 
1908 	return QDF_STATUS_SUCCESS;
1909 }
1910 
1911 QDF_STATUS wlan_mlo_link_peer_delete(struct wlan_objmgr_peer *peer)
1912 {
1913 	struct wlan_mlo_peer_context *ml_peer;
1914 
1915 	ml_peer = peer->mlo_peer_ctx;
1916 
1917 	if (!ml_peer)
1918 		return QDF_STATUS_E_NOENT;
1919 
1920 	if (ml_peer->mlpeer_state != ML_PEER_DISCONN_INITIATED)
1921 		wlan_mlo_peer_wsi_link_delete(ml_peer);
1922 
1923 	mlo_reset_link_peer(ml_peer, peer);
1924 	mlo_peer_detach_link_peer(ml_peer, peer);
1925 
1926 	if (ml_peer->mlpeer_state != ML_PEER_DISCONN_INITIATED)
1927 		wlan_mlo_peer_wsi_link_add(ml_peer);
1928 
1929 	wlan_mlo_peer_release_ref(ml_peer);
1930 
1931 	return QDF_STATUS_SUCCESS;
1932 }
1933 
1934 qdf_export_symbol(wlan_mlo_link_peer_delete);
1935 
1936 qdf_nbuf_t mlo_peer_get_link_peer_assoc_req_buf(
1937 			struct wlan_mlo_peer_context *ml_peer,
1938 			uint8_t link_ix)
1939 {
1940 	struct wlan_objmgr_peer *peer = NULL;
1941 	qdf_nbuf_t assocbuf = NULL;
1942 
1943 	if (!ml_peer)
1944 		return NULL;
1945 
1946 	peer = wlan_mlo_peer_get_assoc_peer(ml_peer);
1947 	if (!peer)
1948 		return NULL;
1949 
1950 	assocbuf = mlo_mlme_get_link_assoc_req(peer, link_ix);
1951 
1952 	return assocbuf;
1953 }
1954 
1955 void wlan_mlo_peer_get_links_info(struct wlan_objmgr_peer *peer,
1956 				  struct mlo_tgt_partner_info *ml_links)
1957 {
1958 	struct wlan_mlo_peer_context *ml_peer;
1959 	struct wlan_mlo_link_peer_entry *peer_entry;
1960 	struct wlan_objmgr_peer *link_peer;
1961 	struct wlan_objmgr_vdev *link_vdev;
1962 	uint8_t i, ix, idx = 0;
1963 	struct wlan_mlo_eml_cap *ml_emlcap;
1964 
1965 	ml_peer = peer->mlo_peer_ctx;
1966 	ml_links->num_partner_links = 0;
1967 
1968 	if (!ml_peer)
1969 		return;
1970 
1971 	ml_emlcap = &ml_peer->mlpeer_emlcap;
1972 
1973 	mlo_peer_lock_acquire(ml_peer);
1974 
1975 	if ((ml_peer->mlpeer_state != ML_PEER_CREATED) &&
1976 	    (ml_peer->mlpeer_state != ML_PEER_ASSOC_DONE)) {
1977 		mlo_peer_lock_release(ml_peer);
1978 		return;
1979 	}
1980 
1981 	for (i = 0; i < MAX_MLO_LINK_PEERS; i++) {
1982 		peer_entry = &ml_peer->peer_list[i];
1983 		link_peer = peer_entry->link_peer;
1984 
1985 		if (!link_peer)
1986 			continue;
1987 		idx++;
1988 		if (link_peer == peer)
1989 			continue;
1990 		link_vdev = wlan_peer_get_vdev(link_peer);
1991 		if (!link_vdev)
1992 			continue;
1993 
1994 		if (ml_links->num_partner_links >= WLAN_UMAC_MLO_MAX_VDEVS)
1995 			break;
1996 
1997 		ix = ml_links->num_partner_links;
1998 		ml_links->link_info[ix].vdev_id = wlan_vdev_get_id(link_vdev);
1999 		ml_links->link_info[ix].hw_mld_link_id = peer_entry->hw_link_id;
2000 		ml_links->link_info[ix].mlo_enabled = 1;
2001 		ml_links->link_info[ix].mlo_assoc_link =
2002 			wlan_peer_mlme_is_assoc_peer(link_peer);
2003 		ml_links->link_info[ix].mlo_primary_umac =
2004 			peer_entry->is_primary;
2005 		ml_links->link_info[ix].mlo_logical_link_index_valid = 1;
2006 		ml_links->link_info[ix].emlsr_support = ml_emlcap->emlsr_supp;
2007 		ml_links->link_info[ix].logical_link_index = idx - 1;
2008 		ml_links->link_info[ix].mlo_bridge_peer = link_peer->mlo_bridge_peer;
2009 		ml_links->num_partner_links++;
2010 	}
2011 	mlo_peer_lock_release(ml_peer);
2012 }
2013 
2014 qdf_export_symbol(wlan_mlo_peer_get_links_info);
2015 
2016 uint8_t wlan_mlo_peer_get_primary_peer_link_id(struct wlan_objmgr_peer *peer)
2017 {
2018 	struct wlan_mlo_peer_context *ml_peer;
2019 
2020 	ml_peer = peer->mlo_peer_ctx;
2021 
2022 	if (!ml_peer) {
2023 		mlo_err("ml_peer is null");
2024 		return WLAN_LINK_ID_INVALID;
2025 	}
2026 
2027 	return wlan_mlo_peer_get_primary_peer_link_id_by_ml_peer(ml_peer);
2028 }
2029 
2030 qdf_export_symbol(wlan_mlo_peer_get_primary_peer_link_id);
2031 
2032 uint8_t wlan_mlo_peer_get_primary_peer_link_id_by_ml_peer(
2033 				struct wlan_mlo_peer_context *ml_peer)
2034 {
2035 	struct wlan_mlo_link_peer_entry *peer_entry;
2036 	struct wlan_objmgr_peer *link_peer;
2037 	struct wlan_objmgr_vdev *link_vdev;
2038 	uint8_t i, vdev_link_id;
2039 
2040 	if (!ml_peer) {
2041 		mlo_err("ml_peer is null");
2042 		return WLAN_LINK_ID_INVALID;
2043 	}
2044 	mlo_peer_lock_acquire(ml_peer);
2045 
2046 	if ((ml_peer->mlpeer_state != ML_PEER_CREATED) &&
2047 	    (ml_peer->mlpeer_state != ML_PEER_ASSOC_DONE)) {
2048 		mlo_peer_lock_release(ml_peer);
2049 		mlo_err("ml_peer is not created and association is not done");
2050 		return WLAN_LINK_ID_INVALID;
2051 	}
2052 
2053 	for (i = 0; i < MAX_MLO_LINK_PEERS; i++) {
2054 		peer_entry = &ml_peer->peer_list[i];
2055 		link_peer = peer_entry->link_peer;
2056 		if (!link_peer)
2057 			continue;
2058 
2059 		if (peer_entry->is_primary) {
2060 			link_vdev = wlan_peer_get_vdev(link_peer);
2061 			if (!link_vdev) {
2062 				mlo_peer_lock_release(ml_peer);
2063 				mlo_err("link vdev not found");
2064 				return WLAN_LINK_ID_INVALID;
2065 			}
2066 			vdev_link_id = wlan_vdev_get_link_id(link_vdev);
2067 			mlo_peer_lock_release(ml_peer);
2068 			return vdev_link_id;
2069 		}
2070 	}
2071 	mlo_peer_lock_release(ml_peer);
2072 	mlo_err("None of the peer is designated as primary");
2073 	return WLAN_LINK_ID_INVALID;
2074 }
2075 
2076 qdf_export_symbol(wlan_mlo_peer_get_primary_peer_link_id_by_ml_peer);
2077 
2078 #ifdef WLAN_MLO_MULTI_CHIP
2079 void wlan_mlo_peer_get_str_capability(struct wlan_objmgr_peer *peer,
2080 				      uint8_t *str_capability)
2081 {
2082 	struct wlan_mlo_peer_context *ml_peer;
2083 	uint8_t i;
2084 
2085 	if (!str_capability)
2086 		return;
2087 
2088 	*str_capability = 1;
2089 	if (!peer)
2090 		return;
2091 	ml_peer = peer->mlo_peer_ctx;
2092 	if (!ml_peer)
2093 		return;
2094 
2095 	mlo_peer_lock_acquire(ml_peer);
2096 	if ((ml_peer->mlpeer_state != ML_PEER_CREATED) &&
2097 	    (ml_peer->mlpeer_state != ML_PEER_ASSOC_DONE)) {
2098 		mlo_peer_lock_release(ml_peer);
2099 		return;
2100 	}
2101 
2102 	for (i = 0; i < WLAN_UMAC_MLO_MAX_VDEVS; i++) {
2103 		if (ml_peer->mlpeer_nstrinfo[i].link_id >= MAX_MLO_LINKS)
2104 			continue;
2105 		if (ml_peer->mlpeer_nstrinfo[i].nstr_lp_present) {
2106 			*str_capability = 0;
2107 			break;
2108 		}
2109 	}
2110 	mlo_peer_lock_release(ml_peer);
2111 }
2112 
2113 void wlan_mlo_peer_get_eml_capability(struct wlan_objmgr_peer *peer,
2114 				      uint8_t *is_emlsr_capable,
2115 				      uint8_t *is_emlmr_capable)
2116 {
2117 	struct wlan_mlo_peer_context *ml_peer;
2118 
2119 	if (!is_emlsr_capable || !is_emlmr_capable)
2120 		return;
2121 
2122 	*is_emlsr_capable = 0;
2123 	*is_emlmr_capable = 0;
2124 	if (!peer)
2125 		return;
2126 	ml_peer = peer->mlo_peer_ctx;
2127 	if (!ml_peer)
2128 		return;
2129 
2130 	mlo_peer_lock_acquire(ml_peer);
2131 	if ((ml_peer->mlpeer_state != ML_PEER_CREATED) &&
2132 	    (ml_peer->mlpeer_state != ML_PEER_ASSOC_DONE)) {
2133 		mlo_peer_lock_release(ml_peer);
2134 		return;
2135 	}
2136 	*is_emlsr_capable = ml_peer->mlpeer_emlcap.emlsr_supp;
2137 	*is_emlmr_capable = ml_peer->mlpeer_emlcap.emlmr_supp;
2138 	mlo_peer_lock_release(ml_peer);
2139 }
2140 #endif
2141 
2142 void wlan_mlo_peer_get_partner_links_info(struct wlan_objmgr_peer *peer,
2143 					  struct mlo_partner_info *ml_links)
2144 {
2145 	struct wlan_mlo_peer_context *ml_peer;
2146 	struct wlan_mlo_link_peer_entry *peer_entry;
2147 	struct wlan_objmgr_peer *link_peer;
2148 	struct wlan_objmgr_vdev *link_vdev;
2149 	uint8_t i, ix;
2150 
2151 	ml_peer = peer->mlo_peer_ctx;
2152 	ml_links->num_partner_links = 0;
2153 
2154 	if (!ml_peer)
2155 		return;
2156 
2157 	mlo_peer_lock_acquire(ml_peer);
2158 
2159 	if ((ml_peer->mlpeer_state != ML_PEER_CREATED) &&
2160 	    (ml_peer->mlpeer_state != ML_PEER_ASSOC_DONE)) {
2161 		mlo_peer_lock_release(ml_peer);
2162 		return;
2163 	}
2164 
2165 	for (i = 0; i < MAX_MLO_LINK_PEERS; i++) {
2166 		peer_entry = &ml_peer->peer_list[i];
2167 		link_peer = peer_entry->link_peer;
2168 
2169 		if (!link_peer)
2170 			continue;
2171 
2172 		if (link_peer == peer)
2173 			continue;
2174 
2175 		link_vdev = wlan_peer_get_vdev(link_peer);
2176 		if (!link_vdev)
2177 			continue;
2178 
2179 		if (ml_links->num_partner_links >= WLAN_UMAC_MLO_MAX_VDEVS)
2180 			break;
2181 
2182 		ix = ml_links->num_partner_links;
2183 		ml_links->partner_link_info[ix].link_id = peer_entry->link_ix;
2184 		ml_links->partner_link_info[ix].is_bridge =
2185 		   (wlan_peer_get_peer_type(link_peer) == WLAN_PEER_MLO_BRIDGE);
2186 
2187 		qdf_copy_macaddr(&ml_links->partner_link_info[ix].link_addr,
2188 				 &peer_entry->link_addr);
2189 		ml_links->num_partner_links++;
2190 	}
2191 	mlo_peer_lock_release(ml_peer);
2192 }
2193 
2194 qdf_export_symbol(wlan_mlo_peer_get_partner_links_info);
2195 
2196 #ifdef UMAC_SUPPORT_MLNAWDS
2197 bool wlan_mlo_peer_is_nawds(struct wlan_mlo_peer_context *ml_peer)
2198 {
2199 	bool status = false;
2200 
2201 	if (!ml_peer)
2202 		return status;
2203 
2204 	mlo_peer_lock_acquire(ml_peer);
2205 	if (ml_peer->is_nawds_ml_peer)
2206 		status = true;
2207 	mlo_peer_lock_release(ml_peer);
2208 
2209 	return status;
2210 }
2211 
2212 qdf_export_symbol(wlan_mlo_peer_is_nawds);
2213 #endif
2214 
2215 #ifdef MESH_MODE_SUPPORT
2216 bool wlan_mlo_peer_is_mesh(struct wlan_mlo_peer_context *ml_peer)
2217 {
2218 	bool status = false;
2219 
2220 	if (!ml_peer)
2221 		return status;
2222 
2223 	mlo_peer_lock_acquire(ml_peer);
2224 	if (ml_peer->is_mesh_ml_peer)
2225 		status = true;
2226 	mlo_peer_lock_release(ml_peer);
2227 
2228 	return status;
2229 }
2230 
2231 qdf_export_symbol(wlan_mlo_peer_is_mesh);
2232 #endif
2233 
2234 #ifdef UMAC_MLO_AUTH_DEFER
2235 void mlo_peer_free_auth_param(struct mlpeer_auth_params *auth_params)
2236 {
2237 	if (auth_params->rs)
2238 		qdf_mem_free(auth_params->rs);
2239 
2240 	if (auth_params->wbuf)
2241 		qdf_nbuf_free(auth_params->wbuf);
2242 
2243 	qdf_mem_free(auth_params);
2244 }
2245 
2246 QDF_STATUS mlo_peer_link_auth_defer(struct wlan_mlo_peer_context *ml_peer,
2247 				    struct qdf_mac_addr *link_mac,
2248 				    struct mlpeer_auth_params *auth_params)
2249 {
2250 	uint8_t i;
2251 	uint8_t free_entries = 0;
2252 	struct mlpeer_auth_params *recv_auth;
2253 	QDF_STATUS status = QDF_STATUS_E_FAILURE;
2254 
2255 	if (!ml_peer)
2256 		return status;
2257 
2258 	mlo_peer_lock_acquire(ml_peer);
2259 	for (i = 0; i < MAX_MLO_LINK_PEERS; i++) {
2260 		recv_auth = ml_peer->pending_auth[i];
2261 		if (!recv_auth) {
2262 			free_entries++;
2263 			continue;
2264 		}
2265 		/* overwrite the entry with latest entry */
2266 		if (qdf_is_macaddr_equal(link_mac, &recv_auth->link_addr)) {
2267 			mlo_peer_free_auth_param(recv_auth);
2268 			ml_peer->pending_auth[i] = auth_params;
2269 			mlo_peer_lock_release(ml_peer);
2270 
2271 			return QDF_STATUS_SUCCESS;
2272 		}
2273 	}
2274 
2275 	if (!free_entries) {
2276 		mlo_peer_lock_release(ml_peer);
2277 		return QDF_STATUS_E_FAILURE;
2278 	}
2279 
2280 	for (i = 0; i < MAX_MLO_LINK_PEERS; i++) {
2281 		recv_auth = ml_peer->pending_auth[i];
2282 		if (!recv_auth) {
2283 			ml_peer->pending_auth[i] = auth_params;
2284 			status = QDF_STATUS_SUCCESS;
2285 			break;
2286 		}
2287 	}
2288 	mlo_peer_lock_release(ml_peer);
2289 
2290 	return status;
2291 }
2292 
2293 bool wlan_mlo_partner_peer_delete_is_allowed(struct wlan_objmgr_peer *src_peer)
2294 {
2295 	struct wlan_objmgr_vdev *vdev = NULL;
2296 	struct wlan_mlo_peer_context *ml_peer;
2297 
2298 	vdev = wlan_peer_get_vdev(src_peer);
2299 	if (!vdev)
2300 		return false;
2301 
2302 	ml_peer = src_peer->mlo_peer_ctx;
2303 	if (!wlan_peer_is_mlo(src_peer) || !ml_peer)
2304 		return false;
2305 
2306 	if (wlan_vdev_mlme_op_flags_get(vdev, WLAN_VDEV_OP_MLO_STOP_LINK_DEL) ||
2307 	    wlan_vdev_mlme_op_flags_get(vdev,
2308 					WLAN_VDEV_OP_MLO_LINK_TBTT_COMPLETE)) {
2309 		/* Single LINK MLO connection */
2310 		if (ml_peer->link_peer_cnt == 1)
2311 			return false;
2312 
2313 		/*
2314 		 * If this link is primary TQM and there is no ongoing migration
2315 		 * from this link, then issue full disconnect.
2316 		 */
2317 		if ((wlan_mlo_peer_get_primary_peer_link_id(src_peer) !=
2318 		    wlan_vdev_get_link_id(vdev)) ||
2319 		    ml_peer->primary_umac_migration_in_progress)
2320 			return false;
2321 	}
2322 
2323 	return true;
2324 }
2325 
2326 qdf_export_symbol(wlan_mlo_partner_peer_delete_is_allowed);
2327 #endif
2328 
2329 QDF_STATUS wlan_mlo_validate_reassocreq(struct wlan_mlo_peer_context *ml_peer)
2330 {
2331 	uint16_t i;
2332 	struct wlan_mlo_link_peer_entry *peer_entry;
2333 	QDF_STATUS status = QDF_STATUS_SUCCESS;
2334 
2335 	if (!ml_peer) {
2336 		mlo_err(" ml peer is NULL");
2337 		return QDF_STATUS_E_FAILURE;
2338 	}
2339 
2340 	mlo_peer_lock_acquire(ml_peer);
2341 
2342 	for (i = 0; i < MAX_MLO_LINK_PEERS; i++) {
2343 		peer_entry = &ml_peer->peer_list[i];
2344 		if (!peer_entry->link_peer)
2345 			continue;
2346 
2347 		/* Check non-assoc link peer Assoc resp buf is valid
2348 		 * (exclude bridge peer)
2349 		 */
2350 		if (i && !peer_entry->assoc_rsp_buf &&
2351 		    (wlan_peer_get_peer_type(peer_entry->link_peer) !=
2352 						WLAN_PEER_MLO_BRIDGE)) {
2353 			status = QDF_STATUS_E_FAILURE;
2354 			break;
2355 		}
2356 	}
2357 
2358 	mlo_peer_lock_release(ml_peer);
2359 
2360 	return status;
2361 }
2362 
2363 #ifdef WLAN_WSI_STATS_SUPPORT
2364 static uint32_t
2365 wlan_mlo_psoc_get_mlo_grp_idx(struct mlo_mgr_context *mlo_mgr,
2366 			      uint32_t psoc_id)
2367 {
2368 	struct mlo_wsi_info *wsi_info = NULL;
2369 	struct mlo_wsi_psoc_grp *mlo_psoc_grp;
2370 	uint8_t grp_id, i;
2371 
2372 	if (!mlo_mgr)
2373 		return MLO_WSI_MAX_MLO_GRPS;
2374 
2375 	/* Retrieve the WSI link info structure */
2376 	wsi_info = mlo_mgr->wsi_info;
2377 	if (!wsi_info)
2378 		return MLO_WSI_MAX_MLO_GRPS;
2379 
2380 	for (grp_id = 0; grp_id < MLO_WSI_MAX_MLO_GRPS; grp_id++) {
2381 		mlo_psoc_grp = &wsi_info->mlo_psoc_grp[grp_id];
2382 		for (i = 0; i < mlo_psoc_grp->num_psoc; i++) {
2383 			if (mlo_psoc_grp->psoc_order[i] == psoc_id)
2384 				return grp_id;
2385 		}
2386 	}
2387 
2388 	return MLO_WSI_MAX_MLO_GRPS;
2389 }
2390 
2391 QDF_STATUS wlan_mlo_wsi_link_info_send_cmd(void)
2392 {
2393 	struct mlo_mgr_context *mlo_mgr = NULL;
2394 	struct mlo_wsi_info *wsi_info = NULL;
2395 	struct wlan_lmac_if_mlo_tx_ops *mlo_tx_ops = NULL;
2396 	struct wlan_objmgr_psoc *psoc_objmgr = NULL;
2397 	struct wlan_objmgr_pdev *pdev = NULL;
2398 	QDF_STATUS error = QDF_STATUS_SUCCESS;
2399 	int i, j;
2400 
2401 	/* Retrieve the MLO manager context */
2402 	mlo_mgr = wlan_objmgr_get_mlo_ctx();
2403 	if (!mlo_mgr)
2404 		return QDF_STATUS_E_INVAL;
2405 
2406 	/* Retrieve the WSI link info structure */
2407 	wsi_info = mlo_mgr->wsi_info;
2408 	if (!wsi_info)
2409 		return QDF_STATUS_E_INVAL;
2410 
2411 	if (wsi_info->block_wmi_cmd) {
2412 		mlo_debug("WMI command is blocked");
2413 		return error;
2414 	}
2415 	/*
2416 	 * Check each PSOC if the WMI command needs to be sent
2417 	 * and send it for each PDEV in that PSOC
2418 	 */
2419 	for (i = 0; i < WLAN_OBJMGR_MAX_DEVICES; i++) {
2420 		if (!wsi_info->link_stats[i].send_wmi_cmd)
2421 			continue;
2422 
2423 		psoc_objmgr = wlan_objmgr_get_psoc_by_id(i, WLAN_MLO_MGR_ID);
2424 		if (!psoc_objmgr) {
2425 			mlo_err("Could not get PSOC obj for index %d", i);
2426 			continue;
2427 		}
2428 
2429 		mlo_tx_ops = &psoc_objmgr->soc_cb.tx_ops->mlo_ops;
2430 		if (!mlo_tx_ops || !mlo_tx_ops->send_wsi_link_info_cmd) {
2431 			mlo_err("mlo_tx_ops is null");
2432 			wlan_objmgr_psoc_release_ref(psoc_objmgr,
2433 						     WLAN_MLO_MGR_ID);
2434 			return QDF_STATUS_E_NULL_VALUE;
2435 		}
2436 
2437 		for (j = 0; j < psoc_objmgr->soc_objmgr.wlan_pdev_count; j++) {
2438 			pdev = psoc_objmgr->soc_objmgr.wlan_pdev_list[j];
2439 			if (!pdev)
2440 				continue;
2441 
2442 			if (mlo_tx_ops->send_wsi_link_info_cmd(
2443 					pdev, &wsi_info->link_stats[i]) !=
2444 						QDF_STATUS_SUCCESS) {
2445 				mlo_err("Could not send WMI command for PDEV %d in PSOC %d",
2446 					j, i);
2447 				error = QDF_STATUS_E_FAILURE;
2448 			} else {
2449 				wsi_info->link_stats[i].send_wmi_cmd = false;
2450 			}
2451 		}
2452 		wlan_objmgr_psoc_release_ref(psoc_objmgr, WLAN_MLO_MGR_ID);
2453 	}
2454 
2455 	return error;
2456 }
2457 
2458 static uint32_t wlan_mlo_psoc_get_ix_in_grp(struct mlo_mgr_context *mlo_mgr,
2459 					    uint32_t grp_id,
2460 					    uint32_t prim_psoc_id)
2461 {
2462 	uint32_t i;
2463 
2464 	if (!mlo_mgr) {
2465 		mlo_err("NULL mlo_mgr");
2466 		return 0xFF;
2467 	}
2468 
2469 	/* Iterate through the PSOC order and find the ID */
2470 	for (i = 0; i < mlo_mgr->wsi_info->mlo_psoc_grp[grp_id].num_psoc; i++) {
2471 		if (mlo_mgr->wsi_info->mlo_psoc_grp[grp_id].psoc_order[i] ==
2472 		    prim_psoc_id) {
2473 			return i;
2474 		}
2475 	}
2476 
2477 	return 0xFF;
2478 }
2479 
2480 static uint32_t
2481 wlan_mlo_get_wsi_next_psoc(struct mlo_wsi_psoc_grp *mlo_psoc_grp,
2482 			   uint32_t prim_psoc_id, uint32_t n)
2483 {
2484 	uint32_t i, j;
2485 	uint32_t psoc_index = MLO_WSI_PSOC_ID_MAX;
2486 
2487 	if (!n)
2488 		return psoc_index;
2489 
2490 	for (i = 0; i < mlo_psoc_grp->num_psoc; i++) {
2491 		if (mlo_psoc_grp->psoc_order[i] == prim_psoc_id) {
2492 			psoc_index = i;
2493 			break;
2494 		}
2495 	}
2496 
2497 	if (psoc_index == MLO_WSI_PSOC_ID_MAX)
2498 		return psoc_index;
2499 
2500 	for (i = 1; i <= WLAN_OBJMGR_MAX_DEVICES; i++) {
2501 		j = (psoc_index + i) % WLAN_OBJMGR_MAX_DEVICES;
2502 		if (mlo_psoc_grp->psoc_order[j] != MLO_WSI_PSOC_ID_MAX)
2503 			n--;
2504 		if (!n)
2505 			return mlo_psoc_grp->psoc_order[j];
2506 	}
2507 
2508 	return MLO_WSI_PSOC_ID_MAX;
2509 }
2510 
2511 static QDF_STATUS
2512 wlan_mlo_peer_wsi_link_update(struct wlan_mlo_peer_context *ml_peer, bool add)
2513 {
2514 	struct mlo_mgr_context *mlo_mgr = NULL;
2515 	struct mlo_wsi_info *wsi_info = NULL;
2516 	struct wlan_mlo_link_peer_entry *peer_entry = NULL;
2517 	uint32_t prim_psoc_id = 0xFF;
2518 	uint32_t sec_psoc_id[MAX_MLO_LINK_PEERS] = {0xFF};
2519 	uint32_t hops, hop_id;
2520 	uint32_t prim_grp_idx, sec_grp_idx;
2521 	uint32_t prim_psoc_ix_grp, sec_psoc_ix_grp;
2522 	uint32_t i, j, n;
2523 	struct mlo_wsi_psoc_grp *mlo_psoc_grp;
2524 	struct wlan_objmgr_psoc *psoc;
2525 
2526 	/* Check if ml_peer is valid */
2527 	if (!ml_peer) {
2528 		mlo_err("ML peer is null");
2529 		return QDF_STATUS_E_INVAL;
2530 	}
2531 
2532 	/* Retrieve the MLO manager context */
2533 	mlo_mgr = wlan_objmgr_get_mlo_ctx();
2534 	if (!mlo_mgr) {
2535 		mlo_err("ML MGR is NULL for ML peer" QDF_MAC_ADDR_FMT,
2536 			QDF_MAC_ADDR_REF(ml_peer->peer_mld_addr.bytes));
2537 		return QDF_STATUS_E_INVAL;
2538 	}
2539 
2540 	/* Retrieve the WSI link info structure */
2541 	wsi_info = mlo_mgr->wsi_info;
2542 	if (!wsi_info) {
2543 		mlo_err("WSI Info is NULL for ML peer" QDF_MAC_ADDR_FMT,
2544 			QDF_MAC_ADDR_REF(ml_peer->peer_mld_addr.bytes));
2545 		return QDF_STATUS_E_INVAL;
2546 	}
2547 
2548 	prim_psoc_id = ml_peer->primary_umac_psoc_id;
2549 	/* Populate the primary PSOC ID of the respective group */
2550 	prim_grp_idx = wlan_mlo_psoc_get_mlo_grp_idx(mlo_mgr, prim_psoc_id);
2551 	if (prim_grp_idx == MLO_WSI_MAX_MLO_GRPS) {
2552 		mlo_err("Group index is invalid for ML peer" QDF_MAC_ADDR_FMT,
2553 			QDF_MAC_ADDR_REF(ml_peer->peer_mld_addr.bytes));
2554 		return QDF_STATUS_E_INVAL;
2555 	}
2556 
2557 	/* Populate MLO primary and secondary link */
2558 	for (i = 0, j = 0; i < MAX_MLO_LINK_PEERS; i++) {
2559 		peer_entry = &ml_peer->peer_list[i];
2560 		if (!peer_entry->link_peer) {
2561 			mlo_debug("link peer is null");
2562 			continue;
2563 		}
2564 
2565 		psoc = wlan_peer_get_psoc(peer_entry->link_peer);
2566 		if (!mlo_get_wsi_stats_info_support(psoc)) {
2567 			mlo_debug("WSI stats support is not enabled on psoc %d",
2568 				  wlan_psoc_get_id(psoc));
2569 			return QDF_STATUS_E_INVAL;
2570 		}
2571 
2572 		/*
2573 		 * Consider all non-primary peers as secondary links.
2574 		 * Additionally, consider all active peers as secondary link if
2575 		 * the TQM is on another PSOC with bridge peer.
2576 		 */
2577 		if (!peer_entry->is_primary) {
2578 			sec_psoc_id[j] = wlan_vdev_get_psoc_id(
2579 						wlan_peer_get_vdev(
2580 						peer_entry->link_peer));
2581 
2582 			sec_grp_idx = wlan_mlo_psoc_get_mlo_grp_idx
2583 							(mlo_mgr,
2584 							 sec_psoc_id[j]);
2585 			if (sec_grp_idx != prim_grp_idx) {
2586 				mlo_err("Secondary link is not part of same MLO group as primary link");
2587 				continue;
2588 			}
2589 			j++;
2590 		}
2591 	}
2592 
2593 	/*
2594 	 * Logic for finding ingress and egress stats:
2595 	 * For a given MLO group, there is a PSOC order
2596 	 *
2597 	 * If there is secondary link, Increment the egress count for
2598 	 * the primary PSOC
2599 	 * (1) Iterate through each secondary link
2600 	 *      (1.1) Set the WMI command to true for that PSOC
2601 	 *      (1.2) Calculate the number of hops from the secondary link
2602 	 *            to that primary link within the group.
2603 	 *      (1.3) Iterate through a decrement sequence from the hop_count
2604 	 *            (1.3.1) Increment the ingress count for that PSOC index
2605 	 */
2606 	prim_psoc_ix_grp = wlan_mlo_psoc_get_ix_in_grp(mlo_mgr, prim_grp_idx,
2607 						       prim_psoc_id);
2608 
2609 	wsi_info->link_stats[prim_psoc_id].send_wmi_cmd = true;
2610 	mlo_psoc_grp = &wsi_info->mlo_psoc_grp[prim_grp_idx];
2611 
2612 	if (j) {
2613 		wsi_info->link_stats[prim_psoc_id].send_wmi_cmd = true;
2614 		if (add)
2615 			wsi_info->link_stats[prim_psoc_id].egress_cnt++;
2616 		else
2617 			wsi_info->link_stats[prim_psoc_id].egress_cnt--;
2618 	}
2619 
2620 	n = 1;
2621 	for (i = 0; i < j; i++) {
2622 		sec_psoc_ix_grp = wlan_mlo_psoc_get_ix_in_grp(mlo_mgr,
2623 							      prim_grp_idx,
2624 							      sec_psoc_id[i]);
2625 		hops = qdf_min(mlo_psoc_grp->num_psoc -
2626 			       (prim_psoc_ix_grp - sec_psoc_ix_grp),
2627 				(sec_psoc_ix_grp - prim_psoc_ix_grp));
2628 
2629 
2630 		if (hops > n) {
2631 			hop_id = wlan_mlo_get_wsi_next_psoc(mlo_psoc_grp,
2632 							    prim_psoc_id, n);
2633 			n++;
2634 			if (hop_id == MLO_WSI_PSOC_ID_MAX)
2635 				continue;
2636 
2637 			wsi_info->link_stats[hop_id].send_wmi_cmd = true;
2638 			if (add)
2639 				wsi_info->link_stats[hop_id].ingress_cnt++;
2640 			else
2641 				wsi_info->link_stats[hop_id].ingress_cnt--;
2642 		}
2643 	}
2644 
2645 	/* Check if WMI bit is set, if yes, then send the command */
2646 	if (wlan_mlo_wsi_link_info_send_cmd() != QDF_STATUS_SUCCESS) {
2647 		mlo_err("WSI link info not sent for ML peer" QDF_MAC_ADDR_FMT,
2648 			QDF_MAC_ADDR_REF(ml_peer->peer_mld_addr.bytes));
2649 		return QDF_STATUS_E_FAILURE;
2650 	}
2651 
2652 	return QDF_STATUS_SUCCESS;
2653 }
2654 
2655 QDF_STATUS wlan_mlo_peer_wsi_link_add(struct wlan_mlo_peer_context *ml_peer)
2656 {
2657 	if (!ml_peer) {
2658 		mlo_err("Invalid peer");
2659 		return QDF_STATUS_E_INVAL;
2660 	}
2661 
2662 	return wlan_mlo_peer_wsi_link_update(ml_peer, 1);
2663 }
2664 
2665 QDF_STATUS wlan_mlo_peer_wsi_link_delete(struct wlan_mlo_peer_context *ml_peer)
2666 {
2667 	if (!ml_peer) {
2668 		mlo_err("Invalid peer");
2669 		return QDF_STATUS_E_INVAL;
2670 	}
2671 
2672 	return wlan_mlo_peer_wsi_link_update(ml_peer, 0);
2673 }
2674 
2675 void wlan_mlo_wsi_stats_block_cmd(void)
2676 {
2677 	struct mlo_mgr_context *mlo_mgr = NULL;
2678 	struct mlo_wsi_info *wsi_info = NULL;
2679 
2680 	/* Retrieve the MLO manager context */
2681 	mlo_mgr = wlan_objmgr_get_mlo_ctx();
2682 	if (!mlo_mgr)
2683 		return;
2684 
2685 	/* Retrieve the WSI link info structure */
2686 	wsi_info = mlo_mgr->wsi_info;
2687 	if (!wsi_info)
2688 		return;
2689 
2690 	wsi_info->block_wmi_cmd++;
2691 }
2692 
2693 void wlan_mlo_wsi_stats_allow_cmd(void)
2694 {
2695 	struct mlo_mgr_context *mlo_mgr = NULL;
2696 	struct mlo_wsi_info *wsi_info = NULL;
2697 
2698 	/* Retrieve the MLO manager context */
2699 	mlo_mgr = wlan_objmgr_get_mlo_ctx();
2700 	if (!mlo_mgr)
2701 		return;
2702 
2703 	/* Retrieve the WSI link info structure */
2704 	wsi_info = mlo_mgr->wsi_info;
2705 	if (!wsi_info)
2706 		return;
2707 
2708 	if (wsi_info->block_wmi_cmd)
2709 		wsi_info->block_wmi_cmd--;
2710 }
2711 
2712 #else
2713 void wlan_mlo_wsi_stats_block_cmd(void)
2714 {
2715 }
2716 
2717 void wlan_mlo_wsi_stats_allow_cmd(void)
2718 {
2719 }
2720 
2721 QDF_STATUS wlan_mlo_wsi_link_info_send_cmd(void)
2722 {
2723 	return QDF_STATUS_SUCCESS;
2724 }
2725 
2726 QDF_STATUS wlan_mlo_peer_wsi_link_add(struct wlan_mlo_peer_context *ml_peer)
2727 {
2728 	return QDF_STATUS_SUCCESS;
2729 }
2730 
2731 QDF_STATUS wlan_mlo_peer_wsi_link_delete(struct wlan_mlo_peer_context *ml_peer)
2732 {
2733 	return QDF_STATUS_SUCCESS;
2734 }
2735 #endif
2736 
2737 void wlan_mlo_ap_vdev_add_assoc_entry(struct wlan_objmgr_vdev *vdev,
2738 				      struct qdf_mac_addr *mld_addr)
2739 {
2740 	struct wlan_mlo_dev_context *mld_ctx = vdev->mlo_dev_ctx;
2741 	struct wlan_mlo_sta_assoc_pending_list *assoc_list;
2742 	struct wlan_mlo_sta_entry *sta_entry = NULL;
2743 
2744 	if (!mld_ctx || !wlan_vdev_mlme_is_mlo_ap(vdev))
2745 		return;
2746 
2747 	assoc_list = &mld_ctx->ap_ctx->assoc_list;
2748 
2749 	sta_entry = wlan_mlo_ap_vdev_find_assoc_entry(vdev, mld_addr);
2750 	if (sta_entry) {
2751 		mlo_err("Duplicate entry " QDF_MAC_ADDR_FMT,
2752 			QDF_MAC_ADDR_REF(mld_addr->bytes));
2753 		return;
2754 	}
2755 
2756 	sta_entry = qdf_mem_malloc(sizeof(*sta_entry));
2757 	if (!sta_entry)
2758 		return;
2759 
2760 	qdf_copy_macaddr((struct qdf_mac_addr *)&sta_entry->peer_mld_addr,
2761 			 (struct qdf_mac_addr *)&mld_addr[0]);
2762 
2763 	qdf_spin_lock_bh(&assoc_list->list_lock);
2764 	qdf_list_insert_back(&assoc_list->peer_list, &sta_entry->mac_node);
2765 	qdf_spin_unlock_bh(&assoc_list->list_lock);
2766 }
2767 
2768 void wlan_mlo_ap_vdev_del_assoc_entry(struct wlan_objmgr_vdev *vdev,
2769 				      struct qdf_mac_addr *mld_addr)
2770 {
2771 	struct wlan_mlo_dev_context *mld_ctx = vdev->mlo_dev_ctx;
2772 	struct wlan_mlo_sta_assoc_pending_list *assoc_list;
2773 	struct wlan_mlo_sta_entry *sta_entry = NULL;
2774 
2775 	if (!mld_ctx || !wlan_vdev_mlme_is_mlo_ap(vdev))
2776 		return;
2777 
2778 	assoc_list = &mld_ctx->ap_ctx->assoc_list;
2779 	sta_entry = wlan_mlo_ap_vdev_find_assoc_entry(vdev, mld_addr);
2780 	if (!sta_entry)
2781 		return;
2782 
2783 	qdf_spin_lock_bh(&assoc_list->list_lock);
2784 	qdf_list_remove_node(&assoc_list->peer_list, &sta_entry->mac_node);
2785 	qdf_spin_unlock_bh(&assoc_list->list_lock);
2786 
2787 	qdf_mem_free(sta_entry);
2788 }
2789 
2790 static inline struct wlan_mlo_sta_entry *
2791 wlan_mlo_assoc_list_peek_head(qdf_list_t *assoc_list)
2792 {
2793 	struct wlan_mlo_sta_entry *sta_entry = NULL;
2794 	qdf_list_node_t *list_node = NULL;
2795 
2796 	/* This API is invoked with lock acquired, do not add log prints */
2797 	if (qdf_list_peek_front(assoc_list, &list_node) != QDF_STATUS_SUCCESS)
2798 		return NULL;
2799 
2800 	sta_entry = qdf_container_of(list_node,
2801 				     struct wlan_mlo_sta_entry, mac_node);
2802 	return sta_entry;
2803 }
2804 
2805 static inline struct wlan_mlo_sta_entry *
2806 wlan_mlo_sta_get_next_sta_entry(qdf_list_t *assoc_list,
2807 				struct wlan_mlo_sta_entry *sta_entry)
2808 {
2809 	struct wlan_mlo_sta_entry *next_sta_entry = NULL;
2810 	qdf_list_node_t *node = &sta_entry->mac_node;
2811 	qdf_list_node_t *next_node = NULL;
2812 
2813 	/* This API is invoked with lock acquired, do not add log prints */
2814 	if (!node)
2815 		return NULL;
2816 
2817 	if (qdf_list_peek_next(assoc_list, node, &next_node) !=
2818 				QDF_STATUS_SUCCESS)
2819 		return NULL;
2820 
2821 	next_sta_entry = qdf_container_of(next_node,
2822 					  struct wlan_mlo_sta_entry, mac_node);
2823 	return next_sta_entry;
2824 }
2825 
2826 struct wlan_mlo_sta_entry *
2827 wlan_mlo_ap_vdev_find_assoc_entry(struct wlan_objmgr_vdev *vdev,
2828 				  struct qdf_mac_addr *mld_addr)
2829 {
2830 	struct wlan_mlo_dev_context *mld_ctx = vdev->mlo_dev_ctx;
2831 	struct wlan_mlo_sta_assoc_pending_list *assoc_list;
2832 	struct wlan_mlo_sta_entry *sta_entry = NULL;
2833 	struct wlan_mlo_sta_entry *next_sta_entry = NULL;
2834 
2835 	if (!mld_ctx || !wlan_vdev_mlme_is_mlo_ap(vdev))
2836 		return NULL;
2837 
2838 	assoc_list = &mld_ctx->ap_ctx->assoc_list;
2839 	if (qdf_list_empty(&assoc_list->peer_list)) {
2840 		mlo_info("list is empty");
2841 		return NULL;
2842 	}
2843 	qdf_spin_lock_bh(&assoc_list->list_lock);
2844 
2845 	sta_entry = wlan_mlo_assoc_list_peek_head(&assoc_list->peer_list);
2846 	while (sta_entry) {
2847 		if (qdf_is_macaddr_equal(&sta_entry->peer_mld_addr, mld_addr)) {
2848 			qdf_spin_unlock_bh(&assoc_list->list_lock);
2849 			return sta_entry;
2850 		}
2851 
2852 		next_sta_entry =
2853 		wlan_mlo_sta_get_next_sta_entry(&assoc_list->peer_list,
2854 						sta_entry);
2855 		sta_entry = next_sta_entry;
2856 	}
2857 	qdf_spin_unlock_bh(&assoc_list->list_lock);
2858 
2859 	return NULL;
2860 }
2861 
2862