xref: /wlan-dirver/qca-wifi-host-cmn/umac/mlo_mgr/src/wlan_mlo_mgr_peer.c (revision 901120c066e139c7f8a2c8e4820561fdd83c67ef)
1 /*
2  * Copyright (c) 2021, The Linux Foundation. All rights reserved.
3  * Copyright (c) 2021-2022 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 
28 static void mlo_partner_peer_create_post(struct wlan_mlo_dev_context *ml_dev,
29 					 struct wlan_objmgr_vdev *vdev_link,
30 					 struct wlan_mlo_peer_context *ml_peer,
31 					 qdf_nbuf_t frm_buf,
32 					 struct mlo_partner_info *ml_info)
33 {
34 	struct peer_create_notif_s peer_create;
35 	QDF_STATUS status;
36 	uint8_t i;
37 	uint8_t link_id;
38 
39 	if (wlan_objmgr_vdev_try_get_ref(vdev_link, WLAN_MLO_MGR_ID) ==
40 							QDF_STATUS_SUCCESS) {
41 		peer_create.vdev_link = vdev_link;
42 	} else {
43 		mlo_err("VDEV is not in created state");
44 		return;
45 	}
46 
47 	wlan_mlo_peer_get_ref(ml_peer);
48 	peer_create.ml_peer = ml_peer;
49 	link_id = wlan_vdev_get_link_id(vdev_link);
50 	for (i = 0; i < ml_info->num_partner_links; i++) {
51 		if (link_id != ml_info->partner_link_info[i].link_id)
52 			continue;
53 
54 		qdf_copy_macaddr(&peer_create.addr,
55 				 &ml_info->partner_link_info[i].link_addr);
56 		break;
57 	}
58 
59 	status = mlo_peer_create_get_frm_buf(ml_peer, &peer_create, frm_buf);
60 
61 	if (QDF_IS_STATUS_ERROR(status)) {
62 		wlan_mlo_peer_release_ref(ml_peer);
63 		wlan_objmgr_vdev_release_ref(vdev_link, WLAN_MLO_MGR_ID);
64 		mlo_err("nbuf clone is failed");
65 		return;
66 	}
67 
68 	status = mlo_msgq_post(MLO_PEER_CREATE, ml_dev, &peer_create);
69 	if (status != QDF_STATUS_SUCCESS) {
70 		qdf_nbuf_free(frm_buf);
71 		wlan_mlo_peer_release_ref(ml_peer);
72 		wlan_objmgr_vdev_release_ref(vdev_link, WLAN_MLO_MGR_ID);
73 	}
74 }
75 
76 static void mlo_link_peer_assoc_notify(struct wlan_mlo_dev_context *ml_dev,
77 				       struct wlan_objmgr_peer *peer)
78 {
79 	struct peer_assoc_notify_s peer_assoc;
80 	QDF_STATUS status;
81 
82 	peer_assoc.peer = peer;
83 	status = mlo_msgq_post(MLO_PEER_ASSOC, ml_dev, &peer_assoc);
84 	if (status != QDF_STATUS_SUCCESS)
85 		wlan_objmgr_peer_release_ref(peer, WLAN_MLO_MGR_ID);
86 }
87 
88 static void mlo_link_peer_send_assoc_fail(struct wlan_mlo_dev_context *ml_dev,
89 					  struct wlan_objmgr_peer *peer)
90 {
91 	struct peer_assoc_fail_notify_s peer_assoc_fail;
92 	QDF_STATUS status;
93 
94 	peer_assoc_fail.peer = peer;
95 	status = mlo_msgq_post(MLO_PEER_ASSOC_FAIL, ml_dev, &peer_assoc_fail);
96 	if (status != QDF_STATUS_SUCCESS)
97 		wlan_objmgr_peer_release_ref(peer, WLAN_MLO_MGR_ID);
98 }
99 
100 static void mlo_link_peer_disconnect_notify(struct wlan_mlo_dev_context *ml_dev,
101 					    struct wlan_objmgr_peer *peer)
102 {
103 	struct peer_discon_notify_s peer_disconn;
104 	QDF_STATUS status;
105 	struct wlan_objmgr_vdev *vdev;
106 	enum QDF_OPMODE opmode;
107 
108 	vdev = wlan_peer_get_vdev(peer);
109 	opmode = wlan_vdev_mlme_get_opmode(vdev);
110 
111 	if (opmode == QDF_SAP_MODE) {
112 		peer_disconn.peer = peer;
113 		status = mlo_msgq_post(MLO_PEER_DISCONNECT, ml_dev,
114 				       &peer_disconn);
115 		if (status != QDF_STATUS_SUCCESS)
116 			wlan_objmgr_peer_release_ref(peer, WLAN_MLO_MGR_ID);
117 	} else {
118 		wlan_objmgr_peer_release_ref(peer, WLAN_MLO_MGR_ID);
119 	}
120 }
121 
122 static void mlo_link_peer_deauth_init(struct wlan_mlo_dev_context *ml_dev,
123 				      struct wlan_objmgr_peer *peer)
124 {
125 	struct peer_deauth_notify_s peer_deauth;
126 	QDF_STATUS status;
127 
128 	peer_deauth.peer = peer;
129 	status = mlo_msgq_post(MLO_PEER_DEAUTH, ml_dev, &peer_deauth);
130 	if (status != QDF_STATUS_SUCCESS)
131 		wlan_objmgr_peer_release_ref(peer, WLAN_MLO_MGR_ID);
132 }
133 
134 #ifdef UMAC_MLO_AUTH_DEFER
135 static void mlo_peer_process_pending_auth(struct wlan_mlo_dev_context *ml_dev,
136 					  struct wlan_mlo_peer_context *ml_peer)
137 {
138 	struct peer_auth_process_notif_s peer_auth;
139 	struct mlpeer_auth_params *recv_auth;
140 	uint8_t i;
141 	QDF_STATUS status;
142 
143 	for (i = 0; i < MAX_MLO_LINK_PEERS; i++) {
144 		mlo_peer_lock_acquire(ml_peer);
145 		recv_auth = ml_peer->pending_auth[i];
146 		if (!recv_auth) {
147 			mlo_peer_lock_release(ml_peer);
148 			continue;
149 		}
150 		peer_auth.auth_params = recv_auth;
151 		ml_peer->pending_auth[i] = NULL;
152 
153 		mlo_peer_lock_release(ml_peer);
154 
155 		status = mlo_msgq_post(MLO_PEER_PENDING_AUTH, ml_dev,
156 				       &peer_auth);
157 		if (QDF_IS_STATUS_ERROR(status))
158 			mlo_peer_free_auth_param(peer_auth.auth_params);
159 	}
160 }
161 #else
162 static void mlo_peer_process_pending_auth(struct wlan_mlo_dev_context *ml_dev,
163 					  struct wlan_mlo_peer_context *ml_peer)
164 {
165 }
166 #endif
167 
168 QDF_STATUS
169 wlan_mlo_peer_is_disconnect_progress(struct wlan_mlo_peer_context *ml_peer)
170 {
171 	QDF_STATUS status;
172 
173 	if (!ml_peer)
174 		return QDF_STATUS_E_FAILURE;
175 
176 	mlo_peer_lock_acquire(ml_peer);
177 
178 	if (ml_peer->mlpeer_state == ML_PEER_DISCONN_INITIATED)
179 		status = QDF_STATUS_SUCCESS;
180 	else
181 		status = QDF_STATUS_E_FAILURE;
182 
183 	mlo_peer_lock_release(ml_peer);
184 
185 	return status;
186 }
187 
188 QDF_STATUS wlan_mlo_peer_is_assoc_done(struct wlan_mlo_peer_context *ml_peer)
189 {
190 	QDF_STATUS status;
191 
192 	if (!ml_peer)
193 		return QDF_STATUS_E_FAILURE;
194 
195 	mlo_peer_lock_acquire(ml_peer);
196 
197 	if (ml_peer->mlpeer_state == ML_PEER_ASSOC_DONE)
198 		status = QDF_STATUS_SUCCESS;
199 	else
200 		status = QDF_STATUS_E_FAILURE;
201 
202 	mlo_peer_lock_release(ml_peer);
203 
204 	return status;
205 }
206 
207 struct wlan_objmgr_peer *wlan_mlo_peer_get_assoc_peer(
208 					struct wlan_mlo_peer_context *ml_peer)
209 {
210 	struct wlan_mlo_link_peer_entry *peer_entry;
211 	struct wlan_objmgr_peer *assoc_peer = NULL;
212 
213 	if (!ml_peer)
214 		return NULL;
215 
216 	mlo_peer_lock_acquire(ml_peer);
217 
218 	peer_entry = &ml_peer->peer_list[0];
219 
220 	if (peer_entry->link_peer)
221 		assoc_peer = peer_entry->link_peer;
222 
223 	mlo_peer_lock_release(ml_peer);
224 
225 	return assoc_peer;
226 }
227 
228 bool mlo_peer_is_assoc_peer(struct wlan_mlo_peer_context *ml_peer,
229 			    struct wlan_objmgr_peer *peer)
230 {
231 	struct wlan_mlo_link_peer_entry *peer_entry;
232 	bool is_assoc_peer = false;
233 
234 	if (!ml_peer || !peer)
235 		return is_assoc_peer;
236 
237 	peer_entry = &ml_peer->peer_list[0];
238 
239 	if (peer_entry->link_peer != peer)
240 		is_assoc_peer = true;
241 
242 	return is_assoc_peer;
243 }
244 
245 bool wlan_mlo_peer_is_assoc_peer(struct wlan_mlo_peer_context *ml_peer,
246 				 struct wlan_objmgr_peer *peer)
247 {
248 	bool is_assoc_peer = false;
249 
250 	if (!ml_peer || !peer)
251 		return is_assoc_peer;
252 
253 	mlo_peer_lock_acquire(ml_peer);
254 
255 	is_assoc_peer = mlo_peer_is_assoc_peer(ml_peer, peer);
256 
257 	mlo_peer_lock_release(ml_peer);
258 
259 	return is_assoc_peer;
260 }
261 
262 void wlan_mlo_partner_peer_assoc_post(struct wlan_objmgr_peer *assoc_peer)
263 {
264 	struct wlan_mlo_dev_context *ml_dev;
265 	struct wlan_mlo_peer_context *ml_peer;
266 	struct wlan_objmgr_peer *link_peer;
267 	struct wlan_objmgr_peer *link_peers[MAX_MLO_LINK_PEERS];
268 	struct wlan_mlo_link_peer_entry *peer_entry;
269 	uint16_t i;
270 
271 	ml_peer = assoc_peer->mlo_peer_ctx;
272 	if (!ml_peer)
273 		return;
274 
275 	mlo_peer_lock_acquire(ml_peer);
276 
277 	if (ml_peer->mlpeer_state != ML_PEER_CREATED) {
278 		mlo_peer_lock_release(ml_peer);
279 		return;
280 	}
281 
282 	ml_peer->mlpeer_state = ML_PEER_ASSOC_DONE;
283 	ml_dev = ml_peer->ml_dev;
284 
285 	for (i = 0; i < MAX_MLO_LINK_PEERS; i++) {
286 		link_peers[i] = NULL;
287 		peer_entry = &ml_peer->peer_list[i];
288 
289 		if (!peer_entry->link_peer)
290 			continue;
291 
292 		if (peer_entry->link_peer == assoc_peer)
293 			continue;
294 
295 		link_peer = peer_entry->link_peer;
296 
297 		if (wlan_objmgr_peer_try_get_ref(link_peer, WLAN_MLO_MGR_ID) !=
298 						 QDF_STATUS_SUCCESS)
299 			continue;
300 
301 		link_peers[i] = link_peer;
302 	}
303 	mlo_peer_lock_release(ml_peer);
304 
305 	for (i = 0; i < MAX_MLO_LINK_PEERS; i++) {
306 		if (!link_peers[i])
307 			continue;
308 
309 		/* Prepare and queue message */
310 		mlo_link_peer_assoc_notify(ml_dev, link_peers[i]);
311 	}
312 }
313 
314 void
315 wlan_mlo_peer_deauth_init(struct wlan_mlo_peer_context *ml_peer)
316 {
317 	struct wlan_mlo_dev_context *ml_dev;
318 	struct wlan_objmgr_peer *link_peer;
319 	struct wlan_objmgr_peer *link_peers[MAX_MLO_LINK_PEERS];
320 	struct wlan_mlo_link_peer_entry *peer_entry;
321 	uint16_t i;
322 
323 	if (!ml_peer)
324 		return;
325 
326 	mlo_peer_lock_acquire(ml_peer);
327 
328 	if (ml_peer->mlpeer_state == ML_PEER_DISCONN_INITIATED) {
329 		mlo_peer_lock_release(ml_peer);
330 		return;
331 	}
332 
333 	ml_dev = ml_peer->ml_dev;
334 
335 	for (i = 0; i < MAX_MLO_LINK_PEERS; i++) {
336 		link_peers[i] = NULL;
337 		peer_entry = &ml_peer->peer_list[i];
338 		if (!peer_entry->link_peer)
339 			continue;
340 
341 		link_peer = peer_entry->link_peer;
342 		/* Skip Deauth if PMF is enabled for the station */
343 		if ((i == 0) &&
344 		    (wlan_crypto_is_pmf_enabled(wlan_peer_get_vdev(link_peer),
345 					       link_peer))) {
346 			mlo_peer_lock_release(ml_peer);
347 			return;
348 		}
349 
350 		if (wlan_objmgr_peer_try_get_ref(link_peer, WLAN_MLO_MGR_ID) !=
351 						QDF_STATUS_SUCCESS)
352 			continue;
353 
354 		link_peers[i] = link_peer;
355 	}
356 
357 	ml_peer->mlpeer_state = ML_PEER_DISCONN_INITIATED;
358 
359 	mlo_peer_lock_release(ml_peer);
360 
361 	for (i = 0; i < MAX_MLO_LINK_PEERS; i++) {
362 		if (!link_peers[i])
363 			continue;
364 
365 		/* Prepare and queue message */
366 		if (i == 0)
367 			mlo_link_peer_deauth_init(ml_dev, link_peers[i]);
368 		else
369 			mlo_link_peer_disconnect_notify(ml_dev, link_peers[i]);
370 	}
371 
372 	return;
373 }
374 
375 void
376 wlan_mlo_partner_peer_create_failed_notify(
377 				struct wlan_mlo_peer_context *ml_peer)
378 {
379 	struct wlan_mlo_dev_context *ml_dev;
380 	struct wlan_objmgr_peer *link_peer;
381 	struct wlan_objmgr_peer *link_peers[MAX_MLO_LINK_PEERS];
382 	struct wlan_mlo_link_peer_entry *peer_entry;
383 	uint16_t i;
384 
385 	if (!ml_peer)
386 		return;
387 
388 	mlo_peer_lock_acquire(ml_peer);
389 
390 	if (ml_peer->mlpeer_state == ML_PEER_DISCONN_INITIATED) {
391 		mlo_peer_lock_release(ml_peer);
392 		return;
393 	}
394 
395 	ml_peer->mlpeer_state = ML_PEER_DISCONN_INITIATED;
396 	ml_dev = ml_peer->ml_dev;
397 
398 	for (i = 0; i < MAX_MLO_LINK_PEERS; i++) {
399 		link_peers[i] = NULL;
400 		peer_entry = &ml_peer->peer_list[i];
401 		if (!peer_entry->link_peer)
402 			continue;
403 
404 		link_peer = peer_entry->link_peer;
405 		if (wlan_objmgr_peer_try_get_ref(link_peer, WLAN_MLO_MGR_ID) !=
406 						QDF_STATUS_SUCCESS)
407 			continue;
408 
409 		link_peers[i] = link_peer;
410 	}
411 	mlo_peer_lock_release(ml_peer);
412 
413 	for (i = 0; i < MAX_MLO_LINK_PEERS; i++) {
414 		if (!link_peers[i])
415 			continue;
416 
417 		/* Prepare and queue message */
418 		if (i == 0)
419 			mlo_link_peer_send_assoc_fail(ml_dev, link_peers[i]);
420 		else
421 			mlo_link_peer_disconnect_notify(ml_dev, link_peers[i]);
422 	}
423 }
424 
425 void wlan_mlo_partner_peer_disconnect_notify(struct wlan_objmgr_peer *src_peer)
426 {
427 	struct wlan_mlo_dev_context *ml_dev;
428 	struct wlan_mlo_peer_context *ml_peer;
429 	struct wlan_objmgr_peer *link_peer;
430 	struct wlan_objmgr_peer *link_peers[MAX_MLO_LINK_PEERS];
431 	struct wlan_mlo_link_peer_entry *peer_entry;
432 	struct wlan_objmgr_vdev *vdev = NULL;
433 	uint16_t i;
434 
435 	ml_peer = src_peer->mlo_peer_ctx;
436 	if (!ml_peer)
437 		return;
438 
439 	mlo_peer_lock_acquire(ml_peer);
440 
441 	if (ml_peer->mlpeer_state == ML_PEER_DISCONN_INITIATED) {
442 		mlo_peer_lock_release(ml_peer);
443 		return;
444 	}
445 
446 	ml_peer->mlpeer_state = ML_PEER_DISCONN_INITIATED;
447 
448 	vdev = wlan_peer_get_vdev(src_peer);
449 	if (!vdev || wlan_vdev_mlme_get_opmode(vdev) == QDF_STA_MODE) {
450 		mlo_peer_lock_release(ml_peer);
451 		return;
452 	}
453 
454 	ml_dev = ml_peer->ml_dev;
455 	for (i = 0; i < MAX_MLO_LINK_PEERS; i++) {
456 		link_peers[i] = NULL;
457 		peer_entry = &ml_peer->peer_list[i];
458 		if (!peer_entry->link_peer) {
459 			mlo_debug("link peer is null");
460 			continue;
461 		}
462 
463 		if (peer_entry->link_peer == src_peer)
464 			continue;
465 
466 		link_peer = peer_entry->link_peer;
467 		if (wlan_objmgr_peer_try_get_ref(link_peer, WLAN_MLO_MGR_ID) !=
468 						QDF_STATUS_SUCCESS)
469 			continue;
470 
471 		link_peers[i] = link_peer;
472 	}
473 	mlo_peer_lock_release(ml_peer);
474 
475 	for (i = 0; i < MAX_MLO_LINK_PEERS; i++) {
476 		if (!link_peers[i])
477 			continue;
478 
479 		/* Prepare and queue message */
480 		mlo_link_peer_disconnect_notify(ml_dev, link_peers[i]);
481 	}
482 }
483 
484 static void mlo_peer_populate_link_peer(
485 			struct wlan_mlo_peer_context *ml_peer,
486 			struct wlan_objmgr_peer *link_peer)
487 {
488 	mlo_peer_lock_acquire(ml_peer);
489 	wlan_mlo_peer_get_ref(ml_peer);
490 	link_peer->mlo_peer_ctx = ml_peer;
491 	mlo_peer_lock_release(ml_peer);
492 }
493 
494 static void mlo_reset_link_peer(
495 			struct wlan_mlo_peer_context *ml_peer,
496 			struct wlan_objmgr_peer *link_peer)
497 {
498 	mlo_peer_lock_acquire(ml_peer);
499 	link_peer->mlo_peer_ctx = NULL;
500 	wlan_peer_clear_mlo(link_peer);
501 	mlo_peer_lock_release(ml_peer);
502 }
503 
504 static void mlo_peer_free(struct wlan_mlo_peer_context *ml_peer)
505 {
506 	struct wlan_mlo_dev_context *ml_dev;
507 
508 	ml_dev = ml_peer->ml_dev;
509 	if (!ml_dev) {
510 		mlo_err("ML DEV is NULL");
511 		return;
512 	}
513 
514 	mlo_peer_lock_destroy(ml_peer);
515 	mlo_ap_ml_peerid_free(ml_peer->mlo_peer_id);
516 	mlo_peer_free_aid(ml_dev, ml_peer);
517 	mlo_peer_free_primary_umac(ml_dev, ml_peer);
518 	qdf_mem_free(ml_peer);
519 }
520 
521 void mlo_peer_cleanup(struct wlan_mlo_peer_context *ml_peer)
522 {
523 	struct wlan_mlo_dev_context *ml_dev;
524 
525 	if (!ml_peer) {
526 		mlo_err("ML PEER is NULL");
527 		return;
528 	}
529 	ml_dev = ml_peer->ml_dev;
530 	if (!ml_dev) {
531 		mlo_err("ML DEV is NULL");
532 		return;
533 	}
534 
535 	mlo_dev_mlpeer_detach(ml_dev, ml_peer);
536 	/* If any Auth req is received during ML peer delete */
537 	mlo_peer_process_pending_auth(ml_dev, ml_peer);
538 	mlo_peer_free(ml_peer);
539 }
540 
541 static QDF_STATUS mlo_peer_attach_link_peer(
542 		struct wlan_mlo_peer_context *ml_peer,
543 		struct wlan_objmgr_peer *link_peer,
544 		qdf_nbuf_t frm_buf)
545 {
546 	struct wlan_mlo_link_peer_entry *peer_entry;
547 	QDF_STATUS status = QDF_STATUS_E_RESOURCES;
548 	struct wlan_objmgr_pdev *pdev;
549 	struct wlan_objmgr_vdev *vdev;
550 	uint16_t i;
551 
552 	if (!link_peer)
553 		return QDF_STATUS_E_FAILURE;
554 
555 	vdev = wlan_peer_get_vdev(link_peer);
556 	if (!vdev)
557 		return QDF_STATUS_E_FAILURE;
558 
559 	mlo_peer_lock_acquire(ml_peer);
560 
561 	if (ml_peer->mlpeer_state != ML_PEER_CREATED) {
562 		mlo_peer_lock_release(ml_peer);
563 		mlo_err("ML Peer " QDF_MAC_ADDR_FMT " is not in created state (state %d)",
564 			QDF_MAC_ADDR_REF(ml_peer->peer_mld_addr.bytes),
565 			ml_peer->mlpeer_state);
566 		return status;
567 	}
568 
569 	for (i = 0; i < MAX_MLO_LINK_PEERS; i++) {
570 		peer_entry = &ml_peer->peer_list[i];
571 		if (peer_entry->link_peer)
572 			continue;
573 
574 		if (wlan_objmgr_peer_try_get_ref(link_peer, WLAN_MLO_MGR_ID) !=
575 						QDF_STATUS_SUCCESS) {
576 			mlo_err("ML Peer " QDF_MAC_ADDR_FMT ", link peer " QDF_MAC_ADDR_FMT " is not in valid state",
577 				QDF_MAC_ADDR_REF(ml_peer->peer_mld_addr.bytes),
578 				QDF_MAC_ADDR_REF
579 					(wlan_peer_get_macaddr(link_peer)));
580 			break;
581 		}
582 		peer_entry->link_peer = link_peer;
583 		qdf_copy_macaddr(&peer_entry->link_addr,
584 				 (struct qdf_mac_addr *)&link_peer->macaddr[0]);
585 
586 		peer_entry->link_ix = wlan_vdev_get_link_id(vdev);
587 		pdev = wlan_vdev_get_pdev(wlan_peer_get_vdev(link_peer));
588 		peer_entry->hw_link_id = wlan_mlo_get_pdev_hw_link_id(pdev);
589 		mlo_peer_assign_primary_umac(ml_peer, peer_entry);
590 		if (frm_buf)
591 			peer_entry->assoc_rsp_buf = frm_buf;
592 		else
593 			peer_entry->assoc_rsp_buf = NULL;
594 
595 		status = QDF_STATUS_SUCCESS;
596 		break;
597 	}
598 	if (QDF_IS_STATUS_SUCCESS(status))
599 		ml_peer->link_peer_cnt++;
600 
601 	mlo_peer_lock_release(ml_peer);
602 
603 	return status;
604 }
605 
606 qdf_nbuf_t mlo_peer_get_link_peer_assoc_resp_buf(
607 		struct wlan_mlo_peer_context *ml_peer,
608 		uint8_t link_ix)
609 {
610 	struct wlan_mlo_link_peer_entry *peer_entry;
611 	qdf_nbuf_t frm_buf = NULL;
612 	uint8_t i;
613 
614 	if (!ml_peer)
615 		return NULL;
616 
617 	if (link_ix > MAX_MLO_LINK_PEERS)
618 		return NULL;
619 
620 	mlo_peer_lock_acquire(ml_peer);
621 	if ((ml_peer->mlpeer_state != ML_PEER_CREATED) &&
622 	    (ml_peer->mlpeer_state != ML_PEER_ASSOC_DONE)) {
623 		mlo_peer_lock_release(ml_peer);
624 		return NULL;
625 	}
626 
627 	for (i = 0; i < MAX_MLO_LINK_PEERS; i++) {
628 		peer_entry = &ml_peer->peer_list[i];
629 
630 		if (!peer_entry->link_peer)
631 			continue;
632 
633 		if (peer_entry->link_ix == link_ix) {
634 			if (!peer_entry->assoc_rsp_buf)
635 				break;
636 
637 			frm_buf = qdf_nbuf_clone(peer_entry->assoc_rsp_buf);
638 			break;
639 		}
640 	}
641 	mlo_peer_lock_release(ml_peer);
642 
643 	return frm_buf;
644 }
645 
646 void wlan_mlo_peer_free_all_link_assoc_resp_buf(
647 			struct wlan_objmgr_peer *link_peer)
648 {
649 	struct wlan_mlo_link_peer_entry *peer_entry;
650 	struct wlan_mlo_peer_context *ml_peer;
651 	uint8_t i;
652 
653 	ml_peer = link_peer->mlo_peer_ctx;
654 	if (!ml_peer)
655 		return;
656 
657 	mlo_peer_lock_acquire(ml_peer);
658 
659 	for (i = 0; i < MAX_MLO_LINK_PEERS; i++) {
660 		peer_entry = &ml_peer->peer_list[i];
661 
662 		if (peer_entry->assoc_rsp_buf) {
663 			qdf_nbuf_free(peer_entry->assoc_rsp_buf);
664 			peer_entry->assoc_rsp_buf = NULL;
665 		}
666 	}
667 	mlo_peer_lock_release(ml_peer);
668 }
669 
670 static QDF_STATUS mlo_peer_detach_link_peer(
671 		struct wlan_mlo_peer_context *ml_peer,
672 		struct wlan_objmgr_peer *link_peer)
673 {
674 	struct wlan_mlo_link_peer_entry *peer_entry;
675 	QDF_STATUS status = QDF_STATUS_E_RESOURCES;
676 	uint16_t i;
677 
678 	mlo_peer_lock_acquire(ml_peer);
679 
680 	if (ml_peer->mlpeer_state != ML_PEER_DISCONN_INITIATED) {
681 		mlo_peer_lock_release(ml_peer);
682 		return status;
683 	}
684 
685 	for (i = 0; i < MAX_MLO_LINK_PEERS; i++) {
686 		peer_entry = &ml_peer->peer_list[i];
687 		if (!peer_entry->link_peer)
688 			continue;
689 
690 		if (peer_entry->link_peer != link_peer)
691 			continue;
692 
693 		if (peer_entry->assoc_rsp_buf) {
694 			qdf_nbuf_free(peer_entry->assoc_rsp_buf);
695 			peer_entry->assoc_rsp_buf = NULL;
696 		}
697 
698 		wlan_objmgr_peer_release_ref(link_peer, WLAN_MLO_MGR_ID);
699 		peer_entry->link_peer = NULL;
700 		ml_peer->link_peer_cnt--;
701 		status = QDF_STATUS_SUCCESS;
702 		break;
703 	}
704 	mlo_peer_lock_release(ml_peer);
705 
706 	return status;
707 }
708 
709 static QDF_STATUS mlo_dev_get_link_vdevs(
710 			struct wlan_objmgr_vdev *vdev,
711 			struct wlan_mlo_dev_context *ml_dev,
712 			struct mlo_partner_info *ml_info,
713 			struct wlan_objmgr_vdev *link_vdevs[])
714 {
715 	uint16_t i, j;
716 	struct wlan_objmgr_vdev *vdev_link;
717 	uint8_t link_id;
718 
719 	if (!ml_dev) {
720 		mlo_err("ml_dev is null");
721 		return QDF_STATUS_E_INVAL;
722 	}
723 
724 	if (!ml_info) {
725 		mlo_err("ml_info is null");
726 		return QDF_STATUS_E_INVAL;
727 	}
728 
729 	mlo_debug("num_partner_links %d", ml_info->num_partner_links);
730 	for (i = 0; i < ml_info->num_partner_links; i++) {
731 		link_id = ml_info->partner_link_info[i].link_id;
732 		vdev_link = mlo_get_vdev_by_link_id(vdev, link_id);
733 		if (vdev_link) {
734 			link_vdevs[i] = vdev_link;
735 		} else {
736 			/* release ref which were taken before failure */
737 			for (j = 0; j < i; j++) {
738 				vdev_link = link_vdevs[j];
739 				if (!vdev_link)
740 					continue;
741 
742 				wlan_objmgr_vdev_release_ref(vdev_link,
743 							     WLAN_MLO_MGR_ID);
744 			}
745 			return QDF_STATUS_E_INVAL;
746 		}
747 	}
748 
749 	return QDF_STATUS_SUCCESS;
750 }
751 
752 static void mlo_dev_release_link_vdevs(
753 			struct wlan_objmgr_vdev *link_vdevs[])
754 {
755 	uint16_t i;
756 	struct wlan_objmgr_vdev *vdev_link;
757 
758 	for (i = 0; i < WLAN_UMAC_MLO_MAX_VDEVS; i++) {
759 		vdev_link = link_vdevs[i];
760 		if (!vdev_link)
761 			continue;
762 
763 		wlan_objmgr_vdev_release_ref(vdev_link, WLAN_MLO_MGR_ID);
764 	}
765 }
766 
767 #ifdef WLAN_FEATURE_11BE
768 static void
769 wlan_mlo_peer_set_t2lm_enable_val(struct wlan_mlo_peer_context *ml_peer,
770 				  struct mlo_partner_info *ml_info)
771 {
772 	ml_peer->t2lm_policy.t2lm_enable_val = ml_info->t2lm_enable_val;
773 }
774 #else
775 static void
776 wlan_mlo_peer_set_t2lm_enable_val(struct wlan_mlo_peer_context *ml_peer,
777 				  struct mlo_partner_info *ml_info)
778 {}
779 #endif /* WLAN_FEATURE_11BE */
780 
781 QDF_STATUS wlan_mlo_peer_create(struct wlan_objmgr_vdev *vdev,
782 				struct wlan_objmgr_peer *link_peer,
783 				struct mlo_partner_info *ml_info,
784 				qdf_nbuf_t frm_buf,
785 				uint16_t aid)
786 {
787 	struct wlan_mlo_dev_context *ml_dev;
788 	struct wlan_mlo_peer_context *ml_peer = NULL;
789 	struct wlan_objmgr_vdev *link_vdevs[WLAN_UMAC_MLO_MAX_VDEVS] = { NULL };
790 	struct wlan_objmgr_vdev *vdev_link;
791 	QDF_STATUS status;
792 	uint16_t i;
793 	struct wlan_objmgr_peer *assoc_peer;
794 	bool is_ml_peer_attached = false;
795 
796 	/* get ML VDEV from VDEV */
797 	ml_dev = vdev->mlo_dev_ctx;
798 
799 	if (!ml_dev) {
800 		mlo_err("ML dev ctx is NULL");
801 		return QDF_STATUS_E_NULL_VALUE;
802 	}
803 
804 	/* Check resources of Partner VDEV */
805 	if (wlan_vdev_mlme_get_opmode(vdev) == QDF_SAP_MODE) {
806 		if (wlan_mlo_is_mld_ctx_exist(
807 		    (struct qdf_mac_addr *)&link_peer->mldaddr[0])) {
808 			mlo_err("MLD ID %d ML Peer " QDF_MAC_ADDR_FMT " is matching with one of the MLD address in the system",
809 				ml_dev->mld_id,
810 				QDF_MAC_ADDR_REF(link_peer->mldaddr));
811 			return QDF_STATUS_E_FAILURE;
812 		}
813 		status = mlo_dev_get_link_vdevs(vdev, ml_dev,
814 						ml_info, link_vdevs);
815 		if (QDF_IS_STATUS_ERROR(status)) {
816 			mlo_err("MLD ID %d ML Peer " QDF_MAC_ADDR_FMT " get link vdevs failed",
817 				ml_dev->mld_id,
818 				QDF_MAC_ADDR_REF(link_peer->mldaddr));
819 			return QDF_STATUS_E_FAILURE;
820 		}
821 
822 		for (i = 0; i < WLAN_UMAC_MLO_MAX_VDEVS; i++) {
823 			vdev_link = link_vdevs[i];
824 			if (!vdev_link) {
825 				mlo_debug("vdev_link is null");
826 				continue;
827 			}
828 
829 			if (wlan_vdev_is_mlo_peer_create_allowed(vdev_link)
830 					!= QDF_STATUS_SUCCESS) {
831 				mlo_dev_release_link_vdevs(link_vdevs);
832 
833 				mlo_err("MLD ID %d ML Peer " QDF_MAC_ADDR_FMT " create not allowed on link vdev %d",
834 					ml_dev->mld_id,
835 					QDF_MAC_ADDR_REF
836 						(link_peer->mldaddr),
837 					wlan_vdev_get_id(vdev_link));
838 				return QDF_STATUS_E_INVAL;
839 			}
840 		}
841 
842 		for (i = 0; i < WLAN_UMAC_MLO_MAX_VDEVS; i++) {
843 			vdev_link = link_vdevs[i];
844 			if (vdev_link && (vdev_link != vdev) &&
845 			    (wlan_vdev_get_peer_count(vdev_link) >
846 			     wlan_vdev_get_max_peer_count(vdev_link))) {
847 				mlo_dev_release_link_vdevs(link_vdevs);
848 				mlo_err("MLD ID %d ML Peer " QDF_MAC_ADDR_FMT " Max peer count reached on link vdev %d",
849 					ml_dev->mld_id,
850 					QDF_MAC_ADDR_REF
851 						(link_peer->mldaddr),
852 					wlan_vdev_get_id(vdev_link));
853 				return QDF_STATUS_E_RESOURCES;
854 			}
855 		}
856 	}
857 	/* When roam to MLO AP, partner link vdev1 is updated first,
858 	 * ml peer need be created and attached for partner link peer.
859 	 *
860 	 * When roam target AP and current AP have same MLD address, don't
861 	 * delete old ML peer and re-create new one, just update different
862 	 * info.
863 	 */
864 	if (wlan_vdev_mlme_get_opmode(vdev) == QDF_STA_MODE) {
865 		ml_peer = wlan_mlo_get_mlpeer(ml_dev,
866 				 (struct qdf_mac_addr *)&link_peer->mldaddr[0]);
867 		if (ml_peer) {
868 			mlo_debug("ML Peer " QDF_MAC_ADDR_FMT
869 				" existed, state %d",
870 				QDF_MAC_ADDR_REF(ml_peer->peer_mld_addr.bytes),
871 				ml_peer->mlpeer_state);
872 			ml_peer->mlpeer_state = ML_PEER_CREATED;
873 			ml_peer->max_links = ml_info->num_partner_links;
874 			wlan_mlo_peer_set_t2lm_enable_val(ml_peer, ml_info);
875 			is_ml_peer_attached = true;
876 		}
877 	}
878 	if (!ml_peer) {
879 		/* Allocate MLO peer */
880 		ml_peer = qdf_mem_malloc(sizeof(*ml_peer));
881 		if (!ml_peer) {
882 			mlo_err("MLD ID %d ML Peer " QDF_MAC_ADDR_FMT " mem alloc failed",
883 				ml_dev->mld_id,
884 				QDF_MAC_ADDR_REF(link_peer->mldaddr));
885 			mlo_dev_release_link_vdevs(link_vdevs);
886 			return QDF_STATUS_E_NOMEM;
887 		}
888 
889 		qdf_atomic_init(&ml_peer->ref_cnt);
890 		mlo_peer_lock_create(ml_peer);
891 		ml_peer->ml_dev = ml_dev;
892 		ml_peer->mlpeer_state = ML_PEER_CREATED;
893 		ml_peer->max_links = ml_info->num_partner_links;
894 		ml_peer->primary_umac_psoc_id = ML_PRIMARY_UMAC_ID_INVAL;
895 
896 		ml_peer->mlo_peer_id = mlo_ap_ml_peerid_alloc();
897 		if (ml_peer->mlo_peer_id == MLO_INVALID_PEER_ID) {
898 			mlo_err("MLD ID %d ML Peer " QDF_MAC_ADDR_FMT " invalid ml peer id",
899 				ml_dev->mld_id,
900 				QDF_MAC_ADDR_REF
901 				(ml_peer->peer_mld_addr.bytes));
902 			mlo_peer_free(ml_peer);
903 			mlo_dev_release_link_vdevs(link_vdevs);
904 			return QDF_STATUS_E_RESOURCES;
905 		}
906 
907 		qdf_copy_macaddr((struct qdf_mac_addr *)&ml_peer->peer_mld_addr,
908 				 (struct qdf_mac_addr *)&link_peer->mldaddr[0]);
909 		wlan_mlo_peer_set_t2lm_enable_val(ml_peer, ml_info);
910 
911 		/* Allocate AID */
912 		if (wlan_vdev_mlme_get_opmode(vdev) == QDF_SAP_MODE) {
913 			if (aid == (uint16_t)-1) {
914 				status = mlo_peer_allocate_aid(ml_dev, ml_peer);
915 				if (status != QDF_STATUS_SUCCESS) {
916 					mlo_err("MLD ID %d ML Peer " QDF_MAC_ADDR_FMT " aid alloc failed",
917 						ml_dev->mld_id,
918 						QDF_MAC_ADDR_REF
919 						(ml_peer->peer_mld_addr.bytes));
920 					mlo_peer_free(ml_peer);
921 					mlo_dev_release_link_vdevs(link_vdevs);
922 					return status;
923 				}
924 			} else {
925 				ml_peer->assoc_id = aid;
926 			}
927 		}
928 	}
929 
930 	/* Populate Link peer pointer, peer MAC address,
931 	 * MLD address. HW link ID, update ref count
932 	 */
933 	status = mlo_peer_attach_link_peer(ml_peer, link_peer, NULL);
934 	if (QDF_IS_STATUS_ERROR(status)) {
935 		mlo_err("MLD ID %d ML Peer " QDF_MAC_ADDR_FMT " link peer attach failed",
936 			ml_dev->mld_id,
937 			QDF_MAC_ADDR_REF
938 			(ml_peer->peer_mld_addr.bytes));
939 		mlo_peer_free(ml_peer);
940 		mlo_dev_release_link_vdevs(link_vdevs);
941 		return status;
942 	}
943 
944 	/* Allocate Primary UMAC */
945 	mlo_peer_allocate_primary_umac(ml_dev, ml_peer, link_vdevs);
946 
947 	/* Store AID, MLO Peer pointer in link peer, take link peer ref count */
948 	mlo_peer_populate_link_peer(ml_peer, link_peer);
949 
950 	mlo_peer_populate_nawds_params(ml_peer, ml_info);
951 
952 	if ((wlan_vdev_mlme_get_opmode(vdev) == QDF_SAP_MODE) ||
953 		((wlan_vdev_mlme_get_opmode(vdev) == QDF_STA_MODE) &&
954 			!is_ml_peer_attached)) {
955 		/* Attach MLO peer to ML Peer table */
956 		status = mlo_dev_mlpeer_attach(ml_dev, ml_peer);
957 		if (status != QDF_STATUS_SUCCESS) {
958 			mlo_err("MLD ID %d ML Peer " QDF_MAC_ADDR_FMT " attach failed",
959 				ml_dev->mld_id,
960 				QDF_MAC_ADDR_REF(ml_peer->peer_mld_addr.bytes));
961 			mlo_reset_link_peer(ml_peer, link_peer);
962 			wlan_objmgr_peer_release_ref(link_peer,
963 						     WLAN_MLO_MGR_ID);
964 			mlo_peer_free(ml_peer);
965 			mlo_dev_release_link_vdevs(link_vdevs);
966 			return status;
967 		}
968 	}
969 
970 	wlan_mlo_peer_get_ref(ml_peer);
971 
972 	if (wlan_vdev_mlme_get_opmode(vdev) == QDF_SAP_MODE) {
973 		/* Notify other vdevs about link peer creation */
974 		for (i = 0; i < WLAN_UMAC_MLO_MAX_VDEVS; i++) {
975 			vdev_link = link_vdevs[i];
976 			if (!vdev_link)
977 				continue;
978 
979 			if (vdev_link == vdev)
980 				continue;
981 
982 			mlo_partner_peer_create_post(ml_dev, vdev_link,
983 						     ml_peer, frm_buf, ml_info);
984 		}
985 	}
986 	mlo_dev_release_link_vdevs(link_vdevs);
987 
988 	if (ml_peer->mlpeer_state == ML_PEER_DISCONN_INITIATED) {
989 		mlo_info("MLD ID %d ML Peer " QDF_MAC_ADDR_FMT " allocation failed",
990 			 ml_dev->mld_id,
991 			 QDF_MAC_ADDR_REF(ml_peer->peer_mld_addr.bytes));
992 		wlan_mlo_peer_release_ref(ml_peer);
993 		return QDF_STATUS_E_FAILURE;
994 	}
995 
996 	mlo_info("MLD ID %d ML Peer " QDF_MAC_ADDR_FMT " allocated %pK",
997 		 ml_dev->mld_id,
998 		 QDF_MAC_ADDR_REF(ml_peer->peer_mld_addr.bytes),
999 		 ml_peer);
1000 
1001 	/*
1002 	 * wlan_mlo_peer_create() is trigggered after getting peer
1003 	 * assoc confirm from FW. For single link MLO connection, it is
1004 	 * OK to trigger assoc response from here.
1005 	 */
1006 	if ((wlan_vdev_mlme_get_opmode(vdev) == QDF_SAP_MODE) &&
1007 	    (!wlan_mlo_peer_is_nawds(ml_peer))) {
1008 		if (ml_peer->max_links == ml_peer->link_peer_cnt) {
1009 			assoc_peer = ml_peer->peer_list[0].link_peer;
1010 			if (assoc_peer)
1011 				mlo_mlme_peer_assoc_resp(assoc_peer);
1012 		}
1013 	}
1014 
1015 	wlan_mlo_peer_release_ref(ml_peer);
1016 
1017 	return QDF_STATUS_SUCCESS;
1018 }
1019 
1020 QDF_STATUS wlan_mlo_link_peer_attach(struct wlan_mlo_peer_context *ml_peer,
1021 				     struct wlan_objmgr_peer *peer,
1022 				     qdf_nbuf_t frm_buf)
1023 {
1024 	QDF_STATUS status;
1025 	struct wlan_objmgr_peer *assoc_peer;
1026 	struct wlan_objmgr_vdev *vdev = NULL;
1027 
1028 	if (!ml_peer)
1029 		return QDF_STATUS_E_FAILURE;
1030 
1031 	vdev = wlan_peer_get_vdev(peer);
1032 	if (!vdev)
1033 		return QDF_STATUS_E_FAILURE;
1034 
1035 	/* Populate Link peer pointer, peer MAC address,
1036 	 * MLD address. HW link ID, update ref count
1037 	 */
1038 	status = mlo_peer_attach_link_peer(ml_peer, peer, frm_buf);
1039 	if (QDF_IS_STATUS_ERROR(status))
1040 		return status;
1041 
1042 	/* Store AID, MLO Peer pointer in link peer, take link peer ref count */
1043 	mlo_peer_populate_link_peer(ml_peer, peer);
1044 
1045 	if (wlan_vdev_mlme_get_opmode(vdev) == QDF_SAP_MODE) {
1046 		if (ml_peer->max_links == ml_peer->link_peer_cnt) {
1047 			assoc_peer = ml_peer->peer_list[0].link_peer;
1048 			if (assoc_peer)
1049 				mlo_mlme_peer_assoc_resp(assoc_peer);
1050 		}
1051 	}
1052 
1053 	return status;
1054 }
1055 
1056 QDF_STATUS wlan_mlo_link_peer_delete(struct wlan_objmgr_peer *peer)
1057 {
1058 	struct wlan_mlo_peer_context *ml_peer;
1059 
1060 	ml_peer = peer->mlo_peer_ctx;
1061 
1062 	if (!ml_peer)
1063 		return QDF_STATUS_E_NOENT;
1064 
1065 	mlo_reset_link_peer(ml_peer, peer);
1066 	mlo_peer_detach_link_peer(ml_peer, peer);
1067 	wlan_mlo_peer_release_ref(ml_peer);
1068 
1069 	return QDF_STATUS_SUCCESS;
1070 }
1071 
1072 qdf_export_symbol(wlan_mlo_link_peer_delete);
1073 
1074 qdf_nbuf_t mlo_peer_get_link_peer_assoc_req_buf(
1075 			struct wlan_mlo_peer_context *ml_peer,
1076 			uint8_t link_ix)
1077 {
1078 	struct wlan_objmgr_peer *peer = NULL;
1079 	qdf_nbuf_t assocbuf = NULL;
1080 
1081 	if (!ml_peer)
1082 		return NULL;
1083 
1084 	peer = wlan_mlo_peer_get_assoc_peer(ml_peer);
1085 	if (!peer)
1086 		return NULL;
1087 
1088 	assocbuf = mlo_mlme_get_link_assoc_req(peer, link_ix);
1089 
1090 	return assocbuf;
1091 }
1092 
1093 void wlan_mlo_peer_get_links_info(struct wlan_objmgr_peer *peer,
1094 				  struct mlo_tgt_partner_info *ml_links)
1095 {
1096 	struct wlan_mlo_peer_context *ml_peer;
1097 	struct wlan_mlo_link_peer_entry *peer_entry;
1098 	struct wlan_objmgr_peer *link_peer;
1099 	struct wlan_objmgr_vdev *link_vdev;
1100 	uint8_t i, ix;
1101 
1102 	ml_peer = peer->mlo_peer_ctx;
1103 	ml_links->num_partner_links = 0;
1104 
1105 	if (!ml_peer)
1106 		return;
1107 
1108 	mlo_peer_lock_acquire(ml_peer);
1109 
1110 	if ((ml_peer->mlpeer_state != ML_PEER_CREATED) &&
1111 	    (ml_peer->mlpeer_state != ML_PEER_ASSOC_DONE)) {
1112 		mlo_peer_lock_release(ml_peer);
1113 		return;
1114 	}
1115 
1116 	for (i = 0; i < MAX_MLO_LINK_PEERS; i++) {
1117 		peer_entry = &ml_peer->peer_list[i];
1118 		link_peer = peer_entry->link_peer;
1119 
1120 		if (!link_peer)
1121 			continue;
1122 		if (link_peer == peer)
1123 			continue;
1124 		link_vdev = wlan_peer_get_vdev(link_peer);
1125 		if (!link_vdev)
1126 			continue;
1127 
1128 		if (ml_links->num_partner_links >= WLAN_UMAC_MLO_MAX_VDEVS)
1129 			break;
1130 
1131 		ix = ml_links->num_partner_links;
1132 		ml_links->link_info[ix].vdev_id = wlan_vdev_get_id(link_vdev);
1133 		ml_links->link_info[ix].hw_mld_link_id = peer_entry->hw_link_id;
1134 		ml_links->num_partner_links++;
1135 	}
1136 	mlo_peer_lock_release(ml_peer);
1137 }
1138 
1139 qdf_export_symbol(wlan_mlo_peer_get_links_info);
1140 
1141 uint8_t wlan_mlo_peer_get_primary_peer_link_id(struct wlan_objmgr_peer *peer)
1142 {
1143 	struct wlan_mlo_peer_context *ml_peer;
1144 	struct wlan_mlo_link_peer_entry *peer_entry;
1145 	struct wlan_objmgr_peer *link_peer;
1146 	struct wlan_objmgr_vdev *link_vdev;
1147 	uint8_t i, vdev_link_id;
1148 
1149 	ml_peer = peer->mlo_peer_ctx;
1150 
1151 	if (!ml_peer) {
1152 		mlo_err("ml_peer is null");
1153 		return WLAN_LINK_ID_INVALID;
1154 	}
1155 	mlo_peer_lock_acquire(ml_peer);
1156 
1157 	if ((ml_peer->mlpeer_state != ML_PEER_CREATED) &&
1158 	    (ml_peer->mlpeer_state != ML_PEER_ASSOC_DONE)) {
1159 		mlo_peer_lock_release(ml_peer);
1160 		mlo_err("ml_peer is not created and association is not done");
1161 		return WLAN_LINK_ID_INVALID;
1162 	}
1163 
1164 	for (i = 0; i < MAX_MLO_LINK_PEERS; i++) {
1165 		peer_entry = &ml_peer->peer_list[i];
1166 		link_peer = peer_entry->link_peer;
1167 		if (!link_peer)
1168 			continue;
1169 
1170 		if (peer_entry->is_primary) {
1171 			link_vdev = wlan_peer_get_vdev(link_peer);
1172 			if (!link_vdev) {
1173 				mlo_peer_lock_release(ml_peer);
1174 				mlo_err("link vdev not found");
1175 				return WLAN_LINK_ID_INVALID;
1176 			}
1177 			vdev_link_id = wlan_vdev_get_link_id(link_vdev);
1178 			mlo_peer_lock_release(ml_peer);
1179 			return vdev_link_id;
1180 		}
1181 	}
1182 	mlo_peer_lock_release(ml_peer);
1183 	mlo_err("None of the peer is designated as primary");
1184 	return WLAN_LINK_ID_INVALID;
1185 }
1186 
1187 qdf_export_symbol(wlan_mlo_peer_get_primary_peer_link_id);
1188 
1189 void wlan_mlo_peer_get_partner_links_info(struct wlan_objmgr_peer *peer,
1190 					  struct mlo_partner_info *ml_links)
1191 {
1192 	struct wlan_mlo_peer_context *ml_peer;
1193 	struct wlan_mlo_link_peer_entry *peer_entry;
1194 	struct wlan_objmgr_peer *link_peer;
1195 	struct wlan_objmgr_vdev *link_vdev;
1196 	uint8_t i, ix;
1197 
1198 	ml_peer = peer->mlo_peer_ctx;
1199 	ml_links->num_partner_links = 0;
1200 
1201 	if (!ml_peer)
1202 		return;
1203 
1204 	mlo_peer_lock_acquire(ml_peer);
1205 
1206 	if ((ml_peer->mlpeer_state != ML_PEER_CREATED) &&
1207 	    (ml_peer->mlpeer_state != ML_PEER_ASSOC_DONE)) {
1208 		mlo_peer_lock_release(ml_peer);
1209 		return;
1210 	}
1211 
1212 	for (i = 0; i < MAX_MLO_LINK_PEERS; i++) {
1213 		peer_entry = &ml_peer->peer_list[i];
1214 		link_peer = peer_entry->link_peer;
1215 
1216 		if (!link_peer)
1217 			continue;
1218 
1219 		if (link_peer == peer)
1220 			continue;
1221 
1222 		link_vdev = wlan_peer_get_vdev(link_peer);
1223 		if (!link_vdev)
1224 			continue;
1225 
1226 		if (ml_links->num_partner_links >= WLAN_UMAC_MLO_MAX_VDEVS)
1227 			break;
1228 
1229 		ix = ml_links->num_partner_links;
1230 		ml_links->partner_link_info[ix].link_id = peer_entry->link_ix;
1231 
1232 		qdf_copy_macaddr(&ml_links->partner_link_info[ix].link_addr,
1233 				 &peer_entry->link_addr);
1234 		ml_links->num_partner_links++;
1235 	}
1236 	mlo_peer_lock_release(ml_peer);
1237 }
1238 
1239 qdf_export_symbol(wlan_mlo_peer_get_partner_links_info);
1240 
1241 #ifdef UMAC_SUPPORT_MLNAWDS
1242 bool wlan_mlo_peer_is_nawds(struct wlan_mlo_peer_context *ml_peer)
1243 {
1244 	bool status = false;
1245 
1246 	if (!ml_peer)
1247 		return status;
1248 
1249 	mlo_peer_lock_acquire(ml_peer);
1250 	if (ml_peer->is_nawds_ml_peer)
1251 		status = true;
1252 	mlo_peer_lock_release(ml_peer);
1253 
1254 	return status;
1255 }
1256 
1257 qdf_export_symbol(wlan_mlo_peer_is_nawds);
1258 #endif
1259 
1260 #ifdef UMAC_MLO_AUTH_DEFER
1261 void mlo_peer_free_auth_param(struct mlpeer_auth_params *auth_params)
1262 {
1263 	if (auth_params->rs)
1264 		qdf_mem_free(auth_params->rs);
1265 
1266 	if (auth_params->wbuf)
1267 		qdf_nbuf_free(auth_params->wbuf);
1268 
1269 	qdf_mem_free(auth_params);
1270 }
1271 
1272 QDF_STATUS mlo_peer_link_auth_defer(struct wlan_mlo_peer_context *ml_peer,
1273 				    struct qdf_mac_addr *link_mac,
1274 				    struct mlpeer_auth_params *auth_params)
1275 {
1276 	uint8_t i;
1277 	uint8_t free_entries = 0;
1278 	struct mlpeer_auth_params *recv_auth;
1279 	QDF_STATUS status = QDF_STATUS_E_FAILURE;
1280 
1281 	if (!ml_peer)
1282 		return status;
1283 
1284 	mlo_peer_lock_acquire(ml_peer);
1285 	for (i = 0; i < MAX_MLO_LINK_PEERS; i++) {
1286 		recv_auth = ml_peer->pending_auth[i];
1287 		if (!recv_auth) {
1288 			free_entries++;
1289 			continue;
1290 		}
1291 		/* overwrite the entry with latest entry */
1292 		if (qdf_is_macaddr_equal(link_mac, &recv_auth->link_addr)) {
1293 			mlo_peer_free_auth_param(recv_auth);
1294 			ml_peer->pending_auth[i] = auth_params;
1295 			mlo_peer_lock_release(ml_peer);
1296 
1297 			return QDF_STATUS_SUCCESS;
1298 		}
1299 	}
1300 
1301 	if (!free_entries) {
1302 		mlo_peer_lock_release(ml_peer);
1303 		return QDF_STATUS_E_FAILURE;
1304 	}
1305 
1306 	for (i = 0; i < MAX_MLO_LINK_PEERS; i++) {
1307 		recv_auth = ml_peer->pending_auth[i];
1308 		if (!recv_auth) {
1309 			ml_peer->pending_auth[i] = auth_params;
1310 			status = QDF_STATUS_SUCCESS;
1311 			break;
1312 		}
1313 	}
1314 	mlo_peer_lock_release(ml_peer);
1315 
1316 	return status;
1317 }
1318 #endif
1319