xref: /wlan-dirver/qca-wifi-host-cmn/umac/mlo_mgr/src/wlan_mlo_mgr_peer.c (revision 45c28558a520fd0e975b20c0ad534a0aa7f08021)
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 			frm_buf = qdf_nbuf_clone(peer_entry->assoc_rsp_buf);
635 			break;
636 		}
637 	}
638 	mlo_peer_lock_release(ml_peer);
639 
640 	return frm_buf;
641 }
642 
643 void wlan_mlo_peer_free_all_link_assoc_resp_buf(
644 			struct wlan_objmgr_peer *link_peer)
645 {
646 	struct wlan_mlo_link_peer_entry *peer_entry;
647 	struct wlan_mlo_peer_context *ml_peer;
648 	uint8_t i;
649 
650 	ml_peer = link_peer->mlo_peer_ctx;
651 	if (!ml_peer)
652 		return;
653 
654 	mlo_peer_lock_acquire(ml_peer);
655 
656 	for (i = 0; i < MAX_MLO_LINK_PEERS; i++) {
657 		peer_entry = &ml_peer->peer_list[i];
658 
659 		if (peer_entry->assoc_rsp_buf) {
660 			qdf_nbuf_free(peer_entry->assoc_rsp_buf);
661 			peer_entry->assoc_rsp_buf = NULL;
662 		}
663 	}
664 	mlo_peer_lock_release(ml_peer);
665 }
666 
667 static QDF_STATUS mlo_peer_detach_link_peer(
668 		struct wlan_mlo_peer_context *ml_peer,
669 		struct wlan_objmgr_peer *link_peer)
670 {
671 	struct wlan_mlo_link_peer_entry *peer_entry;
672 	QDF_STATUS status = QDF_STATUS_E_RESOURCES;
673 	uint16_t i;
674 
675 	mlo_peer_lock_acquire(ml_peer);
676 
677 	if (ml_peer->mlpeer_state != ML_PEER_DISCONN_INITIATED) {
678 		mlo_peer_lock_release(ml_peer);
679 		return status;
680 	}
681 
682 	for (i = 0; i < MAX_MLO_LINK_PEERS; i++) {
683 		peer_entry = &ml_peer->peer_list[i];
684 		if (!peer_entry->link_peer)
685 			continue;
686 
687 		if (peer_entry->link_peer != link_peer)
688 			continue;
689 
690 		if (peer_entry->assoc_rsp_buf) {
691 			qdf_nbuf_free(peer_entry->assoc_rsp_buf);
692 			peer_entry->assoc_rsp_buf = NULL;
693 		}
694 
695 		wlan_objmgr_peer_release_ref(link_peer, WLAN_MLO_MGR_ID);
696 		peer_entry->link_peer = NULL;
697 		ml_peer->link_peer_cnt--;
698 		status = QDF_STATUS_SUCCESS;
699 		break;
700 	}
701 	mlo_peer_lock_release(ml_peer);
702 
703 	return status;
704 }
705 
706 static QDF_STATUS mlo_dev_get_link_vdevs(
707 			struct wlan_objmgr_vdev *vdev,
708 			struct wlan_mlo_dev_context *ml_dev,
709 			struct mlo_partner_info *ml_info,
710 			struct wlan_objmgr_vdev *link_vdevs[])
711 {
712 	uint16_t i, j;
713 	struct wlan_objmgr_vdev *vdev_link;
714 	uint8_t link_id;
715 
716 	if (!ml_dev) {
717 		mlo_err("ml_dev is null");
718 		return QDF_STATUS_E_INVAL;
719 	}
720 
721 	if (!ml_info) {
722 		mlo_err("ml_info is null");
723 		return QDF_STATUS_E_INVAL;
724 	}
725 
726 	mlo_debug("num_partner_links %d", ml_info->num_partner_links);
727 	for (i = 0; i < ml_info->num_partner_links; i++) {
728 		link_id = ml_info->partner_link_info[i].link_id;
729 		vdev_link = mlo_get_vdev_by_link_id(vdev, link_id);
730 		if (vdev_link) {
731 			link_vdevs[i] = vdev_link;
732 		} else {
733 			/* release ref which were taken before failure */
734 			for (j = 0; j < i; j++) {
735 				vdev_link = link_vdevs[j];
736 				if (!vdev_link)
737 					continue;
738 
739 				wlan_objmgr_vdev_release_ref(vdev_link,
740 							     WLAN_MLO_MGR_ID);
741 			}
742 			return QDF_STATUS_E_INVAL;
743 		}
744 	}
745 
746 	return QDF_STATUS_SUCCESS;
747 }
748 
749 static void mlo_dev_release_link_vdevs(
750 			struct wlan_objmgr_vdev *link_vdevs[])
751 {
752 	uint16_t i;
753 	struct wlan_objmgr_vdev *vdev_link;
754 
755 	for (i = 0; i < WLAN_UMAC_MLO_MAX_VDEVS; i++) {
756 		vdev_link = link_vdevs[i];
757 		if (!vdev_link)
758 			continue;
759 
760 		wlan_objmgr_vdev_release_ref(vdev_link, WLAN_MLO_MGR_ID);
761 	}
762 }
763 
764 #ifdef WLAN_FEATURE_11BE
765 static void
766 wlan_mlo_peer_set_t2lm_enable_val(struct wlan_mlo_peer_context *ml_peer,
767 				  struct mlo_partner_info *ml_info)
768 {
769 	ml_peer->t2lm_policy.t2lm_enable_val = ml_info->t2lm_enable_val;
770 }
771 #else
772 static void
773 wlan_mlo_peer_set_t2lm_enable_val(struct wlan_mlo_peer_context *ml_peer,
774 				  struct mlo_partner_info *ml_info)
775 {}
776 #endif /* WLAN_FEATURE_11BE */
777 
778 QDF_STATUS wlan_mlo_peer_create(struct wlan_objmgr_vdev *vdev,
779 				struct wlan_objmgr_peer *link_peer,
780 				struct mlo_partner_info *ml_info,
781 				qdf_nbuf_t frm_buf,
782 				uint16_t aid)
783 {
784 	struct wlan_mlo_dev_context *ml_dev;
785 	struct wlan_mlo_peer_context *ml_peer = NULL;
786 	struct wlan_objmgr_vdev *link_vdevs[WLAN_UMAC_MLO_MAX_VDEVS] = { NULL };
787 	struct wlan_objmgr_vdev *vdev_link;
788 	QDF_STATUS status;
789 	uint16_t i;
790 	struct wlan_objmgr_peer *assoc_peer;
791 	bool is_ml_peer_attached = false;
792 
793 	/* get ML VDEV from VDEV */
794 	ml_dev = vdev->mlo_dev_ctx;
795 
796 	if (!ml_dev) {
797 		mlo_err("ML dev ctx is NULL");
798 		return QDF_STATUS_E_NULL_VALUE;
799 	}
800 
801 	/* Check resources of Partner VDEV */
802 	if (wlan_vdev_mlme_get_opmode(vdev) == QDF_SAP_MODE) {
803 		if (wlan_mlo_is_mld_ctx_exist(
804 		    (struct qdf_mac_addr *)&link_peer->mldaddr[0])) {
805 			mlo_err("MLD ID %d ML Peer " QDF_MAC_ADDR_FMT " is matching with one of the MLD address in the system",
806 				ml_dev->mld_id,
807 				QDF_MAC_ADDR_REF(link_peer->mldaddr));
808 			return QDF_STATUS_E_FAILURE;
809 		}
810 		status = mlo_dev_get_link_vdevs(vdev, ml_dev,
811 						ml_info, link_vdevs);
812 		if (QDF_IS_STATUS_ERROR(status)) {
813 			mlo_err("MLD ID %d ML Peer " QDF_MAC_ADDR_FMT " get link vdevs failed",
814 				ml_dev->mld_id,
815 				QDF_MAC_ADDR_REF(link_peer->mldaddr));
816 			return QDF_STATUS_E_FAILURE;
817 		}
818 
819 		for (i = 0; i < WLAN_UMAC_MLO_MAX_VDEVS; i++) {
820 			vdev_link = link_vdevs[i];
821 			if (!vdev_link) {
822 				mlo_debug("vdev_link is null");
823 				continue;
824 			}
825 
826 			if (wlan_vdev_is_mlo_peer_create_allowed(vdev_link)
827 					!= QDF_STATUS_SUCCESS) {
828 				mlo_dev_release_link_vdevs(link_vdevs);
829 
830 				mlo_err("MLD ID %d ML Peer " QDF_MAC_ADDR_FMT " create not allowed on link vdev %d",
831 					ml_dev->mld_id,
832 					QDF_MAC_ADDR_REF
833 						(link_peer->mldaddr),
834 					wlan_vdev_get_id(vdev_link));
835 				return QDF_STATUS_E_INVAL;
836 			}
837 		}
838 
839 		for (i = 0; i < WLAN_UMAC_MLO_MAX_VDEVS; i++) {
840 			vdev_link = link_vdevs[i];
841 			if (vdev_link && (vdev_link != vdev) &&
842 			    (wlan_vdev_get_peer_count(vdev_link) >
843 			     wlan_vdev_get_max_peer_count(vdev_link))) {
844 				mlo_dev_release_link_vdevs(link_vdevs);
845 				mlo_err("MLD ID %d ML Peer " QDF_MAC_ADDR_FMT " Max peer count reached on link vdev %d",
846 					ml_dev->mld_id,
847 					QDF_MAC_ADDR_REF
848 						(link_peer->mldaddr),
849 					wlan_vdev_get_id(vdev_link));
850 				return QDF_STATUS_E_RESOURCES;
851 			}
852 		}
853 	}
854 	/* When roam to MLO AP, partner link vdev1 is updated first,
855 	 * ml peer need be created and attached for partner link peer.
856 	 *
857 	 * When roam target AP and current AP have same MLD address, don't
858 	 * delete old ML peer and re-create new one, just update different
859 	 * info.
860 	 */
861 	if (wlan_vdev_mlme_get_opmode(vdev) == QDF_STA_MODE) {
862 		ml_peer = wlan_mlo_get_mlpeer(ml_dev,
863 				 (struct qdf_mac_addr *)&link_peer->mldaddr[0]);
864 		if (ml_peer) {
865 			mlo_debug("ML Peer " QDF_MAC_ADDR_FMT
866 				" existed, state %d",
867 				QDF_MAC_ADDR_REF(ml_peer->peer_mld_addr.bytes),
868 				ml_peer->mlpeer_state);
869 			ml_peer->mlpeer_state = ML_PEER_CREATED;
870 			ml_peer->max_links = ml_info->num_partner_links;
871 			wlan_mlo_peer_set_t2lm_enable_val(ml_peer, ml_info);
872 			is_ml_peer_attached = true;
873 		}
874 	}
875 	if (!ml_peer) {
876 		/* Allocate MLO peer */
877 		ml_peer = qdf_mem_malloc(sizeof(*ml_peer));
878 		if (!ml_peer) {
879 			mlo_err("MLD ID %d ML Peer " QDF_MAC_ADDR_FMT " mem alloc failed",
880 				ml_dev->mld_id,
881 				QDF_MAC_ADDR_REF(link_peer->mldaddr));
882 			mlo_dev_release_link_vdevs(link_vdevs);
883 			return QDF_STATUS_E_NOMEM;
884 		}
885 
886 		qdf_atomic_init(&ml_peer->ref_cnt);
887 		mlo_peer_lock_create(ml_peer);
888 		ml_peer->ml_dev = ml_dev;
889 		ml_peer->mlpeer_state = ML_PEER_CREATED;
890 		ml_peer->max_links = ml_info->num_partner_links;
891 		ml_peer->primary_umac_psoc_id = ML_PRIMARY_UMAC_ID_INVAL;
892 
893 		ml_peer->mlo_peer_id = mlo_ap_ml_peerid_alloc();
894 		if (ml_peer->mlo_peer_id == MLO_INVALID_PEER_ID) {
895 			mlo_err("MLD ID %d ML Peer " QDF_MAC_ADDR_FMT " invalid ml peer id",
896 				ml_dev->mld_id,
897 				QDF_MAC_ADDR_REF
898 				(ml_peer->peer_mld_addr.bytes));
899 			mlo_peer_free(ml_peer);
900 			mlo_dev_release_link_vdevs(link_vdevs);
901 			return QDF_STATUS_E_RESOURCES;
902 		}
903 
904 		qdf_copy_macaddr((struct qdf_mac_addr *)&ml_peer->peer_mld_addr,
905 				 (struct qdf_mac_addr *)&link_peer->mldaddr[0]);
906 		wlan_mlo_peer_set_t2lm_enable_val(ml_peer, ml_info);
907 
908 		/* Allocate AID */
909 		if (wlan_vdev_mlme_get_opmode(vdev) == QDF_SAP_MODE) {
910 			if (aid == (uint16_t)-1) {
911 				status = mlo_peer_allocate_aid(ml_dev, ml_peer);
912 				if (status != QDF_STATUS_SUCCESS) {
913 					mlo_err("MLD ID %d ML Peer " QDF_MAC_ADDR_FMT " aid alloc failed",
914 						ml_dev->mld_id,
915 						QDF_MAC_ADDR_REF
916 						(ml_peer->peer_mld_addr.bytes));
917 					mlo_peer_free(ml_peer);
918 					mlo_dev_release_link_vdevs(link_vdevs);
919 					return status;
920 				}
921 			} else {
922 				ml_peer->assoc_id = aid;
923 			}
924 		}
925 	}
926 
927 	/* Populate Link peer pointer, peer MAC address,
928 	 * MLD address. HW link ID, update ref count
929 	 */
930 	status = mlo_peer_attach_link_peer(ml_peer, link_peer, NULL);
931 	if (QDF_IS_STATUS_ERROR(status)) {
932 		mlo_err("MLD ID %d ML Peer " QDF_MAC_ADDR_FMT " link peer attach failed",
933 			ml_dev->mld_id,
934 			QDF_MAC_ADDR_REF
935 			(ml_peer->peer_mld_addr.bytes));
936 		mlo_peer_free(ml_peer);
937 		mlo_dev_release_link_vdevs(link_vdevs);
938 		return status;
939 	}
940 
941 	/* Allocate Primary UMAC */
942 	mlo_peer_allocate_primary_umac(ml_dev, ml_peer, link_vdevs);
943 
944 	/* Store AID, MLO Peer pointer in link peer, take link peer ref count */
945 	mlo_peer_populate_link_peer(ml_peer, link_peer);
946 
947 	mlo_peer_populate_nawds_params(ml_peer, ml_info);
948 
949 	if ((wlan_vdev_mlme_get_opmode(vdev) == QDF_SAP_MODE) ||
950 		((wlan_vdev_mlme_get_opmode(vdev) == QDF_STA_MODE) &&
951 			!is_ml_peer_attached)) {
952 		/* Attach MLO peer to ML Peer table */
953 		status = mlo_dev_mlpeer_attach(ml_dev, ml_peer);
954 		if (status != QDF_STATUS_SUCCESS) {
955 			mlo_err("MLD ID %d ML Peer " QDF_MAC_ADDR_FMT " attach failed",
956 				ml_dev->mld_id,
957 				QDF_MAC_ADDR_REF(ml_peer->peer_mld_addr.bytes));
958 			mlo_reset_link_peer(ml_peer, link_peer);
959 			wlan_objmgr_peer_release_ref(link_peer,
960 						     WLAN_MLO_MGR_ID);
961 			mlo_peer_free(ml_peer);
962 			mlo_dev_release_link_vdevs(link_vdevs);
963 			return status;
964 		}
965 	}
966 
967 	wlan_mlo_peer_get_ref(ml_peer);
968 
969 	if (wlan_vdev_mlme_get_opmode(vdev) == QDF_SAP_MODE) {
970 		/* Notify other vdevs about link peer creation */
971 		for (i = 0; i < WLAN_UMAC_MLO_MAX_VDEVS; i++) {
972 			vdev_link = link_vdevs[i];
973 			if (!vdev_link)
974 				continue;
975 
976 			if (vdev_link == vdev)
977 				continue;
978 
979 			mlo_partner_peer_create_post(ml_dev, vdev_link,
980 						     ml_peer, frm_buf, ml_info);
981 		}
982 	}
983 	mlo_dev_release_link_vdevs(link_vdevs);
984 
985 	if (ml_peer->mlpeer_state == ML_PEER_DISCONN_INITIATED) {
986 		mlo_info("MLD ID %d ML Peer " QDF_MAC_ADDR_FMT " allocation failed",
987 			 ml_dev->mld_id,
988 			 QDF_MAC_ADDR_REF(ml_peer->peer_mld_addr.bytes));
989 		wlan_mlo_peer_release_ref(ml_peer);
990 		return QDF_STATUS_E_FAILURE;
991 	}
992 
993 	mlo_info("MLD ID %d ML Peer " QDF_MAC_ADDR_FMT " allocated %pK",
994 		 ml_dev->mld_id,
995 		 QDF_MAC_ADDR_REF(ml_peer->peer_mld_addr.bytes),
996 		 ml_peer);
997 
998 	/*
999 	 * wlan_mlo_peer_create() is trigggered after getting peer
1000 	 * assoc confirm from FW. For single link MLO connection, it is
1001 	 * OK to trigger assoc response from here.
1002 	 */
1003 	if ((wlan_vdev_mlme_get_opmode(vdev) == QDF_SAP_MODE) &&
1004 	    (!wlan_mlo_peer_is_nawds(ml_peer))) {
1005 		if (ml_peer->max_links == ml_peer->link_peer_cnt) {
1006 			assoc_peer = ml_peer->peer_list[0].link_peer;
1007 			if (assoc_peer)
1008 				mlo_mlme_peer_assoc_resp(assoc_peer);
1009 		}
1010 	}
1011 
1012 	wlan_mlo_peer_release_ref(ml_peer);
1013 
1014 	return QDF_STATUS_SUCCESS;
1015 }
1016 
1017 QDF_STATUS wlan_mlo_link_peer_attach(struct wlan_mlo_peer_context *ml_peer,
1018 				     struct wlan_objmgr_peer *peer,
1019 				     qdf_nbuf_t frm_buf)
1020 {
1021 	QDF_STATUS status;
1022 	struct wlan_objmgr_peer *assoc_peer;
1023 	struct wlan_objmgr_vdev *vdev = NULL;
1024 
1025 	if (!ml_peer)
1026 		return QDF_STATUS_E_FAILURE;
1027 
1028 	vdev = wlan_peer_get_vdev(peer);
1029 	if (!vdev)
1030 		return QDF_STATUS_E_FAILURE;
1031 
1032 	/* Populate Link peer pointer, peer MAC address,
1033 	 * MLD address. HW link ID, update ref count
1034 	 */
1035 	status = mlo_peer_attach_link_peer(ml_peer, peer, frm_buf);
1036 	if (QDF_IS_STATUS_ERROR(status))
1037 		return status;
1038 
1039 	/* Store AID, MLO Peer pointer in link peer, take link peer ref count */
1040 	mlo_peer_populate_link_peer(ml_peer, peer);
1041 
1042 	if (wlan_vdev_mlme_get_opmode(vdev) == QDF_SAP_MODE) {
1043 		if (ml_peer->max_links == ml_peer->link_peer_cnt) {
1044 			assoc_peer = ml_peer->peer_list[0].link_peer;
1045 			if (assoc_peer)
1046 				mlo_mlme_peer_assoc_resp(assoc_peer);
1047 		}
1048 	}
1049 
1050 	return status;
1051 }
1052 
1053 QDF_STATUS wlan_mlo_link_peer_delete(struct wlan_objmgr_peer *peer)
1054 {
1055 	struct wlan_mlo_peer_context *ml_peer;
1056 
1057 	ml_peer = peer->mlo_peer_ctx;
1058 
1059 	if (!ml_peer)
1060 		return QDF_STATUS_E_NOENT;
1061 
1062 	mlo_reset_link_peer(ml_peer, peer);
1063 	mlo_peer_detach_link_peer(ml_peer, peer);
1064 	wlan_mlo_peer_release_ref(ml_peer);
1065 
1066 	return QDF_STATUS_SUCCESS;
1067 }
1068 
1069 qdf_export_symbol(wlan_mlo_link_peer_delete);
1070 
1071 qdf_nbuf_t mlo_peer_get_link_peer_assoc_req_buf(
1072 			struct wlan_mlo_peer_context *ml_peer,
1073 			uint8_t link_ix)
1074 {
1075 	struct wlan_objmgr_peer *peer = NULL;
1076 	qdf_nbuf_t assocbuf = NULL;
1077 
1078 	if (!ml_peer)
1079 		return NULL;
1080 
1081 	peer = wlan_mlo_peer_get_assoc_peer(ml_peer);
1082 	if (!peer)
1083 		return NULL;
1084 
1085 	assocbuf = mlo_mlme_get_link_assoc_req(peer, link_ix);
1086 
1087 	return assocbuf;
1088 }
1089 
1090 void wlan_mlo_peer_get_links_info(struct wlan_objmgr_peer *peer,
1091 				  struct mlo_tgt_partner_info *ml_links)
1092 {
1093 	struct wlan_mlo_peer_context *ml_peer;
1094 	struct wlan_mlo_link_peer_entry *peer_entry;
1095 	struct wlan_objmgr_peer *link_peer;
1096 	struct wlan_objmgr_vdev *link_vdev;
1097 	uint8_t i, ix;
1098 
1099 	ml_peer = peer->mlo_peer_ctx;
1100 	ml_links->num_partner_links = 0;
1101 
1102 	if (!ml_peer)
1103 		return;
1104 
1105 	mlo_peer_lock_acquire(ml_peer);
1106 
1107 	if ((ml_peer->mlpeer_state != ML_PEER_CREATED) &&
1108 	    (ml_peer->mlpeer_state != ML_PEER_ASSOC_DONE)) {
1109 		mlo_peer_lock_release(ml_peer);
1110 		return;
1111 	}
1112 
1113 	for (i = 0; i < MAX_MLO_LINK_PEERS; i++) {
1114 		peer_entry = &ml_peer->peer_list[i];
1115 		link_peer = peer_entry->link_peer;
1116 
1117 		if (!link_peer)
1118 			continue;
1119 		if (link_peer == peer)
1120 			continue;
1121 		link_vdev = wlan_peer_get_vdev(link_peer);
1122 		if (!link_vdev)
1123 			continue;
1124 
1125 		if (ml_links->num_partner_links >= WLAN_UMAC_MLO_MAX_VDEVS)
1126 			break;
1127 
1128 		ix = ml_links->num_partner_links;
1129 		ml_links->link_info[ix].vdev_id = wlan_vdev_get_id(link_vdev);
1130 		ml_links->link_info[ix].hw_mld_link_id = peer_entry->hw_link_id;
1131 		ml_links->num_partner_links++;
1132 	}
1133 	mlo_peer_lock_release(ml_peer);
1134 }
1135 
1136 qdf_export_symbol(wlan_mlo_peer_get_links_info);
1137 
1138 uint8_t wlan_mlo_peer_get_primary_peer_link_id(struct wlan_objmgr_peer *peer)
1139 {
1140 	struct wlan_mlo_peer_context *ml_peer;
1141 	struct wlan_mlo_link_peer_entry *peer_entry;
1142 	struct wlan_objmgr_peer *link_peer;
1143 	struct wlan_objmgr_vdev *link_vdev;
1144 	uint8_t i, vdev_link_id;
1145 
1146 	ml_peer = peer->mlo_peer_ctx;
1147 
1148 	if (!ml_peer) {
1149 		mlo_err("ml_peer is null");
1150 		return WLAN_LINK_ID_INVALID;
1151 	}
1152 	mlo_peer_lock_acquire(ml_peer);
1153 
1154 	if ((ml_peer->mlpeer_state != ML_PEER_CREATED) &&
1155 	    (ml_peer->mlpeer_state != ML_PEER_ASSOC_DONE)) {
1156 		mlo_peer_lock_release(ml_peer);
1157 		mlo_err("ml_peer is not created and association is not done");
1158 		return WLAN_LINK_ID_INVALID;
1159 	}
1160 
1161 	for (i = 0; i < MAX_MLO_LINK_PEERS; i++) {
1162 		peer_entry = &ml_peer->peer_list[i];
1163 		link_peer = peer_entry->link_peer;
1164 		if (!link_peer)
1165 			continue;
1166 
1167 		if (peer_entry->is_primary) {
1168 			link_vdev = wlan_peer_get_vdev(link_peer);
1169 			if (!link_vdev) {
1170 				mlo_peer_lock_release(ml_peer);
1171 				mlo_err("link vdev not found");
1172 				return WLAN_LINK_ID_INVALID;
1173 			}
1174 			vdev_link_id = wlan_vdev_get_link_id(link_vdev);
1175 			mlo_peer_lock_release(ml_peer);
1176 			return vdev_link_id;
1177 		}
1178 	}
1179 	mlo_peer_lock_release(ml_peer);
1180 	mlo_err("None of the peer is designated as primary");
1181 	return WLAN_LINK_ID_INVALID;
1182 }
1183 
1184 qdf_export_symbol(wlan_mlo_peer_get_primary_peer_link_id);
1185 
1186 void wlan_mlo_peer_get_partner_links_info(struct wlan_objmgr_peer *peer,
1187 					  struct mlo_partner_info *ml_links)
1188 {
1189 	struct wlan_mlo_peer_context *ml_peer;
1190 	struct wlan_mlo_link_peer_entry *peer_entry;
1191 	struct wlan_objmgr_peer *link_peer;
1192 	struct wlan_objmgr_vdev *link_vdev;
1193 	uint8_t i, ix;
1194 
1195 	ml_peer = peer->mlo_peer_ctx;
1196 	ml_links->num_partner_links = 0;
1197 
1198 	if (!ml_peer)
1199 		return;
1200 
1201 	mlo_peer_lock_acquire(ml_peer);
1202 
1203 	if ((ml_peer->mlpeer_state != ML_PEER_CREATED) &&
1204 	    (ml_peer->mlpeer_state != ML_PEER_ASSOC_DONE)) {
1205 		mlo_peer_lock_release(ml_peer);
1206 		return;
1207 	}
1208 
1209 	for (i = 0; i < MAX_MLO_LINK_PEERS; i++) {
1210 		peer_entry = &ml_peer->peer_list[i];
1211 		link_peer = peer_entry->link_peer;
1212 
1213 		if (!link_peer)
1214 			continue;
1215 
1216 		if (link_peer == peer)
1217 			continue;
1218 
1219 		link_vdev = wlan_peer_get_vdev(link_peer);
1220 		if (!link_vdev)
1221 			continue;
1222 
1223 		if (ml_links->num_partner_links >= WLAN_UMAC_MLO_MAX_VDEVS)
1224 			break;
1225 
1226 		ix = ml_links->num_partner_links;
1227 		ml_links->partner_link_info[ix].link_id = peer_entry->link_ix;
1228 
1229 		qdf_copy_macaddr(&ml_links->partner_link_info[ix].link_addr,
1230 				 &peer_entry->link_addr);
1231 		ml_links->num_partner_links++;
1232 	}
1233 	mlo_peer_lock_release(ml_peer);
1234 }
1235 
1236 qdf_export_symbol(wlan_mlo_peer_get_partner_links_info);
1237 
1238 #ifdef UMAC_SUPPORT_MLNAWDS
1239 bool wlan_mlo_peer_is_nawds(struct wlan_mlo_peer_context *ml_peer)
1240 {
1241 	bool status = false;
1242 
1243 	if (!ml_peer)
1244 		return status;
1245 
1246 	mlo_peer_lock_acquire(ml_peer);
1247 	if (ml_peer->is_nawds_ml_peer)
1248 		status = true;
1249 	mlo_peer_lock_release(ml_peer);
1250 
1251 	return status;
1252 }
1253 
1254 qdf_export_symbol(wlan_mlo_peer_is_nawds);
1255 #endif
1256 
1257 #ifdef UMAC_MLO_AUTH_DEFER
1258 void mlo_peer_free_auth_param(struct mlpeer_auth_params *auth_params)
1259 {
1260 	if (auth_params->rs)
1261 		qdf_mem_free(auth_params->rs);
1262 
1263 	if (auth_params->wbuf)
1264 		qdf_nbuf_free(auth_params->wbuf);
1265 
1266 	qdf_mem_free(auth_params);
1267 }
1268 
1269 QDF_STATUS mlo_peer_link_auth_defer(struct wlan_mlo_peer_context *ml_peer,
1270 				    struct qdf_mac_addr *link_mac,
1271 				    struct mlpeer_auth_params *auth_params)
1272 {
1273 	uint8_t i;
1274 	uint8_t free_entries = 0;
1275 	struct mlpeer_auth_params *recv_auth;
1276 	QDF_STATUS status = QDF_STATUS_E_FAILURE;
1277 
1278 	if (!ml_peer)
1279 		return status;
1280 
1281 	mlo_peer_lock_acquire(ml_peer);
1282 	for (i = 0; i < MAX_MLO_LINK_PEERS; i++) {
1283 		recv_auth = ml_peer->pending_auth[i];
1284 		if (!recv_auth) {
1285 			free_entries++;
1286 			continue;
1287 		}
1288 		/* overwrite the entry with latest entry */
1289 		if (qdf_is_macaddr_equal(link_mac, &recv_auth->link_addr)) {
1290 			mlo_peer_free_auth_param(recv_auth);
1291 			ml_peer->pending_auth[i] = auth_params;
1292 			mlo_peer_lock_release(ml_peer);
1293 
1294 			return QDF_STATUS_SUCCESS;
1295 		}
1296 	}
1297 
1298 	if (!free_entries) {
1299 		mlo_peer_lock_release(ml_peer);
1300 		return QDF_STATUS_E_FAILURE;
1301 	}
1302 
1303 	for (i = 0; i < MAX_MLO_LINK_PEERS; i++) {
1304 		recv_auth = ml_peer->pending_auth[i];
1305 		if (!recv_auth) {
1306 			ml_peer->pending_auth[i] = auth_params;
1307 			status = QDF_STATUS_SUCCESS;
1308 			break;
1309 		}
1310 	}
1311 	mlo_peer_lock_release(ml_peer);
1312 
1313 	return status;
1314 }
1315 #endif
1316