xref: /wlan-dirver/qca-wifi-host-cmn/umac/mlo_mgr/src/wlan_mlo_mgr_peer.c (revision c7eaf5ac989ac229214b8317faa3e981d261e7db)
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 #include "wlan_mlo_mgr_setup.h"
28 #include "wlan_utility.h"
29 
30 static void mlo_partner_peer_create_post(struct wlan_mlo_dev_context *ml_dev,
31 					 struct wlan_objmgr_vdev *vdev_link,
32 					 struct wlan_mlo_peer_context *ml_peer,
33 					 qdf_nbuf_t frm_buf,
34 					 struct mlo_partner_info *ml_info)
35 {
36 	struct peer_create_notif_s peer_create;
37 	QDF_STATUS status;
38 	uint8_t i;
39 	uint8_t link_id;
40 
41 	if (wlan_objmgr_vdev_try_get_ref(vdev_link, WLAN_MLO_MGR_ID) ==
42 							QDF_STATUS_SUCCESS) {
43 		peer_create.vdev_link = vdev_link;
44 	} else {
45 		mlo_err("VDEV is not in created state");
46 		return;
47 	}
48 
49 	wlan_mlo_peer_get_ref(ml_peer);
50 	peer_create.ml_peer = ml_peer;
51 	link_id = wlan_vdev_get_link_id(vdev_link);
52 	for (i = 0; i < ml_info->num_partner_links; i++) {
53 		if (link_id != ml_info->partner_link_info[i].link_id)
54 			continue;
55 
56 		qdf_copy_macaddr(&peer_create.addr,
57 				 &ml_info->partner_link_info[i].link_addr);
58 		break;
59 	}
60 
61 	status = mlo_peer_create_get_frm_buf(ml_peer, &peer_create, frm_buf);
62 
63 	if (QDF_IS_STATUS_ERROR(status)) {
64 		wlan_mlo_peer_release_ref(ml_peer);
65 		wlan_objmgr_vdev_release_ref(vdev_link, WLAN_MLO_MGR_ID);
66 		mlo_err("nbuf clone is failed");
67 		return;
68 	}
69 
70 	status = mlo_msgq_post(MLO_PEER_CREATE, ml_dev, &peer_create);
71 	if (status != QDF_STATUS_SUCCESS) {
72 		qdf_nbuf_free(frm_buf);
73 		wlan_mlo_peer_release_ref(ml_peer);
74 		wlan_objmgr_vdev_release_ref(vdev_link, WLAN_MLO_MGR_ID);
75 	}
76 }
77 
78 static void mlo_link_peer_assoc_notify(struct wlan_mlo_dev_context *ml_dev,
79 				       struct wlan_objmgr_peer *peer)
80 {
81 	struct peer_assoc_notify_s peer_assoc;
82 	QDF_STATUS status;
83 
84 	peer_assoc.peer = peer;
85 	status = mlo_msgq_post(MLO_PEER_ASSOC, ml_dev, &peer_assoc);
86 	if (status != QDF_STATUS_SUCCESS)
87 		wlan_objmgr_peer_release_ref(peer, WLAN_MLO_MGR_ID);
88 }
89 
90 static void mlo_link_peer_send_assoc_fail(struct wlan_mlo_dev_context *ml_dev,
91 					  struct wlan_objmgr_peer *peer)
92 {
93 	struct peer_assoc_fail_notify_s peer_assoc_fail;
94 	QDF_STATUS status;
95 
96 	peer_assoc_fail.peer = peer;
97 	status = mlo_msgq_post(MLO_PEER_ASSOC_FAIL, ml_dev, &peer_assoc_fail);
98 	if (status != QDF_STATUS_SUCCESS)
99 		wlan_objmgr_peer_release_ref(peer, WLAN_MLO_MGR_ID);
100 }
101 
102 static void mlo_link_peer_disconnect_notify(struct wlan_mlo_dev_context *ml_dev,
103 					    struct wlan_objmgr_peer *peer)
104 {
105 	struct peer_discon_notify_s peer_disconn;
106 	QDF_STATUS status;
107 	struct wlan_objmgr_vdev *vdev;
108 	enum QDF_OPMODE opmode;
109 
110 	vdev = wlan_peer_get_vdev(peer);
111 	opmode = wlan_vdev_mlme_get_opmode(vdev);
112 
113 	if (opmode == QDF_SAP_MODE) {
114 		peer_disconn.peer = peer;
115 		status = mlo_msgq_post(MLO_PEER_DISCONNECT, ml_dev,
116 				       &peer_disconn);
117 		if (status != QDF_STATUS_SUCCESS)
118 			wlan_objmgr_peer_release_ref(peer, WLAN_MLO_MGR_ID);
119 	} else {
120 		wlan_objmgr_peer_release_ref(peer, WLAN_MLO_MGR_ID);
121 	}
122 }
123 
124 static void mlo_link_peer_deauth_init(struct wlan_mlo_dev_context *ml_dev,
125 				      struct wlan_objmgr_peer *peer,
126 				      uint8_t is_disassoc)
127 {
128 	struct peer_deauth_notify_s peer_deauth;
129 	QDF_STATUS status;
130 
131 	peer_deauth.peer = peer;
132 	peer_deauth.is_disassoc = is_disassoc;
133 	status = mlo_msgq_post(MLO_PEER_DEAUTH, ml_dev, &peer_deauth);
134 	if (status != QDF_STATUS_SUCCESS)
135 		wlan_objmgr_peer_release_ref(peer, WLAN_MLO_MGR_ID);
136 }
137 
138 #ifdef UMAC_MLO_AUTH_DEFER
139 static void mlo_peer_process_pending_auth(struct wlan_mlo_dev_context *ml_dev,
140 					  struct wlan_mlo_peer_context *ml_peer)
141 {
142 	struct peer_auth_process_notif_s peer_auth;
143 	struct mlpeer_auth_params *recv_auth;
144 	uint8_t i;
145 	QDF_STATUS status;
146 
147 	for (i = 0; i < MAX_MLO_LINK_PEERS; i++) {
148 		mlo_peer_lock_acquire(ml_peer);
149 		recv_auth = ml_peer->pending_auth[i];
150 		if (!recv_auth) {
151 			mlo_peer_lock_release(ml_peer);
152 			continue;
153 		}
154 		peer_auth.auth_params = recv_auth;
155 		ml_peer->pending_auth[i] = NULL;
156 
157 		mlo_peer_lock_release(ml_peer);
158 
159 		status = mlo_msgq_post(MLO_PEER_PENDING_AUTH, ml_dev,
160 				       &peer_auth);
161 		if (QDF_IS_STATUS_ERROR(status))
162 			mlo_peer_free_auth_param(peer_auth.auth_params);
163 	}
164 }
165 #else
166 static void mlo_peer_process_pending_auth(struct wlan_mlo_dev_context *ml_dev,
167 					  struct wlan_mlo_peer_context *ml_peer)
168 {
169 }
170 #endif
171 
172 QDF_STATUS
173 wlan_mlo_peer_is_disconnect_progress(struct wlan_mlo_peer_context *ml_peer)
174 {
175 	QDF_STATUS status;
176 
177 	if (!ml_peer)
178 		return QDF_STATUS_E_FAILURE;
179 
180 	mlo_peer_lock_acquire(ml_peer);
181 
182 	if (ml_peer->mlpeer_state == ML_PEER_DISCONN_INITIATED)
183 		status = QDF_STATUS_SUCCESS;
184 	else
185 		status = QDF_STATUS_E_FAILURE;
186 
187 	mlo_peer_lock_release(ml_peer);
188 
189 	return status;
190 }
191 
192 QDF_STATUS wlan_mlo_peer_is_assoc_done(struct wlan_mlo_peer_context *ml_peer)
193 {
194 	QDF_STATUS status;
195 
196 	if (!ml_peer)
197 		return QDF_STATUS_E_FAILURE;
198 
199 	mlo_peer_lock_acquire(ml_peer);
200 
201 	if (ml_peer->mlpeer_state == ML_PEER_ASSOC_DONE)
202 		status = QDF_STATUS_SUCCESS;
203 	else
204 		status = QDF_STATUS_E_FAILURE;
205 
206 	mlo_peer_lock_release(ml_peer);
207 
208 	return status;
209 }
210 
211 struct wlan_objmgr_peer *wlan_mlo_peer_get_assoc_peer(
212 					struct wlan_mlo_peer_context *ml_peer)
213 {
214 	struct wlan_mlo_link_peer_entry *peer_entry;
215 	struct wlan_objmgr_peer *assoc_peer = NULL;
216 
217 	if (!ml_peer)
218 		return NULL;
219 
220 	mlo_peer_lock_acquire(ml_peer);
221 
222 	peer_entry = &ml_peer->peer_list[0];
223 
224 	if (peer_entry->link_peer)
225 		assoc_peer = peer_entry->link_peer;
226 
227 	mlo_peer_lock_release(ml_peer);
228 
229 	return assoc_peer;
230 }
231 
232 qdf_export_symbol(wlan_mlo_peer_get_assoc_peer);
233 
234 bool mlo_peer_is_assoc_peer(struct wlan_mlo_peer_context *ml_peer,
235 			    struct wlan_objmgr_peer *peer)
236 {
237 	struct wlan_mlo_link_peer_entry *peer_entry;
238 	bool is_assoc_peer = false;
239 
240 	if (!ml_peer || !peer)
241 		return is_assoc_peer;
242 
243 	peer_entry = &ml_peer->peer_list[0];
244 
245 	if (peer_entry->link_peer != peer)
246 		is_assoc_peer = true;
247 
248 	return is_assoc_peer;
249 }
250 
251 bool wlan_mlo_peer_is_assoc_peer(struct wlan_mlo_peer_context *ml_peer,
252 				 struct wlan_objmgr_peer *peer)
253 {
254 	bool is_assoc_peer = false;
255 
256 	if (!ml_peer || !peer)
257 		return is_assoc_peer;
258 
259 	mlo_peer_lock_acquire(ml_peer);
260 
261 	is_assoc_peer = mlo_peer_is_assoc_peer(ml_peer, peer);
262 
263 	mlo_peer_lock_release(ml_peer);
264 
265 	return is_assoc_peer;
266 }
267 
268 void wlan_mlo_partner_peer_assoc_post(struct wlan_objmgr_peer *assoc_peer)
269 {
270 	struct wlan_mlo_dev_context *ml_dev;
271 	struct wlan_mlo_peer_context *ml_peer;
272 	struct wlan_objmgr_peer *link_peer;
273 	struct wlan_objmgr_peer *link_peers[MAX_MLO_LINK_PEERS];
274 	struct wlan_mlo_link_peer_entry *peer_entry;
275 	uint16_t i;
276 
277 	ml_peer = assoc_peer->mlo_peer_ctx;
278 	if (!ml_peer)
279 		return;
280 
281 	mlo_peer_lock_acquire(ml_peer);
282 
283 	if (ml_peer->mlpeer_state != ML_PEER_CREATED) {
284 		mlo_peer_lock_release(ml_peer);
285 		return;
286 	}
287 
288 	ml_peer->mlpeer_state = ML_PEER_ASSOC_DONE;
289 	ml_dev = ml_peer->ml_dev;
290 
291 	for (i = 0; i < MAX_MLO_LINK_PEERS; i++) {
292 		link_peers[i] = NULL;
293 		peer_entry = &ml_peer->peer_list[i];
294 
295 		if (!peer_entry->link_peer)
296 			continue;
297 
298 		if (peer_entry->link_peer == assoc_peer)
299 			continue;
300 
301 		link_peer = peer_entry->link_peer;
302 
303 		if (wlan_objmgr_peer_try_get_ref(link_peer, WLAN_MLO_MGR_ID) !=
304 						 QDF_STATUS_SUCCESS)
305 			continue;
306 
307 		link_peers[i] = link_peer;
308 	}
309 	mlo_peer_lock_release(ml_peer);
310 
311 	for (i = 0; i < MAX_MLO_LINK_PEERS; i++) {
312 		if (!link_peers[i])
313 			continue;
314 
315 		/* Prepare and queue message */
316 		mlo_link_peer_assoc_notify(ml_dev, link_peers[i]);
317 	}
318 }
319 
320 void
321 wlan_mlo_peer_deauth_init(struct wlan_mlo_peer_context *ml_peer,
322 			  struct wlan_objmgr_peer *src_peer,
323 			  uint8_t is_disassoc)
324 {
325 	struct wlan_mlo_dev_context *ml_dev;
326 	struct wlan_objmgr_peer *link_peer;
327 	struct wlan_objmgr_peer *link_peers[MAX_MLO_LINK_PEERS];
328 	struct wlan_mlo_link_peer_entry *peer_entry;
329 	uint16_t i;
330 	uint8_t deauth_sent = 0;
331 
332 	if (!ml_peer)
333 		return;
334 
335 	mlo_peer_lock_acquire(ml_peer);
336 
337 	if (ml_peer->mlpeer_state == ML_PEER_DISCONN_INITIATED) {
338 		mlo_peer_lock_release(ml_peer);
339 		return;
340 	}
341 
342 	ml_dev = ml_peer->ml_dev;
343 
344 	for (i = 0; i < MAX_MLO_LINK_PEERS; i++) {
345 		link_peers[i] = NULL;
346 		peer_entry = &ml_peer->peer_list[i];
347 		if (!peer_entry->link_peer)
348 			continue;
349 
350 		link_peer = peer_entry->link_peer;
351 
352 		if (wlan_objmgr_peer_try_get_ref(link_peer, WLAN_MLO_MGR_ID) !=
353 						QDF_STATUS_SUCCESS)
354 			continue;
355 
356 		link_peers[i] = link_peer;
357 	}
358 
359 	ml_peer->mlpeer_state = ML_PEER_DISCONN_INITIATED;
360 
361 	mlo_peer_lock_release(ml_peer);
362 
363 	for (i = 0; i < MAX_MLO_LINK_PEERS; i++) {
364 		if (!link_peers[i])
365 			continue;
366 
367 		/* Prepare and queue message */
368 		/* skip sending deauth on src peer */
369 		if ((deauth_sent) ||
370 		    (src_peer && (src_peer == link_peers[i]))) {
371 			mlo_link_peer_disconnect_notify(ml_dev, link_peers[i]);
372 		} else {
373 			mlo_link_peer_deauth_init(ml_dev, link_peers[i],
374 						  is_disassoc);
375 			deauth_sent = 1;
376 		}
377 	}
378 }
379 
380 void wlan_mlo_peer_delete(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_dev = ml_peer->ml_dev;
399 
400 	for (i = 0; i < MAX_MLO_LINK_PEERS; i++) {
401 		link_peers[i] = NULL;
402 		peer_entry = &ml_peer->peer_list[i];
403 		if (!peer_entry->link_peer)
404 			continue;
405 
406 		link_peer = peer_entry->link_peer;
407 
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 
415 	ml_peer->mlpeer_state = ML_PEER_DISCONN_INITIATED;
416 
417 	mlo_peer_lock_release(ml_peer);
418 
419 	for (i = 0; i < MAX_MLO_LINK_PEERS; i++) {
420 		if (!link_peers[i])
421 			continue;
422 
423 		mlo_link_peer_disconnect_notify(ml_dev, link_peers[i]);
424 	}
425 }
426 
427 void
428 wlan_mlo_partner_peer_create_failed_notify(
429 				struct wlan_mlo_peer_context *ml_peer)
430 {
431 	struct wlan_mlo_dev_context *ml_dev;
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 	uint16_t i;
436 
437 	if (!ml_peer)
438 		return;
439 
440 	mlo_peer_lock_acquire(ml_peer);
441 
442 	if (ml_peer->mlpeer_state == ML_PEER_DISCONN_INITIATED) {
443 		mlo_peer_lock_release(ml_peer);
444 		return;
445 	}
446 
447 	ml_peer->mlpeer_state = ML_PEER_DISCONN_INITIATED;
448 	ml_dev = ml_peer->ml_dev;
449 
450 	for (i = 0; i < MAX_MLO_LINK_PEERS; i++) {
451 		link_peers[i] = NULL;
452 		peer_entry = &ml_peer->peer_list[i];
453 		if (!peer_entry->link_peer)
454 			continue;
455 
456 		link_peer = peer_entry->link_peer;
457 		if (wlan_objmgr_peer_try_get_ref(link_peer, WLAN_MLO_MGR_ID) !=
458 						QDF_STATUS_SUCCESS)
459 			continue;
460 
461 		link_peers[i] = link_peer;
462 	}
463 	mlo_peer_lock_release(ml_peer);
464 
465 	for (i = 0; i < MAX_MLO_LINK_PEERS; i++) {
466 		if (!link_peers[i])
467 			continue;
468 
469 		/* Prepare and queue message */
470 		if (i == 0)
471 			mlo_link_peer_send_assoc_fail(ml_dev, link_peers[i]);
472 		else
473 			mlo_link_peer_disconnect_notify(ml_dev, link_peers[i]);
474 	}
475 }
476 
477 void wlan_mlo_partner_peer_disconnect_notify(struct wlan_objmgr_peer *src_peer)
478 {
479 	struct wlan_mlo_dev_context *ml_dev;
480 	struct wlan_mlo_peer_context *ml_peer;
481 	struct wlan_objmgr_peer *link_peer;
482 	struct wlan_objmgr_peer *link_peers[MAX_MLO_LINK_PEERS];
483 	struct wlan_mlo_link_peer_entry *peer_entry;
484 	struct wlan_objmgr_vdev *vdev = NULL;
485 	uint16_t i;
486 
487 	ml_peer = src_peer->mlo_peer_ctx;
488 	if (!ml_peer)
489 		return;
490 
491 	vdev = wlan_peer_get_vdev(src_peer);
492 	if (!vdev)
493 		return;
494 
495 	mlo_peer_lock_acquire(ml_peer);
496 
497 	if (ml_peer->mlpeer_state == ML_PEER_DISCONN_INITIATED) {
498 		mlo_peer_lock_release(ml_peer);
499 		return;
500 	}
501 
502 	ml_peer->mlpeer_state = ML_PEER_DISCONN_INITIATED;
503 
504 	if (wlan_vdev_mlme_get_opmode(vdev) == QDF_STA_MODE) {
505 		mlo_peer_lock_release(ml_peer);
506 		return;
507 	}
508 
509 	ml_dev = ml_peer->ml_dev;
510 	for (i = 0; i < MAX_MLO_LINK_PEERS; i++) {
511 		link_peers[i] = NULL;
512 		peer_entry = &ml_peer->peer_list[i];
513 		if (!peer_entry->link_peer) {
514 			mlo_debug("link peer is null");
515 			continue;
516 		}
517 
518 		if (peer_entry->link_peer == src_peer)
519 			continue;
520 
521 		link_peer = peer_entry->link_peer;
522 		if (wlan_objmgr_peer_try_get_ref(link_peer, WLAN_MLO_MGR_ID) !=
523 						QDF_STATUS_SUCCESS)
524 			continue;
525 
526 		link_peers[i] = link_peer;
527 	}
528 	mlo_peer_lock_release(ml_peer);
529 
530 	for (i = 0; i < MAX_MLO_LINK_PEERS; i++) {
531 		if (!link_peers[i])
532 			continue;
533 
534 		/* Prepare and queue message */
535 		mlo_link_peer_disconnect_notify(ml_dev, link_peers[i]);
536 	}
537 }
538 
539 static void mlo_peer_populate_link_peer(
540 			struct wlan_mlo_peer_context *ml_peer,
541 			struct wlan_objmgr_peer *link_peer)
542 {
543 	mlo_peer_lock_acquire(ml_peer);
544 	wlan_mlo_peer_get_ref(ml_peer);
545 	link_peer->mlo_peer_ctx = ml_peer;
546 	mlo_peer_lock_release(ml_peer);
547 }
548 
549 static void mlo_reset_link_peer(
550 			struct wlan_mlo_peer_context *ml_peer,
551 			struct wlan_objmgr_peer *link_peer)
552 {
553 	mlo_peer_lock_acquire(ml_peer);
554 	link_peer->mlo_peer_ctx = NULL;
555 	wlan_peer_clear_mlo(link_peer);
556 	mlo_peer_lock_release(ml_peer);
557 }
558 
559 static void mlo_peer_free(struct wlan_mlo_peer_context *ml_peer)
560 {
561 	struct wlan_mlo_dev_context *ml_dev;
562 
563 	ml_dev = ml_peer->ml_dev;
564 	if (!ml_dev) {
565 		mlo_err("ML DEV is NULL");
566 		return;
567 	}
568 
569 	mlo_debug("ML Peer " QDF_MAC_ADDR_FMT " is freed",
570 		  QDF_MAC_ADDR_REF(ml_peer->peer_mld_addr.bytes));
571 	mlo_peer_lock_destroy(ml_peer);
572 	mlo_ap_ml_peerid_free(ml_peer->mlo_peer_id);
573 	mlo_peer_free_aid(ml_dev, ml_peer);
574 	mlo_peer_free_primary_umac(ml_dev, ml_peer);
575 	qdf_mem_free(ml_peer);
576 }
577 
578 void mlo_peer_cleanup(struct wlan_mlo_peer_context *ml_peer)
579 {
580 	struct wlan_mlo_dev_context *ml_dev;
581 
582 	if (!ml_peer) {
583 		mlo_err("ML PEER is NULL");
584 		return;
585 	}
586 	ml_dev = ml_peer->ml_dev;
587 	if (!ml_dev) {
588 		mlo_err("ML DEV is NULL");
589 		return;
590 	}
591 
592 	mlo_dev_mlpeer_detach(ml_dev, ml_peer);
593 	/* If any Auth req is received during ML peer delete */
594 	mlo_peer_process_pending_auth(ml_dev, ml_peer);
595 	mlo_peer_free(ml_peer);
596 }
597 
598 static QDF_STATUS mlo_peer_attach_link_peer(
599 		struct wlan_mlo_peer_context *ml_peer,
600 		struct wlan_objmgr_peer *link_peer,
601 		qdf_nbuf_t frm_buf)
602 {
603 	struct wlan_mlo_link_peer_entry *peer_entry;
604 	QDF_STATUS status = QDF_STATUS_E_RESOURCES;
605 	struct wlan_objmgr_pdev *pdev;
606 	struct wlan_objmgr_vdev *vdev;
607 	uint16_t i;
608 
609 	if (!link_peer)
610 		return QDF_STATUS_E_FAILURE;
611 
612 	vdev = wlan_peer_get_vdev(link_peer);
613 	if (!vdev)
614 		return QDF_STATUS_E_FAILURE;
615 
616 	mlo_peer_lock_acquire(ml_peer);
617 
618 	if (ml_peer->mlpeer_state != ML_PEER_CREATED) {
619 		mlo_peer_lock_release(ml_peer);
620 		mlo_err("ML Peer " QDF_MAC_ADDR_FMT " is not in created state (state %d)",
621 			QDF_MAC_ADDR_REF(ml_peer->peer_mld_addr.bytes),
622 			ml_peer->mlpeer_state);
623 		return status;
624 	}
625 
626 	for (i = 0; i < MAX_MLO_LINK_PEERS; i++) {
627 		peer_entry = &ml_peer->peer_list[i];
628 		if (peer_entry->link_peer)
629 			continue;
630 
631 		if (wlan_objmgr_peer_try_get_ref(link_peer, WLAN_MLO_MGR_ID) !=
632 						QDF_STATUS_SUCCESS) {
633 			mlo_err("ML Peer " QDF_MAC_ADDR_FMT ", link peer " QDF_MAC_ADDR_FMT " is not in valid state",
634 				QDF_MAC_ADDR_REF(ml_peer->peer_mld_addr.bytes),
635 				QDF_MAC_ADDR_REF
636 					(wlan_peer_get_macaddr(link_peer)));
637 			break;
638 		}
639 		peer_entry->link_peer = link_peer;
640 		vdev->vdev_objmgr.wlan_ml_peer_count++;
641 		qdf_copy_macaddr(&peer_entry->link_addr,
642 				 (struct qdf_mac_addr *)&link_peer->macaddr[0]);
643 
644 		peer_entry->link_ix = wlan_vdev_get_link_id(vdev);
645 		pdev = wlan_vdev_get_pdev(wlan_peer_get_vdev(link_peer));
646 		peer_entry->hw_link_id = wlan_mlo_get_pdev_hw_link_id(pdev);
647 		mlo_peer_assign_primary_umac(ml_peer, peer_entry);
648 		if (frm_buf)
649 			peer_entry->assoc_rsp_buf = frm_buf;
650 		else
651 			peer_entry->assoc_rsp_buf = NULL;
652 
653 		status = QDF_STATUS_SUCCESS;
654 		break;
655 	}
656 	if (QDF_IS_STATUS_SUCCESS(status))
657 		ml_peer->link_peer_cnt++;
658 
659 	mlo_peer_lock_release(ml_peer);
660 
661 	return status;
662 }
663 
664 qdf_nbuf_t mlo_peer_get_link_peer_assoc_resp_buf(
665 		struct wlan_mlo_peer_context *ml_peer,
666 		uint8_t link_ix)
667 {
668 	struct wlan_mlo_link_peer_entry *peer_entry;
669 	qdf_nbuf_t frm_buf = NULL;
670 	uint8_t i;
671 
672 	if (!ml_peer)
673 		return NULL;
674 
675 	if (link_ix > MAX_MLO_LINK_PEERS)
676 		return NULL;
677 
678 	mlo_peer_lock_acquire(ml_peer);
679 	if ((ml_peer->mlpeer_state != ML_PEER_CREATED) &&
680 	    (ml_peer->mlpeer_state != ML_PEER_ASSOC_DONE)) {
681 		mlo_peer_lock_release(ml_peer);
682 		return NULL;
683 	}
684 
685 	for (i = 0; i < MAX_MLO_LINK_PEERS; i++) {
686 		peer_entry = &ml_peer->peer_list[i];
687 
688 		if (!peer_entry->link_peer)
689 			continue;
690 
691 		if (peer_entry->link_ix == link_ix) {
692 			if (!peer_entry->assoc_rsp_buf)
693 				break;
694 
695 			frm_buf = qdf_nbuf_clone(peer_entry->assoc_rsp_buf);
696 			break;
697 		}
698 	}
699 	mlo_peer_lock_release(ml_peer);
700 
701 	return frm_buf;
702 }
703 
704 void wlan_mlo_peer_free_all_link_assoc_resp_buf(
705 			struct wlan_objmgr_peer *link_peer)
706 {
707 	struct wlan_mlo_link_peer_entry *peer_entry;
708 	struct wlan_mlo_peer_context *ml_peer;
709 	uint8_t i;
710 
711 	ml_peer = link_peer->mlo_peer_ctx;
712 	if (!ml_peer)
713 		return;
714 
715 	mlo_peer_lock_acquire(ml_peer);
716 
717 	for (i = 0; i < MAX_MLO_LINK_PEERS; i++) {
718 		peer_entry = &ml_peer->peer_list[i];
719 
720 		if (peer_entry->assoc_rsp_buf) {
721 			qdf_nbuf_free(peer_entry->assoc_rsp_buf);
722 			peer_entry->assoc_rsp_buf = NULL;
723 		}
724 	}
725 	mlo_peer_lock_release(ml_peer);
726 }
727 
728 static QDF_STATUS mlo_peer_detach_link_peer(
729 		struct wlan_mlo_peer_context *ml_peer,
730 		struct wlan_objmgr_peer *link_peer)
731 {
732 	struct wlan_mlo_link_peer_entry *peer_entry;
733 	QDF_STATUS status = QDF_STATUS_E_RESOURCES;
734 	uint16_t i;
735 	struct wlan_objmgr_vdev *vdev;
736 
737 	mlo_peer_lock_acquire(ml_peer);
738 
739 	for (i = 0; i < MAX_MLO_LINK_PEERS; i++) {
740 		peer_entry = &ml_peer->peer_list[i];
741 		if (!peer_entry->link_peer)
742 			continue;
743 
744 		if (peer_entry->link_peer != link_peer)
745 			continue;
746 
747 		if (peer_entry->assoc_rsp_buf) {
748 			qdf_nbuf_free(peer_entry->assoc_rsp_buf);
749 			peer_entry->assoc_rsp_buf = NULL;
750 		}
751 		vdev =  wlan_peer_get_vdev(link_peer);
752 		if (vdev)
753 			vdev->vdev_objmgr.wlan_ml_peer_count--;
754 
755 		wlan_objmgr_peer_release_ref(link_peer, WLAN_MLO_MGR_ID);
756 		peer_entry->link_peer = NULL;
757 		ml_peer->link_peer_cnt--;
758 		status = QDF_STATUS_SUCCESS;
759 		break;
760 	}
761 	mlo_peer_lock_release(ml_peer);
762 
763 	return status;
764 }
765 
766 static QDF_STATUS mlo_dev_get_link_vdevs(
767 			struct wlan_objmgr_vdev *vdev,
768 			struct wlan_mlo_dev_context *ml_dev,
769 			struct mlo_partner_info *ml_info,
770 			struct wlan_objmgr_vdev *link_vdevs[])
771 {
772 	uint16_t i, j;
773 	struct wlan_objmgr_vdev *vdev_link;
774 	uint8_t link_id;
775 
776 	if (!ml_dev) {
777 		mlo_err("ml_dev is null");
778 		return QDF_STATUS_E_INVAL;
779 	}
780 
781 	if (!ml_info) {
782 		mlo_err("ml_info is null");
783 		return QDF_STATUS_E_INVAL;
784 	}
785 
786 	mlo_debug("num_partner_links %d", ml_info->num_partner_links);
787 	for (i = 0; i < ml_info->num_partner_links; i++) {
788 		link_id = ml_info->partner_link_info[i].link_id;
789 		vdev_link = mlo_get_vdev_by_link_id(vdev, link_id);
790 		if (vdev_link) {
791 			link_vdevs[i] = vdev_link;
792 		} else {
793 			/* release ref which were taken before failure */
794 			for (j = 0; j < i; j++) {
795 				vdev_link = link_vdevs[j];
796 				if (!vdev_link)
797 					continue;
798 
799 				wlan_objmgr_vdev_release_ref(vdev_link,
800 							     WLAN_MLO_MGR_ID);
801 			}
802 			return QDF_STATUS_E_INVAL;
803 		}
804 	}
805 
806 	return QDF_STATUS_SUCCESS;
807 }
808 
809 static void mlo_dev_release_link_vdevs(
810 			struct wlan_objmgr_vdev *link_vdevs[])
811 {
812 	uint16_t i;
813 	struct wlan_objmgr_vdev *vdev_link;
814 
815 	for (i = 0; i < WLAN_UMAC_MLO_MAX_VDEVS; i++) {
816 		vdev_link = link_vdevs[i];
817 		if (!vdev_link)
818 			continue;
819 
820 		wlan_objmgr_vdev_release_ref(vdev_link, WLAN_MLO_MGR_ID);
821 	}
822 }
823 
824 #ifdef WLAN_FEATURE_11BE
825 static void
826 wlan_mlo_peer_set_t2lm_enable_val(struct wlan_mlo_peer_context *ml_peer,
827 				  struct mlo_partner_info *ml_info)
828 {
829 	ml_peer->t2lm_policy.t2lm_enable_val = ml_info->t2lm_enable_val;
830 }
831 #else
832 static void
833 wlan_mlo_peer_set_t2lm_enable_val(struct wlan_mlo_peer_context *ml_peer,
834 				  struct mlo_partner_info *ml_info)
835 {}
836 #endif /* WLAN_FEATURE_11BE */
837 
838 #if defined(WLAN_FEATURE_11BE_MLO) && defined(WLAN_MLO_MULTI_CHIP)
839 static struct wlan_objmgr_vdev*
840 mlo_get_primary_umac_vdev(struct wlan_mlo_dev_context *ml_dev,
841 			  uint8_t psoc_id)
842 {
843 	uint8_t i;
844 	struct wlan_objmgr_vdev *link_vdev;
845 
846 	if (WLAN_OBJMGR_MAX_DEVICES <= psoc_id)
847 		return NULL;
848 
849 	if (!ml_dev)
850 		return NULL;
851 
852 	for (i = 0; i < WLAN_UMAC_MLO_MAX_VDEVS; i++) {
853 		link_vdev = ml_dev->wlan_vdev_list[i];
854 		if (!link_vdev)
855 			continue;
856 		if (psoc_id == wlan_vdev_get_psoc_id(link_vdev))
857 			return link_vdev;
858 	}
859 
860 	return NULL;
861 }
862 
863 static
864 QDF_STATUS mlo_bridge_peer_create_post(struct wlan_mlo_dev_context *ml_dev,
865 				       struct wlan_mlo_peer_context *ml_peer,
866 				       uint8_t psoc_id)
867 {
868 	struct peer_create_notif_s peer_create;
869 	struct wlan_objmgr_vdev *vdev_link;
870 	QDF_STATUS status;
871 
872 	vdev_link = mlo_get_primary_umac_vdev(ml_dev, psoc_id);
873 
874 	if (!vdev_link) {
875 		mlo_err("VDEV derivation in unsuccessful");
876 		return QDF_STATUS_E_FAILURE;
877 	}
878 
879 	if (wlan_objmgr_vdev_try_get_ref(vdev_link, WLAN_MLO_MGR_ID) !=
880 							QDF_STATUS_SUCCESS) {
881 		mlo_err("VDEV is not in created state");
882 		return QDF_STATUS_E_FAILURE;
883 	}
884 	peer_create.vdev_link = vdev_link;
885 	wlan_mlo_peer_get_ref(ml_peer);
886 	peer_create.ml_peer = ml_peer;
887 
888 	qdf_copy_macaddr(&peer_create.addr,
889 			 &ml_peer->peer_mld_addr);
890 
891 	peer_create.frm_buf = NULL;
892 
893 	status = mlo_msgq_post(MLO_BRIDGE_PEER_CREATE, ml_dev, &peer_create);
894 	if (status != QDF_STATUS_SUCCESS) {
895 		wlan_mlo_peer_release_ref(ml_peer);
896 		wlan_objmgr_vdev_release_ref(vdev_link, WLAN_MLO_MGR_ID);
897 	}
898 
899 	return status;
900 }
901 
902 static QDF_STATUS
903 wlan_mlo_check_and_create_bridge_peer(struct wlan_objmgr_vdev *vdev,
904 				      struct wlan_mlo_peer_context *ml_peer,
905 				      struct wlan_objmgr_vdev *link_vdevs[],
906 				      uint8_t num_partner_links)
907 {
908 	struct wlan_mlo_dev_context *ml_dev;
909 	struct wlan_objmgr_vdev *ml_vdev;
910 	uint8_t psoc_ids[WLAN_NUM_TWO_LINK_PSOC];
911 	uint8_t comp_psoc_id, i, is_adjacent;
912 	uint8_t bridge_peer_psoc_id = WLAN_OBJMGR_MAX_DEVICES;
913 	QDF_STATUS status;
914 
915 	if (wlan_vdev_mlme_get_opmode(vdev) != QDF_SAP_MODE)
916 		return QDF_STATUS_SUCCESS;
917 
918 	/* Return from here for 3 link association */
919 	if (WLAN_NUM_TWO_LINK_PSOC != num_partner_links)
920 		return QDF_STATUS_SUCCESS;
921 
922 	ml_dev = vdev->mlo_dev_ctx;
923 	if (!ml_dev)
924 		return QDF_STATUS_E_FAILURE;
925 
926 	for (i = 0; i < WLAN_NUM_TWO_LINK_PSOC; i++)
927 		psoc_ids[i] = wlan_vdev_get_psoc_id(link_vdevs[i]);
928 
929 	status = mlo_chip_adjacent(psoc_ids[0], psoc_ids[1],
930 				   &is_adjacent);
931 	if (QDF_STATUS_SUCCESS != status) {
932 		mlo_err("Unable to get chip adjacency for " QDF_MAC_ADDR_FMT ", psoc_0 %u, psoc_1 %u",
933 			QDF_MAC_ADDR_REF(ml_peer->peer_mld_addr.bytes),
934 			psoc_ids[0], psoc_ids[1]);
935 		return status;
936 	}
937 	if (is_adjacent)
938 		return QDF_STATUS_SUCCESS;
939 	for (i = 0; i < WLAN_UMAC_MLO_MAX_VDEVS; i++) {
940 		ml_vdev = ml_dev->wlan_vdev_list[i];
941 		if (!ml_vdev || (wlan_vdev_is_up(ml_vdev) != QDF_STATUS_SUCCESS))
942 			continue;
943 		comp_psoc_id = wlan_vdev_get_psoc_id(ml_vdev);
944 		if ((comp_psoc_id != psoc_ids[0]) &&
945 		    (comp_psoc_id != psoc_ids[1])) {
946 			bridge_peer_psoc_id = comp_psoc_id;
947 			break;
948 		}
949 	}
950 
951 	if (bridge_peer_psoc_id >= WLAN_OBJMGR_MAX_DEVICES) {
952 		mlo_err("Invalid psoc or psoc not found for " QDF_MAC_ADDR_FMT " psoc %u",
953 			ether_sprintf(ml_peer->peer_mld_addr.bytes),
954 			bridge_peer_psoc_id);
955 		return QDF_STATUS_E_FAILURE;
956 	}
957 
958 	/* Check if derived psoc is adjecent to both links */
959 	for (i = 0; i < WLAN_NUM_TWO_LINK_PSOC; i++) {
960 		status = mlo_chip_adjacent(psoc_ids[i], bridge_peer_psoc_id,
961 					   &is_adjacent);
962 		if (QDF_STATUS_SUCCESS != status) {
963 			mlo_err("Unable to get chip adjacency for " QDF_MAC_ADDR_FMT ", psoc_0 %u, psoc_1 %u",
964 				QDF_MAC_ADDR_REF(ml_peer->peer_mld_addr.bytes),
965 				psoc_ids[i], bridge_peer_psoc_id);
966 			return status;
967 		}
968 		if (!is_adjacent) {
969 			mlo_err("Derived psoc is not adjecent to one of the links for " QDF_MAC_ADDR_FMT ", psoc_0 %u, psoc_1 %u psoc_2 %u",
970 				QDF_MAC_ADDR_REF(ml_peer->peer_mld_addr.bytes),
971 				psoc_ids[0], psoc_ids[1], bridge_peer_psoc_id);
972 			return QDF_STATUS_E_FAILURE;
973 		}
974 	}
975 
976 	/* Assign bridge peer PSOC as primary UMAC */
977 	mlo_peer_overwrite_primary_umac(bridge_peer_psoc_id, ml_peer);
978 	mlo_debug("Creating bridge peer for " QDF_MAC_ADDR_FMT " on psoc %u, is_adjacent %u",
979 		  QDF_MAC_ADDR_REF(ml_peer->peer_mld_addr.bytes),
980 		  bridge_peer_psoc_id, is_adjacent);
981 	/* Create bridge peer */
982 	status = mlo_bridge_peer_create_post(ml_dev, ml_peer,
983 					     bridge_peer_psoc_id);
984 	return status;
985 }
986 #else
987 static QDF_STATUS
988 wlan_mlo_check_and_create_bridge_peer(struct wlan_objmgr_vdev *vdev,
989 				      struct wlan_mlo_peer_context *ml_peer,
990 				      struct wlan_objmgr_vdev *link_vdevs[],
991 				      uint8_t num_partner_links)
992 {
993 	return QDF_STATUS_SUCCESS;
994 }
995 #endif
996 
997 QDF_STATUS wlan_mlo_peer_create(struct wlan_objmgr_vdev *vdev,
998 				struct wlan_objmgr_peer *link_peer,
999 				struct mlo_partner_info *ml_info,
1000 				qdf_nbuf_t frm_buf,
1001 				uint16_t aid)
1002 {
1003 	struct wlan_mlo_dev_context *ml_dev;
1004 	struct wlan_mlo_peer_context *ml_peer = NULL;
1005 	struct wlan_objmgr_vdev *link_vdevs[WLAN_UMAC_MLO_MAX_VDEVS] = { NULL };
1006 	struct wlan_objmgr_vdev *vdev_link;
1007 	QDF_STATUS status;
1008 	uint16_t i;
1009 	struct wlan_objmgr_peer *assoc_peer;
1010 	bool is_ml_peer_attached = false;
1011 
1012 	/* get ML VDEV from VDEV */
1013 	ml_dev = vdev->mlo_dev_ctx;
1014 
1015 	if (!ml_dev) {
1016 		mlo_err("ML dev ctx is NULL");
1017 		return QDF_STATUS_E_NULL_VALUE;
1018 	}
1019 
1020 	/* Check resources of Partner VDEV */
1021 	if (wlan_vdev_mlme_get_opmode(vdev) == QDF_SAP_MODE) {
1022 		if (wlan_mlo_is_mld_ctx_exist(
1023 		    (struct qdf_mac_addr *)&link_peer->mldaddr[0])) {
1024 			mlo_err("MLD ID %d ML Peer " QDF_MAC_ADDR_FMT " is matching with one of the MLD address in the system",
1025 				ml_dev->mld_id,
1026 				QDF_MAC_ADDR_REF(link_peer->mldaddr));
1027 			return QDF_STATUS_E_FAILURE;
1028 		}
1029 		/* Limit max assoc links */
1030 		if (ml_info->num_partner_links > WLAN_UMAC_MLO_ASSOC_MAX_SUPPORTED_LINKS) {
1031 			mlo_err("MLD ID %d ML Peer " QDF_MAC_ADDR_FMT " exceeds MAX assoc limit of %d",
1032 				ml_dev->mld_id,
1033 				QDF_MAC_ADDR_REF(link_peer->mldaddr),
1034 				WLAN_UMAC_MLO_ASSOC_MAX_SUPPORTED_LINKS);
1035 			return QDF_STATUS_E_RESOURCES;
1036 		}
1037 
1038 		status = mlo_dev_get_link_vdevs(vdev, ml_dev,
1039 						ml_info, link_vdevs);
1040 		if (QDF_IS_STATUS_ERROR(status)) {
1041 			mlo_err("MLD ID %d ML Peer " QDF_MAC_ADDR_FMT " get link vdevs failed",
1042 				ml_dev->mld_id,
1043 				QDF_MAC_ADDR_REF(link_peer->mldaddr));
1044 			return QDF_STATUS_E_FAILURE;
1045 		}
1046 
1047 		for (i = 0; i < WLAN_UMAC_MLO_MAX_VDEVS; i++) {
1048 			vdev_link = link_vdevs[i];
1049 			if (!vdev_link) {
1050 				mlo_debug("vdev_link is null");
1051 				continue;
1052 			}
1053 
1054 			if (wlan_vdev_is_mlo_peer_create_allowed(vdev_link)
1055 					!= QDF_STATUS_SUCCESS) {
1056 				mlo_dev_release_link_vdevs(link_vdevs);
1057 
1058 				mlo_err("MLD ID %d ML Peer " QDF_MAC_ADDR_FMT " create not allowed on link vdev %d",
1059 					ml_dev->mld_id,
1060 					QDF_MAC_ADDR_REF
1061 						(link_peer->mldaddr),
1062 					wlan_vdev_get_id(vdev_link));
1063 				return QDF_STATUS_E_INVAL;
1064 			}
1065 		}
1066 
1067 		for (i = 0; i < WLAN_UMAC_MLO_MAX_VDEVS; i++) {
1068 			vdev_link = link_vdevs[i];
1069 			if (vdev_link && (vdev_link != vdev) &&
1070 			    (wlan_vdev_get_peer_count(vdev_link) >
1071 			     wlan_vdev_get_max_peer_count(vdev_link))) {
1072 				mlo_dev_release_link_vdevs(link_vdevs);
1073 				mlo_err("MLD ID %d ML Peer " QDF_MAC_ADDR_FMT " Max peer count reached on link vdev %d",
1074 					ml_dev->mld_id,
1075 					QDF_MAC_ADDR_REF
1076 						(link_peer->mldaddr),
1077 					wlan_vdev_get_id(vdev_link));
1078 				return QDF_STATUS_E_RESOURCES;
1079 			}
1080 		}
1081 	}
1082 	/* When roam to MLO AP, partner link vdev1 is updated first,
1083 	 * ml peer need be created and attached for partner link peer.
1084 	 *
1085 	 * When roam target AP and current AP have same MLD address, don't
1086 	 * delete old ML peer and re-create new one, just update different
1087 	 * info.
1088 	 */
1089 	if (wlan_vdev_mlme_get_opmode(vdev) == QDF_STA_MODE) {
1090 		ml_peer = wlan_mlo_get_mlpeer(ml_dev,
1091 				 (struct qdf_mac_addr *)&link_peer->mldaddr[0]);
1092 		if (ml_peer) {
1093 			mlo_debug("ML Peer " QDF_MAC_ADDR_FMT
1094 				" existed, state %d",
1095 				QDF_MAC_ADDR_REF(ml_peer->peer_mld_addr.bytes),
1096 				ml_peer->mlpeer_state);
1097 			ml_peer->mlpeer_state = ML_PEER_CREATED;
1098 			ml_peer->max_links = ml_info->num_partner_links;
1099 			wlan_mlo_peer_set_t2lm_enable_val(ml_peer, ml_info);
1100 			is_ml_peer_attached = true;
1101 		}
1102 	}
1103 	if (!ml_peer) {
1104 		/* Allocate MLO peer */
1105 		ml_peer = qdf_mem_malloc(sizeof(*ml_peer));
1106 		if (!ml_peer) {
1107 			mlo_err("MLD ID %d ML Peer " QDF_MAC_ADDR_FMT " mem alloc failed",
1108 				ml_dev->mld_id,
1109 				QDF_MAC_ADDR_REF(link_peer->mldaddr));
1110 			mlo_dev_release_link_vdevs(link_vdevs);
1111 			return QDF_STATUS_E_NOMEM;
1112 		}
1113 
1114 		qdf_atomic_init(&ml_peer->ref_cnt);
1115 		mlo_peer_lock_create(ml_peer);
1116 		ml_peer->ml_dev = ml_dev;
1117 		ml_peer->mlpeer_state = ML_PEER_CREATED;
1118 		ml_peer->max_links = ml_info->num_partner_links;
1119 		ml_peer->primary_umac_psoc_id = ML_PRIMARY_UMAC_ID_INVAL;
1120 
1121 		ml_peer->mlo_peer_id = mlo_ap_ml_peerid_alloc();
1122 		if (ml_peer->mlo_peer_id == MLO_INVALID_PEER_ID) {
1123 			mlo_err("MLD ID %d ML Peer " QDF_MAC_ADDR_FMT " invalid ml peer id",
1124 				ml_dev->mld_id,
1125 				QDF_MAC_ADDR_REF
1126 				(ml_peer->peer_mld_addr.bytes));
1127 			mlo_peer_free(ml_peer);
1128 			mlo_dev_release_link_vdevs(link_vdevs);
1129 			return QDF_STATUS_E_RESOURCES;
1130 		}
1131 
1132 		qdf_copy_macaddr((struct qdf_mac_addr *)&ml_peer->peer_mld_addr,
1133 				 (struct qdf_mac_addr *)&link_peer->mldaddr[0]);
1134 		wlan_mlo_peer_set_t2lm_enable_val(ml_peer, ml_info);
1135 
1136 		/* Allocate AID */
1137 		if (wlan_vdev_mlme_get_opmode(vdev) == QDF_SAP_MODE) {
1138 			if (aid == (uint16_t)-1) {
1139 				status = mlo_peer_allocate_aid(ml_dev, ml_peer);
1140 				if (status != QDF_STATUS_SUCCESS) {
1141 					mlo_err("MLD ID %d ML Peer " QDF_MAC_ADDR_FMT " aid alloc failed",
1142 						ml_dev->mld_id,
1143 						QDF_MAC_ADDR_REF
1144 						(ml_peer->peer_mld_addr.bytes));
1145 					mlo_peer_free(ml_peer);
1146 					mlo_dev_release_link_vdevs(link_vdevs);
1147 					return status;
1148 				}
1149 			} else {
1150 				ml_peer->assoc_id = aid;
1151 			}
1152 		}
1153 	}
1154 
1155 	/* Populate Link peer pointer, peer MAC address,
1156 	 * MLD address. HW link ID, update ref count
1157 	 */
1158 	status = mlo_peer_attach_link_peer(ml_peer, link_peer, NULL);
1159 	if (QDF_IS_STATUS_ERROR(status)) {
1160 		mlo_err("MLD ID %d ML Peer " QDF_MAC_ADDR_FMT " link peer attach failed",
1161 			ml_dev->mld_id,
1162 			QDF_MAC_ADDR_REF
1163 			(ml_peer->peer_mld_addr.bytes));
1164 		/* If there is another link peer attached for this ML peer,
1165 		 * ml peer can't be detached and freed.
1166 		 */
1167 		if (is_ml_peer_attached && ml_peer->link_peer_cnt)
1168 			return status;
1169 		if (is_ml_peer_attached)
1170 			mlo_dev_mlpeer_detach(ml_dev, ml_peer);
1171 		mlo_peer_free(ml_peer);
1172 		mlo_dev_release_link_vdevs(link_vdevs);
1173 		return status;
1174 	}
1175 
1176 	/* Allocate Primary UMAC */
1177 	mlo_peer_allocate_primary_umac(ml_dev, ml_peer, link_vdevs);
1178 
1179 	/* Store AID, MLO Peer pointer in link peer, take link peer ref count */
1180 	mlo_peer_populate_link_peer(ml_peer, link_peer);
1181 
1182 	mlo_peer_populate_nawds_params(ml_peer, ml_info);
1183 	mlo_peer_populate_mesh_params(ml_peer, ml_info);
1184 
1185 	if ((wlan_vdev_mlme_get_opmode(vdev) == QDF_SAP_MODE) ||
1186 		((wlan_vdev_mlme_get_opmode(vdev) == QDF_STA_MODE) &&
1187 			!is_ml_peer_attached)) {
1188 		/* Reject creation for AP mode, If ML peer is present with
1189 		 * MLD MAC address, For PSTA case, all MLD STAs are connected
1190 		 * to same MLD AP, it can have duplicate MLD address entries
1191 		 * for STA MLDs
1192 		 */
1193 		if ((wlan_vdev_mlme_get_opmode(vdev) == QDF_SAP_MODE) &&
1194 		    mlo_mgr_ml_peer_exist_on_diff_ml_ctx(&link_peer->mldaddr[0],
1195 							 NULL)) {
1196 			mlo_reset_link_peer(ml_peer, link_peer);
1197 			mlo_peer_free(ml_peer);
1198 			mlo_dev_release_link_vdevs(link_vdevs);
1199 			wlan_objmgr_peer_release_ref(link_peer,
1200 						     WLAN_MLO_MGR_ID);
1201 			mlo_err("MLD ID %d ML Peer " QDF_MAC_ADDR_FMT " is exists, creation failed",
1202 				ml_dev->mld_id,
1203 				QDF_MAC_ADDR_REF(ml_peer->peer_mld_addr.bytes));
1204 			return QDF_STATUS_E_EXISTS;
1205 		}
1206 
1207 		/* Attach MLO peer to ML Peer table */
1208 		status = mlo_dev_mlpeer_attach(ml_dev, ml_peer);
1209 		if (status != QDF_STATUS_SUCCESS) {
1210 			mlo_err("MLD ID %d ML Peer " QDF_MAC_ADDR_FMT " attach failed",
1211 				ml_dev->mld_id,
1212 				QDF_MAC_ADDR_REF(ml_peer->peer_mld_addr.bytes));
1213 			mlo_reset_link_peer(ml_peer, link_peer);
1214 			wlan_objmgr_peer_release_ref(link_peer,
1215 						     WLAN_MLO_MGR_ID);
1216 			mlo_peer_free(ml_peer);
1217 			mlo_dev_release_link_vdevs(link_vdevs);
1218 			return status;
1219 		}
1220 	}
1221 
1222 	wlan_mlo_peer_get_ref(ml_peer);
1223 
1224 	if (wlan_vdev_mlme_get_opmode(vdev) == QDF_SAP_MODE) {
1225 		/* Notify other vdevs about link peer creation */
1226 		for (i = 0; i < WLAN_UMAC_MLO_MAX_VDEVS; i++) {
1227 			vdev_link = link_vdevs[i];
1228 			if (!vdev_link)
1229 				continue;
1230 
1231 			if (vdev_link == vdev)
1232 				continue;
1233 
1234 			mlo_partner_peer_create_post(ml_dev, vdev_link,
1235 						     ml_peer, frm_buf, ml_info);
1236 		}
1237 		status = wlan_mlo_check_and_create_bridge_peer(vdev, ml_peer,
1238 							       link_vdevs,
1239 							       ml_info->num_partner_links);
1240 		if (QDF_STATUS_SUCCESS != status) {
1241 			mlo_err("MLD ID %d: Bridge peer creation failed",
1242 				ml_dev->mld_id);
1243 			wlan_mlo_partner_peer_create_failed_notify(ml_peer);
1244 			mlo_dev_release_link_vdevs(link_vdevs);
1245 			wlan_mlo_peer_release_ref(ml_peer);
1246 			return QDF_STATUS_E_FAILURE;
1247 		}
1248 	}
1249 	mlo_dev_release_link_vdevs(link_vdevs);
1250 
1251 	if (ml_peer->mlpeer_state == ML_PEER_DISCONN_INITIATED) {
1252 		mlo_info("MLD ID %d ML Peer " QDF_MAC_ADDR_FMT " allocation failed",
1253 			 ml_dev->mld_id,
1254 			 QDF_MAC_ADDR_REF(ml_peer->peer_mld_addr.bytes));
1255 		wlan_mlo_peer_release_ref(ml_peer);
1256 		return QDF_STATUS_E_FAILURE;
1257 	}
1258 
1259 	mlo_info("MLD ID %d ML Peer " QDF_MAC_ADDR_FMT " allocated %pK",
1260 		 ml_dev->mld_id,
1261 		 QDF_MAC_ADDR_REF(ml_peer->peer_mld_addr.bytes),
1262 		 ml_peer);
1263 
1264 	/*
1265 	 * wlan_mlo_peer_create() is trigggered after getting peer
1266 	 * assoc confirm from FW. For single link MLO connection, it is
1267 	 * OK to trigger assoc response from here.
1268 	 */
1269 	if ((wlan_vdev_mlme_get_opmode(vdev) == QDF_SAP_MODE) &&
1270 	    (!wlan_mlo_peer_is_nawds(ml_peer))) {
1271 		if ((ml_peer->max_links == 1) &&
1272 		    (ml_peer->link_peer_cnt == 1)) {
1273 			assoc_peer = ml_peer->peer_list[0].link_peer;
1274 			if (assoc_peer)
1275 				mlo_mlme_peer_assoc_resp(assoc_peer);
1276 		}
1277 	}
1278 
1279 	wlan_mlo_peer_release_ref(ml_peer);
1280 
1281 	return QDF_STATUS_SUCCESS;
1282 }
1283 
1284 QDF_STATUS wlan_mlo_link_peer_attach(struct wlan_mlo_peer_context *ml_peer,
1285 				     struct wlan_objmgr_peer *peer,
1286 				     qdf_nbuf_t frm_buf)
1287 {
1288 	QDF_STATUS status;
1289 	struct wlan_objmgr_peer *assoc_peer;
1290 	struct wlan_objmgr_vdev *vdev = NULL;
1291 
1292 	if (!ml_peer)
1293 		return QDF_STATUS_E_FAILURE;
1294 
1295 	vdev = wlan_peer_get_vdev(peer);
1296 	if (!vdev)
1297 		return QDF_STATUS_E_FAILURE;
1298 
1299 	/* Populate Link peer pointer, peer MAC address,
1300 	 * MLD address. HW link ID, update ref count
1301 	 */
1302 	status = mlo_peer_attach_link_peer(ml_peer, peer, frm_buf);
1303 	if (QDF_IS_STATUS_ERROR(status))
1304 		return status;
1305 
1306 	/* Store AID, MLO Peer pointer in link peer, take link peer ref count */
1307 	mlo_peer_populate_link_peer(ml_peer, peer);
1308 
1309 	if (wlan_vdev_mlme_get_opmode(vdev) == QDF_SAP_MODE) {
1310 		if (ml_peer->max_links == ml_peer->link_peer_cnt) {
1311 			assoc_peer = ml_peer->peer_list[0].link_peer;
1312 			if (assoc_peer)
1313 				mlo_mlme_peer_assoc_resp(assoc_peer);
1314 		}
1315 	}
1316 
1317 	return status;
1318 }
1319 
1320 QDF_STATUS wlan_mlo_link_peer_delete(struct wlan_objmgr_peer *peer)
1321 {
1322 	struct wlan_mlo_peer_context *ml_peer;
1323 
1324 	ml_peer = peer->mlo_peer_ctx;
1325 
1326 	if (!ml_peer)
1327 		return QDF_STATUS_E_NOENT;
1328 
1329 	mlo_reset_link_peer(ml_peer, peer);
1330 	mlo_peer_detach_link_peer(ml_peer, peer);
1331 	wlan_mlo_peer_release_ref(ml_peer);
1332 
1333 	return QDF_STATUS_SUCCESS;
1334 }
1335 
1336 qdf_export_symbol(wlan_mlo_link_peer_delete);
1337 
1338 qdf_nbuf_t mlo_peer_get_link_peer_assoc_req_buf(
1339 			struct wlan_mlo_peer_context *ml_peer,
1340 			uint8_t link_ix)
1341 {
1342 	struct wlan_objmgr_peer *peer = NULL;
1343 	qdf_nbuf_t assocbuf = NULL;
1344 
1345 	if (!ml_peer)
1346 		return NULL;
1347 
1348 	peer = wlan_mlo_peer_get_assoc_peer(ml_peer);
1349 	if (!peer)
1350 		return NULL;
1351 
1352 	assocbuf = mlo_mlme_get_link_assoc_req(peer, link_ix);
1353 
1354 	return assocbuf;
1355 }
1356 
1357 void wlan_mlo_peer_get_links_info(struct wlan_objmgr_peer *peer,
1358 				  struct mlo_tgt_partner_info *ml_links)
1359 {
1360 	struct wlan_mlo_peer_context *ml_peer;
1361 	struct wlan_mlo_link_peer_entry *peer_entry;
1362 	struct wlan_objmgr_peer *link_peer;
1363 	struct wlan_objmgr_vdev *link_vdev;
1364 	uint8_t i, ix, idx = 0;
1365 	struct wlan_mlo_eml_cap *ml_emlcap;
1366 
1367 	ml_peer = peer->mlo_peer_ctx;
1368 	ml_links->num_partner_links = 0;
1369 
1370 	if (!ml_peer)
1371 		return;
1372 
1373 	ml_emlcap = &ml_peer->mlpeer_emlcap;
1374 
1375 	mlo_peer_lock_acquire(ml_peer);
1376 
1377 	if ((ml_peer->mlpeer_state != ML_PEER_CREATED) &&
1378 	    (ml_peer->mlpeer_state != ML_PEER_ASSOC_DONE)) {
1379 		mlo_peer_lock_release(ml_peer);
1380 		return;
1381 	}
1382 
1383 	for (i = 0; i < MAX_MLO_LINK_PEERS; i++) {
1384 		peer_entry = &ml_peer->peer_list[i];
1385 		link_peer = peer_entry->link_peer;
1386 
1387 		if (!link_peer)
1388 			continue;
1389 		idx++;
1390 		if (link_peer == peer)
1391 			continue;
1392 		link_vdev = wlan_peer_get_vdev(link_peer);
1393 		if (!link_vdev)
1394 			continue;
1395 
1396 		if (ml_links->num_partner_links >= WLAN_UMAC_MLO_MAX_VDEVS)
1397 			break;
1398 
1399 		ix = ml_links->num_partner_links;
1400 		ml_links->link_info[ix].vdev_id = wlan_vdev_get_id(link_vdev);
1401 		ml_links->link_info[ix].hw_mld_link_id = peer_entry->hw_link_id;
1402 		ml_links->link_info[ix].mlo_enabled = 1;
1403 		ml_links->link_info[ix].mlo_assoc_link =
1404 			wlan_peer_mlme_is_assoc_peer(link_peer);
1405 		ml_links->link_info[ix].mlo_primary_umac =
1406 			peer_entry->is_primary;
1407 		ml_links->link_info[ix].mlo_logical_link_index_valid = 1;
1408 		ml_links->link_info[ix].emlsr_support = ml_emlcap->emlsr_supp;
1409 		ml_links->link_info[ix].logical_link_index = idx - 1;
1410 		ml_links->num_partner_links++;
1411 	}
1412 	mlo_peer_lock_release(ml_peer);
1413 }
1414 
1415 qdf_export_symbol(wlan_mlo_peer_get_links_info);
1416 
1417 uint8_t wlan_mlo_peer_get_primary_peer_link_id(struct wlan_objmgr_peer *peer)
1418 {
1419 	struct wlan_mlo_peer_context *ml_peer;
1420 	struct wlan_mlo_link_peer_entry *peer_entry;
1421 	struct wlan_objmgr_peer *link_peer;
1422 	struct wlan_objmgr_vdev *link_vdev;
1423 	uint8_t i, vdev_link_id;
1424 
1425 	ml_peer = peer->mlo_peer_ctx;
1426 
1427 	if (!ml_peer) {
1428 		mlo_err("ml_peer is null");
1429 		return WLAN_LINK_ID_INVALID;
1430 	}
1431 	mlo_peer_lock_acquire(ml_peer);
1432 
1433 	if ((ml_peer->mlpeer_state != ML_PEER_CREATED) &&
1434 	    (ml_peer->mlpeer_state != ML_PEER_ASSOC_DONE)) {
1435 		mlo_peer_lock_release(ml_peer);
1436 		mlo_err("ml_peer is not created and association is not done");
1437 		return WLAN_LINK_ID_INVALID;
1438 	}
1439 
1440 	for (i = 0; i < MAX_MLO_LINK_PEERS; i++) {
1441 		peer_entry = &ml_peer->peer_list[i];
1442 		link_peer = peer_entry->link_peer;
1443 		if (!link_peer)
1444 			continue;
1445 
1446 		if (peer_entry->is_primary) {
1447 			link_vdev = wlan_peer_get_vdev(link_peer);
1448 			if (!link_vdev) {
1449 				mlo_peer_lock_release(ml_peer);
1450 				mlo_err("link vdev not found");
1451 				return WLAN_LINK_ID_INVALID;
1452 			}
1453 			vdev_link_id = wlan_vdev_get_link_id(link_vdev);
1454 			mlo_peer_lock_release(ml_peer);
1455 			return vdev_link_id;
1456 		}
1457 	}
1458 	mlo_peer_lock_release(ml_peer);
1459 	mlo_err("None of the peer is designated as primary");
1460 	return WLAN_LINK_ID_INVALID;
1461 }
1462 
1463 qdf_export_symbol(wlan_mlo_peer_get_primary_peer_link_id);
1464 
1465 void wlan_mlo_peer_get_partner_links_info(struct wlan_objmgr_peer *peer,
1466 					  struct mlo_partner_info *ml_links)
1467 {
1468 	struct wlan_mlo_peer_context *ml_peer;
1469 	struct wlan_mlo_link_peer_entry *peer_entry;
1470 	struct wlan_objmgr_peer *link_peer;
1471 	struct wlan_objmgr_vdev *link_vdev;
1472 	uint8_t i, ix;
1473 
1474 	ml_peer = peer->mlo_peer_ctx;
1475 	ml_links->num_partner_links = 0;
1476 
1477 	if (!ml_peer)
1478 		return;
1479 
1480 	mlo_peer_lock_acquire(ml_peer);
1481 
1482 	if ((ml_peer->mlpeer_state != ML_PEER_CREATED) &&
1483 	    (ml_peer->mlpeer_state != ML_PEER_ASSOC_DONE)) {
1484 		mlo_peer_lock_release(ml_peer);
1485 		return;
1486 	}
1487 
1488 	for (i = 0; i < MAX_MLO_LINK_PEERS; i++) {
1489 		peer_entry = &ml_peer->peer_list[i];
1490 		link_peer = peer_entry->link_peer;
1491 
1492 		if (!link_peer)
1493 			continue;
1494 
1495 		if (link_peer == peer)
1496 			continue;
1497 
1498 		link_vdev = wlan_peer_get_vdev(link_peer);
1499 		if (!link_vdev)
1500 			continue;
1501 
1502 		if (ml_links->num_partner_links >= WLAN_UMAC_MLO_MAX_VDEVS)
1503 			break;
1504 
1505 		ix = ml_links->num_partner_links;
1506 		ml_links->partner_link_info[ix].link_id = peer_entry->link_ix;
1507 		ml_links->partner_link_info[ix].is_bridge =
1508 		   (wlan_peer_get_peer_type(link_peer) == WLAN_PEER_MLO_BRIDGE);
1509 
1510 		qdf_copy_macaddr(&ml_links->partner_link_info[ix].link_addr,
1511 				 &peer_entry->link_addr);
1512 		ml_links->num_partner_links++;
1513 	}
1514 	mlo_peer_lock_release(ml_peer);
1515 }
1516 
1517 qdf_export_symbol(wlan_mlo_peer_get_partner_links_info);
1518 
1519 #ifdef UMAC_SUPPORT_MLNAWDS
1520 bool wlan_mlo_peer_is_nawds(struct wlan_mlo_peer_context *ml_peer)
1521 {
1522 	bool status = false;
1523 
1524 	if (!ml_peer)
1525 		return status;
1526 
1527 	mlo_peer_lock_acquire(ml_peer);
1528 	if (ml_peer->is_nawds_ml_peer)
1529 		status = true;
1530 	mlo_peer_lock_release(ml_peer);
1531 
1532 	return status;
1533 }
1534 
1535 qdf_export_symbol(wlan_mlo_peer_is_nawds);
1536 #endif
1537 
1538 #ifdef MESH_MODE_SUPPORT
1539 bool wlan_mlo_peer_is_mesh(struct wlan_mlo_peer_context *ml_peer)
1540 {
1541 	bool status = false;
1542 
1543 	if (!ml_peer)
1544 		return status;
1545 
1546 	mlo_peer_lock_acquire(ml_peer);
1547 	if (ml_peer->is_mesh_ml_peer)
1548 		status = true;
1549 	mlo_peer_lock_release(ml_peer);
1550 
1551 	return status;
1552 }
1553 
1554 qdf_export_symbol(wlan_mlo_peer_is_mesh);
1555 #endif
1556 
1557 #ifdef UMAC_MLO_AUTH_DEFER
1558 void mlo_peer_free_auth_param(struct mlpeer_auth_params *auth_params)
1559 {
1560 	if (auth_params->rs)
1561 		qdf_mem_free(auth_params->rs);
1562 
1563 	if (auth_params->wbuf)
1564 		qdf_nbuf_free(auth_params->wbuf);
1565 
1566 	qdf_mem_free(auth_params);
1567 }
1568 
1569 QDF_STATUS mlo_peer_link_auth_defer(struct wlan_mlo_peer_context *ml_peer,
1570 				    struct qdf_mac_addr *link_mac,
1571 				    struct mlpeer_auth_params *auth_params)
1572 {
1573 	uint8_t i;
1574 	uint8_t free_entries = 0;
1575 	struct mlpeer_auth_params *recv_auth;
1576 	QDF_STATUS status = QDF_STATUS_E_FAILURE;
1577 
1578 	if (!ml_peer)
1579 		return status;
1580 
1581 	mlo_peer_lock_acquire(ml_peer);
1582 	for (i = 0; i < MAX_MLO_LINK_PEERS; i++) {
1583 		recv_auth = ml_peer->pending_auth[i];
1584 		if (!recv_auth) {
1585 			free_entries++;
1586 			continue;
1587 		}
1588 		/* overwrite the entry with latest entry */
1589 		if (qdf_is_macaddr_equal(link_mac, &recv_auth->link_addr)) {
1590 			mlo_peer_free_auth_param(recv_auth);
1591 			ml_peer->pending_auth[i] = auth_params;
1592 			mlo_peer_lock_release(ml_peer);
1593 
1594 			return QDF_STATUS_SUCCESS;
1595 		}
1596 	}
1597 
1598 	if (!free_entries) {
1599 		mlo_peer_lock_release(ml_peer);
1600 		return QDF_STATUS_E_FAILURE;
1601 	}
1602 
1603 	for (i = 0; i < MAX_MLO_LINK_PEERS; i++) {
1604 		recv_auth = ml_peer->pending_auth[i];
1605 		if (!recv_auth) {
1606 			ml_peer->pending_auth[i] = auth_params;
1607 			status = QDF_STATUS_SUCCESS;
1608 			break;
1609 		}
1610 	}
1611 	mlo_peer_lock_release(ml_peer);
1612 
1613 	return status;
1614 }
1615 
1616 bool wlan_mlo_partner_peer_delete_is_allowed(struct wlan_objmgr_peer *src_peer)
1617 {
1618 	struct wlan_objmgr_vdev *vdev = NULL;
1619 	struct wlan_mlo_peer_context *ml_peer;
1620 
1621 	vdev = wlan_peer_get_vdev(src_peer);
1622 	if (!vdev)
1623 		return false;
1624 
1625 	ml_peer = src_peer->mlo_peer_ctx;
1626 	if (!wlan_peer_is_mlo(src_peer) || !ml_peer)
1627 		return false;
1628 
1629 	if (wlan_vdev_mlme_op_flags_get(vdev, WLAN_VDEV_OP_MLO_STOP_LINK_DEL) ||
1630 	    wlan_vdev_mlme_op_flags_get(vdev,
1631 					WLAN_VDEV_OP_MLO_LINK_TBTT_COMPLETE)) {
1632 		/* Single LINK MLO connection */
1633 		if (ml_peer->link_peer_cnt == 1)
1634 			return false;
1635 		/*
1636 		 * If this link is primary TQM, then delete MLO connection till
1637 		 * primary umac migration is implemented
1638 		 */
1639 		if (wlan_mlo_peer_get_primary_peer_link_id(src_peer) !=
1640 			wlan_vdev_get_link_id(vdev))
1641 			return false;
1642 	}
1643 
1644 	return true;
1645 }
1646 #endif
1647