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