xref: /wlan-dirver/qca-wifi-host-cmn/umac/mlo_mgr/src/wlan_mlo_mgr_peer.c (revision 7630cc90f02e8e853426e72adcbd746fb48d2d89)
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 
792 	/* get ML VDEV from VDEV */
793 	ml_dev = vdev->mlo_dev_ctx;
794 
795 	if (!ml_dev) {
796 		mlo_err("ML dev ctx is NULL");
797 		return QDF_STATUS_E_NULL_VALUE;
798 	}
799 
800 	/* Check resources of Partner VDEV */
801 	if (wlan_vdev_mlme_get_opmode(vdev) == QDF_SAP_MODE) {
802 		if (wlan_mlo_is_mld_ctx_exist(
803 		    (struct qdf_mac_addr *)&link_peer->mldaddr[0])) {
804 			mlo_err("MLD ID %d ML Peer " QDF_MAC_ADDR_FMT " is matching with one of the MLD address in the system",
805 				ml_dev->mld_id,
806 				QDF_MAC_ADDR_REF(link_peer->mldaddr));
807 			return QDF_STATUS_E_FAILURE;
808 		}
809 		status = mlo_dev_get_link_vdevs(vdev, ml_dev,
810 						ml_info, link_vdevs);
811 		if (QDF_IS_STATUS_ERROR(status)) {
812 			mlo_err("MLD ID %d ML Peer " QDF_MAC_ADDR_FMT " get link vdevs failed",
813 				ml_dev->mld_id,
814 				QDF_MAC_ADDR_REF(link_peer->mldaddr));
815 			return QDF_STATUS_E_FAILURE;
816 		}
817 
818 		for (i = 0; i < WLAN_UMAC_MLO_MAX_VDEVS; i++) {
819 			vdev_link = link_vdevs[i];
820 			if (!vdev_link) {
821 				mlo_debug("vdev_link is null");
822 				continue;
823 			}
824 
825 			if (wlan_vdev_is_mlo_peer_create_allowed(vdev_link)
826 					!= QDF_STATUS_SUCCESS) {
827 				mlo_dev_release_link_vdevs(link_vdevs);
828 
829 				mlo_err("MLD ID %d ML Peer " QDF_MAC_ADDR_FMT " create not allowed on link vdev %d",
830 					ml_dev->mld_id,
831 					QDF_MAC_ADDR_REF
832 						(link_peer->mldaddr),
833 					wlan_vdev_get_id(vdev_link));
834 				return QDF_STATUS_E_INVAL;
835 			}
836 		}
837 
838 		for (i = 0; i < WLAN_UMAC_MLO_MAX_VDEVS; i++) {
839 			vdev_link = link_vdevs[i];
840 			if (vdev_link && (vdev_link != vdev) &&
841 			    (wlan_vdev_get_peer_count(vdev_link) >
842 			     wlan_vdev_get_max_peer_count(vdev_link))) {
843 				mlo_dev_release_link_vdevs(link_vdevs);
844 				mlo_err("MLD ID %d ML Peer " QDF_MAC_ADDR_FMT " Max peer count reached on link vdev %d",
845 					ml_dev->mld_id,
846 					QDF_MAC_ADDR_REF
847 						(link_peer->mldaddr),
848 					wlan_vdev_get_id(vdev_link));
849 				return QDF_STATUS_E_RESOURCES;
850 			}
851 		}
852 	}
853 
854 	if (wlan_vdev_mlme_get_opmode(vdev) == QDF_STA_MODE)
855 		ml_peer = wlan_mlo_get_mlpeer(ml_dev,
856 				 (struct qdf_mac_addr *)&link_peer->mldaddr[0]);
857 
858 	if (!ml_peer) {
859 		/* Allocate MLO peer */
860 		ml_peer = qdf_mem_malloc(sizeof(*ml_peer));
861 		if (!ml_peer) {
862 			mlo_err("MLD ID %d ML Peer " QDF_MAC_ADDR_FMT " mem alloc failed",
863 				ml_dev->mld_id,
864 				QDF_MAC_ADDR_REF(link_peer->mldaddr));
865 			mlo_dev_release_link_vdevs(link_vdevs);
866 			return QDF_STATUS_E_NOMEM;
867 		}
868 
869 		qdf_atomic_init(&ml_peer->ref_cnt);
870 		mlo_peer_lock_create(ml_peer);
871 		ml_peer->ml_dev = ml_dev;
872 		ml_peer->mlpeer_state = ML_PEER_CREATED;
873 		ml_peer->max_links = ml_info->num_partner_links;
874 		ml_peer->primary_umac_psoc_id = ML_PRIMARY_UMAC_ID_INVAL;
875 
876 		ml_peer->mlo_peer_id = mlo_ap_ml_peerid_alloc();
877 		if (ml_peer->mlo_peer_id == MLO_INVALID_PEER_ID) {
878 			mlo_err("MLD ID %d ML Peer " QDF_MAC_ADDR_FMT " invalid ml peer id",
879 				ml_dev->mld_id,
880 				QDF_MAC_ADDR_REF
881 				(ml_peer->peer_mld_addr.bytes));
882 			mlo_peer_free(ml_peer);
883 			mlo_dev_release_link_vdevs(link_vdevs);
884 			return QDF_STATUS_E_RESOURCES;
885 		}
886 
887 		qdf_copy_macaddr((struct qdf_mac_addr *)&ml_peer->peer_mld_addr,
888 				 (struct qdf_mac_addr *)&link_peer->mldaddr[0]);
889 		wlan_mlo_peer_set_t2lm_enable_val(ml_peer, ml_info);
890 
891 		/* Allocate AID */
892 		if (wlan_vdev_mlme_get_opmode(vdev) == QDF_SAP_MODE) {
893 			if (aid == (uint16_t)-1) {
894 				status = mlo_peer_allocate_aid(ml_dev, ml_peer);
895 				if (status != QDF_STATUS_SUCCESS) {
896 					mlo_err("MLD ID %d ML Peer " QDF_MAC_ADDR_FMT " aid alloc failed",
897 						ml_dev->mld_id,
898 						QDF_MAC_ADDR_REF
899 						(ml_peer->peer_mld_addr.bytes));
900 					mlo_peer_free(ml_peer);
901 					mlo_dev_release_link_vdevs(link_vdevs);
902 					return status;
903 				}
904 			} else {
905 				ml_peer->assoc_id = aid;
906 			}
907 		}
908 	}
909 
910 	/* Populate Link peer pointer, peer MAC address,
911 	 * MLD address. HW link ID, update ref count
912 	 */
913 	status = mlo_peer_attach_link_peer(ml_peer, link_peer, NULL);
914 	if (QDF_IS_STATUS_ERROR(status)) {
915 		mlo_err("MLD ID %d ML Peer " QDF_MAC_ADDR_FMT " link peer attach failed",
916 			ml_dev->mld_id,
917 			QDF_MAC_ADDR_REF
918 			(ml_peer->peer_mld_addr.bytes));
919 		mlo_peer_free(ml_peer);
920 		mlo_dev_release_link_vdevs(link_vdevs);
921 		return status;
922 	}
923 
924 	/* Allocate Primary UMAC */
925 	mlo_peer_allocate_primary_umac(ml_dev, ml_peer, link_vdevs);
926 
927 	/* Store AID, MLO Peer pointer in link peer, take link peer ref count */
928 	mlo_peer_populate_link_peer(ml_peer, link_peer);
929 
930 	mlo_peer_populate_nawds_params(ml_peer, ml_info);
931 
932 	if ((wlan_vdev_mlme_get_opmode(vdev) == QDF_SAP_MODE) ||
933 		((wlan_vdev_mlme_get_opmode(vdev) == QDF_STA_MODE) &&
934 			!wlan_vdev_mlme_is_mlo_link_vdev(vdev))) {
935 		/* Attach MLO peer to ML Peer table */
936 		status = mlo_dev_mlpeer_attach(ml_dev, ml_peer);
937 		if (status != QDF_STATUS_SUCCESS) {
938 			mlo_err("MLD ID %d ML Peer " QDF_MAC_ADDR_FMT " attach failed",
939 				ml_dev->mld_id,
940 				QDF_MAC_ADDR_REF(ml_peer->peer_mld_addr.bytes));
941 			mlo_reset_link_peer(ml_peer, link_peer);
942 			wlan_objmgr_peer_release_ref(link_peer,
943 						     WLAN_MLO_MGR_ID);
944 			mlo_peer_free(ml_peer);
945 			mlo_dev_release_link_vdevs(link_vdevs);
946 			return status;
947 		}
948 	}
949 
950 	if (wlan_vdev_mlme_get_opmode(vdev) == QDF_SAP_MODE) {
951 		/* Notify other vdevs about link peer creation */
952 		for (i = 0; i < WLAN_UMAC_MLO_MAX_VDEVS; i++) {
953 			vdev_link = link_vdevs[i];
954 			if (!vdev_link)
955 				continue;
956 
957 			if (vdev_link == vdev)
958 				continue;
959 
960 			mlo_partner_peer_create_post(ml_dev, vdev_link,
961 						     ml_peer, frm_buf, ml_info);
962 		}
963 	}
964 	mlo_dev_release_link_vdevs(link_vdevs);
965 	mlo_info("MLD ID %d ML Peer " QDF_MAC_ADDR_FMT " allocated %pK",
966 		 ml_dev->mld_id,
967 		 QDF_MAC_ADDR_REF(ml_peer->peer_mld_addr.bytes),
968 		 ml_peer);
969 
970 	/*
971 	 * wlan_mlo_peer_create() is trigggered after getting peer
972 	 * assoc confirm from FW. For single link MLO connection, it is
973 	 * OK to trigger assoc response from here.
974 	 */
975 	if ((wlan_vdev_mlme_get_opmode(vdev) == QDF_SAP_MODE) &&
976 	    (!wlan_mlo_peer_is_nawds(ml_peer))) {
977 		if (ml_peer->max_links == ml_peer->link_peer_cnt) {
978 			assoc_peer = ml_peer->peer_list[0].link_peer;
979 			if (assoc_peer)
980 				mlo_mlme_peer_assoc_resp(assoc_peer);
981 		}
982 	}
983 
984 	return QDF_STATUS_SUCCESS;
985 }
986 
987 QDF_STATUS wlan_mlo_link_peer_attach(struct wlan_mlo_peer_context *ml_peer,
988 				     struct wlan_objmgr_peer *peer,
989 				     qdf_nbuf_t frm_buf)
990 {
991 	QDF_STATUS status;
992 	struct wlan_objmgr_peer *assoc_peer;
993 	struct wlan_objmgr_vdev *vdev = NULL;
994 
995 	if (!ml_peer)
996 		return QDF_STATUS_E_FAILURE;
997 
998 	vdev = wlan_peer_get_vdev(peer);
999 	if (!vdev)
1000 		return QDF_STATUS_E_FAILURE;
1001 
1002 	/* Populate Link peer pointer, peer MAC address,
1003 	 * MLD address. HW link ID, update ref count
1004 	 */
1005 	status = mlo_peer_attach_link_peer(ml_peer, peer, frm_buf);
1006 	if (QDF_IS_STATUS_ERROR(status))
1007 		return status;
1008 
1009 	/* Store AID, MLO Peer pointer in link peer, take link peer ref count */
1010 	mlo_peer_populate_link_peer(ml_peer, peer);
1011 
1012 	if (wlan_vdev_mlme_get_opmode(vdev) == QDF_SAP_MODE) {
1013 		if (ml_peer->max_links == ml_peer->link_peer_cnt) {
1014 			assoc_peer = ml_peer->peer_list[0].link_peer;
1015 			if (assoc_peer)
1016 				mlo_mlme_peer_assoc_resp(assoc_peer);
1017 		}
1018 	}
1019 
1020 	return status;
1021 }
1022 
1023 QDF_STATUS wlan_mlo_link_peer_delete(struct wlan_objmgr_peer *peer)
1024 {
1025 	struct wlan_mlo_peer_context *ml_peer;
1026 
1027 	ml_peer = peer->mlo_peer_ctx;
1028 
1029 	if (!ml_peer)
1030 		return QDF_STATUS_E_NOENT;
1031 
1032 	mlo_reset_link_peer(ml_peer, peer);
1033 	mlo_peer_detach_link_peer(ml_peer, peer);
1034 	wlan_mlo_peer_release_ref(ml_peer);
1035 
1036 	return QDF_STATUS_SUCCESS;
1037 }
1038 
1039 qdf_export_symbol(wlan_mlo_link_peer_delete);
1040 
1041 qdf_nbuf_t mlo_peer_get_link_peer_assoc_req_buf(
1042 			struct wlan_mlo_peer_context *ml_peer,
1043 			uint8_t link_ix)
1044 {
1045 	struct wlan_objmgr_peer *peer = NULL;
1046 	qdf_nbuf_t assocbuf = NULL;
1047 
1048 	if (!ml_peer)
1049 		return NULL;
1050 
1051 	peer = wlan_mlo_peer_get_assoc_peer(ml_peer);
1052 	if (!peer)
1053 		return NULL;
1054 
1055 	assocbuf = mlo_mlme_get_link_assoc_req(peer, link_ix);
1056 
1057 	return assocbuf;
1058 }
1059 
1060 void wlan_mlo_peer_get_links_info(struct wlan_objmgr_peer *peer,
1061 				  struct mlo_tgt_partner_info *ml_links)
1062 {
1063 	struct wlan_mlo_peer_context *ml_peer;
1064 	struct wlan_mlo_link_peer_entry *peer_entry;
1065 	struct wlan_objmgr_peer *link_peer;
1066 	struct wlan_objmgr_vdev *link_vdev;
1067 	uint8_t i, ix;
1068 
1069 	ml_peer = peer->mlo_peer_ctx;
1070 	ml_links->num_partner_links = 0;
1071 
1072 	if (!ml_peer)
1073 		return;
1074 
1075 	mlo_peer_lock_acquire(ml_peer);
1076 
1077 	if ((ml_peer->mlpeer_state != ML_PEER_CREATED) &&
1078 	    (ml_peer->mlpeer_state != ML_PEER_ASSOC_DONE)) {
1079 		mlo_peer_lock_release(ml_peer);
1080 		return;
1081 	}
1082 
1083 	for (i = 0; i < MAX_MLO_LINK_PEERS; i++) {
1084 		peer_entry = &ml_peer->peer_list[i];
1085 		link_peer = peer_entry->link_peer;
1086 
1087 		if (!link_peer)
1088 			continue;
1089 
1090 		if (link_peer == peer)
1091 			continue;
1092 
1093 		link_vdev = wlan_peer_get_vdev(link_peer);
1094 		if (!link_vdev)
1095 			continue;
1096 
1097 		if (ml_links->num_partner_links >= WLAN_UMAC_MLO_MAX_VDEVS)
1098 			break;
1099 
1100 		ix = ml_links->num_partner_links;
1101 		ml_links->link_info[ix].vdev_id = wlan_vdev_get_id(link_vdev);
1102 		ml_links->link_info[ix].hw_mld_link_id = peer_entry->hw_link_id;
1103 		ml_links->num_partner_links++;
1104 	}
1105 	mlo_peer_lock_release(ml_peer);
1106 }
1107 
1108 qdf_export_symbol(wlan_mlo_peer_get_links_info);
1109 
1110 void wlan_mlo_peer_get_partner_links_info(struct wlan_objmgr_peer *peer,
1111 					  struct mlo_partner_info *ml_links)
1112 {
1113 	struct wlan_mlo_peer_context *ml_peer;
1114 	struct wlan_mlo_link_peer_entry *peer_entry;
1115 	struct wlan_objmgr_peer *link_peer;
1116 	struct wlan_objmgr_vdev *link_vdev;
1117 	uint8_t i, ix;
1118 
1119 	ml_peer = peer->mlo_peer_ctx;
1120 	ml_links->num_partner_links = 0;
1121 
1122 	if (!ml_peer)
1123 		return;
1124 
1125 	mlo_peer_lock_acquire(ml_peer);
1126 
1127 	if ((ml_peer->mlpeer_state != ML_PEER_CREATED) &&
1128 	    (ml_peer->mlpeer_state != ML_PEER_ASSOC_DONE)) {
1129 		mlo_peer_lock_release(ml_peer);
1130 		return;
1131 	}
1132 
1133 	for (i = 0; i < MAX_MLO_LINK_PEERS; i++) {
1134 		peer_entry = &ml_peer->peer_list[i];
1135 		link_peer = peer_entry->link_peer;
1136 
1137 		if (!link_peer)
1138 			continue;
1139 
1140 		if (link_peer == peer)
1141 			continue;
1142 
1143 		link_vdev = wlan_peer_get_vdev(link_peer);
1144 		if (!link_vdev)
1145 			continue;
1146 
1147 		if (ml_links->num_partner_links >= WLAN_UMAC_MLO_MAX_VDEVS)
1148 			break;
1149 
1150 		ix = ml_links->num_partner_links;
1151 		ml_links->partner_link_info[ix].link_id = peer_entry->link_ix;
1152 
1153 		qdf_copy_macaddr(&ml_links->partner_link_info[ix].link_addr,
1154 				 &peer_entry->link_addr);
1155 		ml_links->num_partner_links++;
1156 	}
1157 	mlo_peer_lock_release(ml_peer);
1158 }
1159 
1160 qdf_export_symbol(wlan_mlo_peer_get_partner_links_info);
1161 
1162 #ifdef UMAC_SUPPORT_MLNAWDS
1163 bool wlan_mlo_peer_is_nawds(struct wlan_mlo_peer_context *ml_peer)
1164 {
1165 	bool status = false;
1166 
1167 	if (!ml_peer)
1168 		return status;
1169 
1170 	mlo_peer_lock_acquire(ml_peer);
1171 	if (ml_peer->is_nawds_ml_peer)
1172 		status = true;
1173 	mlo_peer_lock_release(ml_peer);
1174 
1175 	return status;
1176 }
1177 
1178 qdf_export_symbol(wlan_mlo_peer_is_nawds);
1179 #endif
1180 
1181 #ifdef UMAC_MLO_AUTH_DEFER
1182 void mlo_peer_free_auth_param(struct mlpeer_auth_params *auth_params)
1183 {
1184 	if (auth_params->rs)
1185 		qdf_mem_free(auth_params->rs);
1186 
1187 	if (auth_params->wbuf)
1188 		qdf_nbuf_free(auth_params->wbuf);
1189 
1190 	qdf_mem_free(auth_params);
1191 }
1192 
1193 QDF_STATUS mlo_peer_link_auth_defer(struct wlan_mlo_peer_context *ml_peer,
1194 				    struct qdf_mac_addr *link_mac,
1195 				    struct mlpeer_auth_params *auth_params)
1196 {
1197 	uint8_t i;
1198 	uint8_t free_entries = 0;
1199 	struct mlpeer_auth_params *recv_auth;
1200 	QDF_STATUS status = QDF_STATUS_E_FAILURE;
1201 
1202 	if (!ml_peer)
1203 		return status;
1204 
1205 	mlo_peer_lock_acquire(ml_peer);
1206 	for (i = 0; i < MAX_MLO_LINK_PEERS; i++) {
1207 		recv_auth = ml_peer->pending_auth[i];
1208 		if (!recv_auth) {
1209 			free_entries++;
1210 			continue;
1211 		}
1212 		/* overwrite the entry with latest entry */
1213 		if (qdf_is_macaddr_equal(link_mac, &recv_auth->link_addr)) {
1214 			mlo_peer_free_auth_param(recv_auth);
1215 			ml_peer->pending_auth[i] = auth_params;
1216 			mlo_peer_lock_release(ml_peer);
1217 
1218 			return QDF_STATUS_SUCCESS;
1219 		}
1220 	}
1221 
1222 	if (!free_entries) {
1223 		mlo_peer_lock_release(ml_peer);
1224 		return QDF_STATUS_E_FAILURE;
1225 	}
1226 
1227 	for (i = 0; i < MAX_MLO_LINK_PEERS; i++) {
1228 		recv_auth = ml_peer->pending_auth[i];
1229 		if (!recv_auth) {
1230 			ml_peer->pending_auth[i] = auth_params;
1231 			status = QDF_STATUS_SUCCESS;
1232 			break;
1233 		}
1234 	}
1235 	mlo_peer_lock_release(ml_peer);
1236 
1237 	return status;
1238 }
1239 #endif
1240