xref: /wlan-dirver/qca-wifi-host-cmn/umac/mlo_mgr/src/wlan_mlo_mgr_peer.c (revision d0c05845839e5f2ba5a8dcebe0cd3e4cd4e8dfcf)
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_peer->mlpeer_state = ML_PEER_DISCONN_INITIATED;
334 	ml_dev = ml_peer->ml_dev;
335 
336 	for (i = 0; i < MAX_MLO_LINK_PEERS; i++) {
337 		link_peers[i] = NULL;
338 		peer_entry = &ml_peer->peer_list[i];
339 		if (!peer_entry->link_peer)
340 			continue;
341 
342 		link_peer = peer_entry->link_peer;
343 		/* Skip Deauth if PMF is enabled for the station */
344 		if ((i == 0) &&
345 		    (wlan_crypto_is_pmf_enabled(wlan_peer_get_vdev(link_peer),
346 					       link_peer))) {
347 			mlo_peer_lock_release(ml_peer);
348 			return;
349 		}
350 
351 		if (wlan_objmgr_peer_try_get_ref(link_peer, WLAN_MLO_MGR_ID) !=
352 						QDF_STATUS_SUCCESS)
353 			continue;
354 
355 		link_peers[i] = link_peer;
356 	}
357 	mlo_peer_lock_release(ml_peer);
358 
359 	for (i = 0; i < MAX_MLO_LINK_PEERS; i++) {
360 		if (!link_peers[i])
361 			continue;
362 
363 		/* Prepare and queue message */
364 		if (i == 0)
365 			mlo_link_peer_deauth_init(ml_dev, link_peers[i]);
366 		else
367 			mlo_link_peer_disconnect_notify(ml_dev, link_peers[i]);
368 	}
369 
370 	return;
371 }
372 
373 void
374 wlan_mlo_partner_peer_create_failed_notify(
375 				struct wlan_mlo_peer_context *ml_peer)
376 {
377 	struct wlan_mlo_dev_context *ml_dev;
378 	struct wlan_objmgr_peer *link_peer;
379 	struct wlan_objmgr_peer *link_peers[MAX_MLO_LINK_PEERS];
380 	struct wlan_mlo_link_peer_entry *peer_entry;
381 	uint16_t i;
382 
383 	if (!ml_peer)
384 		return;
385 
386 	mlo_peer_lock_acquire(ml_peer);
387 
388 	if (ml_peer->mlpeer_state == ML_PEER_DISCONN_INITIATED) {
389 		mlo_peer_lock_release(ml_peer);
390 		return;
391 	}
392 
393 	ml_peer->mlpeer_state = ML_PEER_DISCONN_INITIATED;
394 	ml_dev = ml_peer->ml_dev;
395 
396 	for (i = 0; i < MAX_MLO_LINK_PEERS; i++) {
397 		link_peers[i] = NULL;
398 		peer_entry = &ml_peer->peer_list[i];
399 		if (!peer_entry->link_peer)
400 			continue;
401 
402 		link_peer = peer_entry->link_peer;
403 		if (wlan_objmgr_peer_try_get_ref(link_peer, WLAN_MLO_MGR_ID) !=
404 						QDF_STATUS_SUCCESS)
405 			continue;
406 
407 		link_peers[i] = link_peer;
408 	}
409 	mlo_peer_lock_release(ml_peer);
410 
411 	for (i = 0; i < MAX_MLO_LINK_PEERS; i++) {
412 		if (!link_peers[i])
413 			continue;
414 
415 		/* Prepare and queue message */
416 		if (i == 0)
417 			mlo_link_peer_send_assoc_fail(ml_dev, link_peers[i]);
418 		else
419 			mlo_link_peer_disconnect_notify(ml_dev, link_peers[i]);
420 	}
421 }
422 
423 void wlan_mlo_partner_peer_disconnect_notify(struct wlan_objmgr_peer *src_peer)
424 {
425 	struct wlan_mlo_dev_context *ml_dev;
426 	struct wlan_mlo_peer_context *ml_peer;
427 	struct wlan_objmgr_peer *link_peer;
428 	struct wlan_objmgr_peer *link_peers[MAX_MLO_LINK_PEERS];
429 	struct wlan_mlo_link_peer_entry *peer_entry;
430 	struct wlan_objmgr_vdev *vdev = NULL;
431 	uint16_t i;
432 
433 	ml_peer = src_peer->mlo_peer_ctx;
434 	if (!ml_peer)
435 		return;
436 
437 	mlo_peer_lock_acquire(ml_peer);
438 
439 	if (ml_peer->mlpeer_state == ML_PEER_DISCONN_INITIATED) {
440 		mlo_peer_lock_release(ml_peer);
441 		return;
442 	}
443 
444 	ml_peer->mlpeer_state = ML_PEER_DISCONN_INITIATED;
445 
446 	vdev = wlan_peer_get_vdev(src_peer);
447 	if (!vdev || wlan_vdev_mlme_get_opmode(vdev) == QDF_STA_MODE) {
448 		mlo_peer_lock_release(ml_peer);
449 		return;
450 	}
451 
452 	ml_dev = ml_peer->ml_dev;
453 	for (i = 0; i < MAX_MLO_LINK_PEERS; i++) {
454 		link_peers[i] = NULL;
455 		peer_entry = &ml_peer->peer_list[i];
456 		if (!peer_entry->link_peer) {
457 			mlo_debug("link peer is null");
458 			continue;
459 		}
460 
461 		if (peer_entry->link_peer == src_peer)
462 			continue;
463 
464 		link_peer = peer_entry->link_peer;
465 		if (wlan_objmgr_peer_try_get_ref(link_peer, WLAN_MLO_MGR_ID) !=
466 						QDF_STATUS_SUCCESS)
467 			continue;
468 
469 		link_peers[i] = link_peer;
470 	}
471 	mlo_peer_lock_release(ml_peer);
472 
473 	for (i = 0; i < MAX_MLO_LINK_PEERS; i++) {
474 		if (!link_peers[i])
475 			continue;
476 
477 		/* Prepare and queue message */
478 		mlo_link_peer_disconnect_notify(ml_dev, link_peers[i]);
479 	}
480 }
481 
482 static void mlo_peer_populate_link_peer(
483 			struct wlan_mlo_peer_context *ml_peer,
484 			struct wlan_objmgr_peer *link_peer)
485 {
486 	mlo_peer_lock_acquire(ml_peer);
487 	wlan_mlo_peer_get_ref(ml_peer);
488 	link_peer->mlo_peer_ctx = ml_peer;
489 	mlo_peer_lock_release(ml_peer);
490 }
491 
492 static void mlo_reset_link_peer(
493 			struct wlan_mlo_peer_context *ml_peer,
494 			struct wlan_objmgr_peer *link_peer)
495 {
496 	mlo_peer_lock_acquire(ml_peer);
497 	link_peer->mlo_peer_ctx = NULL;
498 	wlan_peer_clear_mlo(link_peer);
499 	mlo_peer_lock_release(ml_peer);
500 }
501 
502 static void mlo_peer_free(struct wlan_mlo_peer_context *ml_peer)
503 {
504 	struct wlan_mlo_dev_context *ml_dev;
505 
506 	ml_dev = ml_peer->ml_dev;
507 	if (!ml_dev) {
508 		mlo_err("ML DEV is NULL");
509 		return;
510 	}
511 
512 	mlo_peer_lock_destroy(ml_peer);
513 	mlo_ap_ml_peerid_free(ml_peer->mlo_peer_id);
514 	mlo_peer_free_aid(ml_dev, ml_peer);
515 	mlo_peer_free_primary_umac(ml_dev, ml_peer);
516 	qdf_mem_free(ml_peer);
517 }
518 
519 void mlo_peer_cleanup(struct wlan_mlo_peer_context *ml_peer)
520 {
521 	struct wlan_mlo_dev_context *ml_dev;
522 
523 	if (!ml_peer) {
524 		mlo_err("ML PEER is NULL");
525 		return;
526 	}
527 	ml_dev = ml_peer->ml_dev;
528 	if (!ml_dev) {
529 		mlo_err("ML DEV is NULL");
530 		return;
531 	}
532 
533 	mlo_dev_mlpeer_detach(ml_dev, ml_peer);
534 	/* If any Auth req is received during ML peer delete */
535 	mlo_peer_process_pending_auth(ml_dev, ml_peer);
536 	mlo_peer_free(ml_peer);
537 }
538 
539 static QDF_STATUS mlo_peer_attach_link_peer(
540 		struct wlan_mlo_peer_context *ml_peer,
541 		struct wlan_objmgr_peer *link_peer,
542 		qdf_nbuf_t frm_buf)
543 {
544 	struct wlan_mlo_link_peer_entry *peer_entry;
545 	QDF_STATUS status = QDF_STATUS_E_RESOURCES;
546 	struct wlan_objmgr_pdev *pdev;
547 	struct wlan_objmgr_vdev *vdev;
548 	uint16_t i;
549 
550 	if (!link_peer)
551 		return QDF_STATUS_E_FAILURE;
552 
553 	vdev = wlan_peer_get_vdev(link_peer);
554 	if (!vdev)
555 		return QDF_STATUS_E_FAILURE;
556 
557 	mlo_peer_lock_acquire(ml_peer);
558 
559 	if (ml_peer->mlpeer_state != ML_PEER_CREATED) {
560 		mlo_peer_lock_release(ml_peer);
561 		mlo_err("ML Peer " QDF_MAC_ADDR_FMT " is not in created state (state %d)",
562 			QDF_MAC_ADDR_REF(ml_peer->peer_mld_addr.bytes),
563 			ml_peer->mlpeer_state);
564 		return status;
565 	}
566 
567 	for (i = 0; i < MAX_MLO_LINK_PEERS; i++) {
568 		peer_entry = &ml_peer->peer_list[i];
569 		if (peer_entry->link_peer)
570 			continue;
571 
572 		if (wlan_objmgr_peer_try_get_ref(link_peer, WLAN_MLO_MGR_ID) !=
573 						QDF_STATUS_SUCCESS) {
574 			mlo_err("ML Peer " QDF_MAC_ADDR_FMT ", link peer " QDF_MAC_ADDR_FMT " is not in valid state",
575 				QDF_MAC_ADDR_REF(ml_peer->peer_mld_addr.bytes),
576 				QDF_MAC_ADDR_REF
577 					(wlan_peer_get_macaddr(link_peer)));
578 			break;
579 		}
580 		peer_entry->link_peer = link_peer;
581 		qdf_copy_macaddr(&peer_entry->link_addr,
582 				 (struct qdf_mac_addr *)&link_peer->macaddr[0]);
583 
584 		peer_entry->link_ix = wlan_vdev_get_link_id(vdev);
585 		pdev = wlan_vdev_get_pdev(wlan_peer_get_vdev(link_peer));
586 		peer_entry->hw_link_id = wlan_mlo_get_pdev_hw_link_id(pdev);
587 		mlo_peer_assign_primary_umac(ml_peer, peer_entry);
588 		if (frm_buf)
589 			peer_entry->assoc_rsp_buf = frm_buf;
590 		else
591 			peer_entry->assoc_rsp_buf = NULL;
592 
593 		status = QDF_STATUS_SUCCESS;
594 		break;
595 	}
596 	if (QDF_IS_STATUS_SUCCESS(status))
597 		ml_peer->link_peer_cnt++;
598 
599 	mlo_peer_lock_release(ml_peer);
600 
601 	return status;
602 }
603 
604 qdf_nbuf_t mlo_peer_get_link_peer_assoc_resp_buf(
605 		struct wlan_mlo_peer_context *ml_peer,
606 		uint8_t link_ix)
607 {
608 	struct wlan_mlo_link_peer_entry *peer_entry;
609 	qdf_nbuf_t frm_buf = NULL;
610 	uint8_t i;
611 
612 	if (!ml_peer)
613 		return NULL;
614 
615 	if (link_ix > MAX_MLO_LINK_PEERS)
616 		return NULL;
617 
618 	mlo_peer_lock_acquire(ml_peer);
619 	if ((ml_peer->mlpeer_state != ML_PEER_CREATED) &&
620 	    (ml_peer->mlpeer_state != ML_PEER_ASSOC_DONE)) {
621 		mlo_peer_lock_release(ml_peer);
622 		return NULL;
623 	}
624 
625 	for (i = 0; i < MAX_MLO_LINK_PEERS; i++) {
626 		peer_entry = &ml_peer->peer_list[i];
627 
628 		if (!peer_entry->link_peer)
629 			continue;
630 
631 		if (peer_entry->link_ix == link_ix) {
632 			frm_buf = qdf_nbuf_clone(peer_entry->assoc_rsp_buf);
633 			break;
634 		}
635 	}
636 	mlo_peer_lock_release(ml_peer);
637 
638 	return frm_buf;
639 }
640 
641 void wlan_mlo_peer_free_all_link_assoc_resp_buf(
642 			struct wlan_objmgr_peer *link_peer)
643 {
644 	struct wlan_mlo_link_peer_entry *peer_entry;
645 	struct wlan_mlo_peer_context *ml_peer;
646 	uint8_t i;
647 
648 	ml_peer = link_peer->mlo_peer_ctx;
649 	if (!ml_peer)
650 		return;
651 
652 	mlo_peer_lock_acquire(ml_peer);
653 
654 	for (i = 0; i < MAX_MLO_LINK_PEERS; i++) {
655 		peer_entry = &ml_peer->peer_list[i];
656 
657 		if (peer_entry->assoc_rsp_buf) {
658 			qdf_nbuf_free(peer_entry->assoc_rsp_buf);
659 			peer_entry->assoc_rsp_buf = NULL;
660 		}
661 	}
662 	mlo_peer_lock_release(ml_peer);
663 }
664 
665 static QDF_STATUS mlo_peer_detach_link_peer(
666 		struct wlan_mlo_peer_context *ml_peer,
667 		struct wlan_objmgr_peer *link_peer)
668 {
669 	struct wlan_mlo_link_peer_entry *peer_entry;
670 	QDF_STATUS status = QDF_STATUS_E_RESOURCES;
671 	uint16_t i;
672 
673 	mlo_peer_lock_acquire(ml_peer);
674 
675 	if (ml_peer->mlpeer_state != ML_PEER_DISCONN_INITIATED) {
676 		mlo_peer_lock_release(ml_peer);
677 		return status;
678 	}
679 
680 	for (i = 0; i < MAX_MLO_LINK_PEERS; i++) {
681 		peer_entry = &ml_peer->peer_list[i];
682 		if (!peer_entry->link_peer)
683 			continue;
684 
685 		if (peer_entry->link_peer != link_peer)
686 			continue;
687 
688 		if (peer_entry->assoc_rsp_buf) {
689 			qdf_nbuf_free(peer_entry->assoc_rsp_buf);
690 			peer_entry->assoc_rsp_buf = NULL;
691 		}
692 
693 		wlan_objmgr_peer_release_ref(link_peer, WLAN_MLO_MGR_ID);
694 		peer_entry->link_peer = NULL;
695 		ml_peer->link_peer_cnt--;
696 		status = QDF_STATUS_SUCCESS;
697 		break;
698 	}
699 	mlo_peer_lock_release(ml_peer);
700 
701 	return status;
702 }
703 
704 static QDF_STATUS mlo_dev_get_link_vdevs(
705 			struct wlan_objmgr_vdev *vdev,
706 			struct wlan_mlo_dev_context *ml_dev,
707 			struct mlo_partner_info *ml_info,
708 			struct wlan_objmgr_vdev *link_vdevs[])
709 {
710 	uint16_t i, j;
711 	struct wlan_objmgr_vdev *vdev_link;
712 	uint8_t link_id;
713 
714 	if (!ml_dev) {
715 		mlo_err("ml_dev is null");
716 		return QDF_STATUS_E_INVAL;
717 	}
718 
719 	if (!ml_info) {
720 		mlo_err("ml_info is null");
721 		return QDF_STATUS_E_INVAL;
722 	}
723 
724 	mlo_debug("num_partner_links %d", ml_info->num_partner_links);
725 	for (i = 0; i < ml_info->num_partner_links; i++) {
726 		link_id = ml_info->partner_link_info[i].link_id;
727 		vdev_link = mlo_get_vdev_by_link_id(vdev, link_id);
728 		if (vdev_link) {
729 			link_vdevs[i] = vdev_link;
730 		} else {
731 			/* release ref which were taken before failure */
732 			for (j = 0; j < i; j++) {
733 				vdev_link = link_vdevs[j];
734 				if (!vdev_link)
735 					continue;
736 
737 				wlan_objmgr_vdev_release_ref(vdev_link,
738 							     WLAN_MLO_MGR_ID);
739 			}
740 			return QDF_STATUS_E_INVAL;
741 		}
742 	}
743 
744 	return QDF_STATUS_SUCCESS;
745 }
746 
747 static void mlo_dev_release_link_vdevs(
748 			struct wlan_objmgr_vdev *link_vdevs[])
749 {
750 	uint16_t i;
751 	struct wlan_objmgr_vdev *vdev_link;
752 
753 	for (i = 0; i < WLAN_UMAC_MLO_MAX_VDEVS; i++) {
754 		vdev_link = link_vdevs[i];
755 		if (!vdev_link)
756 			continue;
757 
758 		wlan_objmgr_vdev_release_ref(vdev_link, WLAN_MLO_MGR_ID);
759 	}
760 }
761 
762 #ifdef WLAN_FEATURE_11BE
763 static void
764 wlan_mlo_peer_set_t2lm_enable_val(struct wlan_mlo_peer_context *ml_peer,
765 				  struct mlo_partner_info *ml_info)
766 {
767 	ml_peer->t2lm_policy.t2lm_enable_val = ml_info->t2lm_enable_val;
768 }
769 #else
770 static void
771 wlan_mlo_peer_set_t2lm_enable_val(struct wlan_mlo_peer_context *ml_peer,
772 				  struct mlo_partner_info *ml_info)
773 {}
774 #endif /* WLAN_FEATURE_11BE */
775 
776 QDF_STATUS wlan_mlo_peer_create(struct wlan_objmgr_vdev *vdev,
777 				struct wlan_objmgr_peer *link_peer,
778 				struct mlo_partner_info *ml_info,
779 				qdf_nbuf_t frm_buf,
780 				uint16_t aid)
781 {
782 	struct wlan_mlo_dev_context *ml_dev;
783 	struct wlan_mlo_peer_context *ml_peer = NULL;
784 	struct wlan_objmgr_vdev *link_vdevs[WLAN_UMAC_MLO_MAX_VDEVS] = { NULL };
785 	struct wlan_objmgr_vdev *vdev_link;
786 	QDF_STATUS status;
787 	uint16_t i;
788 	struct wlan_objmgr_peer *assoc_peer;
789 
790 	/* get ML VDEV from VDEV */
791 	ml_dev = vdev->mlo_dev_ctx;
792 
793 	if (!ml_dev) {
794 		mlo_err("ML dev ctx is NULL");
795 		return QDF_STATUS_E_NULL_VALUE;
796 	}
797 
798 	/* Check resources of Partner VDEV */
799 	if (wlan_vdev_mlme_get_opmode(vdev) == QDF_SAP_MODE) {
800 		if (wlan_mlo_is_mld_ctx_exist(
801 		    (struct qdf_mac_addr *)&link_peer->mldaddr[0])) {
802 			mlo_err("MLD ID %d ML Peer " QDF_MAC_ADDR_FMT " is matching with one of the MLD address in the system",
803 				ml_dev->mld_id,
804 				QDF_MAC_ADDR_REF(link_peer->mldaddr));
805 			return QDF_STATUS_E_FAILURE;
806 		}
807 		status = mlo_dev_get_link_vdevs(vdev, ml_dev,
808 						ml_info, link_vdevs);
809 		if (QDF_IS_STATUS_ERROR(status)) {
810 			mlo_err("MLD ID %d ML Peer " QDF_MAC_ADDR_FMT " get link vdevs failed",
811 				ml_dev->mld_id,
812 				QDF_MAC_ADDR_REF(link_peer->mldaddr));
813 			return QDF_STATUS_E_FAILURE;
814 		}
815 
816 		for (i = 0; i < WLAN_UMAC_MLO_MAX_VDEVS; i++) {
817 			vdev_link = link_vdevs[i];
818 			if (!vdev_link) {
819 				mlo_debug("vdev_link is null");
820 				continue;
821 			}
822 
823 			if (wlan_vdev_is_mlo_peer_create_allowed(vdev_link)
824 					!= QDF_STATUS_SUCCESS) {
825 				mlo_dev_release_link_vdevs(link_vdevs);
826 
827 				mlo_err("MLD ID %d ML Peer " QDF_MAC_ADDR_FMT " create not allowed on link vdev %d",
828 					ml_dev->mld_id,
829 					QDF_MAC_ADDR_REF
830 						(link_peer->mldaddr),
831 					wlan_vdev_get_id(vdev_link));
832 				return QDF_STATUS_E_INVAL;
833 			}
834 		}
835 
836 		for (i = 0; i < WLAN_UMAC_MLO_MAX_VDEVS; i++) {
837 			vdev_link = link_vdevs[i];
838 			if (vdev_link && (vdev_link != vdev) &&
839 			    (wlan_vdev_get_peer_count(vdev_link) >
840 			     wlan_vdev_get_max_peer_count(vdev_link))) {
841 				mlo_dev_release_link_vdevs(link_vdevs);
842 				mlo_err("MLD ID %d ML Peer " QDF_MAC_ADDR_FMT " Max peer count reached on link vdev %d",
843 					ml_dev->mld_id,
844 					QDF_MAC_ADDR_REF
845 						(link_peer->mldaddr),
846 					wlan_vdev_get_id(vdev_link));
847 				return QDF_STATUS_E_RESOURCES;
848 			}
849 		}
850 	}
851 
852 	if (wlan_vdev_mlme_get_opmode(vdev) == QDF_STA_MODE)
853 		ml_peer = wlan_mlo_get_mlpeer(ml_dev,
854 				 (struct qdf_mac_addr *)&link_peer->mldaddr[0]);
855 
856 	if (!ml_peer) {
857 		/* Allocate MLO peer */
858 		ml_peer = qdf_mem_malloc(sizeof(*ml_peer));
859 		if (!ml_peer) {
860 			mlo_err("MLD ID %d ML Peer " QDF_MAC_ADDR_FMT " mem alloc failed",
861 				ml_dev->mld_id,
862 				QDF_MAC_ADDR_REF(link_peer->mldaddr));
863 			mlo_dev_release_link_vdevs(link_vdevs);
864 			return QDF_STATUS_E_NOMEM;
865 		}
866 
867 		qdf_atomic_init(&ml_peer->ref_cnt);
868 		mlo_peer_lock_create(ml_peer);
869 		ml_peer->ml_dev = ml_dev;
870 		ml_peer->mlpeer_state = ML_PEER_CREATED;
871 		ml_peer->max_links = ml_info->num_partner_links;
872 		ml_peer->primary_umac_psoc_id = ML_PRIMARY_UMAC_ID_INVAL;
873 
874 		ml_peer->mlo_peer_id = mlo_ap_ml_peerid_alloc();
875 		if (ml_peer->mlo_peer_id == MLO_INVALID_PEER_ID) {
876 			mlo_err("MLD ID %d ML Peer " QDF_MAC_ADDR_FMT " invalid ml peer id",
877 				ml_dev->mld_id,
878 				QDF_MAC_ADDR_REF
879 				(ml_peer->peer_mld_addr.bytes));
880 			mlo_peer_free(ml_peer);
881 			mlo_dev_release_link_vdevs(link_vdevs);
882 			return QDF_STATUS_E_RESOURCES;
883 		}
884 
885 		qdf_copy_macaddr((struct qdf_mac_addr *)&ml_peer->peer_mld_addr,
886 				 (struct qdf_mac_addr *)&link_peer->mldaddr[0]);
887 		wlan_mlo_peer_set_t2lm_enable_val(ml_peer, ml_info);
888 
889 		/* Allocate AID */
890 		if (wlan_vdev_mlme_get_opmode(vdev) == QDF_SAP_MODE) {
891 			if (aid == (uint16_t)-1) {
892 				status = mlo_peer_allocate_aid(ml_dev, ml_peer);
893 				if (status != QDF_STATUS_SUCCESS) {
894 					mlo_err("MLD ID %d ML Peer " QDF_MAC_ADDR_FMT " aid alloc failed",
895 						ml_dev->mld_id,
896 						QDF_MAC_ADDR_REF
897 						(ml_peer->peer_mld_addr.bytes));
898 					mlo_peer_free(ml_peer);
899 					mlo_dev_release_link_vdevs(link_vdevs);
900 					return status;
901 				}
902 			} else {
903 				ml_peer->assoc_id = aid;
904 			}
905 		}
906 	}
907 
908 	/* Populate Link peer pointer, peer MAC address,
909 	 * MLD address. HW link ID, update ref count
910 	 */
911 	status = mlo_peer_attach_link_peer(ml_peer, link_peer, NULL);
912 	if (QDF_IS_STATUS_ERROR(status)) {
913 		mlo_err("MLD ID %d ML Peer " QDF_MAC_ADDR_FMT " link peer attach 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 
922 	/* Allocate Primary UMAC */
923 	mlo_peer_allocate_primary_umac(ml_dev, ml_peer, link_vdevs);
924 
925 	/* Store AID, MLO Peer pointer in link peer, take link peer ref count */
926 	mlo_peer_populate_link_peer(ml_peer, link_peer);
927 
928 	mlo_peer_populate_nawds_params(ml_peer, ml_info);
929 
930 	if ((wlan_vdev_mlme_get_opmode(vdev) == QDF_SAP_MODE) ||
931 		((wlan_vdev_mlme_get_opmode(vdev) == QDF_STA_MODE) &&
932 			!wlan_vdev_mlme_is_mlo_link_vdev(vdev))) {
933 		/* Attach MLO peer to ML Peer table */
934 		status = mlo_dev_mlpeer_attach(ml_dev, ml_peer);
935 		if (status != QDF_STATUS_SUCCESS) {
936 			mlo_err("MLD ID %d ML Peer " QDF_MAC_ADDR_FMT " attach failed",
937 				ml_dev->mld_id,
938 				QDF_MAC_ADDR_REF(ml_peer->peer_mld_addr.bytes));
939 			mlo_reset_link_peer(ml_peer, link_peer);
940 			wlan_objmgr_peer_release_ref(link_peer,
941 						     WLAN_MLO_MGR_ID);
942 			mlo_peer_free(ml_peer);
943 			mlo_dev_release_link_vdevs(link_vdevs);
944 			return status;
945 		}
946 	}
947 
948 	if (wlan_vdev_mlme_get_opmode(vdev) == QDF_SAP_MODE) {
949 		/* Notify other vdevs about link peer creation */
950 		for (i = 0; i < WLAN_UMAC_MLO_MAX_VDEVS; i++) {
951 			vdev_link = link_vdevs[i];
952 			if (!vdev_link)
953 				continue;
954 
955 			if (vdev_link == vdev)
956 				continue;
957 
958 			mlo_partner_peer_create_post(ml_dev, vdev_link,
959 						     ml_peer, frm_buf, ml_info);
960 		}
961 	}
962 	mlo_dev_release_link_vdevs(link_vdevs);
963 	mlo_info("MLD ID %d ML Peer " QDF_MAC_ADDR_FMT " allocated %pK",
964 		 ml_dev->mld_id,
965 		 QDF_MAC_ADDR_REF(ml_peer->peer_mld_addr.bytes),
966 		 ml_peer);
967 
968 	/*
969 	 * wlan_mlo_peer_create() is trigggered after getting peer
970 	 * assoc confirm from FW. For single link MLO connection, it is
971 	 * OK to trigger assoc response from here.
972 	 */
973 	if ((wlan_vdev_mlme_get_opmode(vdev) == QDF_SAP_MODE) &&
974 	    (!wlan_mlo_peer_is_nawds(ml_peer))) {
975 		if (ml_peer->max_links == ml_peer->link_peer_cnt) {
976 			assoc_peer = ml_peer->peer_list[0].link_peer;
977 			if (assoc_peer)
978 				mlo_mlme_peer_assoc_resp(assoc_peer);
979 		}
980 	}
981 
982 	return QDF_STATUS_SUCCESS;
983 }
984 
985 QDF_STATUS wlan_mlo_link_peer_attach(struct wlan_mlo_peer_context *ml_peer,
986 				     struct wlan_objmgr_peer *peer,
987 				     qdf_nbuf_t frm_buf)
988 {
989 	QDF_STATUS status;
990 	struct wlan_objmgr_peer *assoc_peer;
991 	struct wlan_objmgr_vdev *vdev = NULL;
992 
993 	if (!ml_peer)
994 		return QDF_STATUS_E_FAILURE;
995 
996 	vdev = wlan_peer_get_vdev(peer);
997 	if (!vdev)
998 		return QDF_STATUS_E_FAILURE;
999 
1000 	/* Populate Link peer pointer, peer MAC address,
1001 	 * MLD address. HW link ID, update ref count
1002 	 */
1003 	status = mlo_peer_attach_link_peer(ml_peer, peer, frm_buf);
1004 	if (QDF_IS_STATUS_ERROR(status))
1005 		return status;
1006 
1007 	/* Store AID, MLO Peer pointer in link peer, take link peer ref count */
1008 	mlo_peer_populate_link_peer(ml_peer, peer);
1009 
1010 	if (wlan_vdev_mlme_get_opmode(vdev) == QDF_SAP_MODE) {
1011 		if (ml_peer->max_links == ml_peer->link_peer_cnt) {
1012 			assoc_peer = ml_peer->peer_list[0].link_peer;
1013 			if (assoc_peer)
1014 				mlo_mlme_peer_assoc_resp(assoc_peer);
1015 		}
1016 	}
1017 
1018 	return status;
1019 }
1020 
1021 QDF_STATUS wlan_mlo_link_peer_delete(struct wlan_objmgr_peer *peer)
1022 {
1023 	struct wlan_mlo_peer_context *ml_peer;
1024 
1025 	ml_peer = peer->mlo_peer_ctx;
1026 
1027 	if (!ml_peer)
1028 		return QDF_STATUS_E_NOENT;
1029 
1030 	mlo_reset_link_peer(ml_peer, peer);
1031 	mlo_peer_detach_link_peer(ml_peer, peer);
1032 	wlan_mlo_peer_release_ref(ml_peer);
1033 
1034 	return QDF_STATUS_SUCCESS;
1035 }
1036 
1037 qdf_export_symbol(wlan_mlo_link_peer_delete);
1038 
1039 qdf_nbuf_t mlo_peer_get_link_peer_assoc_req_buf(
1040 			struct wlan_mlo_peer_context *ml_peer,
1041 			uint8_t link_ix)
1042 {
1043 	struct wlan_objmgr_peer *peer = NULL;
1044 	qdf_nbuf_t assocbuf = NULL;
1045 
1046 	if (!ml_peer)
1047 		return NULL;
1048 
1049 	peer = wlan_mlo_peer_get_assoc_peer(ml_peer);
1050 	if (!peer)
1051 		return NULL;
1052 
1053 	assocbuf = mlo_mlme_get_link_assoc_req(peer, link_ix);
1054 
1055 	return assocbuf;
1056 }
1057 
1058 void wlan_mlo_peer_get_links_info(struct wlan_objmgr_peer *peer,
1059 				  struct mlo_tgt_partner_info *ml_links)
1060 {
1061 	struct wlan_mlo_peer_context *ml_peer;
1062 	struct wlan_mlo_link_peer_entry *peer_entry;
1063 	struct wlan_objmgr_peer *link_peer;
1064 	struct wlan_objmgr_vdev *link_vdev;
1065 	uint8_t i, ix;
1066 
1067 	ml_peer = peer->mlo_peer_ctx;
1068 	ml_links->num_partner_links = 0;
1069 
1070 	if (!ml_peer)
1071 		return;
1072 
1073 	mlo_peer_lock_acquire(ml_peer);
1074 
1075 	if ((ml_peer->mlpeer_state != ML_PEER_CREATED) &&
1076 	    (ml_peer->mlpeer_state != ML_PEER_ASSOC_DONE)) {
1077 		mlo_peer_lock_release(ml_peer);
1078 		return;
1079 	}
1080 
1081 	for (i = 0; i < MAX_MLO_LINK_PEERS; i++) {
1082 		peer_entry = &ml_peer->peer_list[i];
1083 		link_peer = peer_entry->link_peer;
1084 
1085 		if (!link_peer)
1086 			continue;
1087 
1088 		if (link_peer == peer)
1089 			continue;
1090 
1091 		link_vdev = wlan_peer_get_vdev(link_peer);
1092 		if (!link_vdev)
1093 			continue;
1094 
1095 		if (ml_links->num_partner_links >= WLAN_UMAC_MLO_MAX_VDEVS)
1096 			break;
1097 
1098 		ix = ml_links->num_partner_links;
1099 		ml_links->link_info[ix].vdev_id = wlan_vdev_get_id(link_vdev);
1100 		ml_links->link_info[ix].hw_mld_link_id = peer_entry->hw_link_id;
1101 		ml_links->num_partner_links++;
1102 	}
1103 	mlo_peer_lock_release(ml_peer);
1104 }
1105 
1106 qdf_export_symbol(wlan_mlo_peer_get_links_info);
1107 
1108 void wlan_mlo_peer_get_partner_links_info(struct wlan_objmgr_peer *peer,
1109 					  struct mlo_partner_info *ml_links)
1110 {
1111 	struct wlan_mlo_peer_context *ml_peer;
1112 	struct wlan_mlo_link_peer_entry *peer_entry;
1113 	struct wlan_objmgr_peer *link_peer;
1114 	struct wlan_objmgr_vdev *link_vdev;
1115 	uint8_t i, ix;
1116 
1117 	ml_peer = peer->mlo_peer_ctx;
1118 	ml_links->num_partner_links = 0;
1119 
1120 	if (!ml_peer)
1121 		return;
1122 
1123 	mlo_peer_lock_acquire(ml_peer);
1124 
1125 	if ((ml_peer->mlpeer_state != ML_PEER_CREATED) &&
1126 	    (ml_peer->mlpeer_state != ML_PEER_ASSOC_DONE)) {
1127 		mlo_peer_lock_release(ml_peer);
1128 		return;
1129 	}
1130 
1131 	for (i = 0; i < MAX_MLO_LINK_PEERS; i++) {
1132 		peer_entry = &ml_peer->peer_list[i];
1133 		link_peer = peer_entry->link_peer;
1134 
1135 		if (!link_peer)
1136 			continue;
1137 
1138 		if (link_peer == peer)
1139 			continue;
1140 
1141 		link_vdev = wlan_peer_get_vdev(link_peer);
1142 		if (!link_vdev)
1143 			continue;
1144 
1145 		if (ml_links->num_partner_links >= WLAN_UMAC_MLO_MAX_VDEVS)
1146 			break;
1147 
1148 		ix = ml_links->num_partner_links;
1149 		ml_links->partner_link_info[ix].link_id = peer_entry->link_ix;
1150 
1151 		qdf_copy_macaddr(&ml_links->partner_link_info[ix].link_addr,
1152 				 &peer_entry->link_addr);
1153 		ml_links->num_partner_links++;
1154 	}
1155 	mlo_peer_lock_release(ml_peer);
1156 }
1157 
1158 qdf_export_symbol(wlan_mlo_peer_get_partner_links_info);
1159 
1160 #ifdef UMAC_SUPPORT_MLNAWDS
1161 bool wlan_mlo_peer_is_nawds(struct wlan_mlo_peer_context *ml_peer)
1162 {
1163 	bool status = false;
1164 
1165 	if (!ml_peer)
1166 		return status;
1167 
1168 	mlo_peer_lock_acquire(ml_peer);
1169 	if (ml_peer->is_nawds_ml_peer)
1170 		status = true;
1171 	mlo_peer_lock_release(ml_peer);
1172 
1173 	return status;
1174 }
1175 
1176 qdf_export_symbol(wlan_mlo_peer_is_nawds);
1177 #endif
1178 
1179 #ifdef UMAC_MLO_AUTH_DEFER
1180 void mlo_peer_free_auth_param(struct mlpeer_auth_params *auth_params)
1181 {
1182 	if (auth_params->rs)
1183 		qdf_mem_free(auth_params->rs);
1184 
1185 	if (auth_params->wbuf)
1186 		qdf_nbuf_free(auth_params->wbuf);
1187 
1188 	qdf_mem_free(auth_params);
1189 }
1190 
1191 QDF_STATUS mlo_peer_link_auth_defer(struct wlan_mlo_peer_context *ml_peer,
1192 				    struct qdf_mac_addr *link_mac,
1193 				    struct mlpeer_auth_params *auth_params)
1194 {
1195 	uint8_t i;
1196 	uint8_t free_entries = 0;
1197 	struct mlpeer_auth_params *recv_auth;
1198 	QDF_STATUS status = QDF_STATUS_E_FAILURE;
1199 
1200 	if (!ml_peer)
1201 		return status;
1202 
1203 	mlo_peer_lock_acquire(ml_peer);
1204 	for (i = 0; i < MAX_MLO_LINK_PEERS; i++) {
1205 		recv_auth = ml_peer->pending_auth[i];
1206 		if (!recv_auth) {
1207 			free_entries++;
1208 			continue;
1209 		}
1210 		/* overwrite the entry with latest entry */
1211 		if (qdf_is_macaddr_equal(link_mac, &recv_auth->link_addr)) {
1212 			mlo_peer_free_auth_param(recv_auth);
1213 			ml_peer->pending_auth[i] = auth_params;
1214 			mlo_peer_lock_release(ml_peer);
1215 
1216 			return QDF_STATUS_SUCCESS;
1217 		}
1218 	}
1219 
1220 	if (!free_entries) {
1221 		mlo_peer_lock_release(ml_peer);
1222 		return QDF_STATUS_E_FAILURE;
1223 	}
1224 
1225 	for (i = 0; i < MAX_MLO_LINK_PEERS; i++) {
1226 		recv_auth = ml_peer->pending_auth[i];
1227 		if (!recv_auth) {
1228 			ml_peer->pending_auth[i] = auth_params;
1229 			status = QDF_STATUS_SUCCESS;
1230 			break;
1231 		}
1232 	}
1233 	mlo_peer_lock_release(ml_peer);
1234 
1235 	return status;
1236 }
1237 #endif
1238