xref: /wlan-dirver/qca-wifi-host-cmn/umac/mlo_mgr/src/wlan_mlo_mgr_peer.c (revision ce3c51dc44030780cb63103cbb4a4b0e7fc5129f)
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 
1019 static QDF_STATUS mlo_dev_get_link_vdevs(
1020 			struct wlan_objmgr_vdev *vdev,
1021 			struct wlan_mlo_dev_context *ml_dev,
1022 			struct mlo_partner_info *ml_info,
1023 			struct wlan_objmgr_vdev *link_vdevs[])
1024 {
1025 	uint16_t i, j;
1026 	struct wlan_objmgr_vdev *vdev_link;
1027 	uint8_t link_id;
1028 
1029 	if (!ml_dev) {
1030 		mlo_err("ml_dev is null");
1031 		return QDF_STATUS_E_INVAL;
1032 	}
1033 
1034 	if (!ml_info) {
1035 		mlo_err("ml_info is null");
1036 		return QDF_STATUS_E_INVAL;
1037 	}
1038 
1039 	mlo_debug("num_partner_links %d", ml_info->num_partner_links);
1040 	for (i = 0; i < ml_info->num_partner_links; i++) {
1041 		link_id = ml_info->partner_link_info[i].link_id;
1042 		vdev_link = mlo_get_vdev_by_link_id(vdev, link_id);
1043 		if (vdev_link) {
1044 			link_vdevs[i] = vdev_link;
1045 		} else {
1046 			/* release ref which were taken before failure */
1047 			for (j = 0; j < i; j++) {
1048 				vdev_link = link_vdevs[j];
1049 				if (!vdev_link)
1050 					continue;
1051 
1052 				wlan_objmgr_vdev_release_ref(vdev_link,
1053 							     WLAN_MLO_MGR_ID);
1054 			}
1055 			return QDF_STATUS_E_INVAL;
1056 		}
1057 	}
1058 
1059 	return QDF_STATUS_SUCCESS;
1060 }
1061 
1062 static void mlo_dev_release_link_vdevs(
1063 			struct wlan_objmgr_vdev *link_vdevs[])
1064 {
1065 	uint16_t i;
1066 	struct wlan_objmgr_vdev *vdev_link;
1067 
1068 	for (i = 0; i < WLAN_UMAC_MLO_MAX_VDEVS; i++) {
1069 		vdev_link = link_vdevs[i];
1070 		if (!vdev_link)
1071 			continue;
1072 
1073 		wlan_objmgr_vdev_release_ref(vdev_link, WLAN_MLO_MGR_ID);
1074 	}
1075 }
1076 
1077 #ifdef WLAN_FEATURE_11BE
1078 static void
1079 wlan_mlo_peer_set_t2lm_enable_val(struct wlan_mlo_peer_context *ml_peer,
1080 				  struct mlo_partner_info *ml_info)
1081 {
1082 	ml_peer->t2lm_policy.t2lm_enable_val = ml_info->t2lm_enable_val;
1083 }
1084 
1085 static void
1086 wlan_mlo_peer_initialize_epcs_info(struct wlan_mlo_peer_context *ml_peer)
1087 {
1088 	ml_peer->epcs_info.state = EPCS_DOWN;
1089 	ml_peer->epcs_info.self_gen_dialog_token = 0;
1090 }
1091 
1092 #else
1093 static void
1094 wlan_mlo_peer_set_t2lm_enable_val(struct wlan_mlo_peer_context *ml_peer,
1095 				  struct mlo_partner_info *ml_info)
1096 {}
1097 
1098 static void
1099 wlan_mlo_peer_initialize_epcs_info(struct wlan_mlo_peer_context *ml_peer)
1100 {}
1101 #endif /* WLAN_FEATURE_11BE */
1102 
1103 #if defined(WLAN_FEATURE_11BE_MLO) && defined(WLAN_MLO_MULTI_CHIP)
1104 struct wlan_objmgr_vdev*
1105 mlo_get_link_vdev_from_psoc_id(struct wlan_mlo_dev_context *ml_dev,
1106 			       uint8_t psoc_id, bool get_bridge_vdev)
1107 {
1108 	uint8_t i;
1109 	uint16_t num_bridge_vdev = 0;
1110 	uint8_t max_vdevs = WLAN_UMAC_MLO_MAX_BRIDGE_VDEVS;
1111 	struct wlan_objmgr_vdev *link_vdev;
1112 	QDF_STATUS status;
1113 
1114 	if (WLAN_OBJMGR_MAX_DEVICES <= psoc_id)
1115 		return NULL;
1116 
1117 	if (!ml_dev)
1118 		return NULL;
1119 
1120 	/* if there are no bridge vdevs available,
1121 	 * fall back to actual link vdevs
1122 	 */
1123 	status = mlo_ap_get_bridge_vdev_count(ml_dev, &num_bridge_vdev);
1124 	if (!get_bridge_vdev || (status != QDF_STATUS_SUCCESS) ||
1125 	    !num_bridge_vdev)
1126 		max_vdevs = WLAN_UMAC_MLO_MAX_VDEVS;
1127 
1128 	for (i = 0; i < max_vdevs; i++) {
1129 		if (max_vdevs == WLAN_UMAC_MLO_MAX_BRIDGE_VDEVS)
1130 			link_vdev = ml_dev->wlan_bridge_vdev_list[i];
1131 		else
1132 			link_vdev = ml_dev->wlan_vdev_list[i];
1133 		if (!link_vdev)
1134 			continue;
1135 		if (psoc_id != wlan_vdev_get_psoc_id(link_vdev))
1136 			continue;
1137 		if (wlan_objmgr_vdev_try_get_ref(link_vdev, WLAN_MLO_MGR_ID) !=
1138 							QDF_STATUS_SUCCESS) {
1139 			mlo_err("VDEV is not in created state");
1140 			return NULL;
1141 		}
1142 		return link_vdev;
1143 	}
1144 
1145 	return NULL;
1146 }
1147 
1148 static
1149 QDF_STATUS mlo_bridge_peer_create_post(struct wlan_mlo_dev_context *ml_dev,
1150 				       struct wlan_mlo_peer_context *ml_peer,
1151 				       uint8_t psoc_id)
1152 {
1153 	struct peer_create_notif_s peer_create;
1154 	struct wlan_objmgr_vdev *vdev_link;
1155 	QDF_STATUS status;
1156 
1157 	/* Bridge peer not required */
1158 	if (psoc_id >= WLAN_OBJMGR_MAX_DEVICES)
1159 		return QDF_STATUS_SUCCESS;
1160 
1161 	vdev_link = mlo_get_link_vdev_from_psoc_id(ml_dev, psoc_id, true);
1162 
1163 	if (!vdev_link) {
1164 		mlo_err("VDEV derivation in unsuccessful for %u psoc",
1165 			psoc_id);
1166 		return QDF_STATUS_E_FAILURE;
1167 	}
1168 
1169 	peer_create.vdev_link = vdev_link;
1170 	wlan_mlo_peer_get_ref(ml_peer);
1171 	peer_create.ml_peer = ml_peer;
1172 
1173 	qdf_copy_macaddr(&peer_create.addr,
1174 			 &ml_peer->peer_mld_addr);
1175 
1176 	peer_create.frm_buf = NULL;
1177 
1178 	status = mlo_msgq_post(MLO_BRIDGE_PEER_CREATE, ml_dev, &peer_create);
1179 	if (status != QDF_STATUS_SUCCESS) {
1180 		wlan_mlo_peer_release_ref(ml_peer);
1181 		wlan_objmgr_vdev_release_ref(vdev_link, WLAN_MLO_MGR_ID);
1182 	}
1183 
1184 	return status;
1185 }
1186 
1187 static QDF_STATUS
1188 wlan_mlo_get_bridge_peer_psoc_id(struct wlan_objmgr_vdev *vdev,
1189 				 struct wlan_mlo_peer_context *ml_peer,
1190 				 struct wlan_objmgr_vdev *link_vdevs[],
1191 				 uint8_t num_partner_links,
1192 				 uint8_t *bridge_psoc_id)
1193 {
1194 	struct wlan_mlo_dev_context *ml_dev;
1195 	struct wlan_objmgr_vdev *ml_vdev;
1196 	uint8_t psoc_ids[WLAN_NUM_TWO_LINK_PSOC];
1197 	uint8_t comp_psoc_id, i, is_adjacent;
1198 	uint8_t bridge_peer_psoc_id = WLAN_OBJMGR_MAX_DEVICES;
1199 	uint16_t num_bridge_vdev = 0;
1200 	uint8_t max_vdevs = WLAN_UMAC_MLO_MAX_BRIDGE_VDEVS;
1201 	QDF_STATUS status;
1202 
1203 	if (wlan_vdev_mlme_get_opmode(vdev) != QDF_SAP_MODE)
1204 		return QDF_STATUS_SUCCESS;
1205 
1206 	/* Return from here for 3 link association */
1207 	if (WLAN_NUM_TWO_LINK_PSOC != num_partner_links)
1208 		return QDF_STATUS_SUCCESS;
1209 
1210 	ml_dev = vdev->mlo_dev_ctx;
1211 	if (!ml_dev)
1212 		return QDF_STATUS_E_FAILURE;
1213 
1214 	for (i = 0; i < WLAN_NUM_TWO_LINK_PSOC; i++)
1215 		psoc_ids[i] = wlan_vdev_get_psoc_id(link_vdevs[i]);
1216 
1217 	status = mlo_chip_adjacent(psoc_ids[0], psoc_ids[1],
1218 				   &is_adjacent);
1219 	if (QDF_STATUS_SUCCESS != status) {
1220 		mlo_err("Unable to get chip adjacency for " QDF_MAC_ADDR_FMT ", psoc_0 %u, psoc_1 %u",
1221 			QDF_MAC_ADDR_REF(ml_peer->peer_mld_addr.bytes),
1222 			psoc_ids[0], psoc_ids[1]);
1223 		return status;
1224 	}
1225 
1226 	if (is_adjacent)
1227 		return QDF_STATUS_SUCCESS;
1228 
1229 	/* if there are no bridge vdevs available,
1230 	 * fall back to actual link vdevs
1231 	 */
1232 	status = mlo_ap_get_bridge_vdev_count(ml_dev, &num_bridge_vdev);
1233 	if ((status != QDF_STATUS_SUCCESS) || !num_bridge_vdev) {
1234 		mlo_err_rl("Using actual vdev as bridge vdev");
1235 		max_vdevs = WLAN_UMAC_MLO_MAX_VDEVS;
1236 	}
1237 
1238 	for (i = 0; i < max_vdevs; i++) {
1239 		if (max_vdevs == WLAN_UMAC_MLO_MAX_BRIDGE_VDEVS)
1240 			ml_vdev = ml_dev->wlan_bridge_vdev_list[i];
1241 		else
1242 			ml_vdev = ml_dev->wlan_vdev_list[i];
1243 		if (!ml_vdev || (wlan_vdev_is_up(ml_vdev) != QDF_STATUS_SUCCESS))
1244 			continue;
1245 		comp_psoc_id = wlan_vdev_get_psoc_id(ml_vdev);
1246 		if ((comp_psoc_id != psoc_ids[0]) &&
1247 		    (comp_psoc_id != psoc_ids[1])) {
1248 			bridge_peer_psoc_id = comp_psoc_id;
1249 			break;
1250 		}
1251 	}
1252 
1253 	if (bridge_peer_psoc_id >= WLAN_OBJMGR_MAX_DEVICES) {
1254 		mlo_err("Invalid psoc or psoc not found for " QDF_MAC_ADDR_FMT " psoc %u",
1255 			ether_sprintf(ml_peer->peer_mld_addr.bytes),
1256 			bridge_peer_psoc_id);
1257 		return QDF_STATUS_E_FAILURE;
1258 	}
1259 
1260 	/* Check if derived psoc is adjecent to both links */
1261 	for (i = 0; i < WLAN_NUM_TWO_LINK_PSOC; i++) {
1262 		status = mlo_chip_adjacent(psoc_ids[i], bridge_peer_psoc_id,
1263 					   &is_adjacent);
1264 		if (QDF_STATUS_SUCCESS != status) {
1265 			mlo_err("Unable to get chip adjacency for " QDF_MAC_ADDR_FMT ", psoc_0 %u, psoc_1 %u",
1266 				QDF_MAC_ADDR_REF(ml_peer->peer_mld_addr.bytes),
1267 				psoc_ids[i], bridge_peer_psoc_id);
1268 			return status;
1269 		}
1270 		if (!is_adjacent) {
1271 			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",
1272 				QDF_MAC_ADDR_REF(ml_peer->peer_mld_addr.bytes),
1273 				psoc_ids[0], psoc_ids[1], bridge_peer_psoc_id);
1274 			return QDF_STATUS_E_FAILURE;
1275 		}
1276 	}
1277 
1278 	/* Add vdev corresponds to bridge link to link_vdevs so
1279 	 * that primary UMAC derivation follows 3-link assoc.
1280 	 */
1281 	for (i = 0; i < WLAN_UMAC_MLO_MAX_VDEVS; i++) {
1282 		if (link_vdevs[i])
1283 			continue;
1284 
1285 		link_vdevs[i] = mlo_get_link_vdev_from_psoc_id(ml_dev,
1286 							       bridge_peer_psoc_id,
1287 							       true);
1288 		if (!link_vdevs[i])
1289 			return QDF_STATUS_E_FAILURE;
1290 
1291 		ml_peer->max_links++;
1292 		*bridge_psoc_id = bridge_peer_psoc_id;
1293 		break;
1294 	}
1295 
1296 	if (i == WLAN_UMAC_MLO_MAX_VDEVS) {
1297 		mlo_err("Unable to append bridge peer vdev to link vdev list");
1298 		return QDF_STATUS_E_FAILURE;
1299 	}
1300 
1301 	mlo_debug("%u is adjecent psoc for " QDF_MAC_ADDR_FMT " is_adjacent %u",
1302 		  bridge_peer_psoc_id,
1303 		  QDF_MAC_ADDR_REF(ml_peer->peer_mld_addr.bytes),
1304 		  is_adjacent);
1305 
1306 	return status;
1307 }
1308 #else
1309 static
1310 QDF_STATUS mlo_bridge_peer_create_post(struct wlan_mlo_dev_context *ml_dev,
1311 				       struct wlan_mlo_peer_context *ml_peer,
1312 				       uint8_t psoc_id)
1313 {
1314 	return QDF_STATUS_SUCCESS;
1315 }
1316 
1317 static QDF_STATUS
1318 wlan_mlo_get_bridge_peer_psoc_id(struct wlan_objmgr_vdev *vdev,
1319 				 struct wlan_mlo_peer_context *ml_peer,
1320 				 struct wlan_objmgr_vdev *link_vdevs[],
1321 				 uint8_t num_partner_links,
1322 				 uint8_t *bridge_psoc_id)
1323 {
1324 	return QDF_STATUS_SUCCESS;
1325 }
1326 #endif
1327 
1328 QDF_STATUS wlan_mlo_peer_asreq(struct wlan_objmgr_vdev *vdev,
1329 			       struct wlan_objmgr_peer *link_peer,
1330 			       struct mlo_partner_info *ml_info,
1331 			       qdf_nbuf_t frm_buf)
1332 {
1333 	struct wlan_mlo_dev_context *ml_dev;
1334 	struct wlan_mlo_peer_context *ml_peer = NULL;
1335 	struct wlan_objmgr_vdev *link_vdevs[WLAN_UMAC_MLO_MAX_VDEVS] = { NULL };
1336 	struct wlan_objmgr_vdev *vdev_link;
1337 	QDF_STATUS status;
1338 	uint16_t i;
1339 	uint16_t j;
1340 	uint16_t link_count;
1341 	struct wlan_mlo_link_peer_entry *peer_entry;
1342 	struct wlan_objmgr_peer *iter_peer;
1343 
1344 	/* get ML VDEV from VDEV */
1345 	ml_dev = vdev->mlo_dev_ctx;
1346 	if (!ml_dev) {
1347 		mlo_err("ML dev ctx is NULL");
1348 		return QDF_STATUS_E_NULL_VALUE;
1349 	}
1350 
1351 	ml_peer = link_peer->mlo_peer_ctx;
1352 	if (!ml_peer) {
1353 		mlo_err("MLD ID %d ML Peer " QDF_MAC_ADDR_FMT " ML peer is NULL",
1354 			ml_dev->mld_id,
1355 			QDF_MAC_ADDR_REF(link_peer->mldaddr));
1356 
1357 		return QDF_STATUS_E_FAILURE;
1358 	}
1359 
1360 	if (!wlan_mlo_peer_is_assoc_peer(ml_peer, link_peer)) {
1361 		mlo_err("MLD ID %d ML Peer " QDF_MAC_ADDR_FMT "Assoc req received on non-assoc peer" QDF_MAC_ADDR_FMT,
1362 			ml_dev->mld_id,
1363 			QDF_MAC_ADDR_REF(link_peer->mldaddr),
1364 			QDF_MAC_ADDR_REF(link_peer->macaddr));
1365 
1366 		return QDF_STATUS_E_FAILURE;
1367 	}
1368 
1369 	status = mlo_dev_get_link_vdevs(vdev, ml_dev,
1370 					ml_info, link_vdevs);
1371 	if (QDF_IS_STATUS_ERROR(status)) {
1372 		mlo_err("MLD ID %d ML Peer " QDF_MAC_ADDR_FMT " get link vdevs failed",
1373 			ml_dev->mld_id,
1374 			QDF_MAC_ADDR_REF(link_peer->mldaddr));
1375 		return QDF_STATUS_E_FAILURE;
1376 	}
1377 
1378 	/* If ML peer state is not in Assoc done state, drop REASSOC req */
1379 	if (ml_peer->mlpeer_state != ML_PEER_ASSOC_DONE) {
1380 		mlo_err("MLD ID %d ML Peer " QDF_MAC_ADDR_FMT " invalid state %d",
1381 			ml_dev->mld_id,
1382 			QDF_MAC_ADDR_REF(link_peer->mldaddr),
1383 			ml_peer->mlpeer_state);
1384 
1385 		mlo_dev_release_link_vdevs(link_vdevs);
1386 
1387 		return QDF_STATUS_E_FAILURE;
1388 	}
1389 
1390 	link_count = 0;
1391 	for (j = 0; j < ml_peer->max_links; j++) {
1392 		peer_entry = &ml_peer->peer_list[j];
1393 		iter_peer = peer_entry->link_peer;
1394 		if (!iter_peer)
1395 			continue;
1396 
1397 		if (wlan_peer_get_peer_type(iter_peer) ==
1398 						WLAN_PEER_MLO_BRIDGE) {
1399 			link_count++;
1400 			continue;
1401 		}
1402 
1403 		for (i = 0; i < WLAN_UMAC_MLO_MAX_VDEVS; i++) {
1404 			vdev_link = link_vdevs[i];
1405 			if (!vdev_link)
1406 				continue;
1407 
1408 			if (vdev_link != wlan_peer_get_vdev(iter_peer))
1409 				continue;
1410 
1411 			link_count++;
1412 			break;
1413 		}
1414 	}
1415 	if (link_count != ml_peer->link_peer_cnt) {
1416 		mlo_err("MLD ID %d ML Peer " QDF_MAC_ADDR_FMT " incorrect link peers",
1417 			ml_dev->mld_id,
1418 			QDF_MAC_ADDR_REF(link_peer->mldaddr));
1419 		mlo_dev_release_link_vdevs(link_vdevs);
1420 
1421 		return QDF_STATUS_E_INVAL;
1422 	}
1423 
1424 	/* Notify other vdevs about assoc req */
1425 	for (i = 0; i < WLAN_UMAC_MLO_MAX_VDEVS; i++) {
1426 		vdev_link = link_vdevs[i];
1427 		if (!vdev_link)
1428 			continue;
1429 
1430 		if (vdev_link == vdev)
1431 			continue;
1432 
1433 		mlo_partner_peer_reassoc_post(ml_dev, vdev_link,
1434 					      ml_peer, frm_buf, ml_info);
1435 	}
1436 
1437 	mlo_dev_release_link_vdevs(link_vdevs);
1438 
1439 	if (QDF_IS_STATUS_ERROR(wlan_mlo_validate_reassocreq(ml_peer))) {
1440 		mlo_info("MLD ID %d ML Peer " QDF_MAC_ADDR_FMT " reassoc proc is failed %pK",
1441 			 ml_dev->mld_id,
1442 			 QDF_MAC_ADDR_REF(ml_peer->peer_mld_addr.bytes),
1443 			 ml_peer);
1444 
1445 		return QDF_STATUS_E_FAILURE;
1446 	}
1447 
1448 	mlo_info("MLD ID %d ML Peer " QDF_MAC_ADDR_FMT " reassoc handled %pK",
1449 		 ml_dev->mld_id,
1450 		 QDF_MAC_ADDR_REF(ml_peer->peer_mld_addr.bytes),
1451 		 ml_peer);
1452 
1453 	return QDF_STATUS_SUCCESS;
1454 }
1455 
1456 QDF_STATUS wlan_mlo_peer_create(struct wlan_objmgr_vdev *vdev,
1457 				struct wlan_objmgr_peer *link_peer,
1458 				struct mlo_partner_info *ml_info,
1459 				qdf_nbuf_t frm_buf,
1460 				uint16_t aid)
1461 {
1462 	struct wlan_mlo_dev_context *ml_dev;
1463 	struct wlan_mlo_peer_context *ml_peer = NULL;
1464 	struct wlan_objmgr_vdev *link_vdevs[WLAN_UMAC_MLO_MAX_VDEVS] = { NULL };
1465 	struct wlan_objmgr_vdev *tmp_link_vdevs[WLAN_UMAC_MLO_MAX_VDEVS] = { NULL };
1466 	struct wlan_objmgr_vdev *vdev_link;
1467 	QDF_STATUS status;
1468 	uint16_t i, j;
1469 	struct wlan_objmgr_peer *assoc_peer;
1470 	uint8_t bridge_peer_psoc_id = WLAN_OBJMGR_MAX_DEVICES;
1471 	bool is_ml_peer_attached = false;
1472 
1473 	/* get ML VDEV from VDEV */
1474 	ml_dev = vdev->mlo_dev_ctx;
1475 
1476 	if (!ml_dev) {
1477 		mlo_err("ML dev ctx is NULL");
1478 		return QDF_STATUS_E_NULL_VALUE;
1479 	}
1480 
1481 	/* Check resources of Partner VDEV */
1482 	if (wlan_vdev_mlme_get_opmode(vdev) == QDF_SAP_MODE) {
1483 		if (wlan_mlo_is_mld_ctx_exist(
1484 		    (struct qdf_mac_addr *)&link_peer->mldaddr[0])) {
1485 			mlo_err("MLD ID %d ML Peer " QDF_MAC_ADDR_FMT " is matching with one of the MLD address in the system",
1486 				ml_dev->mld_id,
1487 				QDF_MAC_ADDR_REF(link_peer->mldaddr));
1488 			return QDF_STATUS_E_FAILURE;
1489 		}
1490 		/* Limit max assoc links */
1491 		if (ml_info->num_partner_links > WLAN_UMAC_MLO_ASSOC_MAX_SUPPORTED_LINKS) {
1492 			mlo_err("MLD ID %d ML Peer " QDF_MAC_ADDR_FMT " exceeds MAX assoc limit of %d",
1493 				ml_dev->mld_id,
1494 				QDF_MAC_ADDR_REF(link_peer->mldaddr),
1495 				WLAN_UMAC_MLO_ASSOC_MAX_SUPPORTED_LINKS);
1496 			return QDF_STATUS_E_RESOURCES;
1497 		}
1498 
1499 		status = mlo_dev_get_link_vdevs(vdev, ml_dev,
1500 						ml_info, link_vdevs);
1501 		if (QDF_IS_STATUS_ERROR(status)) {
1502 			mlo_err("MLD ID %d ML Peer " QDF_MAC_ADDR_FMT " get link vdevs failed",
1503 				ml_dev->mld_id,
1504 				QDF_MAC_ADDR_REF(link_peer->mldaddr));
1505 			return QDF_STATUS_E_FAILURE;
1506 		}
1507 
1508 		for (i = 0; i < WLAN_UMAC_MLO_MAX_VDEVS; i++) {
1509 			vdev_link = link_vdevs[i];
1510 			if (!vdev_link) {
1511 				mlo_debug("vdev_link is null");
1512 				continue;
1513 			}
1514 
1515 			if (wlan_vdev_is_mlo_peer_create_allowed(vdev_link)
1516 					!= QDF_STATUS_SUCCESS) {
1517 				mlo_dev_release_link_vdevs(link_vdevs);
1518 
1519 				mlo_err("MLD ID %d ML Peer " QDF_MAC_ADDR_FMT " create not allowed on link vdev %d",
1520 					ml_dev->mld_id,
1521 					QDF_MAC_ADDR_REF
1522 						(link_peer->mldaddr),
1523 					wlan_vdev_get_id(vdev_link));
1524 				return QDF_STATUS_E_INVAL;
1525 			}
1526 		}
1527 
1528 		for (i = 0; i < WLAN_UMAC_MLO_MAX_VDEVS; i++) {
1529 			vdev_link = link_vdevs[i];
1530 			if (vdev_link && (vdev_link != vdev) &&
1531 			    (wlan_vdev_get_peer_count(vdev_link) >
1532 			     wlan_vdev_get_max_peer_count(vdev_link))) {
1533 				mlo_dev_release_link_vdevs(link_vdevs);
1534 				mlo_err("MLD ID %d ML Peer " QDF_MAC_ADDR_FMT " Max peer count reached on link vdev %d",
1535 					ml_dev->mld_id,
1536 					QDF_MAC_ADDR_REF
1537 						(link_peer->mldaddr),
1538 					wlan_vdev_get_id(vdev_link));
1539 				return QDF_STATUS_E_RESOURCES;
1540 			}
1541 		}
1542 	}
1543 	/* When roam to MLO AP, partner link vdev1 is updated first,
1544 	 * ml peer need be created and attached for partner link peer.
1545 	 *
1546 	 * When roam target AP and current AP have same MLD address, don't
1547 	 * delete old ML peer and re-create new one, just update different
1548 	 * info.
1549 	 */
1550 	if (wlan_vdev_mlme_get_opmode(vdev) == QDF_STA_MODE) {
1551 		ml_peer = wlan_mlo_get_mlpeer(ml_dev,
1552 				 (struct qdf_mac_addr *)&link_peer->mldaddr[0]);
1553 		if (ml_peer) {
1554 			mlo_debug("ML Peer " QDF_MAC_ADDR_FMT
1555 				" existed, state %d",
1556 				QDF_MAC_ADDR_REF(ml_peer->peer_mld_addr.bytes),
1557 				ml_peer->mlpeer_state);
1558 			ml_peer->mlpeer_state = ML_PEER_CREATED;
1559 			ml_peer->max_links = ml_info->num_partner_links;
1560 			wlan_mlo_peer_set_t2lm_enable_val(ml_peer, ml_info);
1561 			is_ml_peer_attached = true;
1562 		}
1563 	}
1564 	if (!ml_peer) {
1565 		/* Allocate MLO peer */
1566 		ml_peer = qdf_mem_malloc(sizeof(*ml_peer));
1567 		if (!ml_peer) {
1568 			mlo_err("MLD ID %d ML Peer " QDF_MAC_ADDR_FMT " mem alloc failed",
1569 				ml_dev->mld_id,
1570 				QDF_MAC_ADDR_REF(link_peer->mldaddr));
1571 			mlo_dev_release_link_vdevs(link_vdevs);
1572 			return QDF_STATUS_E_NOMEM;
1573 		}
1574 
1575 		qdf_atomic_init(&ml_peer->ref_cnt);
1576 		mlo_peer_lock_create(ml_peer);
1577 		ml_peer->ml_dev = ml_dev;
1578 		ml_peer->mlpeer_state = ML_PEER_CREATED;
1579 		ml_peer->max_links = ml_info->num_partner_links;
1580 		ml_peer->primary_umac_psoc_id = ML_PRIMARY_UMAC_ID_INVAL;
1581 		ml_peer->migrate_primary_umac_psoc_id =
1582 						ML_PRIMARY_UMAC_ID_INVAL;
1583 		ml_peer->primary_umac_migration_in_progress = false;
1584 
1585 		ml_peer->mlo_peer_id = mlo_ap_ml_peerid_alloc();
1586 		if (ml_peer->mlo_peer_id == MLO_INVALID_PEER_ID) {
1587 			mlo_err("MLD ID %d ML Peer " QDF_MAC_ADDR_FMT " invalid ml peer id",
1588 				ml_dev->mld_id,
1589 				QDF_MAC_ADDR_REF
1590 				(ml_peer->peer_mld_addr.bytes));
1591 			mlo_peer_free(ml_peer);
1592 			mlo_dev_release_link_vdevs(link_vdevs);
1593 			return QDF_STATUS_E_RESOURCES;
1594 		}
1595 
1596 		qdf_copy_macaddr((struct qdf_mac_addr *)&ml_peer->peer_mld_addr,
1597 				 (struct qdf_mac_addr *)&link_peer->mldaddr[0]);
1598 		wlan_mlo_peer_set_t2lm_enable_val(ml_peer, ml_info);
1599 		epcs_dev_peer_lock_create(&ml_peer->epcs_info);
1600 		wlan_mlo_peer_initialize_epcs_info(ml_peer);
1601 
1602 		/* Allocate AID */
1603 		if (wlan_vdev_mlme_get_opmode(vdev) == QDF_SAP_MODE) {
1604 			if (aid == (uint16_t)-1) {
1605 				status = mlo_peer_allocate_aid(ml_dev, ml_peer);
1606 				if (status != QDF_STATUS_SUCCESS) {
1607 					mlo_err("MLD ID %d ML Peer " QDF_MAC_ADDR_FMT " aid alloc failed",
1608 						ml_dev->mld_id,
1609 						QDF_MAC_ADDR_REF
1610 						(ml_peer->peer_mld_addr.bytes));
1611 					mlo_peer_free(ml_peer);
1612 					mlo_dev_release_link_vdevs(link_vdevs);
1613 					return status;
1614 				}
1615 			} else {
1616 				ml_peer->assoc_id = aid;
1617 			}
1618 		}
1619 	}
1620 
1621 	/* Populate Link peer pointer, peer MAC address,
1622 	 * MLD address. HW link ID, update ref count
1623 	 */
1624 	status = mlo_peer_attach_link_peer(ml_peer, link_peer, NULL);
1625 	if (QDF_IS_STATUS_ERROR(status)) {
1626 		mlo_err("MLD ID %d ML Peer " QDF_MAC_ADDR_FMT " link peer attach failed",
1627 			ml_dev->mld_id,
1628 			QDF_MAC_ADDR_REF
1629 			(ml_peer->peer_mld_addr.bytes));
1630 		/* If there is another link peer attached for this ML peer,
1631 		 * ml peer can't be detached and freed.
1632 		 */
1633 		if (is_ml_peer_attached && ml_peer->link_peer_cnt)
1634 			return status;
1635 		if (is_ml_peer_attached)
1636 			mlo_dev_mlpeer_detach(ml_dev, ml_peer);
1637 		mlo_peer_free(ml_peer);
1638 		mlo_dev_release_link_vdevs(link_vdevs);
1639 		return status;
1640 	}
1641 
1642 	if (wlan_vdev_mlme_get_opmode(vdev) == QDF_SAP_MODE) {
1643 		for (i = 0; i < WLAN_UMAC_MLO_MAX_VDEVS; i++) {
1644 			if (!link_vdevs[i]) {
1645 				mlo_debug("vdev_link is null");
1646 				continue;
1647 			}
1648 
1649 			if (wlan_objmgr_vdev_try_get_ref(link_vdevs[i], WLAN_MLO_MGR_ID) !=
1650 					QDF_STATUS_SUCCESS) {
1651 				mlo_err("VDEV is not in created state");
1652 				/* release ref which were taken before failure */
1653 				for (j = 0; j < i; j++) {
1654 					if (!link_vdevs[i])
1655 						continue;
1656 
1657 					wlan_objmgr_vdev_release_ref(link_vdevs[i],
1658 								     WLAN_MLO_MGR_ID);
1659 				}
1660 				mlo_reset_link_peer(ml_peer, link_peer);
1661 				mlo_peer_free(ml_peer);
1662 				mlo_dev_release_link_vdevs(link_vdevs);
1663 
1664 				return QDF_STATUS_E_FAILURE;
1665 			}
1666 			tmp_link_vdevs[i] = link_vdevs[i];
1667 		}
1668 
1669 		status = wlan_mlo_get_bridge_peer_psoc_id(vdev, ml_peer,
1670 							  tmp_link_vdevs,
1671 							  ml_info->num_partner_links,
1672 							  &bridge_peer_psoc_id);
1673 		if (QDF_STATUS_SUCCESS != status) {
1674 			mlo_err("MLD ID %d: Failed to derive bridge peer psoc id",
1675 				ml_dev->mld_id);
1676 			mlo_reset_link_peer(ml_peer, link_peer);
1677 			mlo_peer_free(ml_peer);
1678 			mlo_dev_release_link_vdevs(link_vdevs);
1679 			mlo_dev_release_link_vdevs(tmp_link_vdevs);
1680 			wlan_objmgr_peer_release_ref(link_peer,
1681 						     WLAN_MLO_MGR_ID);
1682 			return QDF_STATUS_E_FAILURE;
1683 		}
1684 	}
1685 
1686 	/* Allocate Primary UMAC */
1687 	mlo_peer_allocate_primary_umac(ml_dev, ml_peer, tmp_link_vdevs);
1688 
1689 	if (wlan_vdev_mlme_get_opmode(vdev) == QDF_SAP_MODE)
1690 		mlo_dev_release_link_vdevs(tmp_link_vdevs);
1691 
1692 	/* Store AID, MLO Peer pointer in link peer, take link peer ref count */
1693 	mlo_peer_populate_link_peer(ml_peer, link_peer);
1694 
1695 	mlo_peer_populate_nawds_params(ml_peer, ml_info);
1696 	mlo_peer_populate_mesh_params(ml_peer, ml_info);
1697 
1698 	if ((wlan_vdev_mlme_get_opmode(vdev) == QDF_SAP_MODE) ||
1699 		((wlan_vdev_mlme_get_opmode(vdev) == QDF_STA_MODE) &&
1700 			!is_ml_peer_attached)) {
1701 		/* Reject creation for AP mode, If ML peer is present with
1702 		 * MLD MAC address, For PSTA case, all MLD STAs are connected
1703 		 * to same MLD AP, it can have duplicate MLD address entries
1704 		 * for STA MLDs
1705 		 */
1706 		if ((wlan_vdev_mlme_get_opmode(vdev) == QDF_SAP_MODE) &&
1707 		    mlo_mgr_ml_peer_exist_on_diff_ml_ctx(&link_peer->mldaddr[0],
1708 							 NULL)) {
1709 			mlo_err("MLD ID %d ML Peer " QDF_MAC_ADDR_FMT " is exists, creation failed",
1710 				ml_dev->mld_id,
1711 				QDF_MAC_ADDR_REF(ml_peer->peer_mld_addr.bytes));
1712 			mlo_reset_link_peer(ml_peer, link_peer);
1713 			mlo_peer_free(ml_peer);
1714 			mlo_dev_release_link_vdevs(link_vdevs);
1715 			wlan_objmgr_peer_release_ref(link_peer,
1716 						     WLAN_MLO_MGR_ID);
1717 			return QDF_STATUS_E_EXISTS;
1718 		}
1719 
1720 		/* Attach MLO peer to ML Peer table */
1721 		status = mlo_dev_mlpeer_attach(ml_dev, ml_peer);
1722 		if (status != QDF_STATUS_SUCCESS) {
1723 			mlo_err("MLD ID %d ML Peer " QDF_MAC_ADDR_FMT " attach failed",
1724 				ml_dev->mld_id,
1725 				QDF_MAC_ADDR_REF(ml_peer->peer_mld_addr.bytes));
1726 			mlo_reset_link_peer(ml_peer, link_peer);
1727 			wlan_objmgr_peer_release_ref(link_peer,
1728 						     WLAN_MLO_MGR_ID);
1729 			mlo_peer_free(ml_peer);
1730 			mlo_dev_release_link_vdevs(link_vdevs);
1731 			return status;
1732 		}
1733 	}
1734 
1735 	wlan_mlo_peer_get_ref(ml_peer);
1736 
1737 	if (wlan_vdev_mlme_get_opmode(vdev) == QDF_SAP_MODE) {
1738 		/* Notify other vdevs about link peer creation */
1739 		for (i = 0; i < WLAN_UMAC_MLO_MAX_VDEVS; i++) {
1740 			vdev_link = link_vdevs[i];
1741 			if (!vdev_link)
1742 				continue;
1743 
1744 			if (vdev_link == vdev)
1745 				continue;
1746 
1747 			mlo_partner_peer_create_post(ml_dev, vdev_link,
1748 						     ml_peer, frm_buf, ml_info);
1749 		}
1750 		/* Create bridge peer */
1751 		status = mlo_bridge_peer_create_post(ml_dev, ml_peer,
1752 						     bridge_peer_psoc_id);
1753 		if (QDF_STATUS_SUCCESS != status) {
1754 			mlo_err("MLD ID %d: Bridge peer creation failed",
1755 				ml_dev->mld_id);
1756 			wlan_mlo_partner_peer_create_failed_notify(ml_peer);
1757 			mlo_dev_release_link_vdevs(link_vdevs);
1758 			wlan_mlo_peer_release_ref(ml_peer);
1759 			return QDF_STATUS_E_FAILURE;
1760 		}
1761 	}
1762 	mlo_dev_release_link_vdevs(link_vdevs);
1763 
1764 	if (ml_peer->mlpeer_state == ML_PEER_DISCONN_INITIATED) {
1765 		mlo_info("MLD ID %d ML Peer " QDF_MAC_ADDR_FMT " allocation failed",
1766 			 ml_dev->mld_id,
1767 			 QDF_MAC_ADDR_REF(ml_peer->peer_mld_addr.bytes));
1768 		wlan_mlo_peer_release_ref(ml_peer);
1769 		return QDF_STATUS_E_FAILURE;
1770 	}
1771 
1772 	mlo_info("MLD ID %d ML Peer " QDF_MAC_ADDR_FMT " allocated %pK",
1773 		 ml_dev->mld_id,
1774 		 QDF_MAC_ADDR_REF(ml_peer->peer_mld_addr.bytes),
1775 		 ml_peer);
1776 
1777 	/*
1778 	 * wlan_mlo_peer_create() is trigggered after getting peer
1779 	 * assoc confirm from FW. For single link MLO connection, it is
1780 	 * OK to trigger assoc response from here.
1781 	 */
1782 	if ((wlan_vdev_mlme_get_opmode(vdev) == QDF_SAP_MODE) &&
1783 	    (!wlan_mlo_peer_is_nawds(ml_peer))) {
1784 		if ((ml_peer->max_links == 1) &&
1785 		    (ml_peer->link_peer_cnt == 1)) {
1786 			assoc_peer = ml_peer->peer_list[0].link_peer;
1787 			if (assoc_peer)
1788 				mlo_mlme_peer_assoc_resp(assoc_peer);
1789 		}
1790 	}
1791 
1792 	if (wlan_vdev_mlme_get_opmode(vdev) == QDF_STA_MODE)
1793 		wlan_clear_peer_level_tid_to_link_mapping(vdev);
1794 
1795 	wlan_mlo_peer_release_ref(ml_peer);
1796 
1797 	return QDF_STATUS_SUCCESS;
1798 }
1799 
1800 QDF_STATUS wlan_mlo_link_peer_attach(struct wlan_mlo_peer_context *ml_peer,
1801 				     struct wlan_objmgr_peer *peer,
1802 				     qdf_nbuf_t frm_buf)
1803 {
1804 	QDF_STATUS status;
1805 	struct wlan_objmgr_peer *assoc_peer;
1806 	struct wlan_objmgr_vdev *vdev = NULL;
1807 
1808 	if (!ml_peer)
1809 		return QDF_STATUS_E_FAILURE;
1810 
1811 	vdev = wlan_peer_get_vdev(peer);
1812 	if (!vdev)
1813 		return QDF_STATUS_E_FAILURE;
1814 
1815 	/* Populate Link peer pointer, peer MAC address,
1816 	 * MLD address. HW link ID, update ref count
1817 	 */
1818 	status = mlo_peer_attach_link_peer(ml_peer, peer, frm_buf);
1819 	if (QDF_IS_STATUS_ERROR(status))
1820 		return status;
1821 
1822 	/* Store AID, MLO Peer pointer in link peer, take link peer ref count */
1823 	mlo_peer_populate_link_peer(ml_peer, peer);
1824 
1825 	if (wlan_vdev_mlme_get_opmode(vdev) == QDF_SAP_MODE) {
1826 		if (ml_peer->max_links == ml_peer->link_peer_cnt) {
1827 			assoc_peer = ml_peer->peer_list[0].link_peer;
1828 			if (assoc_peer)
1829 				mlo_mlme_peer_assoc_resp(assoc_peer);
1830 		}
1831 	}
1832 
1833 	return status;
1834 }
1835 
1836 QDF_STATUS wlan_mlo_link_asresp_attach(struct wlan_mlo_peer_context *ml_peer,
1837 				       struct wlan_objmgr_peer *peer,
1838 				       qdf_nbuf_t frm_buf)
1839 {
1840 	uint16_t i;
1841 	struct wlan_mlo_link_peer_entry *peer_entry;
1842 
1843 	if (!ml_peer) {
1844 		mlo_err(" ml peer is NULL");
1845 		return QDF_STATUS_E_FAILURE;
1846 	}
1847 
1848 	if (!peer) {
1849 		ml_peer->link_asresp_cnt++;
1850 		mlo_err(" ml peer or link peer pointer is NULL");
1851 		return QDF_STATUS_E_FAILURE;
1852 	}
1853 	mlo_peer_lock_acquire(ml_peer);
1854 
1855 	for (i = 0; i < MAX_MLO_LINK_PEERS; i++) {
1856 		peer_entry = &ml_peer->peer_list[i];
1857 		if (!peer_entry->link_peer)
1858 			continue;
1859 
1860 		if (peer == peer_entry->link_peer) {
1861 			ml_peer->link_asresp_cnt++;
1862 			/* Free previous assoc resp buffer */
1863 			if (peer_entry->assoc_rsp_buf) {
1864 				qdf_nbuf_free(peer_entry->assoc_rsp_buf);
1865 				peer_entry->assoc_rsp_buf = NULL;
1866 			}
1867 
1868 			if (frm_buf)
1869 				peer_entry->assoc_rsp_buf = frm_buf;
1870 			else
1871 				peer_entry->assoc_rsp_buf = NULL;
1872 
1873 			break;
1874 		}
1875 	}
1876 
1877 	mlo_peer_lock_release(ml_peer);
1878 
1879 	return QDF_STATUS_SUCCESS;
1880 }
1881 
1882 QDF_STATUS wlan_mlo_link_peer_delete(struct wlan_objmgr_peer *peer)
1883 {
1884 	struct wlan_mlo_peer_context *ml_peer;
1885 
1886 	ml_peer = peer->mlo_peer_ctx;
1887 
1888 	if (!ml_peer)
1889 		return QDF_STATUS_E_NOENT;
1890 
1891 	if (ml_peer->mlpeer_state != ML_PEER_DISCONN_INITIATED)
1892 		wlan_mlo_peer_wsi_link_delete(ml_peer);
1893 
1894 	mlo_reset_link_peer(ml_peer, peer);
1895 	mlo_peer_detach_link_peer(ml_peer, peer);
1896 
1897 	if (ml_peer->mlpeer_state != ML_PEER_DISCONN_INITIATED)
1898 		wlan_mlo_peer_wsi_link_add(ml_peer);
1899 
1900 	wlan_mlo_peer_release_ref(ml_peer);
1901 
1902 	return QDF_STATUS_SUCCESS;
1903 }
1904 
1905 qdf_export_symbol(wlan_mlo_link_peer_delete);
1906 
1907 qdf_nbuf_t mlo_peer_get_link_peer_assoc_req_buf(
1908 			struct wlan_mlo_peer_context *ml_peer,
1909 			uint8_t link_ix)
1910 {
1911 	struct wlan_objmgr_peer *peer = NULL;
1912 	qdf_nbuf_t assocbuf = NULL;
1913 
1914 	if (!ml_peer)
1915 		return NULL;
1916 
1917 	peer = wlan_mlo_peer_get_assoc_peer(ml_peer);
1918 	if (!peer)
1919 		return NULL;
1920 
1921 	assocbuf = mlo_mlme_get_link_assoc_req(peer, link_ix);
1922 
1923 	return assocbuf;
1924 }
1925 
1926 void wlan_mlo_peer_get_links_info(struct wlan_objmgr_peer *peer,
1927 				  struct mlo_tgt_partner_info *ml_links)
1928 {
1929 	struct wlan_mlo_peer_context *ml_peer;
1930 	struct wlan_mlo_link_peer_entry *peer_entry;
1931 	struct wlan_objmgr_peer *link_peer;
1932 	struct wlan_objmgr_vdev *link_vdev;
1933 	uint8_t i, ix, idx = 0;
1934 	struct wlan_mlo_eml_cap *ml_emlcap;
1935 
1936 	ml_peer = peer->mlo_peer_ctx;
1937 	ml_links->num_partner_links = 0;
1938 
1939 	if (!ml_peer)
1940 		return;
1941 
1942 	ml_emlcap = &ml_peer->mlpeer_emlcap;
1943 
1944 	mlo_peer_lock_acquire(ml_peer);
1945 
1946 	if ((ml_peer->mlpeer_state != ML_PEER_CREATED) &&
1947 	    (ml_peer->mlpeer_state != ML_PEER_ASSOC_DONE)) {
1948 		mlo_peer_lock_release(ml_peer);
1949 		return;
1950 	}
1951 
1952 	for (i = 0; i < MAX_MLO_LINK_PEERS; i++) {
1953 		peer_entry = &ml_peer->peer_list[i];
1954 		link_peer = peer_entry->link_peer;
1955 
1956 		if (!link_peer)
1957 			continue;
1958 		idx++;
1959 		if (link_peer == peer)
1960 			continue;
1961 		link_vdev = wlan_peer_get_vdev(link_peer);
1962 		if (!link_vdev)
1963 			continue;
1964 
1965 		if (ml_links->num_partner_links >= WLAN_UMAC_MLO_MAX_VDEVS)
1966 			break;
1967 
1968 		ix = ml_links->num_partner_links;
1969 		ml_links->link_info[ix].vdev_id = wlan_vdev_get_id(link_vdev);
1970 		ml_links->link_info[ix].hw_mld_link_id = peer_entry->hw_link_id;
1971 		ml_links->link_info[ix].mlo_enabled = 1;
1972 		ml_links->link_info[ix].mlo_assoc_link =
1973 			wlan_peer_mlme_is_assoc_peer(link_peer);
1974 		ml_links->link_info[ix].mlo_primary_umac =
1975 			peer_entry->is_primary;
1976 		ml_links->link_info[ix].mlo_logical_link_index_valid = 1;
1977 		ml_links->link_info[ix].emlsr_support = ml_emlcap->emlsr_supp;
1978 		ml_links->link_info[ix].logical_link_index = idx - 1;
1979 		ml_links->link_info[ix].mlo_bridge_peer = link_peer->mlo_bridge_peer;
1980 		ml_links->num_partner_links++;
1981 	}
1982 	mlo_peer_lock_release(ml_peer);
1983 }
1984 
1985 qdf_export_symbol(wlan_mlo_peer_get_links_info);
1986 
1987 uint8_t wlan_mlo_peer_get_primary_peer_link_id(struct wlan_objmgr_peer *peer)
1988 {
1989 	struct wlan_mlo_peer_context *ml_peer;
1990 
1991 	ml_peer = peer->mlo_peer_ctx;
1992 
1993 	if (!ml_peer) {
1994 		mlo_err("ml_peer is null");
1995 		return WLAN_LINK_ID_INVALID;
1996 	}
1997 
1998 	return wlan_mlo_peer_get_primary_peer_link_id_by_ml_peer(ml_peer);
1999 }
2000 
2001 qdf_export_symbol(wlan_mlo_peer_get_primary_peer_link_id);
2002 
2003 uint8_t wlan_mlo_peer_get_primary_peer_link_id_by_ml_peer(
2004 				struct wlan_mlo_peer_context *ml_peer)
2005 {
2006 	struct wlan_mlo_link_peer_entry *peer_entry;
2007 	struct wlan_objmgr_peer *link_peer;
2008 	struct wlan_objmgr_vdev *link_vdev;
2009 	uint8_t i, vdev_link_id;
2010 
2011 	if (!ml_peer) {
2012 		mlo_err("ml_peer is null");
2013 		return WLAN_LINK_ID_INVALID;
2014 	}
2015 	mlo_peer_lock_acquire(ml_peer);
2016 
2017 	if ((ml_peer->mlpeer_state != ML_PEER_CREATED) &&
2018 	    (ml_peer->mlpeer_state != ML_PEER_ASSOC_DONE)) {
2019 		mlo_peer_lock_release(ml_peer);
2020 		mlo_err("ml_peer is not created and association is not done");
2021 		return WLAN_LINK_ID_INVALID;
2022 	}
2023 
2024 	for (i = 0; i < MAX_MLO_LINK_PEERS; i++) {
2025 		peer_entry = &ml_peer->peer_list[i];
2026 		link_peer = peer_entry->link_peer;
2027 		if (!link_peer)
2028 			continue;
2029 
2030 		if (peer_entry->is_primary) {
2031 			link_vdev = wlan_peer_get_vdev(link_peer);
2032 			if (!link_vdev) {
2033 				mlo_peer_lock_release(ml_peer);
2034 				mlo_err("link vdev not found");
2035 				return WLAN_LINK_ID_INVALID;
2036 			}
2037 			vdev_link_id = wlan_vdev_get_link_id(link_vdev);
2038 			mlo_peer_lock_release(ml_peer);
2039 			return vdev_link_id;
2040 		}
2041 	}
2042 	mlo_peer_lock_release(ml_peer);
2043 	mlo_err("None of the peer is designated as primary");
2044 	return WLAN_LINK_ID_INVALID;
2045 }
2046 
2047 qdf_export_symbol(wlan_mlo_peer_get_primary_peer_link_id_by_ml_peer);
2048 
2049 #ifdef WLAN_MLO_MULTI_CHIP
2050 void wlan_mlo_peer_get_str_capability(struct wlan_objmgr_peer *peer,
2051 				      uint8_t *str_capability)
2052 {
2053 	struct wlan_mlo_peer_context *ml_peer;
2054 	uint8_t i;
2055 
2056 	if (!str_capability)
2057 		return;
2058 
2059 	*str_capability = 1;
2060 	if (!peer)
2061 		return;
2062 	ml_peer = peer->mlo_peer_ctx;
2063 	if (!ml_peer)
2064 		return;
2065 
2066 	mlo_peer_lock_acquire(ml_peer);
2067 	if ((ml_peer->mlpeer_state != ML_PEER_CREATED) &&
2068 	    (ml_peer->mlpeer_state != ML_PEER_ASSOC_DONE)) {
2069 		mlo_peer_lock_release(ml_peer);
2070 		return;
2071 	}
2072 
2073 	for (i = 0; i < WLAN_UMAC_MLO_MAX_VDEVS; i++) {
2074 		if (ml_peer->mlpeer_nstrinfo[i].link_id >= MAX_MLO_LINKS)
2075 			continue;
2076 		if (ml_peer->mlpeer_nstrinfo[i].nstr_lp_present) {
2077 			*str_capability = 0;
2078 			break;
2079 		}
2080 	}
2081 	mlo_peer_lock_release(ml_peer);
2082 }
2083 
2084 void wlan_mlo_peer_get_eml_capability(struct wlan_objmgr_peer *peer,
2085 				      uint8_t *is_emlsr_capable,
2086 				      uint8_t *is_emlmr_capable)
2087 {
2088 	struct wlan_mlo_peer_context *ml_peer;
2089 
2090 	if (!is_emlsr_capable || !is_emlmr_capable)
2091 		return;
2092 
2093 	*is_emlsr_capable = 0;
2094 	*is_emlmr_capable = 0;
2095 	if (!peer)
2096 		return;
2097 	ml_peer = peer->mlo_peer_ctx;
2098 	if (!ml_peer)
2099 		return;
2100 
2101 	mlo_peer_lock_acquire(ml_peer);
2102 	if ((ml_peer->mlpeer_state != ML_PEER_CREATED) &&
2103 	    (ml_peer->mlpeer_state != ML_PEER_ASSOC_DONE)) {
2104 		mlo_peer_lock_release(ml_peer);
2105 		return;
2106 	}
2107 	*is_emlsr_capable = ml_peer->mlpeer_emlcap.emlsr_supp;
2108 	*is_emlmr_capable = ml_peer->mlpeer_emlcap.emlmr_supp;
2109 	mlo_peer_lock_release(ml_peer);
2110 }
2111 #endif
2112 
2113 void wlan_mlo_peer_get_partner_links_info(struct wlan_objmgr_peer *peer,
2114 					  struct mlo_partner_info *ml_links)
2115 {
2116 	struct wlan_mlo_peer_context *ml_peer;
2117 	struct wlan_mlo_link_peer_entry *peer_entry;
2118 	struct wlan_objmgr_peer *link_peer;
2119 	struct wlan_objmgr_vdev *link_vdev;
2120 	uint8_t i, ix;
2121 
2122 	ml_peer = peer->mlo_peer_ctx;
2123 	ml_links->num_partner_links = 0;
2124 
2125 	if (!ml_peer)
2126 		return;
2127 
2128 	mlo_peer_lock_acquire(ml_peer);
2129 
2130 	if ((ml_peer->mlpeer_state != ML_PEER_CREATED) &&
2131 	    (ml_peer->mlpeer_state != ML_PEER_ASSOC_DONE)) {
2132 		mlo_peer_lock_release(ml_peer);
2133 		return;
2134 	}
2135 
2136 	for (i = 0; i < MAX_MLO_LINK_PEERS; i++) {
2137 		peer_entry = &ml_peer->peer_list[i];
2138 		link_peer = peer_entry->link_peer;
2139 
2140 		if (!link_peer)
2141 			continue;
2142 
2143 		if (link_peer == peer)
2144 			continue;
2145 
2146 		link_vdev = wlan_peer_get_vdev(link_peer);
2147 		if (!link_vdev)
2148 			continue;
2149 
2150 		if (ml_links->num_partner_links >= WLAN_UMAC_MLO_MAX_VDEVS)
2151 			break;
2152 
2153 		ix = ml_links->num_partner_links;
2154 		ml_links->partner_link_info[ix].link_id = peer_entry->link_ix;
2155 		ml_links->partner_link_info[ix].is_bridge =
2156 		   (wlan_peer_get_peer_type(link_peer) == WLAN_PEER_MLO_BRIDGE);
2157 
2158 		qdf_copy_macaddr(&ml_links->partner_link_info[ix].link_addr,
2159 				 &peer_entry->link_addr);
2160 		ml_links->num_partner_links++;
2161 	}
2162 	mlo_peer_lock_release(ml_peer);
2163 }
2164 
2165 qdf_export_symbol(wlan_mlo_peer_get_partner_links_info);
2166 
2167 #ifdef UMAC_SUPPORT_MLNAWDS
2168 bool wlan_mlo_peer_is_nawds(struct wlan_mlo_peer_context *ml_peer)
2169 {
2170 	bool status = false;
2171 
2172 	if (!ml_peer)
2173 		return status;
2174 
2175 	mlo_peer_lock_acquire(ml_peer);
2176 	if (ml_peer->is_nawds_ml_peer)
2177 		status = true;
2178 	mlo_peer_lock_release(ml_peer);
2179 
2180 	return status;
2181 }
2182 
2183 qdf_export_symbol(wlan_mlo_peer_is_nawds);
2184 #endif
2185 
2186 #ifdef MESH_MODE_SUPPORT
2187 bool wlan_mlo_peer_is_mesh(struct wlan_mlo_peer_context *ml_peer)
2188 {
2189 	bool status = false;
2190 
2191 	if (!ml_peer)
2192 		return status;
2193 
2194 	mlo_peer_lock_acquire(ml_peer);
2195 	if (ml_peer->is_mesh_ml_peer)
2196 		status = true;
2197 	mlo_peer_lock_release(ml_peer);
2198 
2199 	return status;
2200 }
2201 
2202 qdf_export_symbol(wlan_mlo_peer_is_mesh);
2203 #endif
2204 
2205 #ifdef UMAC_MLO_AUTH_DEFER
2206 void mlo_peer_free_auth_param(struct mlpeer_auth_params *auth_params)
2207 {
2208 	if (auth_params->rs)
2209 		qdf_mem_free(auth_params->rs);
2210 
2211 	if (auth_params->wbuf)
2212 		qdf_nbuf_free(auth_params->wbuf);
2213 
2214 	qdf_mem_free(auth_params);
2215 }
2216 
2217 QDF_STATUS mlo_peer_link_auth_defer(struct wlan_mlo_peer_context *ml_peer,
2218 				    struct qdf_mac_addr *link_mac,
2219 				    struct mlpeer_auth_params *auth_params)
2220 {
2221 	uint8_t i;
2222 	uint8_t free_entries = 0;
2223 	struct mlpeer_auth_params *recv_auth;
2224 	QDF_STATUS status = QDF_STATUS_E_FAILURE;
2225 
2226 	if (!ml_peer)
2227 		return status;
2228 
2229 	mlo_peer_lock_acquire(ml_peer);
2230 	for (i = 0; i < MAX_MLO_LINK_PEERS; i++) {
2231 		recv_auth = ml_peer->pending_auth[i];
2232 		if (!recv_auth) {
2233 			free_entries++;
2234 			continue;
2235 		}
2236 		/* overwrite the entry with latest entry */
2237 		if (qdf_is_macaddr_equal(link_mac, &recv_auth->link_addr)) {
2238 			mlo_peer_free_auth_param(recv_auth);
2239 			ml_peer->pending_auth[i] = auth_params;
2240 			mlo_peer_lock_release(ml_peer);
2241 
2242 			return QDF_STATUS_SUCCESS;
2243 		}
2244 	}
2245 
2246 	if (!free_entries) {
2247 		mlo_peer_lock_release(ml_peer);
2248 		return QDF_STATUS_E_FAILURE;
2249 	}
2250 
2251 	for (i = 0; i < MAX_MLO_LINK_PEERS; i++) {
2252 		recv_auth = ml_peer->pending_auth[i];
2253 		if (!recv_auth) {
2254 			ml_peer->pending_auth[i] = auth_params;
2255 			status = QDF_STATUS_SUCCESS;
2256 			break;
2257 		}
2258 	}
2259 	mlo_peer_lock_release(ml_peer);
2260 
2261 	return status;
2262 }
2263 
2264 bool wlan_mlo_partner_peer_delete_is_allowed(struct wlan_objmgr_peer *src_peer)
2265 {
2266 	struct wlan_objmgr_vdev *vdev = NULL;
2267 	struct wlan_mlo_peer_context *ml_peer;
2268 
2269 	vdev = wlan_peer_get_vdev(src_peer);
2270 	if (!vdev)
2271 		return false;
2272 
2273 	ml_peer = src_peer->mlo_peer_ctx;
2274 	if (!wlan_peer_is_mlo(src_peer) || !ml_peer)
2275 		return false;
2276 
2277 	if (wlan_vdev_mlme_op_flags_get(vdev, WLAN_VDEV_OP_MLO_STOP_LINK_DEL) ||
2278 	    wlan_vdev_mlme_op_flags_get(vdev,
2279 					WLAN_VDEV_OP_MLO_LINK_TBTT_COMPLETE)) {
2280 		/* Single LINK MLO connection */
2281 		if (ml_peer->link_peer_cnt == 1)
2282 			return false;
2283 
2284 		/*
2285 		 * If this link is primary TQM and there is no ongoing migration
2286 		 * from this link, then issue full disconnect.
2287 		 */
2288 		if ((wlan_mlo_peer_get_primary_peer_link_id(src_peer) !=
2289 		    wlan_vdev_get_link_id(vdev)) ||
2290 		    ml_peer->primary_umac_migration_in_progress)
2291 			return false;
2292 	}
2293 
2294 	return true;
2295 }
2296 
2297 qdf_export_symbol(wlan_mlo_partner_peer_delete_is_allowed);
2298 #endif
2299 
2300 QDF_STATUS wlan_mlo_validate_reassocreq(struct wlan_mlo_peer_context *ml_peer)
2301 {
2302 	uint16_t i;
2303 	struct wlan_mlo_link_peer_entry *peer_entry;
2304 	QDF_STATUS status = QDF_STATUS_SUCCESS;
2305 
2306 	if (!ml_peer) {
2307 		mlo_err(" ml peer is NULL");
2308 		return QDF_STATUS_E_FAILURE;
2309 	}
2310 
2311 	mlo_peer_lock_acquire(ml_peer);
2312 
2313 	for (i = 0; i < MAX_MLO_LINK_PEERS; i++) {
2314 		peer_entry = &ml_peer->peer_list[i];
2315 		if (!peer_entry->link_peer)
2316 			continue;
2317 
2318 		/* Check non-assoc link peer Assoc resp buf is valid
2319 		 * (exclude bridge peer)
2320 		 */
2321 		if (i && !peer_entry->assoc_rsp_buf &&
2322 		    (wlan_peer_get_peer_type(peer_entry->link_peer) !=
2323 						WLAN_PEER_MLO_BRIDGE)) {
2324 			status = QDF_STATUS_E_FAILURE;
2325 			break;
2326 		}
2327 	}
2328 
2329 	mlo_peer_lock_release(ml_peer);
2330 
2331 	return status;
2332 }
2333 
2334 #ifdef WLAN_WSI_STATS_SUPPORT
2335 static uint32_t
2336 wlan_mlo_psoc_get_mlo_grp_idx(struct mlo_mgr_context *mlo_mgr,
2337 			      uint32_t psoc_id)
2338 {
2339 	struct mlo_wsi_info *wsi_info = NULL;
2340 	struct mlo_wsi_psoc_grp *mlo_psoc_grp;
2341 	uint8_t grp_id, i;
2342 
2343 	if (!mlo_mgr)
2344 		return MLO_WSI_MAX_MLO_GRPS;
2345 
2346 	/* Retrieve the WSI link info structure */
2347 	wsi_info = mlo_mgr->wsi_info;
2348 	if (!wsi_info)
2349 		return MLO_WSI_MAX_MLO_GRPS;
2350 
2351 	for (grp_id = 0; grp_id < MLO_WSI_MAX_MLO_GRPS; grp_id++) {
2352 		mlo_psoc_grp = &wsi_info->mlo_psoc_grp[grp_id];
2353 		for (i = 0; i < mlo_psoc_grp->num_psoc; i++) {
2354 			if (mlo_psoc_grp->psoc_order[i] == psoc_id)
2355 				return grp_id;
2356 		}
2357 	}
2358 
2359 	return MLO_WSI_MAX_MLO_GRPS;
2360 }
2361 
2362 QDF_STATUS wlan_mlo_wsi_link_info_send_cmd(void)
2363 {
2364 	struct mlo_mgr_context *mlo_mgr = NULL;
2365 	struct mlo_wsi_info *wsi_info = NULL;
2366 	struct wlan_lmac_if_mlo_tx_ops *mlo_tx_ops = NULL;
2367 	struct wlan_objmgr_psoc *psoc_objmgr = NULL;
2368 	struct wlan_objmgr_pdev *pdev = NULL;
2369 	QDF_STATUS error = QDF_STATUS_SUCCESS;
2370 	int i, j;
2371 
2372 	/* Retrieve the MLO manager context */
2373 	mlo_mgr = wlan_objmgr_get_mlo_ctx();
2374 	if (!mlo_mgr)
2375 		return QDF_STATUS_E_INVAL;
2376 
2377 	/* Retrieve the WSI link info structure */
2378 	wsi_info = mlo_mgr->wsi_info;
2379 	if (!wsi_info)
2380 		return QDF_STATUS_E_INVAL;
2381 
2382 	if (wsi_info->block_wmi_cmd) {
2383 		mlo_debug("WMI command is blocked");
2384 		return error;
2385 	}
2386 	/*
2387 	 * Check each PSOC if the WMI command needs to be sent
2388 	 * and send it for each PDEV in that PSOC
2389 	 */
2390 	for (i = 0; i < WLAN_OBJMGR_MAX_DEVICES; i++) {
2391 		if (!wsi_info->link_stats[i].send_wmi_cmd)
2392 			continue;
2393 
2394 		psoc_objmgr = wlan_objmgr_get_psoc_by_id(i, WLAN_MLO_MGR_ID);
2395 		if (!psoc_objmgr) {
2396 			mlo_err("Could not get PSOC obj for index %d", i);
2397 			continue;
2398 		}
2399 
2400 		mlo_tx_ops = &psoc_objmgr->soc_cb.tx_ops->mlo_ops;
2401 		if (!mlo_tx_ops || !mlo_tx_ops->send_wsi_link_info_cmd) {
2402 			mlo_err("mlo_tx_ops is null");
2403 			wlan_objmgr_psoc_release_ref(psoc_objmgr,
2404 						     WLAN_MLO_MGR_ID);
2405 			return QDF_STATUS_E_NULL_VALUE;
2406 		}
2407 
2408 		for (j = 0; j < psoc_objmgr->soc_objmgr.wlan_pdev_count; j++) {
2409 			pdev = psoc_objmgr->soc_objmgr.wlan_pdev_list[j];
2410 			if (!pdev)
2411 				continue;
2412 
2413 			if (mlo_tx_ops->send_wsi_link_info_cmd(
2414 					pdev, &wsi_info->link_stats[i]) !=
2415 						QDF_STATUS_SUCCESS) {
2416 				mlo_err("Could not send WMI command for PDEV %d in PSOC %d",
2417 					j, i);
2418 				error = QDF_STATUS_E_FAILURE;
2419 			} else {
2420 				wsi_info->link_stats[i].send_wmi_cmd = false;
2421 			}
2422 		}
2423 		wlan_objmgr_psoc_release_ref(psoc_objmgr, WLAN_MLO_MGR_ID);
2424 	}
2425 
2426 	return error;
2427 }
2428 
2429 static uint32_t wlan_mlo_psoc_get_ix_in_grp(struct mlo_mgr_context *mlo_mgr,
2430 					    uint32_t grp_id,
2431 					    uint32_t prim_psoc_id)
2432 {
2433 	uint32_t i;
2434 
2435 	if (!mlo_mgr) {
2436 		mlo_err("NULL mlo_mgr");
2437 		return 0xFF;
2438 	}
2439 
2440 	/* Iterate through the PSOC order and find the ID */
2441 	for (i = 0; i < mlo_mgr->wsi_info->mlo_psoc_grp[grp_id].num_psoc; i++) {
2442 		if (mlo_mgr->wsi_info->mlo_psoc_grp[grp_id].psoc_order[i] ==
2443 		    prim_psoc_id) {
2444 			return i;
2445 		}
2446 	}
2447 
2448 	return 0xFF;
2449 }
2450 
2451 static QDF_STATUS
2452 wlan_mlo_peer_wsi_link_update(struct wlan_mlo_peer_context *ml_peer, bool add)
2453 {
2454 	struct mlo_mgr_context *mlo_mgr = NULL;
2455 	struct mlo_wsi_info *wsi_info = NULL;
2456 	struct wlan_mlo_link_peer_entry *peer_entry = NULL;
2457 	uint32_t prim_psoc_id = 0xFF;
2458 	uint32_t sec_psoc_id[MAX_MLO_LINK_PEERS] = {0xFF};
2459 	uint32_t hops, hop_id;
2460 	uint32_t prim_grp_idx, sec_grp_idx;
2461 	uint32_t prim_psoc_ix_grp, sec_psoc_ix_grp;
2462 	uint32_t i, j;
2463 	struct mlo_wsi_psoc_grp *mlo_psoc_grp;
2464 	struct wlan_objmgr_psoc *psoc;
2465 
2466 	/* Check if ml_peer is valid */
2467 	if (!ml_peer) {
2468 		mlo_err("ML peer is null");
2469 		return QDF_STATUS_E_INVAL;
2470 	}
2471 
2472 	/* Retrieve the MLO manager context */
2473 	mlo_mgr = wlan_objmgr_get_mlo_ctx();
2474 	if (!mlo_mgr) {
2475 		mlo_err("ML MGR is NULL for ML peer" QDF_MAC_ADDR_FMT,
2476 			QDF_MAC_ADDR_REF(ml_peer->peer_mld_addr.bytes));
2477 		return QDF_STATUS_E_INVAL;
2478 	}
2479 
2480 	/* Retrieve the WSI link info structure */
2481 	wsi_info = mlo_mgr->wsi_info;
2482 	if (!wsi_info) {
2483 		mlo_err("WSI Info is NULL for ML peer" QDF_MAC_ADDR_FMT,
2484 			QDF_MAC_ADDR_REF(ml_peer->peer_mld_addr.bytes));
2485 		return QDF_STATUS_E_INVAL;
2486 	}
2487 
2488 	prim_psoc_id = ml_peer->primary_umac_psoc_id;
2489 	/* Populate the primary PSOC ID of the respective group */
2490 	prim_grp_idx = wlan_mlo_psoc_get_mlo_grp_idx(mlo_mgr, prim_psoc_id);
2491 	if (prim_grp_idx == MLO_WSI_MAX_MLO_GRPS) {
2492 		mlo_err("Group index is invalid for ML peer" QDF_MAC_ADDR_FMT,
2493 			QDF_MAC_ADDR_REF(ml_peer->peer_mld_addr.bytes));
2494 		return QDF_STATUS_E_INVAL;
2495 	}
2496 
2497 	/* Populate MLO primary and secondary link */
2498 	for (i = 0, j = 0; i < MAX_MLO_LINK_PEERS; i++) {
2499 		peer_entry = &ml_peer->peer_list[i];
2500 		if (!peer_entry->link_peer) {
2501 			mlo_err("link peer is null");
2502 			continue;
2503 		}
2504 
2505 		psoc = wlan_peer_get_psoc(peer_entry->link_peer);
2506 		if (!mlo_get_wsi_stats_info_support(psoc)) {
2507 			mlo_info("WSI stats support is not enabled on psoc %d",
2508 				 wlan_psoc_get_id(psoc));
2509 			return QDF_STATUS_E_INVAL;
2510 		}
2511 
2512 		/*
2513 		 * Consider all non-primary peers as secondary links.
2514 		 * Additionally, consider all active peers as secondary link if
2515 		 * the TQM is on another PSOC with bridge peer.
2516 		 */
2517 		if (!peer_entry->is_primary) {
2518 			sec_psoc_id[j] = wlan_vdev_get_psoc_id(
2519 						wlan_peer_get_vdev(
2520 						peer_entry->link_peer));
2521 
2522 			sec_grp_idx = wlan_mlo_psoc_get_mlo_grp_idx
2523 							(mlo_mgr,
2524 							 sec_psoc_id[j]);
2525 			if (sec_grp_idx != prim_grp_idx) {
2526 				mlo_err("Secondary link is not part of same MLO group as primary link");
2527 				continue;
2528 			}
2529 			j++;
2530 		}
2531 	}
2532 
2533 	/*
2534 	 * Logic for finding ingress and egress stats:
2535 	 * For a given MLO group, there is a PSOC order
2536 	 * (1) Iterate through each secondary link
2537 	 *      (1.1) Set the WMI command to true for that PSOC
2538 	 *      (1.2) Increment the ingress count for that PSOC
2539 	 *      (1.3) Calculate the number of hops from the secondary link
2540 	 *            to that primary link within the group.
2541 	 *      (1.4) Iterate through a decrement sequence from the hop_count
2542 	 *            (1.4.1) Increment the egress count for that PSOC index
2543 	 */
2544 	prim_psoc_ix_grp = wlan_mlo_psoc_get_ix_in_grp(mlo_mgr, prim_grp_idx,
2545 						       prim_psoc_id);
2546 
2547 	wsi_info->link_stats[prim_psoc_id].send_wmi_cmd = true;
2548 	mlo_psoc_grp = &wsi_info->mlo_psoc_grp[prim_grp_idx];
2549 	for (i = 0; i < j; i++) {
2550 		sec_psoc_ix_grp = wlan_mlo_psoc_get_ix_in_grp(mlo_mgr,
2551 							      prim_grp_idx,
2552 							      sec_psoc_id[i]);
2553 		hops = qdf_min(mlo_psoc_grp->num_psoc -
2554 			       (prim_psoc_ix_grp - sec_psoc_ix_grp),
2555 				(sec_psoc_ix_grp - prim_psoc_ix_grp));
2556 
2557 		wsi_info->link_stats[sec_psoc_id[i]].send_wmi_cmd = true;
2558 		if (add)
2559 			wsi_info->link_stats[sec_psoc_id[i]].ingress_cnt++;
2560 		else
2561 			wsi_info->link_stats[sec_psoc_id[i]].ingress_cnt--;
2562 
2563 		while (hops > 1) {
2564 			hops--;
2565 			hop_id = mlo_psoc_grp->psoc_order[hops];
2566 			wsi_info->link_stats[hop_id].send_wmi_cmd = true;
2567 			if (add)
2568 				wsi_info->link_stats[hop_id].egress_cnt++;
2569 			else
2570 				wsi_info->link_stats[hop_id].egress_cnt--;
2571 		}
2572 	}
2573 
2574 	/* Check if WMI bit is set, if yes, then send the command */
2575 	if (wlan_mlo_wsi_link_info_send_cmd() != QDF_STATUS_SUCCESS) {
2576 		mlo_err("WSI link info not sent for ML peer" QDF_MAC_ADDR_FMT,
2577 			QDF_MAC_ADDR_REF(ml_peer->peer_mld_addr.bytes));
2578 		return QDF_STATUS_E_FAILURE;
2579 	}
2580 
2581 	return QDF_STATUS_SUCCESS;
2582 }
2583 
2584 QDF_STATUS wlan_mlo_peer_wsi_link_add(struct wlan_mlo_peer_context *ml_peer)
2585 {
2586 	if (!ml_peer) {
2587 		mlo_err("Invalid peer");
2588 		return QDF_STATUS_E_INVAL;
2589 	}
2590 
2591 	return wlan_mlo_peer_wsi_link_update(ml_peer, 1);
2592 }
2593 
2594 QDF_STATUS wlan_mlo_peer_wsi_link_delete(struct wlan_mlo_peer_context *ml_peer)
2595 {
2596 	if (!ml_peer) {
2597 		mlo_err("Invalid peer");
2598 		return QDF_STATUS_E_INVAL;
2599 	}
2600 
2601 	return wlan_mlo_peer_wsi_link_update(ml_peer, 0);
2602 }
2603 
2604 void wlan_mlo_wsi_stats_block_cmd(void)
2605 {
2606 	struct mlo_mgr_context *mlo_mgr = NULL;
2607 	struct mlo_wsi_info *wsi_info = NULL;
2608 
2609 	/* Retrieve the MLO manager context */
2610 	mlo_mgr = wlan_objmgr_get_mlo_ctx();
2611 	if (!mlo_mgr)
2612 		return;
2613 
2614 	/* Retrieve the WSI link info structure */
2615 	wsi_info = mlo_mgr->wsi_info;
2616 	if (!wsi_info)
2617 		return;
2618 
2619 	wsi_info->block_wmi_cmd++;
2620 }
2621 
2622 void wlan_mlo_wsi_stats_allow_cmd(void)
2623 {
2624 	struct mlo_mgr_context *mlo_mgr = NULL;
2625 	struct mlo_wsi_info *wsi_info = NULL;
2626 
2627 	/* Retrieve the MLO manager context */
2628 	mlo_mgr = wlan_objmgr_get_mlo_ctx();
2629 	if (!mlo_mgr)
2630 		return;
2631 
2632 	/* Retrieve the WSI link info structure */
2633 	wsi_info = mlo_mgr->wsi_info;
2634 	if (!wsi_info)
2635 		return;
2636 
2637 	if (wsi_info->block_wmi_cmd)
2638 		wsi_info->block_wmi_cmd--;
2639 }
2640 
2641 #else
2642 void wlan_mlo_wsi_stats_block_cmd(void)
2643 {
2644 }
2645 
2646 void wlan_mlo_wsi_stats_allow_cmd(void)
2647 {
2648 }
2649 
2650 QDF_STATUS wlan_mlo_wsi_link_info_send_cmd(void)
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 	return QDF_STATUS_SUCCESS;
2658 }
2659 
2660 QDF_STATUS wlan_mlo_peer_wsi_link_delete(struct wlan_mlo_peer_context *ml_peer)
2661 {
2662 	return QDF_STATUS_SUCCESS;
2663 }
2664 #endif
2665