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