xref: /wlan-driver/qca-wifi-host-cmn/umac/mlo_mgr/src/wlan_mlo_mgr_peer.c (revision 5113495b16420b49004c444715d2daae2066e7dc)
1*5113495bSYour Name /*
2*5113495bSYour Name  * Copyright (c) 2021, The Linux Foundation. All rights reserved.
3*5113495bSYour Name  * Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved.
4*5113495bSYour Name  *
5*5113495bSYour Name  * Permission to use, copy, modify, and/or distribute this software for any
6*5113495bSYour Name  * purpose with or without fee is hereby granted, provided that the above
7*5113495bSYour Name  * copyright notice and this permission notice appear in all copies.
8*5113495bSYour Name  *
9*5113495bSYour Name  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10*5113495bSYour Name  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11*5113495bSYour Name  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12*5113495bSYour Name  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13*5113495bSYour Name  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14*5113495bSYour Name  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15*5113495bSYour Name  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16*5113495bSYour Name  */
17*5113495bSYour Name 
18*5113495bSYour Name #include "wlan_mlo_mgr_main.h"
19*5113495bSYour Name #include "qdf_module.h"
20*5113495bSYour Name #include "qdf_types.h"
21*5113495bSYour Name #include "wlan_cmn.h"
22*5113495bSYour Name #include "wlan_mlo_mgr_msgq.h"
23*5113495bSYour Name #include "wlan_objmgr_peer_obj.h"
24*5113495bSYour Name #include "wlan_mlo_mgr_peer.h"
25*5113495bSYour Name #include "wlan_mlo_mgr_ap.h"
26*5113495bSYour Name #include "wlan_crypto_global_api.h"
27*5113495bSYour Name #include "wlan_mlo_mgr_setup.h"
28*5113495bSYour Name #include "wlan_utility.h"
29*5113495bSYour Name #include "wlan_mlo_epcs.h"
30*5113495bSYour Name 
mlo_partner_peer_create_post(struct wlan_mlo_dev_context * ml_dev,struct wlan_objmgr_vdev * vdev_link,struct wlan_mlo_peer_context * ml_peer,qdf_nbuf_t frm_buf,struct mlo_partner_info * ml_info)31*5113495bSYour Name static void mlo_partner_peer_create_post(struct wlan_mlo_dev_context *ml_dev,
32*5113495bSYour Name 					 struct wlan_objmgr_vdev *vdev_link,
33*5113495bSYour Name 					 struct wlan_mlo_peer_context *ml_peer,
34*5113495bSYour Name 					 qdf_nbuf_t frm_buf,
35*5113495bSYour Name 					 struct mlo_partner_info *ml_info)
36*5113495bSYour Name {
37*5113495bSYour Name 	struct peer_create_notif_s peer_create;
38*5113495bSYour Name 	QDF_STATUS status;
39*5113495bSYour Name 	uint8_t i;
40*5113495bSYour Name 	uint8_t link_id;
41*5113495bSYour Name 
42*5113495bSYour Name 	if (wlan_objmgr_vdev_try_get_ref(vdev_link, WLAN_MLO_MGR_ID) ==
43*5113495bSYour Name 							QDF_STATUS_SUCCESS) {
44*5113495bSYour Name 		peer_create.vdev_link = vdev_link;
45*5113495bSYour Name 	} else {
46*5113495bSYour Name 		mlo_err("VDEV is not in created state");
47*5113495bSYour Name 		return;
48*5113495bSYour Name 	}
49*5113495bSYour Name 
50*5113495bSYour Name 	wlan_mlo_peer_get_ref(ml_peer);
51*5113495bSYour Name 	peer_create.ml_peer = ml_peer;
52*5113495bSYour Name 	link_id = wlan_vdev_get_link_id(vdev_link);
53*5113495bSYour Name 	for (i = 0; i < ml_info->num_partner_links; i++) {
54*5113495bSYour Name 		if (link_id != ml_info->partner_link_info[i].link_id)
55*5113495bSYour Name 			continue;
56*5113495bSYour Name 
57*5113495bSYour Name 		qdf_copy_macaddr(&peer_create.addr,
58*5113495bSYour Name 				 &ml_info->partner_link_info[i].link_addr);
59*5113495bSYour Name 		break;
60*5113495bSYour Name 	}
61*5113495bSYour Name 
62*5113495bSYour Name 	status = mlo_peer_create_get_frm_buf(ml_peer, &peer_create, frm_buf);
63*5113495bSYour Name 
64*5113495bSYour Name 	if (QDF_IS_STATUS_ERROR(status)) {
65*5113495bSYour Name 		wlan_mlo_peer_release_ref(ml_peer);
66*5113495bSYour Name 		wlan_objmgr_vdev_release_ref(vdev_link, WLAN_MLO_MGR_ID);
67*5113495bSYour Name 		mlo_err("nbuf clone is failed");
68*5113495bSYour Name 		return;
69*5113495bSYour Name 	}
70*5113495bSYour Name 
71*5113495bSYour Name 	status = mlo_msgq_post(MLO_PEER_CREATE, ml_dev, &peer_create);
72*5113495bSYour Name 	if (status != QDF_STATUS_SUCCESS) {
73*5113495bSYour Name 		qdf_nbuf_free(frm_buf);
74*5113495bSYour Name 		wlan_mlo_peer_release_ref(ml_peer);
75*5113495bSYour Name 		wlan_objmgr_vdev_release_ref(vdev_link, WLAN_MLO_MGR_ID);
76*5113495bSYour Name 	}
77*5113495bSYour Name }
78*5113495bSYour Name 
mlo_partner_peer_reassoc_post(struct wlan_mlo_dev_context * ml_dev,struct wlan_objmgr_vdev * vdev_link,struct wlan_mlo_peer_context * ml_peer,qdf_nbuf_t frm_buf,struct mlo_partner_info * ml_info)79*5113495bSYour Name static void mlo_partner_peer_reassoc_post(struct wlan_mlo_dev_context *ml_dev,
80*5113495bSYour Name 					  struct wlan_objmgr_vdev *vdev_link,
81*5113495bSYour Name 					  struct wlan_mlo_peer_context *ml_peer,
82*5113495bSYour Name 					  qdf_nbuf_t frm_buf,
83*5113495bSYour Name 					  struct mlo_partner_info *ml_info)
84*5113495bSYour Name {
85*5113495bSYour Name 	struct peer_create_notif_s peer_create;
86*5113495bSYour Name 	QDF_STATUS status;
87*5113495bSYour Name 	uint8_t i;
88*5113495bSYour Name 	uint8_t link_id;
89*5113495bSYour Name 
90*5113495bSYour Name 	if (wlan_objmgr_vdev_try_get_ref(vdev_link, WLAN_MLO_MGR_ID) ==
91*5113495bSYour Name 							QDF_STATUS_SUCCESS) {
92*5113495bSYour Name 		peer_create.vdev_link = vdev_link;
93*5113495bSYour Name 	} else {
94*5113495bSYour Name 		mlo_err("VDEV is not in created state");
95*5113495bSYour Name 		return;
96*5113495bSYour Name 	}
97*5113495bSYour Name 
98*5113495bSYour Name 	wlan_mlo_peer_get_ref(ml_peer);
99*5113495bSYour Name 	peer_create.ml_peer = ml_peer;
100*5113495bSYour Name 	link_id = wlan_vdev_get_link_id(vdev_link);
101*5113495bSYour Name 	for (i = 0; i < ml_info->num_partner_links; i++) {
102*5113495bSYour Name 		if (link_id != ml_info->partner_link_info[i].link_id)
103*5113495bSYour Name 			continue;
104*5113495bSYour Name 
105*5113495bSYour Name 		qdf_copy_macaddr(&peer_create.addr,
106*5113495bSYour Name 				 &ml_info->partner_link_info[i].link_addr);
107*5113495bSYour Name 		break;
108*5113495bSYour Name 	}
109*5113495bSYour Name 
110*5113495bSYour Name 	status = mlo_peer_create_get_frm_buf(ml_peer, &peer_create, frm_buf);
111*5113495bSYour Name 
112*5113495bSYour Name 	if (QDF_IS_STATUS_ERROR(status)) {
113*5113495bSYour Name 		wlan_mlo_peer_release_ref(ml_peer);
114*5113495bSYour Name 		wlan_objmgr_vdev_release_ref(vdev_link, WLAN_MLO_MGR_ID);
115*5113495bSYour Name 		mlo_err("nbuf clone is failed");
116*5113495bSYour Name 		return;
117*5113495bSYour Name 	}
118*5113495bSYour Name 
119*5113495bSYour Name 	status = mlo_msgq_post(MLO_PEER_REASSOC, ml_dev, &peer_create);
120*5113495bSYour Name 	if (status != QDF_STATUS_SUCCESS) {
121*5113495bSYour Name 		qdf_nbuf_free(frm_buf);
122*5113495bSYour Name 		wlan_mlo_peer_release_ref(ml_peer);
123*5113495bSYour Name 		wlan_objmgr_vdev_release_ref(vdev_link, WLAN_MLO_MGR_ID);
124*5113495bSYour Name 	}
125*5113495bSYour Name }
126*5113495bSYour Name 
mlo_link_peer_assoc_notify(struct wlan_mlo_dev_context * ml_dev,struct wlan_objmgr_peer * peer)127*5113495bSYour Name static void mlo_link_peer_assoc_notify(struct wlan_mlo_dev_context *ml_dev,
128*5113495bSYour Name 				       struct wlan_objmgr_peer *peer)
129*5113495bSYour Name {
130*5113495bSYour Name 	struct peer_assoc_notify_s peer_assoc;
131*5113495bSYour Name 	QDF_STATUS status;
132*5113495bSYour Name 
133*5113495bSYour Name 	peer_assoc.peer = peer;
134*5113495bSYour Name 	status = mlo_msgq_post(MLO_PEER_ASSOC, ml_dev, &peer_assoc);
135*5113495bSYour Name 	if (status != QDF_STATUS_SUCCESS)
136*5113495bSYour Name 		wlan_objmgr_peer_release_ref(peer, WLAN_MLO_MGR_ID);
137*5113495bSYour Name }
138*5113495bSYour Name 
mlo_link_peer_send_assoc_fail(struct wlan_mlo_dev_context * ml_dev,struct wlan_objmgr_peer * peer)139*5113495bSYour Name static void mlo_link_peer_send_assoc_fail(struct wlan_mlo_dev_context *ml_dev,
140*5113495bSYour Name 					  struct wlan_objmgr_peer *peer)
141*5113495bSYour Name {
142*5113495bSYour Name 	struct peer_assoc_fail_notify_s peer_assoc_fail;
143*5113495bSYour Name 	QDF_STATUS status;
144*5113495bSYour Name 
145*5113495bSYour Name 	peer_assoc_fail.peer = peer;
146*5113495bSYour Name 	status = mlo_msgq_post(MLO_PEER_ASSOC_FAIL, ml_dev, &peer_assoc_fail);
147*5113495bSYour Name 	if (status != QDF_STATUS_SUCCESS)
148*5113495bSYour Name 		wlan_objmgr_peer_release_ref(peer, WLAN_MLO_MGR_ID);
149*5113495bSYour Name }
150*5113495bSYour Name 
mlo_link_peer_disconnect_notify(struct wlan_mlo_dev_context * ml_dev,struct wlan_objmgr_peer * peer)151*5113495bSYour Name static void mlo_link_peer_disconnect_notify(struct wlan_mlo_dev_context *ml_dev,
152*5113495bSYour Name 					    struct wlan_objmgr_peer *peer)
153*5113495bSYour Name {
154*5113495bSYour Name 	struct peer_discon_notify_s peer_disconn;
155*5113495bSYour Name 	QDF_STATUS status;
156*5113495bSYour Name 	struct wlan_objmgr_vdev *vdev;
157*5113495bSYour Name 	enum QDF_OPMODE opmode;
158*5113495bSYour Name 
159*5113495bSYour Name 	vdev = wlan_peer_get_vdev(peer);
160*5113495bSYour Name 	opmode = wlan_vdev_mlme_get_opmode(vdev);
161*5113495bSYour Name 
162*5113495bSYour Name 	if (opmode == QDF_SAP_MODE) {
163*5113495bSYour Name 		peer_disconn.peer = peer;
164*5113495bSYour Name 		status = mlo_msgq_post(MLO_PEER_DISCONNECT, ml_dev,
165*5113495bSYour Name 				       &peer_disconn);
166*5113495bSYour Name 		if (status != QDF_STATUS_SUCCESS)
167*5113495bSYour Name 			wlan_objmgr_peer_release_ref(peer, WLAN_MLO_MGR_ID);
168*5113495bSYour Name 	} else {
169*5113495bSYour Name 		wlan_objmgr_peer_release_ref(peer, WLAN_MLO_MGR_ID);
170*5113495bSYour Name 	}
171*5113495bSYour Name }
172*5113495bSYour Name 
mlo_link_peer_deauth_init(struct wlan_mlo_dev_context * ml_dev,struct wlan_objmgr_peer * peer,uint8_t is_disassoc)173*5113495bSYour Name static void mlo_link_peer_deauth_init(struct wlan_mlo_dev_context *ml_dev,
174*5113495bSYour Name 				      struct wlan_objmgr_peer *peer,
175*5113495bSYour Name 				      uint8_t is_disassoc)
176*5113495bSYour Name {
177*5113495bSYour Name 	struct peer_deauth_notify_s peer_deauth;
178*5113495bSYour Name 	QDF_STATUS status;
179*5113495bSYour Name 
180*5113495bSYour Name 	peer_deauth.peer = peer;
181*5113495bSYour Name 	peer_deauth.is_disassoc = is_disassoc;
182*5113495bSYour Name 	status = mlo_msgq_post(MLO_PEER_DEAUTH, ml_dev, &peer_deauth);
183*5113495bSYour Name 	if (status != QDF_STATUS_SUCCESS)
184*5113495bSYour Name 		wlan_objmgr_peer_release_ref(peer, WLAN_MLO_MGR_ID);
185*5113495bSYour Name }
186*5113495bSYour Name 
187*5113495bSYour Name #ifdef UMAC_MLO_AUTH_DEFER
mlo_peer_process_pending_auth(struct wlan_mlo_dev_context * ml_dev,struct wlan_mlo_peer_context * ml_peer)188*5113495bSYour Name static void mlo_peer_process_pending_auth(struct wlan_mlo_dev_context *ml_dev,
189*5113495bSYour Name 					  struct wlan_mlo_peer_context *ml_peer)
190*5113495bSYour Name {
191*5113495bSYour Name 	struct peer_auth_process_notif_s peer_auth;
192*5113495bSYour Name 	struct mlpeer_auth_params *recv_auth;
193*5113495bSYour Name 	uint8_t i;
194*5113495bSYour Name 	QDF_STATUS status;
195*5113495bSYour Name 
196*5113495bSYour Name 	for (i = 0; i < MAX_MLO_LINK_PEERS; i++) {
197*5113495bSYour Name 		mlo_peer_lock_acquire(ml_peer);
198*5113495bSYour Name 		recv_auth = ml_peer->pending_auth[i];
199*5113495bSYour Name 		if (!recv_auth) {
200*5113495bSYour Name 			mlo_peer_lock_release(ml_peer);
201*5113495bSYour Name 			continue;
202*5113495bSYour Name 		}
203*5113495bSYour Name 		peer_auth.auth_params = recv_auth;
204*5113495bSYour Name 		ml_peer->pending_auth[i] = NULL;
205*5113495bSYour Name 
206*5113495bSYour Name 		mlo_peer_lock_release(ml_peer);
207*5113495bSYour Name 
208*5113495bSYour Name 		status = mlo_msgq_post(MLO_PEER_PENDING_AUTH, ml_dev,
209*5113495bSYour Name 				       &peer_auth);
210*5113495bSYour Name 		if (QDF_IS_STATUS_ERROR(status))
211*5113495bSYour Name 			mlo_peer_free_auth_param(peer_auth.auth_params);
212*5113495bSYour Name 	}
213*5113495bSYour Name }
214*5113495bSYour Name #else
mlo_peer_process_pending_auth(struct wlan_mlo_dev_context * ml_dev,struct wlan_mlo_peer_context * ml_peer)215*5113495bSYour Name static void mlo_peer_process_pending_auth(struct wlan_mlo_dev_context *ml_dev,
216*5113495bSYour Name 					  struct wlan_mlo_peer_context *ml_peer)
217*5113495bSYour Name {
218*5113495bSYour Name }
219*5113495bSYour Name #endif
220*5113495bSYour Name 
221*5113495bSYour Name QDF_STATUS
wlan_mlo_peer_is_disconnect_progress(struct wlan_mlo_peer_context * ml_peer)222*5113495bSYour Name wlan_mlo_peer_is_disconnect_progress(struct wlan_mlo_peer_context *ml_peer)
223*5113495bSYour Name {
224*5113495bSYour Name 	QDF_STATUS status;
225*5113495bSYour Name 
226*5113495bSYour Name 	if (!ml_peer)
227*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
228*5113495bSYour Name 
229*5113495bSYour Name 	mlo_peer_lock_acquire(ml_peer);
230*5113495bSYour Name 
231*5113495bSYour Name 	if (ml_peer->mlpeer_state == ML_PEER_DISCONN_INITIATED)
232*5113495bSYour Name 		status = QDF_STATUS_SUCCESS;
233*5113495bSYour Name 	else
234*5113495bSYour Name 		status = QDF_STATUS_E_FAILURE;
235*5113495bSYour Name 
236*5113495bSYour Name 	mlo_peer_lock_release(ml_peer);
237*5113495bSYour Name 
238*5113495bSYour Name 	return status;
239*5113495bSYour Name }
240*5113495bSYour Name 
wlan_mlo_peer_is_assoc_done(struct wlan_mlo_peer_context * ml_peer)241*5113495bSYour Name QDF_STATUS wlan_mlo_peer_is_assoc_done(struct wlan_mlo_peer_context *ml_peer)
242*5113495bSYour Name {
243*5113495bSYour Name 	QDF_STATUS status;
244*5113495bSYour Name 
245*5113495bSYour Name 	if (!ml_peer)
246*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
247*5113495bSYour Name 
248*5113495bSYour Name 	mlo_peer_lock_acquire(ml_peer);
249*5113495bSYour Name 
250*5113495bSYour Name 	if (ml_peer->mlpeer_state == ML_PEER_ASSOC_DONE)
251*5113495bSYour Name 		status = QDF_STATUS_SUCCESS;
252*5113495bSYour Name 	else
253*5113495bSYour Name 		status = QDF_STATUS_E_FAILURE;
254*5113495bSYour Name 
255*5113495bSYour Name 	mlo_peer_lock_release(ml_peer);
256*5113495bSYour Name 
257*5113495bSYour Name 	return status;
258*5113495bSYour Name }
259*5113495bSYour Name 
260*5113495bSYour Name qdf_export_symbol(wlan_mlo_peer_is_assoc_done);
261*5113495bSYour Name 
wlan_mlo_peer_get_assoc_peer(struct wlan_mlo_peer_context * ml_peer)262*5113495bSYour Name struct wlan_objmgr_peer *wlan_mlo_peer_get_assoc_peer(
263*5113495bSYour Name 					struct wlan_mlo_peer_context *ml_peer)
264*5113495bSYour Name {
265*5113495bSYour Name 	struct wlan_mlo_link_peer_entry *peer_entry;
266*5113495bSYour Name 	struct wlan_objmgr_peer *assoc_peer = NULL;
267*5113495bSYour Name 
268*5113495bSYour Name 	if (!ml_peer)
269*5113495bSYour Name 		return NULL;
270*5113495bSYour Name 
271*5113495bSYour Name 	mlo_peer_lock_acquire(ml_peer);
272*5113495bSYour Name 
273*5113495bSYour Name 	peer_entry = &ml_peer->peer_list[0];
274*5113495bSYour Name 
275*5113495bSYour Name 	if (peer_entry->link_peer)
276*5113495bSYour Name 		assoc_peer = peer_entry->link_peer;
277*5113495bSYour Name 
278*5113495bSYour Name 	mlo_peer_lock_release(ml_peer);
279*5113495bSYour Name 
280*5113495bSYour Name 	return assoc_peer;
281*5113495bSYour Name }
282*5113495bSYour Name 
283*5113495bSYour Name qdf_export_symbol(wlan_mlo_peer_get_assoc_peer);
284*5113495bSYour Name 
wlan_mlo_peer_get_bridge_peer(struct wlan_mlo_peer_context * ml_peer)285*5113495bSYour Name struct wlan_objmgr_peer *wlan_mlo_peer_get_bridge_peer(
286*5113495bSYour Name 					struct wlan_mlo_peer_context *ml_peer)
287*5113495bSYour Name {
288*5113495bSYour Name 	struct wlan_mlo_link_peer_entry *peer_entry = NULL;
289*5113495bSYour Name 	struct wlan_objmgr_peer *bridge_peer = NULL;
290*5113495bSYour Name 	struct wlan_objmgr_peer *link_peer = NULL;
291*5113495bSYour Name 	int i = 0;
292*5113495bSYour Name 
293*5113495bSYour Name 	if (!ml_peer)
294*5113495bSYour Name 		return NULL;
295*5113495bSYour Name 
296*5113495bSYour Name 	mlo_peer_lock_acquire(ml_peer);
297*5113495bSYour Name 
298*5113495bSYour Name 	for (i = 0; i < MAX_MLO_LINK_PEERS; i++) {
299*5113495bSYour Name 		peer_entry = &ml_peer->peer_list[i];
300*5113495bSYour Name 		if (!peer_entry)
301*5113495bSYour Name 			continue;
302*5113495bSYour Name 
303*5113495bSYour Name 		link_peer = peer_entry->link_peer;
304*5113495bSYour Name 		if (!link_peer)
305*5113495bSYour Name 			continue;
306*5113495bSYour Name 
307*5113495bSYour Name 		if (wlan_peer_get_peer_type(link_peer) ==
308*5113495bSYour Name 		    WLAN_PEER_MLO_BRIDGE) {
309*5113495bSYour Name 			if (peer_entry->is_primary)
310*5113495bSYour Name 				bridge_peer = link_peer;
311*5113495bSYour Name 			else
312*5113495bSYour Name 				mlo_err("Bridge peer is not primary");
313*5113495bSYour Name 
314*5113495bSYour Name 			break;
315*5113495bSYour Name 		}
316*5113495bSYour Name 	}
317*5113495bSYour Name 	mlo_peer_lock_release(ml_peer);
318*5113495bSYour Name 
319*5113495bSYour Name 	return bridge_peer;
320*5113495bSYour Name }
321*5113495bSYour Name 
322*5113495bSYour Name qdf_export_symbol(wlan_mlo_peer_get_bridge_peer);
323*5113495bSYour Name 
324*5113495bSYour Name struct wlan_objmgr_vdev *
wlan_mlo_peer_get_primary_link_vdev(struct wlan_mlo_peer_context * ml_peer)325*5113495bSYour Name wlan_mlo_peer_get_primary_link_vdev(struct wlan_mlo_peer_context *ml_peer)
326*5113495bSYour Name {
327*5113495bSYour Name 	struct wlan_mlo_link_peer_entry *peer_entry = NULL;
328*5113495bSYour Name 	struct wlan_objmgr_peer *link_peer;
329*5113495bSYour Name 	struct wlan_objmgr_vdev *link_vdev;
330*5113495bSYour Name 	uint8_t i;
331*5113495bSYour Name 
332*5113495bSYour Name 	if (!ml_peer) {
333*5113495bSYour Name 		mlo_err("ml_peer is null");
334*5113495bSYour Name 		return NULL;
335*5113495bSYour Name 	}
336*5113495bSYour Name 	mlo_peer_lock_acquire(ml_peer);
337*5113495bSYour Name 
338*5113495bSYour Name 	if ((ml_peer->mlpeer_state != ML_PEER_CREATED) &&
339*5113495bSYour Name 	    (ml_peer->mlpeer_state != ML_PEER_ASSOC_DONE)) {
340*5113495bSYour Name 		mlo_peer_lock_release(ml_peer);
341*5113495bSYour Name 		mlo_err("ml_peer is not created and association is not done");
342*5113495bSYour Name 		return NULL;
343*5113495bSYour Name 	}
344*5113495bSYour Name 
345*5113495bSYour Name 	for (i = 0; i < MAX_MLO_LINK_PEERS; i++) {
346*5113495bSYour Name 		peer_entry = &ml_peer->peer_list[i];
347*5113495bSYour Name 		link_peer = peer_entry->link_peer;
348*5113495bSYour Name 		if (!link_peer)
349*5113495bSYour Name 			continue;
350*5113495bSYour Name 
351*5113495bSYour Name 		if (peer_entry->is_primary) {
352*5113495bSYour Name 			link_vdev = wlan_peer_get_vdev(link_peer);
353*5113495bSYour Name 			if (!link_vdev) {
354*5113495bSYour Name 				mlo_peer_lock_release(ml_peer);
355*5113495bSYour Name 				mlo_err("link vdev not found");
356*5113495bSYour Name 				return NULL;
357*5113495bSYour Name 			}
358*5113495bSYour Name 			if (wlan_objmgr_vdev_try_get_ref(link_vdev, WLAN_MLO_MGR_ID) !=
359*5113495bSYour Name 					QDF_STATUS_SUCCESS) {
360*5113495bSYour Name 				mlo_peer_lock_release(ml_peer);
361*5113495bSYour Name 				mlo_err("taking ref failed");
362*5113495bSYour Name 				return NULL;
363*5113495bSYour Name 			}
364*5113495bSYour Name 			mlo_peer_lock_release(ml_peer);
365*5113495bSYour Name 			return link_vdev;
366*5113495bSYour Name 		}
367*5113495bSYour Name 	}
368*5113495bSYour Name 	mlo_peer_lock_release(ml_peer);
369*5113495bSYour Name 	mlo_err("None of the peer is designated as primary");
370*5113495bSYour Name 
371*5113495bSYour Name 	return NULL;
372*5113495bSYour Name }
373*5113495bSYour Name 
mlo_peer_is_assoc_peer(struct wlan_mlo_peer_context * ml_peer,struct wlan_objmgr_peer * peer)374*5113495bSYour Name bool mlo_peer_is_assoc_peer(struct wlan_mlo_peer_context *ml_peer,
375*5113495bSYour Name 			    struct wlan_objmgr_peer *peer)
376*5113495bSYour Name {
377*5113495bSYour Name 	struct wlan_mlo_link_peer_entry *peer_entry;
378*5113495bSYour Name 	bool is_assoc_peer = false;
379*5113495bSYour Name 
380*5113495bSYour Name 	if (!ml_peer || !peer)
381*5113495bSYour Name 		return is_assoc_peer;
382*5113495bSYour Name 
383*5113495bSYour Name 	peer_entry = &ml_peer->peer_list[0];
384*5113495bSYour Name 
385*5113495bSYour Name 	if (peer_entry->link_peer == peer)
386*5113495bSYour Name 		is_assoc_peer = true;
387*5113495bSYour Name 
388*5113495bSYour Name 	return is_assoc_peer;
389*5113495bSYour Name }
390*5113495bSYour Name 
wlan_mlo_peer_is_assoc_peer(struct wlan_mlo_peer_context * ml_peer,struct wlan_objmgr_peer * peer)391*5113495bSYour Name bool wlan_mlo_peer_is_assoc_peer(struct wlan_mlo_peer_context *ml_peer,
392*5113495bSYour Name 				 struct wlan_objmgr_peer *peer)
393*5113495bSYour Name {
394*5113495bSYour Name 	bool is_assoc_peer = false;
395*5113495bSYour Name 
396*5113495bSYour Name 	if (!ml_peer || !peer)
397*5113495bSYour Name 		return is_assoc_peer;
398*5113495bSYour Name 
399*5113495bSYour Name 	mlo_peer_lock_acquire(ml_peer);
400*5113495bSYour Name 
401*5113495bSYour Name 	is_assoc_peer = mlo_peer_is_assoc_peer(ml_peer, peer);
402*5113495bSYour Name 
403*5113495bSYour Name 	mlo_peer_lock_release(ml_peer);
404*5113495bSYour Name 
405*5113495bSYour Name 	return is_assoc_peer;
406*5113495bSYour Name }
407*5113495bSYour Name 
wlan_mlo_peer_is_link_peer(struct wlan_mlo_peer_context * ml_peer,struct wlan_objmgr_peer * peer)408*5113495bSYour Name bool wlan_mlo_peer_is_link_peer(struct wlan_mlo_peer_context *ml_peer,
409*5113495bSYour Name 				struct wlan_objmgr_peer *peer)
410*5113495bSYour Name {
411*5113495bSYour Name 	struct wlan_mlo_link_peer_entry *peer_entry;
412*5113495bSYour Name 	bool is_link_peer = false;
413*5113495bSYour Name 	uint16_t i;
414*5113495bSYour Name 
415*5113495bSYour Name 	if (!ml_peer || !peer)
416*5113495bSYour Name 		return is_link_peer;
417*5113495bSYour Name 
418*5113495bSYour Name 	mlo_peer_lock_acquire(ml_peer);
419*5113495bSYour Name 
420*5113495bSYour Name 	for (i = 0; i < MAX_MLO_LINK_PEERS; i++) {
421*5113495bSYour Name 		peer_entry = &ml_peer->peer_list[i];
422*5113495bSYour Name 		if (!peer_entry->link_peer)
423*5113495bSYour Name 			continue;
424*5113495bSYour Name 
425*5113495bSYour Name 		if (peer == peer_entry->link_peer) {
426*5113495bSYour Name 			is_link_peer = true;
427*5113495bSYour Name 			break;
428*5113495bSYour Name 		}
429*5113495bSYour Name 	}
430*5113495bSYour Name 
431*5113495bSYour Name 	mlo_peer_lock_release(ml_peer);
432*5113495bSYour Name 
433*5113495bSYour Name 	return is_link_peer;
434*5113495bSYour Name }
435*5113495bSYour Name 
wlan_mlo_partner_peer_assoc_post(struct wlan_objmgr_peer * assoc_peer)436*5113495bSYour Name void wlan_mlo_partner_peer_assoc_post(struct wlan_objmgr_peer *assoc_peer)
437*5113495bSYour Name {
438*5113495bSYour Name 	struct wlan_mlo_dev_context *ml_dev;
439*5113495bSYour Name 	struct wlan_mlo_peer_context *ml_peer;
440*5113495bSYour Name 	struct wlan_objmgr_peer *link_peer;
441*5113495bSYour Name 	struct wlan_objmgr_peer *link_peers[MAX_MLO_LINK_PEERS];
442*5113495bSYour Name 	struct wlan_mlo_link_peer_entry *peer_entry;
443*5113495bSYour Name 	uint16_t i;
444*5113495bSYour Name 
445*5113495bSYour Name 	ml_peer = assoc_peer->mlo_peer_ctx;
446*5113495bSYour Name 	if (!ml_peer)
447*5113495bSYour Name 		return;
448*5113495bSYour Name 
449*5113495bSYour Name 	mlo_peer_lock_acquire(ml_peer);
450*5113495bSYour Name 
451*5113495bSYour Name 	if (ml_peer->mlpeer_state != ML_PEER_CREATED) {
452*5113495bSYour Name 		mlo_peer_lock_release(ml_peer);
453*5113495bSYour Name 		return;
454*5113495bSYour Name 	}
455*5113495bSYour Name 
456*5113495bSYour Name 	ml_peer->mlpeer_state = ML_PEER_ASSOC_DONE;
457*5113495bSYour Name 	ml_dev = ml_peer->ml_dev;
458*5113495bSYour Name 
459*5113495bSYour Name 	for (i = 0; i < MAX_MLO_LINK_PEERS; i++) {
460*5113495bSYour Name 		link_peers[i] = NULL;
461*5113495bSYour Name 		peer_entry = &ml_peer->peer_list[i];
462*5113495bSYour Name 
463*5113495bSYour Name 		if (!peer_entry->link_peer)
464*5113495bSYour Name 			continue;
465*5113495bSYour Name 
466*5113495bSYour Name 		if (peer_entry->link_peer == assoc_peer)
467*5113495bSYour Name 			continue;
468*5113495bSYour Name 
469*5113495bSYour Name 		link_peer = peer_entry->link_peer;
470*5113495bSYour Name 
471*5113495bSYour Name 		if (wlan_objmgr_peer_try_get_ref(link_peer, WLAN_MLO_MGR_ID) !=
472*5113495bSYour Name 						 QDF_STATUS_SUCCESS)
473*5113495bSYour Name 			continue;
474*5113495bSYour Name 
475*5113495bSYour Name 		link_peers[i] = link_peer;
476*5113495bSYour Name 	}
477*5113495bSYour Name 	wlan_mlo_peer_wsi_link_add(ml_peer);
478*5113495bSYour Name 	mlo_peer_lock_release(ml_peer);
479*5113495bSYour Name 
480*5113495bSYour Name 	for (i = 0; i < MAX_MLO_LINK_PEERS; i++) {
481*5113495bSYour Name 		if (!link_peers[i])
482*5113495bSYour Name 			continue;
483*5113495bSYour Name 
484*5113495bSYour Name 		/* Prepare and queue message */
485*5113495bSYour Name 		mlo_link_peer_assoc_notify(ml_dev, link_peers[i]);
486*5113495bSYour Name 	}
487*5113495bSYour Name }
488*5113495bSYour Name 
wlan_mlo_link_peer_assoc_set(struct wlan_objmgr_peer * peer,bool is_sent)489*5113495bSYour Name void wlan_mlo_link_peer_assoc_set(struct wlan_objmgr_peer *peer, bool is_sent)
490*5113495bSYour Name {
491*5113495bSYour Name 	struct wlan_mlo_peer_context *ml_peer;
492*5113495bSYour Name 	struct wlan_mlo_link_peer_entry *peer_entry;
493*5113495bSYour Name 	uint16_t i;
494*5113495bSYour Name 
495*5113495bSYour Name 	ml_peer = peer->mlo_peer_ctx;
496*5113495bSYour Name 	if (!ml_peer)
497*5113495bSYour Name 		return;
498*5113495bSYour Name 
499*5113495bSYour Name 	mlo_peer_lock_acquire(ml_peer);
500*5113495bSYour Name 
501*5113495bSYour Name 	for (i = 0; i < MAX_MLO_LINK_PEERS; i++) {
502*5113495bSYour Name 		peer_entry = &ml_peer->peer_list[i];
503*5113495bSYour Name 
504*5113495bSYour Name 		if (!peer_entry->link_peer)
505*5113495bSYour Name 			continue;
506*5113495bSYour Name 
507*5113495bSYour Name 		if (peer_entry->link_peer == peer) {
508*5113495bSYour Name 			peer_entry->peer_assoc_sent = is_sent;
509*5113495bSYour Name 			break;
510*5113495bSYour Name 		}
511*5113495bSYour Name 	}
512*5113495bSYour Name 	mlo_peer_lock_release(ml_peer);
513*5113495bSYour Name }
514*5113495bSYour Name 
515*5113495bSYour Name qdf_export_symbol(wlan_mlo_link_peer_assoc_set);
516*5113495bSYour Name 
wlan_mlo_peer_get_del_hw_bitmap(struct wlan_objmgr_peer * peer,uint32_t * hw_link_id_bitmap)517*5113495bSYour Name void wlan_mlo_peer_get_del_hw_bitmap(struct wlan_objmgr_peer *peer,
518*5113495bSYour Name 				     uint32_t *hw_link_id_bitmap)
519*5113495bSYour Name {
520*5113495bSYour Name 	struct wlan_mlo_peer_context *ml_peer;
521*5113495bSYour Name 	struct wlan_mlo_link_peer_entry *peer_entry;
522*5113495bSYour Name 	uint16_t i;
523*5113495bSYour Name 
524*5113495bSYour Name 	ml_peer = peer->mlo_peer_ctx;
525*5113495bSYour Name 	if (!ml_peer)
526*5113495bSYour Name 		return;
527*5113495bSYour Name 
528*5113495bSYour Name 	mlo_peer_lock_acquire(ml_peer);
529*5113495bSYour Name 
530*5113495bSYour Name 	for (i = 0; i < MAX_MLO_LINK_PEERS; i++) {
531*5113495bSYour Name 		peer_entry = &ml_peer->peer_list[i];
532*5113495bSYour Name 
533*5113495bSYour Name 		if (!peer_entry->link_peer)
534*5113495bSYour Name 			continue;
535*5113495bSYour Name 
536*5113495bSYour Name 		if (peer_entry->link_peer == peer) {
537*5113495bSYour Name 			/* Peer assoc is not sent, no need to send bitmap */
538*5113495bSYour Name 			if (!peer_entry->peer_assoc_sent)
539*5113495bSYour Name 				break;
540*5113495bSYour Name 
541*5113495bSYour Name 			continue;
542*5113495bSYour Name 		}
543*5113495bSYour Name 		if (!peer_entry->peer_assoc_sent)
544*5113495bSYour Name 			*hw_link_id_bitmap |= 1 << peer_entry->hw_link_id;
545*5113495bSYour Name 	}
546*5113495bSYour Name 	mlo_peer_lock_release(ml_peer);
547*5113495bSYour Name }
548*5113495bSYour Name 
549*5113495bSYour Name qdf_export_symbol(wlan_mlo_peer_get_del_hw_bitmap);
550*5113495bSYour Name 
551*5113495bSYour Name void
wlan_mlo_peer_deauth_init(struct wlan_mlo_peer_context * ml_peer,struct wlan_objmgr_peer * src_peer,uint8_t is_disassoc)552*5113495bSYour Name wlan_mlo_peer_deauth_init(struct wlan_mlo_peer_context *ml_peer,
553*5113495bSYour Name 			  struct wlan_objmgr_peer *src_peer,
554*5113495bSYour Name 			  uint8_t is_disassoc)
555*5113495bSYour Name {
556*5113495bSYour Name 	struct wlan_mlo_dev_context *ml_dev;
557*5113495bSYour Name 	struct wlan_objmgr_peer *link_peer;
558*5113495bSYour Name 	struct wlan_objmgr_peer *link_peers[MAX_MLO_LINK_PEERS];
559*5113495bSYour Name 	struct wlan_mlo_link_peer_entry *peer_entry;
560*5113495bSYour Name 	uint16_t i;
561*5113495bSYour Name 	uint8_t deauth_sent = 0;
562*5113495bSYour Name 
563*5113495bSYour Name 	if (!ml_peer)
564*5113495bSYour Name 		return;
565*5113495bSYour Name 
566*5113495bSYour Name 	mlo_peer_lock_acquire(ml_peer);
567*5113495bSYour Name 
568*5113495bSYour Name 	if (ml_peer->mlpeer_state == ML_PEER_DISCONN_INITIATED) {
569*5113495bSYour Name 		mlo_peer_lock_release(ml_peer);
570*5113495bSYour Name 		return;
571*5113495bSYour Name 	}
572*5113495bSYour Name 
573*5113495bSYour Name 	ml_dev = ml_peer->ml_dev;
574*5113495bSYour Name 
575*5113495bSYour Name 	for (i = 0; i < MAX_MLO_LINK_PEERS; i++) {
576*5113495bSYour Name 		link_peers[i] = NULL;
577*5113495bSYour Name 		peer_entry = &ml_peer->peer_list[i];
578*5113495bSYour Name 		if (!peer_entry->link_peer)
579*5113495bSYour Name 			continue;
580*5113495bSYour Name 
581*5113495bSYour Name 		link_peer = peer_entry->link_peer;
582*5113495bSYour Name 
583*5113495bSYour Name 		if (wlan_objmgr_peer_try_get_ref(link_peer, WLAN_MLO_MGR_ID) !=
584*5113495bSYour Name 						QDF_STATUS_SUCCESS)
585*5113495bSYour Name 			continue;
586*5113495bSYour Name 
587*5113495bSYour Name 		link_peers[i] = link_peer;
588*5113495bSYour Name 	}
589*5113495bSYour Name 
590*5113495bSYour Name 	ml_peer->mlpeer_state = ML_PEER_DISCONN_INITIATED;
591*5113495bSYour Name 
592*5113495bSYour Name 	mlo_peer_lock_release(ml_peer);
593*5113495bSYour Name 
594*5113495bSYour Name 	for (i = 0; i < MAX_MLO_LINK_PEERS; i++) {
595*5113495bSYour Name 		if (!link_peers[i])
596*5113495bSYour Name 			continue;
597*5113495bSYour Name 
598*5113495bSYour Name 		/* Prepare and queue message */
599*5113495bSYour Name 		/* skip sending deauth on src peer */
600*5113495bSYour Name 		if ((deauth_sent) ||
601*5113495bSYour Name 		    (src_peer && (src_peer == link_peers[i]))) {
602*5113495bSYour Name 			mlo_link_peer_disconnect_notify(ml_dev, link_peers[i]);
603*5113495bSYour Name 		} else {
604*5113495bSYour Name 			mlo_link_peer_deauth_init(ml_dev, link_peers[i],
605*5113495bSYour Name 						  is_disassoc);
606*5113495bSYour Name 			deauth_sent = 1;
607*5113495bSYour Name 		}
608*5113495bSYour Name 	}
609*5113495bSYour Name }
610*5113495bSYour Name 
611*5113495bSYour Name qdf_export_symbol(wlan_mlo_peer_deauth_init);
612*5113495bSYour Name 
wlan_mlo_peer_delete(struct wlan_mlo_peer_context * ml_peer)613*5113495bSYour Name void wlan_mlo_peer_delete(struct wlan_mlo_peer_context *ml_peer)
614*5113495bSYour Name {
615*5113495bSYour Name 	struct wlan_mlo_dev_context *ml_dev;
616*5113495bSYour Name 	struct wlan_objmgr_peer *link_peer;
617*5113495bSYour Name 	struct wlan_objmgr_peer *link_peers[MAX_MLO_LINK_PEERS];
618*5113495bSYour Name 	struct wlan_mlo_link_peer_entry *peer_entry;
619*5113495bSYour Name 	uint16_t i;
620*5113495bSYour Name 
621*5113495bSYour Name 	if (!ml_peer)
622*5113495bSYour Name 		return;
623*5113495bSYour Name 
624*5113495bSYour Name 	mlo_peer_lock_acquire(ml_peer);
625*5113495bSYour Name 
626*5113495bSYour Name 	if (ml_peer->mlpeer_state == ML_PEER_DISCONN_INITIATED) {
627*5113495bSYour Name 		mlo_peer_lock_release(ml_peer);
628*5113495bSYour Name 		return;
629*5113495bSYour Name 	}
630*5113495bSYour Name 
631*5113495bSYour Name 	ml_dev = ml_peer->ml_dev;
632*5113495bSYour Name 
633*5113495bSYour Name 	for (i = 0; i < MAX_MLO_LINK_PEERS; i++) {
634*5113495bSYour Name 		link_peers[i] = NULL;
635*5113495bSYour Name 		peer_entry = &ml_peer->peer_list[i];
636*5113495bSYour Name 		if (!peer_entry->link_peer)
637*5113495bSYour Name 			continue;
638*5113495bSYour Name 
639*5113495bSYour Name 		link_peer = peer_entry->link_peer;
640*5113495bSYour Name 
641*5113495bSYour Name 		if (wlan_objmgr_peer_try_get_ref(link_peer, WLAN_MLO_MGR_ID) !=
642*5113495bSYour Name 						QDF_STATUS_SUCCESS)
643*5113495bSYour Name 			continue;
644*5113495bSYour Name 
645*5113495bSYour Name 		link_peers[i] = link_peer;
646*5113495bSYour Name 	}
647*5113495bSYour Name 
648*5113495bSYour Name 	ml_peer->mlpeer_state = ML_PEER_DISCONN_INITIATED;
649*5113495bSYour Name 
650*5113495bSYour Name 	mlo_peer_lock_release(ml_peer);
651*5113495bSYour Name 
652*5113495bSYour Name 	for (i = 0; i < MAX_MLO_LINK_PEERS; i++) {
653*5113495bSYour Name 		if (!link_peers[i])
654*5113495bSYour Name 			continue;
655*5113495bSYour Name 
656*5113495bSYour Name 		mlo_link_peer_disconnect_notify(ml_dev, link_peers[i]);
657*5113495bSYour Name 	}
658*5113495bSYour Name }
659*5113495bSYour Name 
660*5113495bSYour Name void
wlan_mlo_partner_peer_create_failed_notify(struct wlan_mlo_peer_context * ml_peer)661*5113495bSYour Name wlan_mlo_partner_peer_create_failed_notify(
662*5113495bSYour Name 				struct wlan_mlo_peer_context *ml_peer)
663*5113495bSYour Name {
664*5113495bSYour Name 	struct wlan_mlo_dev_context *ml_dev;
665*5113495bSYour Name 	struct wlan_objmgr_peer *link_peer;
666*5113495bSYour Name 	struct wlan_objmgr_peer *link_peers[MAX_MLO_LINK_PEERS];
667*5113495bSYour Name 	struct wlan_mlo_link_peer_entry *peer_entry;
668*5113495bSYour Name 	uint16_t i;
669*5113495bSYour Name 
670*5113495bSYour Name 	if (!ml_peer)
671*5113495bSYour Name 		return;
672*5113495bSYour Name 
673*5113495bSYour Name 	mlo_peer_lock_acquire(ml_peer);
674*5113495bSYour Name 
675*5113495bSYour Name 	if (ml_peer->mlpeer_state == ML_PEER_DISCONN_INITIATED) {
676*5113495bSYour Name 		mlo_peer_lock_release(ml_peer);
677*5113495bSYour Name 		return;
678*5113495bSYour Name 	}
679*5113495bSYour Name 
680*5113495bSYour Name 	ml_peer->mlpeer_state = ML_PEER_DISCONN_INITIATED;
681*5113495bSYour Name 	ml_dev = ml_peer->ml_dev;
682*5113495bSYour Name 
683*5113495bSYour Name 	for (i = 0; i < MAX_MLO_LINK_PEERS; i++) {
684*5113495bSYour Name 		link_peers[i] = NULL;
685*5113495bSYour Name 		peer_entry = &ml_peer->peer_list[i];
686*5113495bSYour Name 		if (!peer_entry->link_peer)
687*5113495bSYour Name 			continue;
688*5113495bSYour Name 
689*5113495bSYour Name 		link_peer = peer_entry->link_peer;
690*5113495bSYour Name 		if (wlan_objmgr_peer_try_get_ref(link_peer, WLAN_MLO_MGR_ID) !=
691*5113495bSYour Name 						QDF_STATUS_SUCCESS)
692*5113495bSYour Name 			continue;
693*5113495bSYour Name 
694*5113495bSYour Name 		link_peers[i] = link_peer;
695*5113495bSYour Name 	}
696*5113495bSYour Name 	mlo_peer_lock_release(ml_peer);
697*5113495bSYour Name 
698*5113495bSYour Name 	for (i = 0; i < MAX_MLO_LINK_PEERS; i++) {
699*5113495bSYour Name 		if (!link_peers[i])
700*5113495bSYour Name 			continue;
701*5113495bSYour Name 
702*5113495bSYour Name 		/* Prepare and queue message */
703*5113495bSYour Name 		if (i == 0)
704*5113495bSYour Name 			mlo_link_peer_send_assoc_fail(ml_dev, link_peers[i]);
705*5113495bSYour Name 		else
706*5113495bSYour Name 			mlo_link_peer_disconnect_notify(ml_dev, link_peers[i]);
707*5113495bSYour Name 	}
708*5113495bSYour Name }
709*5113495bSYour Name 
wlan_mlo_partner_peer_disconnect_notify(struct wlan_objmgr_peer * src_peer)710*5113495bSYour Name void wlan_mlo_partner_peer_disconnect_notify(struct wlan_objmgr_peer *src_peer)
711*5113495bSYour Name {
712*5113495bSYour Name 	struct wlan_mlo_dev_context *ml_dev;
713*5113495bSYour Name 	struct wlan_mlo_peer_context *ml_peer;
714*5113495bSYour Name 	struct wlan_objmgr_peer *link_peer;
715*5113495bSYour Name 	struct wlan_objmgr_peer *link_peers[MAX_MLO_LINK_PEERS];
716*5113495bSYour Name 	struct wlan_mlo_link_peer_entry *peer_entry;
717*5113495bSYour Name 	struct wlan_objmgr_vdev *vdev = NULL;
718*5113495bSYour Name 	uint16_t i;
719*5113495bSYour Name 
720*5113495bSYour Name 	ml_peer = src_peer->mlo_peer_ctx;
721*5113495bSYour Name 	if (!ml_peer)
722*5113495bSYour Name 		return;
723*5113495bSYour Name 
724*5113495bSYour Name 	vdev = wlan_peer_get_vdev(src_peer);
725*5113495bSYour Name 	if (!vdev)
726*5113495bSYour Name 		return;
727*5113495bSYour Name 
728*5113495bSYour Name 	/* Do not change peer state to disconnect initiated for
729*5113495bSYour Name 	 * link switch case, this can lead to not sending deauth frame
730*5113495bSYour Name 	 * incase of actual disconnect and AP might drop the next connect
731*5113495bSYour Name 	 * request as it might think STA is still in connected state.
732*5113495bSYour Name 	 */
733*5113495bSYour Name 	if (wlan_vdev_mlme_is_mlo_link_switch_in_progress(vdev))
734*5113495bSYour Name 		return;
735*5113495bSYour Name 
736*5113495bSYour Name 	mlo_peer_lock_acquire(ml_peer);
737*5113495bSYour Name 
738*5113495bSYour Name 	if (ml_peer->mlpeer_state == ML_PEER_DISCONN_INITIATED) {
739*5113495bSYour Name 		mlo_peer_lock_release(ml_peer);
740*5113495bSYour Name 		return;
741*5113495bSYour Name 	}
742*5113495bSYour Name 
743*5113495bSYour Name 	wlan_mlo_peer_wsi_link_delete(ml_peer);
744*5113495bSYour Name 
745*5113495bSYour Name 	ml_peer->mlpeer_state = ML_PEER_DISCONN_INITIATED;
746*5113495bSYour Name 
747*5113495bSYour Name 	if (wlan_vdev_mlme_get_opmode(vdev) == QDF_STA_MODE) {
748*5113495bSYour Name 		mlo_peer_lock_release(ml_peer);
749*5113495bSYour Name 		return;
750*5113495bSYour Name 	}
751*5113495bSYour Name 
752*5113495bSYour Name 	ml_dev = ml_peer->ml_dev;
753*5113495bSYour Name 	for (i = 0; i < MAX_MLO_LINK_PEERS; i++) {
754*5113495bSYour Name 		link_peers[i] = NULL;
755*5113495bSYour Name 		peer_entry = &ml_peer->peer_list[i];
756*5113495bSYour Name 		if (!peer_entry->link_peer) {
757*5113495bSYour Name 			mlo_debug("link peer is null");
758*5113495bSYour Name 			continue;
759*5113495bSYour Name 		}
760*5113495bSYour Name 
761*5113495bSYour Name 		if (peer_entry->link_peer == src_peer)
762*5113495bSYour Name 			continue;
763*5113495bSYour Name 
764*5113495bSYour Name 		link_peer = peer_entry->link_peer;
765*5113495bSYour Name 		if (wlan_objmgr_peer_try_get_ref(link_peer, WLAN_MLO_MGR_ID) !=
766*5113495bSYour Name 						QDF_STATUS_SUCCESS)
767*5113495bSYour Name 			continue;
768*5113495bSYour Name 
769*5113495bSYour Name 		link_peers[i] = link_peer;
770*5113495bSYour Name 	}
771*5113495bSYour Name 	mlo_peer_lock_release(ml_peer);
772*5113495bSYour Name 
773*5113495bSYour Name 	for (i = 0; i < MAX_MLO_LINK_PEERS; i++) {
774*5113495bSYour Name 		if (!link_peers[i])
775*5113495bSYour Name 			continue;
776*5113495bSYour Name 
777*5113495bSYour Name 		/* Prepare and queue message */
778*5113495bSYour Name 		mlo_link_peer_disconnect_notify(ml_dev, link_peers[i]);
779*5113495bSYour Name 	}
780*5113495bSYour Name }
781*5113495bSYour Name 
782*5113495bSYour Name qdf_export_symbol(wlan_mlo_partner_peer_disconnect_notify);
783*5113495bSYour Name 
mlo_peer_populate_link_peer(struct wlan_mlo_peer_context * ml_peer,struct wlan_objmgr_peer * link_peer)784*5113495bSYour Name static void mlo_peer_populate_link_peer(
785*5113495bSYour Name 			struct wlan_mlo_peer_context *ml_peer,
786*5113495bSYour Name 			struct wlan_objmgr_peer *link_peer)
787*5113495bSYour Name {
788*5113495bSYour Name 	mlo_peer_lock_acquire(ml_peer);
789*5113495bSYour Name 	wlan_mlo_peer_get_ref(ml_peer);
790*5113495bSYour Name 	link_peer->mlo_peer_ctx = ml_peer;
791*5113495bSYour Name 	mlo_peer_lock_release(ml_peer);
792*5113495bSYour Name }
793*5113495bSYour Name 
mlo_reset_link_peer(struct wlan_mlo_peer_context * ml_peer,struct wlan_objmgr_peer * link_peer)794*5113495bSYour Name static void mlo_reset_link_peer(
795*5113495bSYour Name 			struct wlan_mlo_peer_context *ml_peer,
796*5113495bSYour Name 			struct wlan_objmgr_peer *link_peer)
797*5113495bSYour Name {
798*5113495bSYour Name 	mlo_peer_lock_acquire(ml_peer);
799*5113495bSYour Name 	link_peer->mlo_peer_ctx = NULL;
800*5113495bSYour Name 	wlan_peer_clear_mlo(link_peer);
801*5113495bSYour Name 	mlo_peer_lock_release(ml_peer);
802*5113495bSYour Name }
803*5113495bSYour Name 
mlo_peer_free(struct wlan_mlo_peer_context * ml_peer)804*5113495bSYour Name static void mlo_peer_free(struct wlan_mlo_peer_context *ml_peer)
805*5113495bSYour Name {
806*5113495bSYour Name 	struct wlan_mlo_dev_context *ml_dev;
807*5113495bSYour Name 
808*5113495bSYour Name 	ml_dev = ml_peer->ml_dev;
809*5113495bSYour Name 	if (!ml_dev) {
810*5113495bSYour Name 		mlo_err("ML DEV is NULL");
811*5113495bSYour Name 		return;
812*5113495bSYour Name 	}
813*5113495bSYour Name 
814*5113495bSYour Name 	mlo_debug("ML Peer " QDF_MAC_ADDR_FMT " is freed",
815*5113495bSYour Name 		  QDF_MAC_ADDR_REF(ml_peer->peer_mld_addr.bytes));
816*5113495bSYour Name 	mlo_peer_lock_destroy(ml_peer);
817*5113495bSYour Name 	epcs_dev_peer_lock_destroy(&ml_peer->epcs_info);
818*5113495bSYour Name 	mlo_ap_ml_ptqm_peerid_free(ml_dev, ml_peer->mlo_peer_id);
819*5113495bSYour Name 	mlo_ap_ml_peerid_free(ml_peer->mlo_peer_id);
820*5113495bSYour Name 	mlo_peer_free_aid(ml_dev, ml_peer);
821*5113495bSYour Name 	mlo_peer_free_primary_umac(ml_dev, ml_peer);
822*5113495bSYour Name 	qdf_mem_free(ml_peer);
823*5113495bSYour Name }
824*5113495bSYour Name 
mlo_peer_cleanup(struct wlan_mlo_peer_context * ml_peer)825*5113495bSYour Name void mlo_peer_cleanup(struct wlan_mlo_peer_context *ml_peer)
826*5113495bSYour Name {
827*5113495bSYour Name 	struct wlan_mlo_dev_context *ml_dev;
828*5113495bSYour Name 
829*5113495bSYour Name 	if (!ml_peer) {
830*5113495bSYour Name 		mlo_err("ML PEER is NULL");
831*5113495bSYour Name 		return;
832*5113495bSYour Name 	}
833*5113495bSYour Name 	ml_dev = ml_peer->ml_dev;
834*5113495bSYour Name 	if (!ml_dev) {
835*5113495bSYour Name 		mlo_err("ML DEV is NULL");
836*5113495bSYour Name 		return;
837*5113495bSYour Name 	}
838*5113495bSYour Name 
839*5113495bSYour Name 	mlo_dev_mlpeer_detach(ml_dev, ml_peer);
840*5113495bSYour Name 	/* If any Auth req is received during ML peer delete */
841*5113495bSYour Name 	mlo_peer_process_pending_auth(ml_dev, ml_peer);
842*5113495bSYour Name 	mlo_peer_free(ml_peer);
843*5113495bSYour Name }
844*5113495bSYour Name 
mlo_peer_attach_link_peer(struct wlan_mlo_peer_context * ml_peer,struct wlan_objmgr_peer * link_peer,qdf_nbuf_t frm_buf)845*5113495bSYour Name static QDF_STATUS mlo_peer_attach_link_peer(
846*5113495bSYour Name 		struct wlan_mlo_peer_context *ml_peer,
847*5113495bSYour Name 		struct wlan_objmgr_peer *link_peer,
848*5113495bSYour Name 		qdf_nbuf_t frm_buf)
849*5113495bSYour Name {
850*5113495bSYour Name 	struct wlan_mlo_link_peer_entry *peer_entry;
851*5113495bSYour Name 	QDF_STATUS status = QDF_STATUS_E_RESOURCES;
852*5113495bSYour Name 	struct wlan_objmgr_pdev *pdev;
853*5113495bSYour Name 	struct wlan_objmgr_vdev *vdev;
854*5113495bSYour Name 	uint16_t i;
855*5113495bSYour Name 
856*5113495bSYour Name 	if (!link_peer)
857*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
858*5113495bSYour Name 
859*5113495bSYour Name 	vdev = wlan_peer_get_vdev(link_peer);
860*5113495bSYour Name 	if (!vdev)
861*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
862*5113495bSYour Name 
863*5113495bSYour Name 	mlo_peer_lock_acquire(ml_peer);
864*5113495bSYour Name 
865*5113495bSYour Name 	if (ml_peer->mlpeer_state != ML_PEER_CREATED) {
866*5113495bSYour Name 		mlo_peer_lock_release(ml_peer);
867*5113495bSYour Name 		mlo_err("ML Peer " QDF_MAC_ADDR_FMT " is not in created state (state %d)",
868*5113495bSYour Name 			QDF_MAC_ADDR_REF(ml_peer->peer_mld_addr.bytes),
869*5113495bSYour Name 			ml_peer->mlpeer_state);
870*5113495bSYour Name 		return status;
871*5113495bSYour Name 	}
872*5113495bSYour Name 
873*5113495bSYour Name 	for (i = 0; i < MAX_MLO_LINK_PEERS; i++) {
874*5113495bSYour Name 		peer_entry = &ml_peer->peer_list[i];
875*5113495bSYour Name 		if (peer_entry->link_peer)
876*5113495bSYour Name 			continue;
877*5113495bSYour Name 
878*5113495bSYour Name 		if (wlan_objmgr_peer_try_get_ref(link_peer, WLAN_MLO_MGR_ID) !=
879*5113495bSYour Name 						QDF_STATUS_SUCCESS) {
880*5113495bSYour Name 			mlo_err("ML Peer " QDF_MAC_ADDR_FMT ", link peer " QDF_MAC_ADDR_FMT " is not in valid state",
881*5113495bSYour Name 				QDF_MAC_ADDR_REF(ml_peer->peer_mld_addr.bytes),
882*5113495bSYour Name 				QDF_MAC_ADDR_REF
883*5113495bSYour Name 					(wlan_peer_get_macaddr(link_peer)));
884*5113495bSYour Name 			break;
885*5113495bSYour Name 		}
886*5113495bSYour Name 		peer_entry->link_peer = link_peer;
887*5113495bSYour Name 		qdf_atomic_inc(&vdev->vdev_objmgr.wlan_ml_peer_count);
888*5113495bSYour Name 		qdf_copy_macaddr(&peer_entry->link_addr,
889*5113495bSYour Name 				 (struct qdf_mac_addr *)&link_peer->macaddr[0]);
890*5113495bSYour Name 
891*5113495bSYour Name 		peer_entry->link_ix = wlan_vdev_get_link_id(vdev);
892*5113495bSYour Name 		pdev = wlan_vdev_get_pdev(wlan_peer_get_vdev(link_peer));
893*5113495bSYour Name 		peer_entry->hw_link_id = wlan_mlo_get_pdev_hw_link_id(pdev);
894*5113495bSYour Name 		mlo_peer_assign_primary_umac(ml_peer, peer_entry);
895*5113495bSYour Name 		if (frm_buf)
896*5113495bSYour Name 			peer_entry->assoc_rsp_buf = frm_buf;
897*5113495bSYour Name 		else
898*5113495bSYour Name 			peer_entry->assoc_rsp_buf = NULL;
899*5113495bSYour Name 
900*5113495bSYour Name 		status = QDF_STATUS_SUCCESS;
901*5113495bSYour Name 		break;
902*5113495bSYour Name 	}
903*5113495bSYour Name 	if (QDF_IS_STATUS_SUCCESS(status))
904*5113495bSYour Name 		ml_peer->link_peer_cnt++;
905*5113495bSYour Name 
906*5113495bSYour Name 	mlo_peer_lock_release(ml_peer);
907*5113495bSYour Name 
908*5113495bSYour Name 	return status;
909*5113495bSYour Name }
910*5113495bSYour Name 
mlo_peer_get_link_peer_assoc_resp_buf(struct wlan_mlo_peer_context * ml_peer,uint8_t link_ix)911*5113495bSYour Name qdf_nbuf_t mlo_peer_get_link_peer_assoc_resp_buf(
912*5113495bSYour Name 		struct wlan_mlo_peer_context *ml_peer,
913*5113495bSYour Name 		uint8_t link_ix)
914*5113495bSYour Name {
915*5113495bSYour Name 	struct wlan_mlo_link_peer_entry *peer_entry;
916*5113495bSYour Name 	qdf_nbuf_t frm_buf = NULL;
917*5113495bSYour Name 	uint8_t i;
918*5113495bSYour Name 
919*5113495bSYour Name 	if (!ml_peer)
920*5113495bSYour Name 		return NULL;
921*5113495bSYour Name 
922*5113495bSYour Name 	if (link_ix > MAX_MLO_LINK_PEERS)
923*5113495bSYour Name 		return NULL;
924*5113495bSYour Name 
925*5113495bSYour Name 	mlo_peer_lock_acquire(ml_peer);
926*5113495bSYour Name 	if ((ml_peer->mlpeer_state != ML_PEER_CREATED) &&
927*5113495bSYour Name 	    (ml_peer->mlpeer_state != ML_PEER_ASSOC_DONE)) {
928*5113495bSYour Name 		mlo_peer_lock_release(ml_peer);
929*5113495bSYour Name 		return NULL;
930*5113495bSYour Name 	}
931*5113495bSYour Name 
932*5113495bSYour Name 	for (i = 0; i < MAX_MLO_LINK_PEERS; i++) {
933*5113495bSYour Name 		peer_entry = &ml_peer->peer_list[i];
934*5113495bSYour Name 
935*5113495bSYour Name 		if (!peer_entry->link_peer)
936*5113495bSYour Name 			continue;
937*5113495bSYour Name 
938*5113495bSYour Name 		if (peer_entry->link_ix == link_ix) {
939*5113495bSYour Name 			if (!peer_entry->assoc_rsp_buf)
940*5113495bSYour Name 				break;
941*5113495bSYour Name 
942*5113495bSYour Name 			frm_buf = qdf_nbuf_clone(peer_entry->assoc_rsp_buf);
943*5113495bSYour Name 			break;
944*5113495bSYour Name 		}
945*5113495bSYour Name 	}
946*5113495bSYour Name 	mlo_peer_lock_release(ml_peer);
947*5113495bSYour Name 
948*5113495bSYour Name 	return frm_buf;
949*5113495bSYour Name }
950*5113495bSYour Name 
wlan_mlo_peer_free_all_link_assoc_resp_buf(struct wlan_objmgr_peer * link_peer)951*5113495bSYour Name void wlan_mlo_peer_free_all_link_assoc_resp_buf(
952*5113495bSYour Name 			struct wlan_objmgr_peer *link_peer)
953*5113495bSYour Name {
954*5113495bSYour Name 	struct wlan_mlo_link_peer_entry *peer_entry;
955*5113495bSYour Name 	struct wlan_mlo_peer_context *ml_peer;
956*5113495bSYour Name 	uint8_t i;
957*5113495bSYour Name 
958*5113495bSYour Name 	ml_peer = link_peer->mlo_peer_ctx;
959*5113495bSYour Name 	if (!ml_peer)
960*5113495bSYour Name 		return;
961*5113495bSYour Name 
962*5113495bSYour Name 	mlo_peer_lock_acquire(ml_peer);
963*5113495bSYour Name 
964*5113495bSYour Name 	for (i = 0; i < MAX_MLO_LINK_PEERS; i++) {
965*5113495bSYour Name 		peer_entry = &ml_peer->peer_list[i];
966*5113495bSYour Name 
967*5113495bSYour Name 		if (peer_entry->assoc_rsp_buf) {
968*5113495bSYour Name 			qdf_nbuf_free(peer_entry->assoc_rsp_buf);
969*5113495bSYour Name 			peer_entry->assoc_rsp_buf = NULL;
970*5113495bSYour Name 		}
971*5113495bSYour Name 	}
972*5113495bSYour Name 	mlo_peer_lock_release(ml_peer);
973*5113495bSYour Name }
974*5113495bSYour Name 
mlo_peer_detach_link_peer(struct wlan_mlo_peer_context * ml_peer,struct wlan_objmgr_peer * link_peer)975*5113495bSYour Name static QDF_STATUS mlo_peer_detach_link_peer(
976*5113495bSYour Name 		struct wlan_mlo_peer_context *ml_peer,
977*5113495bSYour Name 		struct wlan_objmgr_peer *link_peer)
978*5113495bSYour Name {
979*5113495bSYour Name 	struct wlan_mlo_link_peer_entry *peer_entry;
980*5113495bSYour Name 	QDF_STATUS status = QDF_STATUS_E_RESOURCES;
981*5113495bSYour Name 	uint16_t i;
982*5113495bSYour Name 	struct wlan_objmgr_vdev *vdev;
983*5113495bSYour Name 
984*5113495bSYour Name 	mlo_peer_lock_acquire(ml_peer);
985*5113495bSYour Name 
986*5113495bSYour Name 	for (i = 0; i < MAX_MLO_LINK_PEERS; i++) {
987*5113495bSYour Name 		peer_entry = &ml_peer->peer_list[i];
988*5113495bSYour Name 		if (!peer_entry->link_peer)
989*5113495bSYour Name 			continue;
990*5113495bSYour Name 
991*5113495bSYour Name 		if (peer_entry->link_peer != link_peer)
992*5113495bSYour Name 			continue;
993*5113495bSYour Name 
994*5113495bSYour Name 		if (peer_entry->assoc_rsp_buf) {
995*5113495bSYour Name 			qdf_nbuf_free(peer_entry->assoc_rsp_buf);
996*5113495bSYour Name 			peer_entry->assoc_rsp_buf = NULL;
997*5113495bSYour Name 		}
998*5113495bSYour Name 		vdev =  wlan_peer_get_vdev(link_peer);
999*5113495bSYour Name 		if (vdev) {
1000*5113495bSYour Name 			qdf_atomic_dec(&vdev->vdev_objmgr.wlan_ml_peer_count);
1001*5113495bSYour Name 		} else {
1002*5113495bSYour Name 			mlo_err("vdev is null for ml_peer: " QDF_MAC_ADDR_FMT
1003*5113495bSYour Name 				"mld mac addr: " QDF_MAC_ADDR_FMT,
1004*5113495bSYour Name 				QDF_MAC_ADDR_REF(link_peer->macaddr),
1005*5113495bSYour Name 				QDF_MAC_ADDR_REF(link_peer->mldaddr));
1006*5113495bSYour Name 			qdf_assert_always(vdev);
1007*5113495bSYour Name 		}
1008*5113495bSYour Name 		wlan_objmgr_peer_release_ref(link_peer, WLAN_MLO_MGR_ID);
1009*5113495bSYour Name 		peer_entry->link_peer = NULL;
1010*5113495bSYour Name 		ml_peer->link_peer_cnt--;
1011*5113495bSYour Name 		status = QDF_STATUS_SUCCESS;
1012*5113495bSYour Name 		break;
1013*5113495bSYour Name 	}
1014*5113495bSYour Name 	mlo_peer_lock_release(ml_peer);
1015*5113495bSYour Name 
1016*5113495bSYour Name 	return status;
1017*5113495bSYour Name }
1018*5113495bSYour Name #if defined (SAP_MULTI_LINK_EMULATION)
1019*5113495bSYour Name /*Skip link vdev check. Second link does not have vdev*/
mlo_dev_get_link_vdevs(struct wlan_objmgr_vdev * vdev,struct wlan_mlo_dev_context * ml_dev,struct mlo_partner_info * ml_info,struct wlan_objmgr_vdev * link_vdevs[])1020*5113495bSYour Name static QDF_STATUS mlo_dev_get_link_vdevs(
1021*5113495bSYour Name 			struct wlan_objmgr_vdev *vdev,
1022*5113495bSYour Name 			struct wlan_mlo_dev_context *ml_dev,
1023*5113495bSYour Name 			struct mlo_partner_info *ml_info,
1024*5113495bSYour Name 			struct wlan_objmgr_vdev *link_vdevs[])
1025*5113495bSYour Name {
1026*5113495bSYour Name 	return QDF_STATUS_SUCCESS;
1027*5113495bSYour Name }
1028*5113495bSYour Name #else
mlo_dev_get_link_vdevs(struct wlan_objmgr_vdev * vdev,struct wlan_mlo_dev_context * ml_dev,struct mlo_partner_info * ml_info,struct wlan_objmgr_vdev * link_vdevs[])1029*5113495bSYour Name static QDF_STATUS mlo_dev_get_link_vdevs(
1030*5113495bSYour Name 			struct wlan_objmgr_vdev *vdev,
1031*5113495bSYour Name 			struct wlan_mlo_dev_context *ml_dev,
1032*5113495bSYour Name 			struct mlo_partner_info *ml_info,
1033*5113495bSYour Name 			struct wlan_objmgr_vdev *link_vdevs[])
1034*5113495bSYour Name {
1035*5113495bSYour Name 	uint16_t i, j;
1036*5113495bSYour Name 	struct wlan_objmgr_vdev *vdev_link;
1037*5113495bSYour Name 	uint8_t link_id;
1038*5113495bSYour Name 
1039*5113495bSYour Name 	if (!ml_dev) {
1040*5113495bSYour Name 		mlo_err("ml_dev is null");
1041*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
1042*5113495bSYour Name 	}
1043*5113495bSYour Name 
1044*5113495bSYour Name 	if (!ml_info) {
1045*5113495bSYour Name 		mlo_err("ml_info is null");
1046*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
1047*5113495bSYour Name 	}
1048*5113495bSYour Name 
1049*5113495bSYour Name 	mlo_debug("num_partner_links %d", ml_info->num_partner_links);
1050*5113495bSYour Name 	for (i = 0; i < ml_info->num_partner_links; i++) {
1051*5113495bSYour Name 		link_id = ml_info->partner_link_info[i].link_id;
1052*5113495bSYour Name 		vdev_link = mlo_get_vdev_by_link_id(vdev, link_id,
1053*5113495bSYour Name 						    WLAN_MLO_MGR_ID);
1054*5113495bSYour Name 		if (vdev_link) {
1055*5113495bSYour Name 			link_vdevs[i] = vdev_link;
1056*5113495bSYour Name 		} else {
1057*5113495bSYour Name 			/* release ref which were taken before failure */
1058*5113495bSYour Name 			for (j = 0; j < i; j++) {
1059*5113495bSYour Name 				vdev_link = link_vdevs[j];
1060*5113495bSYour Name 				if (!vdev_link)
1061*5113495bSYour Name 					continue;
1062*5113495bSYour Name 
1063*5113495bSYour Name 				wlan_objmgr_vdev_release_ref(vdev_link,
1064*5113495bSYour Name 							     WLAN_MLO_MGR_ID);
1065*5113495bSYour Name 			}
1066*5113495bSYour Name 			return QDF_STATUS_E_INVAL;
1067*5113495bSYour Name 		}
1068*5113495bSYour Name 	}
1069*5113495bSYour Name 
1070*5113495bSYour Name 	return QDF_STATUS_SUCCESS;
1071*5113495bSYour Name }
1072*5113495bSYour Name #endif
1073*5113495bSYour Name 
mlo_dev_release_link_vdevs(struct wlan_objmgr_vdev * link_vdevs[])1074*5113495bSYour Name static void mlo_dev_release_link_vdevs(
1075*5113495bSYour Name 			struct wlan_objmgr_vdev *link_vdevs[])
1076*5113495bSYour Name {
1077*5113495bSYour Name 	uint16_t i;
1078*5113495bSYour Name 	struct wlan_objmgr_vdev *vdev_link;
1079*5113495bSYour Name 
1080*5113495bSYour Name 	for (i = 0; i < WLAN_UMAC_MLO_MAX_VDEVS; i++) {
1081*5113495bSYour Name 		vdev_link = link_vdevs[i];
1082*5113495bSYour Name 		if (!vdev_link)
1083*5113495bSYour Name 			continue;
1084*5113495bSYour Name 
1085*5113495bSYour Name 		wlan_objmgr_vdev_release_ref(vdev_link, WLAN_MLO_MGR_ID);
1086*5113495bSYour Name 	}
1087*5113495bSYour Name }
1088*5113495bSYour Name 
1089*5113495bSYour Name #ifdef WLAN_FEATURE_11BE
1090*5113495bSYour Name static void
wlan_mlo_peer_set_t2lm_enable_val(struct wlan_mlo_peer_context * ml_peer,struct mlo_partner_info * ml_info)1091*5113495bSYour Name wlan_mlo_peer_set_t2lm_enable_val(struct wlan_mlo_peer_context *ml_peer,
1092*5113495bSYour Name 				  struct mlo_partner_info *ml_info)
1093*5113495bSYour Name {
1094*5113495bSYour Name 	ml_peer->t2lm_policy.t2lm_enable_val = ml_info->t2lm_enable_val;
1095*5113495bSYour Name }
1096*5113495bSYour Name 
1097*5113495bSYour Name static void
wlan_mlo_peer_initialize_epcs_info(struct wlan_mlo_peer_context * ml_peer)1098*5113495bSYour Name wlan_mlo_peer_initialize_epcs_info(struct wlan_mlo_peer_context *ml_peer)
1099*5113495bSYour Name {
1100*5113495bSYour Name 	ml_peer->epcs_info.state = EPCS_DOWN;
1101*5113495bSYour Name 	ml_peer->epcs_info.self_gen_dialog_token = 0;
1102*5113495bSYour Name }
1103*5113495bSYour Name 
1104*5113495bSYour Name #else
1105*5113495bSYour Name static void
wlan_mlo_peer_set_t2lm_enable_val(struct wlan_mlo_peer_context * ml_peer,struct mlo_partner_info * ml_info)1106*5113495bSYour Name wlan_mlo_peer_set_t2lm_enable_val(struct wlan_mlo_peer_context *ml_peer,
1107*5113495bSYour Name 				  struct mlo_partner_info *ml_info)
1108*5113495bSYour Name {}
1109*5113495bSYour Name 
1110*5113495bSYour Name static void
wlan_mlo_peer_initialize_epcs_info(struct wlan_mlo_peer_context * ml_peer)1111*5113495bSYour Name wlan_mlo_peer_initialize_epcs_info(struct wlan_mlo_peer_context *ml_peer)
1112*5113495bSYour Name {}
1113*5113495bSYour Name #endif /* WLAN_FEATURE_11BE */
1114*5113495bSYour Name 
1115*5113495bSYour Name #if defined(WLAN_FEATURE_11BE_MLO) && defined(WLAN_MLO_MULTI_CHIP)
1116*5113495bSYour Name struct wlan_objmgr_vdev*
mlo_get_link_vdev_from_psoc_id(struct wlan_mlo_dev_context * ml_dev,uint8_t psoc_id,bool get_bridge_vdev)1117*5113495bSYour Name mlo_get_link_vdev_from_psoc_id(struct wlan_mlo_dev_context *ml_dev,
1118*5113495bSYour Name 			       uint8_t psoc_id, bool get_bridge_vdev)
1119*5113495bSYour Name {
1120*5113495bSYour Name 	uint8_t i;
1121*5113495bSYour Name 	uint16_t num_bridge_vdev = 0;
1122*5113495bSYour Name 	uint8_t max_vdevs = WLAN_UMAC_MLO_MAX_BRIDGE_VDEVS;
1123*5113495bSYour Name 	struct wlan_objmgr_vdev *link_vdev;
1124*5113495bSYour Name 	QDF_STATUS status;
1125*5113495bSYour Name 
1126*5113495bSYour Name 	if (WLAN_OBJMGR_MAX_DEVICES <= psoc_id)
1127*5113495bSYour Name 		return NULL;
1128*5113495bSYour Name 
1129*5113495bSYour Name 	if (!ml_dev)
1130*5113495bSYour Name 		return NULL;
1131*5113495bSYour Name 
1132*5113495bSYour Name 	/* if there are no bridge vdevs available,
1133*5113495bSYour Name 	 * fall back to actual link vdevs
1134*5113495bSYour Name 	 */
1135*5113495bSYour Name 	status = mlo_ap_get_bridge_vdev_count(ml_dev, &num_bridge_vdev);
1136*5113495bSYour Name 	if (!get_bridge_vdev || (status != QDF_STATUS_SUCCESS) ||
1137*5113495bSYour Name 	    !num_bridge_vdev)
1138*5113495bSYour Name 		max_vdevs = WLAN_UMAC_MLO_MAX_VDEVS;
1139*5113495bSYour Name 
1140*5113495bSYour Name 	for (i = 0; i < max_vdevs; i++) {
1141*5113495bSYour Name 		if (max_vdevs == WLAN_UMAC_MLO_MAX_BRIDGE_VDEVS)
1142*5113495bSYour Name 			link_vdev = ml_dev->wlan_bridge_vdev_list[i];
1143*5113495bSYour Name 		else
1144*5113495bSYour Name 			link_vdev = ml_dev->wlan_vdev_list[i];
1145*5113495bSYour Name 		if (!link_vdev)
1146*5113495bSYour Name 			continue;
1147*5113495bSYour Name 		if (psoc_id != wlan_vdev_get_psoc_id(link_vdev))
1148*5113495bSYour Name 			continue;
1149*5113495bSYour Name 		if (wlan_objmgr_vdev_try_get_ref(link_vdev, WLAN_MLO_MGR_ID) !=
1150*5113495bSYour Name 							QDF_STATUS_SUCCESS) {
1151*5113495bSYour Name 			mlo_err("VDEV is not in created state");
1152*5113495bSYour Name 			return NULL;
1153*5113495bSYour Name 		}
1154*5113495bSYour Name 		return link_vdev;
1155*5113495bSYour Name 	}
1156*5113495bSYour Name 
1157*5113495bSYour Name 	return NULL;
1158*5113495bSYour Name }
1159*5113495bSYour Name 
1160*5113495bSYour Name static
mlo_bridge_peer_create_post(struct wlan_mlo_dev_context * ml_dev,struct wlan_mlo_peer_context * ml_peer,uint8_t psoc_id)1161*5113495bSYour Name QDF_STATUS mlo_bridge_peer_create_post(struct wlan_mlo_dev_context *ml_dev,
1162*5113495bSYour Name 				       struct wlan_mlo_peer_context *ml_peer,
1163*5113495bSYour Name 				       uint8_t psoc_id)
1164*5113495bSYour Name {
1165*5113495bSYour Name 	struct peer_create_notif_s peer_create;
1166*5113495bSYour Name 	struct wlan_objmgr_vdev *vdev_link;
1167*5113495bSYour Name 	QDF_STATUS status;
1168*5113495bSYour Name 
1169*5113495bSYour Name 	/* Bridge peer not required */
1170*5113495bSYour Name 	if (psoc_id >= WLAN_OBJMGR_MAX_DEVICES)
1171*5113495bSYour Name 		return QDF_STATUS_SUCCESS;
1172*5113495bSYour Name 
1173*5113495bSYour Name 	vdev_link = mlo_get_link_vdev_from_psoc_id(ml_dev, psoc_id, true);
1174*5113495bSYour Name 
1175*5113495bSYour Name 	if (!vdev_link) {
1176*5113495bSYour Name 		mlo_err("VDEV derivation in unsuccessful for %u psoc",
1177*5113495bSYour Name 			psoc_id);
1178*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
1179*5113495bSYour Name 	}
1180*5113495bSYour Name 
1181*5113495bSYour Name 	peer_create.vdev_link = vdev_link;
1182*5113495bSYour Name 	wlan_mlo_peer_get_ref(ml_peer);
1183*5113495bSYour Name 	peer_create.ml_peer = ml_peer;
1184*5113495bSYour Name 
1185*5113495bSYour Name 	qdf_copy_macaddr(&peer_create.addr,
1186*5113495bSYour Name 			 &ml_peer->peer_mld_addr);
1187*5113495bSYour Name 
1188*5113495bSYour Name 	peer_create.frm_buf = NULL;
1189*5113495bSYour Name 
1190*5113495bSYour Name 	status = mlo_msgq_post(MLO_BRIDGE_PEER_CREATE, ml_dev, &peer_create);
1191*5113495bSYour Name 	if (status != QDF_STATUS_SUCCESS) {
1192*5113495bSYour Name 		wlan_mlo_peer_release_ref(ml_peer);
1193*5113495bSYour Name 		wlan_objmgr_vdev_release_ref(vdev_link, WLAN_MLO_MGR_ID);
1194*5113495bSYour Name 	}
1195*5113495bSYour Name 
1196*5113495bSYour Name 	return status;
1197*5113495bSYour Name }
1198*5113495bSYour Name 
1199*5113495bSYour Name static QDF_STATUS
wlan_mlo_get_bridge_peer_psoc_id(struct wlan_objmgr_vdev * vdev,struct wlan_mlo_peer_context * ml_peer,struct wlan_objmgr_vdev * link_vdevs[],uint8_t num_partner_links,uint8_t * bridge_psoc_id)1200*5113495bSYour Name wlan_mlo_get_bridge_peer_psoc_id(struct wlan_objmgr_vdev *vdev,
1201*5113495bSYour Name 				 struct wlan_mlo_peer_context *ml_peer,
1202*5113495bSYour Name 				 struct wlan_objmgr_vdev *link_vdevs[],
1203*5113495bSYour Name 				 uint8_t num_partner_links,
1204*5113495bSYour Name 				 uint8_t *bridge_psoc_id)
1205*5113495bSYour Name {
1206*5113495bSYour Name 	struct wlan_mlo_dev_context *ml_dev;
1207*5113495bSYour Name 	struct wlan_objmgr_vdev *ml_vdev;
1208*5113495bSYour Name 	uint8_t psoc_ids[WLAN_NUM_TWO_LINK_PSOC];
1209*5113495bSYour Name 	uint8_t comp_psoc_id, i, is_adjacent;
1210*5113495bSYour Name 	uint8_t bridge_peer_psoc_id = WLAN_OBJMGR_MAX_DEVICES;
1211*5113495bSYour Name 	uint16_t num_bridge_vdev = 0;
1212*5113495bSYour Name 	uint8_t max_vdevs = WLAN_UMAC_MLO_MAX_BRIDGE_VDEVS;
1213*5113495bSYour Name 	QDF_STATUS status;
1214*5113495bSYour Name 
1215*5113495bSYour Name 	if (wlan_vdev_mlme_get_opmode(vdev) != QDF_SAP_MODE)
1216*5113495bSYour Name 		return QDF_STATUS_SUCCESS;
1217*5113495bSYour Name 
1218*5113495bSYour Name 	/* Return from here for 3 link association */
1219*5113495bSYour Name 	if (WLAN_NUM_TWO_LINK_PSOC != num_partner_links)
1220*5113495bSYour Name 		return QDF_STATUS_SUCCESS;
1221*5113495bSYour Name 
1222*5113495bSYour Name 	ml_dev = vdev->mlo_dev_ctx;
1223*5113495bSYour Name 	if (!ml_dev)
1224*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
1225*5113495bSYour Name 
1226*5113495bSYour Name 	for (i = 0; i < WLAN_NUM_TWO_LINK_PSOC; i++)
1227*5113495bSYour Name 		psoc_ids[i] = wlan_vdev_get_psoc_id(link_vdevs[i]);
1228*5113495bSYour Name 
1229*5113495bSYour Name 	status = mlo_chip_adjacent(psoc_ids[0], psoc_ids[1],
1230*5113495bSYour Name 				   &is_adjacent);
1231*5113495bSYour Name 	if (QDF_STATUS_SUCCESS != status) {
1232*5113495bSYour Name 		mlo_err("Unable to get chip adjacency for " QDF_MAC_ADDR_FMT ", psoc_0 %u, psoc_1 %u",
1233*5113495bSYour Name 			QDF_MAC_ADDR_REF(ml_peer->peer_mld_addr.bytes),
1234*5113495bSYour Name 			psoc_ids[0], psoc_ids[1]);
1235*5113495bSYour Name 		return status;
1236*5113495bSYour Name 	}
1237*5113495bSYour Name 
1238*5113495bSYour Name 	if (is_adjacent)
1239*5113495bSYour Name 		return QDF_STATUS_SUCCESS;
1240*5113495bSYour Name 
1241*5113495bSYour Name 	/* if there are no bridge vdevs available,
1242*5113495bSYour Name 	 * fall back to actual link vdevs
1243*5113495bSYour Name 	 */
1244*5113495bSYour Name 	status = mlo_ap_get_bridge_vdev_count(ml_dev, &num_bridge_vdev);
1245*5113495bSYour Name 	if ((status != QDF_STATUS_SUCCESS) || !num_bridge_vdev) {
1246*5113495bSYour Name 		mlo_err_rl("Using actual vdev as bridge vdev");
1247*5113495bSYour Name 		max_vdevs = WLAN_UMAC_MLO_MAX_VDEVS;
1248*5113495bSYour Name 	}
1249*5113495bSYour Name 
1250*5113495bSYour Name 	for (i = 0; i < max_vdevs; i++) {
1251*5113495bSYour Name 		if (max_vdevs == WLAN_UMAC_MLO_MAX_BRIDGE_VDEVS)
1252*5113495bSYour Name 			ml_vdev = ml_dev->wlan_bridge_vdev_list[i];
1253*5113495bSYour Name 		else
1254*5113495bSYour Name 			ml_vdev = ml_dev->wlan_vdev_list[i];
1255*5113495bSYour Name 		if (!ml_vdev || (wlan_vdev_is_up(ml_vdev) != QDF_STATUS_SUCCESS))
1256*5113495bSYour Name 			continue;
1257*5113495bSYour Name 		comp_psoc_id = wlan_vdev_get_psoc_id(ml_vdev);
1258*5113495bSYour Name 		if ((comp_psoc_id != psoc_ids[0]) &&
1259*5113495bSYour Name 		    (comp_psoc_id != psoc_ids[1])) {
1260*5113495bSYour Name 			bridge_peer_psoc_id = comp_psoc_id;
1261*5113495bSYour Name 			break;
1262*5113495bSYour Name 		}
1263*5113495bSYour Name 	}
1264*5113495bSYour Name 
1265*5113495bSYour Name 	if (bridge_peer_psoc_id >= WLAN_OBJMGR_MAX_DEVICES) {
1266*5113495bSYour Name 		mlo_err("Invalid psoc or psoc not found for " QDF_MAC_ADDR_FMT " psoc %u",
1267*5113495bSYour Name 			ether_sprintf(ml_peer->peer_mld_addr.bytes),
1268*5113495bSYour Name 			bridge_peer_psoc_id);
1269*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
1270*5113495bSYour Name 	}
1271*5113495bSYour Name 
1272*5113495bSYour Name 	/* Check if derived psoc is adjecent to both links */
1273*5113495bSYour Name 	for (i = 0; i < WLAN_NUM_TWO_LINK_PSOC; i++) {
1274*5113495bSYour Name 		status = mlo_chip_adjacent(psoc_ids[i], bridge_peer_psoc_id,
1275*5113495bSYour Name 					   &is_adjacent);
1276*5113495bSYour Name 		if (QDF_STATUS_SUCCESS != status) {
1277*5113495bSYour Name 			mlo_err("Unable to get chip adjacency for " QDF_MAC_ADDR_FMT ", psoc_0 %u, psoc_1 %u",
1278*5113495bSYour Name 				QDF_MAC_ADDR_REF(ml_peer->peer_mld_addr.bytes),
1279*5113495bSYour Name 				psoc_ids[i], bridge_peer_psoc_id);
1280*5113495bSYour Name 			return status;
1281*5113495bSYour Name 		}
1282*5113495bSYour Name 		if (!is_adjacent) {
1283*5113495bSYour Name 			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",
1284*5113495bSYour Name 				QDF_MAC_ADDR_REF(ml_peer->peer_mld_addr.bytes),
1285*5113495bSYour Name 				psoc_ids[0], psoc_ids[1], bridge_peer_psoc_id);
1286*5113495bSYour Name 			return QDF_STATUS_E_FAILURE;
1287*5113495bSYour Name 		}
1288*5113495bSYour Name 	}
1289*5113495bSYour Name 
1290*5113495bSYour Name 	/* Add vdev corresponds to bridge link to link_vdevs so
1291*5113495bSYour Name 	 * that primary UMAC derivation follows 3-link assoc.
1292*5113495bSYour Name 	 */
1293*5113495bSYour Name 	for (i = 0; i < WLAN_UMAC_MLO_MAX_VDEVS; i++) {
1294*5113495bSYour Name 		if (link_vdevs[i])
1295*5113495bSYour Name 			continue;
1296*5113495bSYour Name 
1297*5113495bSYour Name 		link_vdevs[i] = mlo_get_link_vdev_from_psoc_id(ml_dev,
1298*5113495bSYour Name 							       bridge_peer_psoc_id,
1299*5113495bSYour Name 							       true);
1300*5113495bSYour Name 		if (!link_vdevs[i])
1301*5113495bSYour Name 			return QDF_STATUS_E_FAILURE;
1302*5113495bSYour Name 
1303*5113495bSYour Name 		ml_peer->max_links++;
1304*5113495bSYour Name 		*bridge_psoc_id = bridge_peer_psoc_id;
1305*5113495bSYour Name 		break;
1306*5113495bSYour Name 	}
1307*5113495bSYour Name 
1308*5113495bSYour Name 	if (i == WLAN_UMAC_MLO_MAX_VDEVS) {
1309*5113495bSYour Name 		mlo_err("Unable to append bridge peer vdev to link vdev list");
1310*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
1311*5113495bSYour Name 	}
1312*5113495bSYour Name 
1313*5113495bSYour Name 	mlo_debug("%u is adjecent psoc for " QDF_MAC_ADDR_FMT " is_adjacent %u",
1314*5113495bSYour Name 		  bridge_peer_psoc_id,
1315*5113495bSYour Name 		  QDF_MAC_ADDR_REF(ml_peer->peer_mld_addr.bytes),
1316*5113495bSYour Name 		  is_adjacent);
1317*5113495bSYour Name 
1318*5113495bSYour Name 	return status;
1319*5113495bSYour Name }
1320*5113495bSYour Name #else
1321*5113495bSYour Name static
mlo_bridge_peer_create_post(struct wlan_mlo_dev_context * ml_dev,struct wlan_mlo_peer_context * ml_peer,uint8_t psoc_id)1322*5113495bSYour Name QDF_STATUS mlo_bridge_peer_create_post(struct wlan_mlo_dev_context *ml_dev,
1323*5113495bSYour Name 				       struct wlan_mlo_peer_context *ml_peer,
1324*5113495bSYour Name 				       uint8_t psoc_id)
1325*5113495bSYour Name {
1326*5113495bSYour Name 	return QDF_STATUS_SUCCESS;
1327*5113495bSYour Name }
1328*5113495bSYour Name 
1329*5113495bSYour Name static QDF_STATUS
wlan_mlo_get_bridge_peer_psoc_id(struct wlan_objmgr_vdev * vdev,struct wlan_mlo_peer_context * ml_peer,struct wlan_objmgr_vdev * link_vdevs[],uint8_t num_partner_links,uint8_t * bridge_psoc_id)1330*5113495bSYour Name wlan_mlo_get_bridge_peer_psoc_id(struct wlan_objmgr_vdev *vdev,
1331*5113495bSYour Name 				 struct wlan_mlo_peer_context *ml_peer,
1332*5113495bSYour Name 				 struct wlan_objmgr_vdev *link_vdevs[],
1333*5113495bSYour Name 				 uint8_t num_partner_links,
1334*5113495bSYour Name 				 uint8_t *bridge_psoc_id)
1335*5113495bSYour Name {
1336*5113495bSYour Name 	return QDF_STATUS_SUCCESS;
1337*5113495bSYour Name }
1338*5113495bSYour Name #endif
1339*5113495bSYour Name 
wlan_mlo_peer_asreq(struct wlan_objmgr_vdev * vdev,struct wlan_objmgr_peer * link_peer,struct mlo_partner_info * ml_info,qdf_nbuf_t frm_buf)1340*5113495bSYour Name QDF_STATUS wlan_mlo_peer_asreq(struct wlan_objmgr_vdev *vdev,
1341*5113495bSYour Name 			       struct wlan_objmgr_peer *link_peer,
1342*5113495bSYour Name 			       struct mlo_partner_info *ml_info,
1343*5113495bSYour Name 			       qdf_nbuf_t frm_buf)
1344*5113495bSYour Name {
1345*5113495bSYour Name 	struct wlan_mlo_dev_context *ml_dev;
1346*5113495bSYour Name 	struct wlan_mlo_peer_context *ml_peer = NULL;
1347*5113495bSYour Name 	struct wlan_objmgr_vdev *link_vdevs[WLAN_UMAC_MLO_MAX_VDEVS] = { NULL };
1348*5113495bSYour Name 	struct wlan_objmgr_vdev *vdev_link;
1349*5113495bSYour Name 	QDF_STATUS status;
1350*5113495bSYour Name 	uint16_t i;
1351*5113495bSYour Name 	uint16_t j;
1352*5113495bSYour Name 	uint16_t link_count;
1353*5113495bSYour Name 	struct wlan_mlo_link_peer_entry *peer_entry;
1354*5113495bSYour Name 	struct wlan_objmgr_peer *iter_peer;
1355*5113495bSYour Name 
1356*5113495bSYour Name 	/* get ML VDEV from VDEV */
1357*5113495bSYour Name 	ml_dev = vdev->mlo_dev_ctx;
1358*5113495bSYour Name 	if (!ml_dev) {
1359*5113495bSYour Name 		mlo_err("ML dev ctx is NULL");
1360*5113495bSYour Name 		return QDF_STATUS_E_NULL_VALUE;
1361*5113495bSYour Name 	}
1362*5113495bSYour Name 
1363*5113495bSYour Name 	ml_peer = link_peer->mlo_peer_ctx;
1364*5113495bSYour Name 	if (!ml_peer) {
1365*5113495bSYour Name 		mlo_err("MLD ID %d ML Peer " QDF_MAC_ADDR_FMT " ML peer is NULL",
1366*5113495bSYour Name 			ml_dev->mld_id,
1367*5113495bSYour Name 			QDF_MAC_ADDR_REF(link_peer->mldaddr));
1368*5113495bSYour Name 
1369*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
1370*5113495bSYour Name 	}
1371*5113495bSYour Name 
1372*5113495bSYour Name 	if (!wlan_mlo_peer_is_assoc_peer(ml_peer, link_peer)) {
1373*5113495bSYour Name 		mlo_err("MLD ID %d ML Peer " QDF_MAC_ADDR_FMT "Assoc req received on non-assoc peer" QDF_MAC_ADDR_FMT,
1374*5113495bSYour Name 			ml_dev->mld_id,
1375*5113495bSYour Name 			QDF_MAC_ADDR_REF(link_peer->mldaddr),
1376*5113495bSYour Name 			QDF_MAC_ADDR_REF(link_peer->macaddr));
1377*5113495bSYour Name 
1378*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
1379*5113495bSYour Name 	}
1380*5113495bSYour Name 
1381*5113495bSYour Name 	status = mlo_dev_get_link_vdevs(vdev, ml_dev,
1382*5113495bSYour Name 					ml_info, link_vdevs);
1383*5113495bSYour Name 	if (QDF_IS_STATUS_ERROR(status)) {
1384*5113495bSYour Name 		mlo_err("MLD ID %d ML Peer " QDF_MAC_ADDR_FMT " get link vdevs failed",
1385*5113495bSYour Name 			ml_dev->mld_id,
1386*5113495bSYour Name 			QDF_MAC_ADDR_REF(link_peer->mldaddr));
1387*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
1388*5113495bSYour Name 	}
1389*5113495bSYour Name 
1390*5113495bSYour Name 	/* If ML peer state is not in Assoc done state, drop REASSOC req */
1391*5113495bSYour Name 	if (ml_peer->mlpeer_state != ML_PEER_ASSOC_DONE) {
1392*5113495bSYour Name 		mlo_err("MLD ID %d ML Peer " QDF_MAC_ADDR_FMT " invalid state %d",
1393*5113495bSYour Name 			ml_dev->mld_id,
1394*5113495bSYour Name 			QDF_MAC_ADDR_REF(link_peer->mldaddr),
1395*5113495bSYour Name 			ml_peer->mlpeer_state);
1396*5113495bSYour Name 
1397*5113495bSYour Name 		mlo_dev_release_link_vdevs(link_vdevs);
1398*5113495bSYour Name 
1399*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
1400*5113495bSYour Name 	}
1401*5113495bSYour Name 
1402*5113495bSYour Name 	link_count = 0;
1403*5113495bSYour Name 	for (j = 0; j < ml_peer->max_links; j++) {
1404*5113495bSYour Name 		peer_entry = &ml_peer->peer_list[j];
1405*5113495bSYour Name 		iter_peer = peer_entry->link_peer;
1406*5113495bSYour Name 		if (!iter_peer)
1407*5113495bSYour Name 			continue;
1408*5113495bSYour Name 
1409*5113495bSYour Name 		if (wlan_peer_get_peer_type(iter_peer) ==
1410*5113495bSYour Name 						WLAN_PEER_MLO_BRIDGE) {
1411*5113495bSYour Name 			link_count++;
1412*5113495bSYour Name 			continue;
1413*5113495bSYour Name 		}
1414*5113495bSYour Name 
1415*5113495bSYour Name 		for (i = 0; i < WLAN_UMAC_MLO_MAX_VDEVS; i++) {
1416*5113495bSYour Name 			vdev_link = link_vdevs[i];
1417*5113495bSYour Name 			if (!vdev_link)
1418*5113495bSYour Name 				continue;
1419*5113495bSYour Name 
1420*5113495bSYour Name 			if (vdev_link != wlan_peer_get_vdev(iter_peer))
1421*5113495bSYour Name 				continue;
1422*5113495bSYour Name 
1423*5113495bSYour Name 			link_count++;
1424*5113495bSYour Name 			break;
1425*5113495bSYour Name 		}
1426*5113495bSYour Name 	}
1427*5113495bSYour Name 	if (link_count != ml_peer->link_peer_cnt) {
1428*5113495bSYour Name 		mlo_err("MLD ID %d ML Peer " QDF_MAC_ADDR_FMT " incorrect link peers",
1429*5113495bSYour Name 			ml_dev->mld_id,
1430*5113495bSYour Name 			QDF_MAC_ADDR_REF(link_peer->mldaddr));
1431*5113495bSYour Name 		mlo_dev_release_link_vdevs(link_vdevs);
1432*5113495bSYour Name 
1433*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
1434*5113495bSYour Name 	}
1435*5113495bSYour Name 
1436*5113495bSYour Name 	/* Notify other vdevs about assoc req */
1437*5113495bSYour Name 	for (i = 0; i < WLAN_UMAC_MLO_MAX_VDEVS; i++) {
1438*5113495bSYour Name 		vdev_link = link_vdevs[i];
1439*5113495bSYour Name 		if (!vdev_link)
1440*5113495bSYour Name 			continue;
1441*5113495bSYour Name 
1442*5113495bSYour Name 		if (vdev_link == vdev)
1443*5113495bSYour Name 			continue;
1444*5113495bSYour Name 
1445*5113495bSYour Name 		mlo_partner_peer_reassoc_post(ml_dev, vdev_link,
1446*5113495bSYour Name 					      ml_peer, frm_buf, ml_info);
1447*5113495bSYour Name 	}
1448*5113495bSYour Name 
1449*5113495bSYour Name 	mlo_dev_release_link_vdevs(link_vdevs);
1450*5113495bSYour Name 
1451*5113495bSYour Name 	if (QDF_IS_STATUS_ERROR(wlan_mlo_validate_reassocreq(ml_peer))) {
1452*5113495bSYour Name 		mlo_info("MLD ID %d ML Peer " QDF_MAC_ADDR_FMT " reassoc proc is failed %pK",
1453*5113495bSYour Name 			 ml_dev->mld_id,
1454*5113495bSYour Name 			 QDF_MAC_ADDR_REF(ml_peer->peer_mld_addr.bytes),
1455*5113495bSYour Name 			 ml_peer);
1456*5113495bSYour Name 
1457*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
1458*5113495bSYour Name 	}
1459*5113495bSYour Name 
1460*5113495bSYour Name 	mlo_info("MLD ID %d ML Peer " QDF_MAC_ADDR_FMT " reassoc handled %pK",
1461*5113495bSYour Name 		 ml_dev->mld_id,
1462*5113495bSYour Name 		 QDF_MAC_ADDR_REF(ml_peer->peer_mld_addr.bytes),
1463*5113495bSYour Name 		 ml_peer);
1464*5113495bSYour Name 
1465*5113495bSYour Name 	return QDF_STATUS_SUCCESS;
1466*5113495bSYour Name }
1467*5113495bSYour Name #if defined (SAP_MULTI_LINK_EMULATION)
1468*5113495bSYour Name static void
set_assoc_peer_for_2link_sap(struct wlan_objmgr_peer * assoc_peer,struct wlan_mlo_peer_context * ml_peer)1469*5113495bSYour Name set_assoc_peer_for_2link_sap(struct wlan_objmgr_peer *assoc_peer,
1470*5113495bSYour Name 			     struct wlan_mlo_peer_context *ml_peer)
1471*5113495bSYour Name {
1472*5113495bSYour Name 	assoc_peer = ml_peer->peer_list[0].link_peer;
1473*5113495bSYour Name 	if (assoc_peer)
1474*5113495bSYour Name 		mlo_mlme_peer_assoc_resp(assoc_peer);
1475*5113495bSYour Name }
1476*5113495bSYour Name #else
1477*5113495bSYour Name static void
set_assoc_peer_for_2link_sap(struct wlan_objmgr_peer * assoc_peer,struct wlan_mlo_peer_context * ml_peer)1478*5113495bSYour Name set_assoc_peer_for_2link_sap(struct wlan_objmgr_peer *assoc_peer,
1479*5113495bSYour Name 			     struct wlan_mlo_peer_context *ml_peer)
1480*5113495bSYour Name {
1481*5113495bSYour Name }
1482*5113495bSYour Name #endif
wlan_mlo_peer_create(struct wlan_objmgr_vdev * vdev,struct wlan_objmgr_peer * link_peer,struct mlo_partner_info * ml_info,qdf_nbuf_t frm_buf,uint16_t aid)1483*5113495bSYour Name QDF_STATUS wlan_mlo_peer_create(struct wlan_objmgr_vdev *vdev,
1484*5113495bSYour Name 				struct wlan_objmgr_peer *link_peer,
1485*5113495bSYour Name 				struct mlo_partner_info *ml_info,
1486*5113495bSYour Name 				qdf_nbuf_t frm_buf,
1487*5113495bSYour Name 				uint16_t aid)
1488*5113495bSYour Name {
1489*5113495bSYour Name 	struct wlan_mlo_dev_context *ml_dev;
1490*5113495bSYour Name 	struct wlan_mlo_peer_context *ml_peer = NULL;
1491*5113495bSYour Name 	struct wlan_objmgr_vdev *link_vdevs[WLAN_UMAC_MLO_MAX_VDEVS] = { NULL };
1492*5113495bSYour Name 	struct wlan_objmgr_vdev *tmp_link_vdevs[WLAN_UMAC_MLO_MAX_VDEVS] = { NULL };
1493*5113495bSYour Name 	struct wlan_objmgr_vdev *vdev_link;
1494*5113495bSYour Name 	QDF_STATUS status;
1495*5113495bSYour Name 	uint16_t i, j;
1496*5113495bSYour Name 	struct wlan_objmgr_peer *assoc_peer = NULL;
1497*5113495bSYour Name 	uint8_t bridge_peer_psoc_id = WLAN_OBJMGR_MAX_DEVICES;
1498*5113495bSYour Name 	bool is_ml_peer_attached = false;
1499*5113495bSYour Name 
1500*5113495bSYour Name 	/* get ML VDEV from VDEV */
1501*5113495bSYour Name 	ml_dev = vdev->mlo_dev_ctx;
1502*5113495bSYour Name 
1503*5113495bSYour Name 	if (!ml_dev) {
1504*5113495bSYour Name 		mlo_err("ML dev ctx is NULL");
1505*5113495bSYour Name 		return QDF_STATUS_E_NULL_VALUE;
1506*5113495bSYour Name 	}
1507*5113495bSYour Name 
1508*5113495bSYour Name 	/* Check resources of Partner VDEV */
1509*5113495bSYour Name 	if (wlan_vdev_mlme_get_opmode(vdev) == QDF_SAP_MODE) {
1510*5113495bSYour Name 		if (wlan_mlo_is_mld_ctx_exist(
1511*5113495bSYour Name 		    (struct qdf_mac_addr *)&link_peer->mldaddr[0])) {
1512*5113495bSYour Name 			mlo_err("MLD ID %d ML Peer " QDF_MAC_ADDR_FMT " is matching with one of the MLD address in the system",
1513*5113495bSYour Name 				ml_dev->mld_id,
1514*5113495bSYour Name 				QDF_MAC_ADDR_REF(link_peer->mldaddr));
1515*5113495bSYour Name 			return QDF_STATUS_E_FAILURE;
1516*5113495bSYour Name 		}
1517*5113495bSYour Name 		/* Limit max assoc links */
1518*5113495bSYour Name 		if (ml_info->num_partner_links > WLAN_UMAC_MLO_ASSOC_MAX_SUPPORTED_LINKS) {
1519*5113495bSYour Name 			mlo_err("MLD ID %d ML Peer " QDF_MAC_ADDR_FMT " exceeds MAX assoc limit of %d",
1520*5113495bSYour Name 				ml_dev->mld_id,
1521*5113495bSYour Name 				QDF_MAC_ADDR_REF(link_peer->mldaddr),
1522*5113495bSYour Name 				WLAN_UMAC_MLO_ASSOC_MAX_SUPPORTED_LINKS);
1523*5113495bSYour Name 			return QDF_STATUS_E_RESOURCES;
1524*5113495bSYour Name 		}
1525*5113495bSYour Name 
1526*5113495bSYour Name 		status = mlo_dev_get_link_vdevs(vdev, ml_dev,
1527*5113495bSYour Name 						ml_info, link_vdevs);
1528*5113495bSYour Name 		if (QDF_IS_STATUS_ERROR(status)) {
1529*5113495bSYour Name 			mlo_err("MLD ID %d ML Peer " QDF_MAC_ADDR_FMT " get link vdevs failed",
1530*5113495bSYour Name 				ml_dev->mld_id,
1531*5113495bSYour Name 				QDF_MAC_ADDR_REF(link_peer->mldaddr));
1532*5113495bSYour Name 			return QDF_STATUS_E_FAILURE;
1533*5113495bSYour Name 		}
1534*5113495bSYour Name 		for (i = 0; i < WLAN_UMAC_MLO_MAX_VDEVS; i++) {
1535*5113495bSYour Name 			vdev_link = link_vdevs[i];
1536*5113495bSYour Name 			if (!vdev_link) {
1537*5113495bSYour Name 				mlo_debug("vdev_link is null");
1538*5113495bSYour Name 				continue;
1539*5113495bSYour Name 			}
1540*5113495bSYour Name 
1541*5113495bSYour Name 			if (wlan_vdev_is_mlo_peer_create_allowed(vdev_link)
1542*5113495bSYour Name 					!= QDF_STATUS_SUCCESS) {
1543*5113495bSYour Name 				mlo_dev_release_link_vdevs(link_vdevs);
1544*5113495bSYour Name 
1545*5113495bSYour Name 				mlo_err("MLD ID %d ML Peer " QDF_MAC_ADDR_FMT " create not allowed on link vdev %d",
1546*5113495bSYour Name 					ml_dev->mld_id,
1547*5113495bSYour Name 					QDF_MAC_ADDR_REF
1548*5113495bSYour Name 						(link_peer->mldaddr),
1549*5113495bSYour Name 					wlan_vdev_get_id(vdev_link));
1550*5113495bSYour Name 				return QDF_STATUS_E_INVAL;
1551*5113495bSYour Name 			}
1552*5113495bSYour Name 		}
1553*5113495bSYour Name 
1554*5113495bSYour Name 		for (i = 0; i < WLAN_UMAC_MLO_MAX_VDEVS; i++) {
1555*5113495bSYour Name 			vdev_link = link_vdevs[i];
1556*5113495bSYour Name 			if (vdev_link && (vdev_link != vdev) &&
1557*5113495bSYour Name 			    (wlan_vdev_get_peer_count(vdev_link) >
1558*5113495bSYour Name 			     wlan_vdev_get_max_peer_count(vdev_link))) {
1559*5113495bSYour Name 				mlo_dev_release_link_vdevs(link_vdevs);
1560*5113495bSYour Name 				mlo_err("MLD ID %d ML Peer " QDF_MAC_ADDR_FMT " Max peer count reached on link vdev %d",
1561*5113495bSYour Name 					ml_dev->mld_id,
1562*5113495bSYour Name 					QDF_MAC_ADDR_REF
1563*5113495bSYour Name 						(link_peer->mldaddr),
1564*5113495bSYour Name 					wlan_vdev_get_id(vdev_link));
1565*5113495bSYour Name 				return QDF_STATUS_E_RESOURCES;
1566*5113495bSYour Name 			}
1567*5113495bSYour Name 		}
1568*5113495bSYour Name 	}
1569*5113495bSYour Name 	/* When roam to MLO AP, partner link vdev1 is updated first,
1570*5113495bSYour Name 	 * ml peer need be created and attached for partner link peer.
1571*5113495bSYour Name 	 *
1572*5113495bSYour Name 	 * When roam target AP and current AP have same MLD address, don't
1573*5113495bSYour Name 	 * delete old ML peer and re-create new one, just update different
1574*5113495bSYour Name 	 * info.
1575*5113495bSYour Name 	 */
1576*5113495bSYour Name 	if (wlan_vdev_mlme_get_opmode(vdev) == QDF_STA_MODE) {
1577*5113495bSYour Name 		ml_peer = wlan_mlo_get_mlpeer(ml_dev,
1578*5113495bSYour Name 				 (struct qdf_mac_addr *)&link_peer->mldaddr[0]);
1579*5113495bSYour Name 		if (ml_peer) {
1580*5113495bSYour Name 			mlo_debug("ML Peer " QDF_MAC_ADDR_FMT
1581*5113495bSYour Name 				" existed, state %d",
1582*5113495bSYour Name 				QDF_MAC_ADDR_REF(ml_peer->peer_mld_addr.bytes),
1583*5113495bSYour Name 				ml_peer->mlpeer_state);
1584*5113495bSYour Name 			ml_peer->mlpeer_state = ML_PEER_CREATED;
1585*5113495bSYour Name 			ml_peer->max_links = ml_info->num_partner_links;
1586*5113495bSYour Name 			wlan_mlo_peer_set_t2lm_enable_val(ml_peer, ml_info);
1587*5113495bSYour Name 			is_ml_peer_attached = true;
1588*5113495bSYour Name 		}
1589*5113495bSYour Name 	}
1590*5113495bSYour Name 	if (!ml_peer) {
1591*5113495bSYour Name 		/* Allocate MLO peer */
1592*5113495bSYour Name 		ml_peer = qdf_mem_malloc(sizeof(*ml_peer));
1593*5113495bSYour Name 		if (!ml_peer) {
1594*5113495bSYour Name 			mlo_err("MLD ID %d ML Peer " QDF_MAC_ADDR_FMT " mem alloc failed",
1595*5113495bSYour Name 				ml_dev->mld_id,
1596*5113495bSYour Name 				QDF_MAC_ADDR_REF(link_peer->mldaddr));
1597*5113495bSYour Name 			mlo_dev_release_link_vdevs(link_vdevs);
1598*5113495bSYour Name 			return QDF_STATUS_E_NOMEM;
1599*5113495bSYour Name 		}
1600*5113495bSYour Name 
1601*5113495bSYour Name 		qdf_atomic_init(&ml_peer->ref_cnt);
1602*5113495bSYour Name 		mlo_peer_lock_create(ml_peer);
1603*5113495bSYour Name 		ml_peer->ml_dev = ml_dev;
1604*5113495bSYour Name 		ml_peer->mlpeer_state = ML_PEER_CREATED;
1605*5113495bSYour Name 		ml_peer->max_links = ml_info->num_partner_links;
1606*5113495bSYour Name 		ml_peer->primary_umac_psoc_id = ML_PRIMARY_UMAC_ID_INVAL;
1607*5113495bSYour Name 		ml_peer->migrate_primary_umac_psoc_id =
1608*5113495bSYour Name 						ML_PRIMARY_UMAC_ID_INVAL;
1609*5113495bSYour Name 		ml_peer->primary_umac_migration_in_progress = false;
1610*5113495bSYour Name 
1611*5113495bSYour Name 		ml_peer->mlo_peer_id = mlo_ap_ml_peerid_alloc();
1612*5113495bSYour Name 		if (ml_peer->mlo_peer_id == MLO_INVALID_PEER_ID) {
1613*5113495bSYour Name 			mlo_err("MLD ID %d ML Peer " QDF_MAC_ADDR_FMT " invalid ml peer id",
1614*5113495bSYour Name 				ml_dev->mld_id,
1615*5113495bSYour Name 				QDF_MAC_ADDR_REF
1616*5113495bSYour Name 				(ml_peer->peer_mld_addr.bytes));
1617*5113495bSYour Name 			mlo_peer_free(ml_peer);
1618*5113495bSYour Name 			mlo_dev_release_link_vdevs(link_vdevs);
1619*5113495bSYour Name 			return QDF_STATUS_E_RESOURCES;
1620*5113495bSYour Name 		}
1621*5113495bSYour Name 
1622*5113495bSYour Name 		qdf_copy_macaddr((struct qdf_mac_addr *)&ml_peer->peer_mld_addr,
1623*5113495bSYour Name 				 (struct qdf_mac_addr *)&link_peer->mldaddr[0]);
1624*5113495bSYour Name 		wlan_mlo_peer_set_t2lm_enable_val(ml_peer, ml_info);
1625*5113495bSYour Name 		epcs_dev_peer_lock_create(&ml_peer->epcs_info);
1626*5113495bSYour Name 		wlan_mlo_peer_initialize_epcs_info(ml_peer);
1627*5113495bSYour Name 
1628*5113495bSYour Name 		/* Allocate AID */
1629*5113495bSYour Name 		if (wlan_vdev_mlme_get_opmode(vdev) == QDF_SAP_MODE) {
1630*5113495bSYour Name 			if (aid == (uint16_t)-1) {
1631*5113495bSYour Name 				status = mlo_peer_allocate_aid(ml_dev, ml_peer);
1632*5113495bSYour Name 				if (status != QDF_STATUS_SUCCESS) {
1633*5113495bSYour Name 					mlo_err("MLD ID %d ML Peer " QDF_MAC_ADDR_FMT " aid alloc failed",
1634*5113495bSYour Name 						ml_dev->mld_id,
1635*5113495bSYour Name 						QDF_MAC_ADDR_REF
1636*5113495bSYour Name 						(ml_peer->peer_mld_addr.bytes));
1637*5113495bSYour Name 					mlo_peer_free(ml_peer);
1638*5113495bSYour Name 					mlo_dev_release_link_vdevs(link_vdevs);
1639*5113495bSYour Name 					return status;
1640*5113495bSYour Name 				}
1641*5113495bSYour Name 			} else {
1642*5113495bSYour Name 				ml_peer->assoc_id = aid;
1643*5113495bSYour Name 			}
1644*5113495bSYour Name 		}
1645*5113495bSYour Name 	}
1646*5113495bSYour Name 
1647*5113495bSYour Name 	/* Populate Link peer pointer, peer MAC address,
1648*5113495bSYour Name 	 * MLD address. HW link ID, update ref count
1649*5113495bSYour Name 	 */
1650*5113495bSYour Name 	status = mlo_peer_attach_link_peer(ml_peer, link_peer, NULL);
1651*5113495bSYour Name 	if (QDF_IS_STATUS_ERROR(status)) {
1652*5113495bSYour Name 		mlo_err("MLD ID %d ML Peer " QDF_MAC_ADDR_FMT " link peer attach failed",
1653*5113495bSYour Name 			ml_dev->mld_id,
1654*5113495bSYour Name 			QDF_MAC_ADDR_REF
1655*5113495bSYour Name 			(ml_peer->peer_mld_addr.bytes));
1656*5113495bSYour Name 		/* If there is another link peer attached for this ML peer,
1657*5113495bSYour Name 		 * ml peer can't be detached and freed.
1658*5113495bSYour Name 		 */
1659*5113495bSYour Name 		if (is_ml_peer_attached && ml_peer->link_peer_cnt)
1660*5113495bSYour Name 			return status;
1661*5113495bSYour Name 		if (is_ml_peer_attached)
1662*5113495bSYour Name 			mlo_dev_mlpeer_detach(ml_dev, ml_peer);
1663*5113495bSYour Name 		mlo_peer_free(ml_peer);
1664*5113495bSYour Name 		mlo_dev_release_link_vdevs(link_vdevs);
1665*5113495bSYour Name 		return status;
1666*5113495bSYour Name 	}
1667*5113495bSYour Name 
1668*5113495bSYour Name 	if (wlan_vdev_mlme_get_opmode(vdev) == QDF_SAP_MODE) {
1669*5113495bSYour Name 		for (i = 0; i < WLAN_UMAC_MLO_MAX_VDEVS; i++) {
1670*5113495bSYour Name 			if (!link_vdevs[i]) {
1671*5113495bSYour Name 				mlo_debug("vdev_link is null");
1672*5113495bSYour Name 				continue;
1673*5113495bSYour Name 			}
1674*5113495bSYour Name 
1675*5113495bSYour Name 			if (wlan_objmgr_vdev_try_get_ref(link_vdevs[i], WLAN_MLO_MGR_ID) !=
1676*5113495bSYour Name 					QDF_STATUS_SUCCESS) {
1677*5113495bSYour Name 				mlo_err("VDEV is not in created state");
1678*5113495bSYour Name 				/* release ref which were taken before failure */
1679*5113495bSYour Name 				for (j = 0; j < i; j++) {
1680*5113495bSYour Name 					if (!link_vdevs[i])
1681*5113495bSYour Name 						continue;
1682*5113495bSYour Name 
1683*5113495bSYour Name 					wlan_objmgr_vdev_release_ref(link_vdevs[i],
1684*5113495bSYour Name 								     WLAN_MLO_MGR_ID);
1685*5113495bSYour Name 				}
1686*5113495bSYour Name 				mlo_reset_link_peer(ml_peer, link_peer);
1687*5113495bSYour Name 				mlo_peer_free(ml_peer);
1688*5113495bSYour Name 				mlo_dev_release_link_vdevs(link_vdevs);
1689*5113495bSYour Name 
1690*5113495bSYour Name 				return QDF_STATUS_E_FAILURE;
1691*5113495bSYour Name 			}
1692*5113495bSYour Name 			tmp_link_vdevs[i] = link_vdevs[i];
1693*5113495bSYour Name 		}
1694*5113495bSYour Name 
1695*5113495bSYour Name 		status = wlan_mlo_get_bridge_peer_psoc_id(vdev, ml_peer,
1696*5113495bSYour Name 							  tmp_link_vdevs,
1697*5113495bSYour Name 							  ml_info->num_partner_links,
1698*5113495bSYour Name 							  &bridge_peer_psoc_id);
1699*5113495bSYour Name 		if (QDF_STATUS_SUCCESS != status) {
1700*5113495bSYour Name 			mlo_err("MLD ID %d: Failed to derive bridge peer psoc id",
1701*5113495bSYour Name 				ml_dev->mld_id);
1702*5113495bSYour Name 			mlo_reset_link_peer(ml_peer, link_peer);
1703*5113495bSYour Name 			mlo_peer_free(ml_peer);
1704*5113495bSYour Name 			mlo_dev_release_link_vdevs(link_vdevs);
1705*5113495bSYour Name 			mlo_dev_release_link_vdevs(tmp_link_vdevs);
1706*5113495bSYour Name 			wlan_objmgr_peer_release_ref(link_peer,
1707*5113495bSYour Name 						     WLAN_MLO_MGR_ID);
1708*5113495bSYour Name 			return QDF_STATUS_E_FAILURE;
1709*5113495bSYour Name 		}
1710*5113495bSYour Name 	}
1711*5113495bSYour Name 
1712*5113495bSYour Name 	/* Allocate Primary UMAC */
1713*5113495bSYour Name 	mlo_peer_allocate_primary_umac(ml_dev, ml_peer, tmp_link_vdevs);
1714*5113495bSYour Name 
1715*5113495bSYour Name 	if (wlan_vdev_mlme_get_opmode(vdev) == QDF_SAP_MODE)
1716*5113495bSYour Name 		mlo_dev_release_link_vdevs(tmp_link_vdevs);
1717*5113495bSYour Name 
1718*5113495bSYour Name 	/* Store AID, MLO Peer pointer in link peer, take link peer ref count */
1719*5113495bSYour Name 	mlo_peer_populate_link_peer(ml_peer, link_peer);
1720*5113495bSYour Name 
1721*5113495bSYour Name 	mlo_peer_populate_nawds_params(ml_peer, ml_info);
1722*5113495bSYour Name 	mlo_peer_populate_mesh_params(ml_peer, ml_info);
1723*5113495bSYour Name 
1724*5113495bSYour Name 	if ((wlan_vdev_mlme_get_opmode(vdev) == QDF_SAP_MODE) ||
1725*5113495bSYour Name 		((wlan_vdev_mlme_get_opmode(vdev) == QDF_STA_MODE) &&
1726*5113495bSYour Name 			!is_ml_peer_attached)) {
1727*5113495bSYour Name 		/* Reject creation for AP mode, If ML peer is present with
1728*5113495bSYour Name 		 * MLD MAC address, For PSTA case, all MLD STAs are connected
1729*5113495bSYour Name 		 * to same MLD AP, it can have duplicate MLD address entries
1730*5113495bSYour Name 		 * for STA MLDs
1731*5113495bSYour Name 		 */
1732*5113495bSYour Name 		if ((wlan_vdev_mlme_get_opmode(vdev) == QDF_SAP_MODE) &&
1733*5113495bSYour Name 		    mlo_mgr_ml_peer_exist_on_diff_ml_ctx(&link_peer->mldaddr[0],
1734*5113495bSYour Name 							 NULL)) {
1735*5113495bSYour Name 			mlo_err("MLD ID %d ML Peer " QDF_MAC_ADDR_FMT " is exists, creation failed",
1736*5113495bSYour Name 				ml_dev->mld_id,
1737*5113495bSYour Name 				QDF_MAC_ADDR_REF(ml_peer->peer_mld_addr.bytes));
1738*5113495bSYour Name 			mlo_reset_link_peer(ml_peer, link_peer);
1739*5113495bSYour Name 			mlo_peer_free(ml_peer);
1740*5113495bSYour Name 			mlo_dev_release_link_vdevs(link_vdevs);
1741*5113495bSYour Name 			wlan_objmgr_peer_release_ref(link_peer,
1742*5113495bSYour Name 						     WLAN_MLO_MGR_ID);
1743*5113495bSYour Name 			return QDF_STATUS_E_EXISTS;
1744*5113495bSYour Name 		}
1745*5113495bSYour Name 
1746*5113495bSYour Name 		/* Attach MLO peer to ML Peer table */
1747*5113495bSYour Name 		status = mlo_dev_mlpeer_attach(ml_dev, ml_peer);
1748*5113495bSYour Name 		if (status != QDF_STATUS_SUCCESS) {
1749*5113495bSYour Name 			mlo_err("MLD ID %d ML Peer " QDF_MAC_ADDR_FMT " attach failed",
1750*5113495bSYour Name 				ml_dev->mld_id,
1751*5113495bSYour Name 				QDF_MAC_ADDR_REF(ml_peer->peer_mld_addr.bytes));
1752*5113495bSYour Name 			mlo_reset_link_peer(ml_peer, link_peer);
1753*5113495bSYour Name 			wlan_objmgr_peer_release_ref(link_peer,
1754*5113495bSYour Name 						     WLAN_MLO_MGR_ID);
1755*5113495bSYour Name 			mlo_peer_free(ml_peer);
1756*5113495bSYour Name 			mlo_dev_release_link_vdevs(link_vdevs);
1757*5113495bSYour Name 			return status;
1758*5113495bSYour Name 		}
1759*5113495bSYour Name 	}
1760*5113495bSYour Name 
1761*5113495bSYour Name 	wlan_mlo_peer_get_ref(ml_peer);
1762*5113495bSYour Name 
1763*5113495bSYour Name 	if (wlan_vdev_mlme_get_opmode(vdev) == QDF_SAP_MODE) {
1764*5113495bSYour Name 		/* Notify other vdevs about link peer creation */
1765*5113495bSYour Name 		for (i = 0; i < WLAN_UMAC_MLO_MAX_VDEVS; i++) {
1766*5113495bSYour Name 			vdev_link = link_vdevs[i];
1767*5113495bSYour Name 			if (!vdev_link)
1768*5113495bSYour Name 				continue;
1769*5113495bSYour Name 
1770*5113495bSYour Name 			if (vdev_link == vdev)
1771*5113495bSYour Name 				continue;
1772*5113495bSYour Name 
1773*5113495bSYour Name 			mlo_partner_peer_create_post(ml_dev, vdev_link,
1774*5113495bSYour Name 						     ml_peer, frm_buf, ml_info);
1775*5113495bSYour Name 		}
1776*5113495bSYour Name 		/* Create bridge peer */
1777*5113495bSYour Name 		status = mlo_bridge_peer_create_post(ml_dev, ml_peer,
1778*5113495bSYour Name 						     bridge_peer_psoc_id);
1779*5113495bSYour Name 		if (QDF_STATUS_SUCCESS != status) {
1780*5113495bSYour Name 			mlo_err("MLD ID %d: Bridge peer creation failed",
1781*5113495bSYour Name 				ml_dev->mld_id);
1782*5113495bSYour Name 			wlan_mlo_partner_peer_create_failed_notify(ml_peer);
1783*5113495bSYour Name 			mlo_dev_release_link_vdevs(link_vdevs);
1784*5113495bSYour Name 			wlan_mlo_peer_release_ref(ml_peer);
1785*5113495bSYour Name 			return QDF_STATUS_E_FAILURE;
1786*5113495bSYour Name 		}
1787*5113495bSYour Name 	}
1788*5113495bSYour Name 	mlo_dev_release_link_vdevs(link_vdevs);
1789*5113495bSYour Name 
1790*5113495bSYour Name 	if (ml_peer->mlpeer_state == ML_PEER_DISCONN_INITIATED) {
1791*5113495bSYour Name 		mlo_info("MLD ID %d ML Peer " QDF_MAC_ADDR_FMT " allocation failed",
1792*5113495bSYour Name 			 ml_dev->mld_id,
1793*5113495bSYour Name 			 QDF_MAC_ADDR_REF(ml_peer->peer_mld_addr.bytes));
1794*5113495bSYour Name 		wlan_mlo_peer_release_ref(ml_peer);
1795*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
1796*5113495bSYour Name 	}
1797*5113495bSYour Name 
1798*5113495bSYour Name 	mlo_info("MLD ID %d ML Peer " QDF_MAC_ADDR_FMT " allocated %pK",
1799*5113495bSYour Name 		 ml_dev->mld_id,
1800*5113495bSYour Name 		 QDF_MAC_ADDR_REF(ml_peer->peer_mld_addr.bytes),
1801*5113495bSYour Name 		 ml_peer);
1802*5113495bSYour Name 
1803*5113495bSYour Name 	/*
1804*5113495bSYour Name 	 * wlan_mlo_peer_create() is trigggered after getting peer
1805*5113495bSYour Name 	 * assoc confirm from FW. For single link MLO connection, it is
1806*5113495bSYour Name 	 * OK to trigger assoc response from here.
1807*5113495bSYour Name 	 */
1808*5113495bSYour Name 	if ((wlan_vdev_mlme_get_opmode(vdev) == QDF_SAP_MODE) &&
1809*5113495bSYour Name 	    (!wlan_mlo_peer_is_nawds(ml_peer))) {
1810*5113495bSYour Name 		if ((ml_peer->max_links == 1) &&
1811*5113495bSYour Name 		    (ml_peer->link_peer_cnt == 1)) {
1812*5113495bSYour Name 			assoc_peer = ml_peer->peer_list[0].link_peer;
1813*5113495bSYour Name 			if (assoc_peer)
1814*5113495bSYour Name 				mlo_mlme_peer_assoc_resp(assoc_peer);
1815*5113495bSYour Name 		} else {
1816*5113495bSYour Name 			set_assoc_peer_for_2link_sap(assoc_peer, ml_peer);
1817*5113495bSYour Name 		}
1818*5113495bSYour Name 	}
1819*5113495bSYour Name 
1820*5113495bSYour Name 
1821*5113495bSYour Name 	if (wlan_vdev_mlme_get_opmode(vdev) == QDF_STA_MODE)
1822*5113495bSYour Name 		wlan_clear_peer_level_tid_to_link_mapping(vdev);
1823*5113495bSYour Name 
1824*5113495bSYour Name 	wlan_mlo_peer_release_ref(ml_peer);
1825*5113495bSYour Name 
1826*5113495bSYour Name 	return QDF_STATUS_SUCCESS;
1827*5113495bSYour Name }
1828*5113495bSYour Name 
wlan_mlo_link_peer_attach(struct wlan_mlo_peer_context * ml_peer,struct wlan_objmgr_peer * peer,qdf_nbuf_t frm_buf)1829*5113495bSYour Name QDF_STATUS wlan_mlo_link_peer_attach(struct wlan_mlo_peer_context *ml_peer,
1830*5113495bSYour Name 				     struct wlan_objmgr_peer *peer,
1831*5113495bSYour Name 				     qdf_nbuf_t frm_buf)
1832*5113495bSYour Name {
1833*5113495bSYour Name 	QDF_STATUS status;
1834*5113495bSYour Name 	struct wlan_objmgr_peer *assoc_peer;
1835*5113495bSYour Name 	struct wlan_objmgr_vdev *vdev = NULL;
1836*5113495bSYour Name 
1837*5113495bSYour Name 	if (!ml_peer)
1838*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
1839*5113495bSYour Name 
1840*5113495bSYour Name 	vdev = wlan_peer_get_vdev(peer);
1841*5113495bSYour Name 	if (!vdev)
1842*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
1843*5113495bSYour Name 
1844*5113495bSYour Name 	/* Populate Link peer pointer, peer MAC address,
1845*5113495bSYour Name 	 * MLD address. HW link ID, update ref count
1846*5113495bSYour Name 	 */
1847*5113495bSYour Name 	status = mlo_peer_attach_link_peer(ml_peer, peer, frm_buf);
1848*5113495bSYour Name 	if (QDF_IS_STATUS_ERROR(status))
1849*5113495bSYour Name 		return status;
1850*5113495bSYour Name 
1851*5113495bSYour Name 	/* Store AID, MLO Peer pointer in link peer, take link peer ref count */
1852*5113495bSYour Name 	mlo_peer_populate_link_peer(ml_peer, peer);
1853*5113495bSYour Name 
1854*5113495bSYour Name 	if (wlan_vdev_mlme_get_opmode(vdev) == QDF_SAP_MODE) {
1855*5113495bSYour Name 		if (ml_peer->max_links == ml_peer->link_peer_cnt) {
1856*5113495bSYour Name 			assoc_peer = ml_peer->peer_list[0].link_peer;
1857*5113495bSYour Name 			if (assoc_peer)
1858*5113495bSYour Name 				mlo_mlme_peer_assoc_resp(assoc_peer);
1859*5113495bSYour Name 		}
1860*5113495bSYour Name 	}
1861*5113495bSYour Name 
1862*5113495bSYour Name 	return status;
1863*5113495bSYour Name }
1864*5113495bSYour Name 
wlan_mlo_link_asresp_attach(struct wlan_mlo_peer_context * ml_peer,struct wlan_objmgr_peer * peer,qdf_nbuf_t frm_buf)1865*5113495bSYour Name QDF_STATUS wlan_mlo_link_asresp_attach(struct wlan_mlo_peer_context *ml_peer,
1866*5113495bSYour Name 				       struct wlan_objmgr_peer *peer,
1867*5113495bSYour Name 				       qdf_nbuf_t frm_buf)
1868*5113495bSYour Name {
1869*5113495bSYour Name 	uint16_t i;
1870*5113495bSYour Name 	struct wlan_mlo_link_peer_entry *peer_entry;
1871*5113495bSYour Name 
1872*5113495bSYour Name 	if (!ml_peer) {
1873*5113495bSYour Name 		mlo_err(" ml peer is NULL");
1874*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
1875*5113495bSYour Name 	}
1876*5113495bSYour Name 
1877*5113495bSYour Name 	if (!peer) {
1878*5113495bSYour Name 		ml_peer->link_asresp_cnt++;
1879*5113495bSYour Name 		mlo_err(" ml peer or link peer pointer is NULL");
1880*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
1881*5113495bSYour Name 	}
1882*5113495bSYour Name 	mlo_peer_lock_acquire(ml_peer);
1883*5113495bSYour Name 
1884*5113495bSYour Name 	for (i = 0; i < MAX_MLO_LINK_PEERS; i++) {
1885*5113495bSYour Name 		peer_entry = &ml_peer->peer_list[i];
1886*5113495bSYour Name 		if (!peer_entry->link_peer)
1887*5113495bSYour Name 			continue;
1888*5113495bSYour Name 
1889*5113495bSYour Name 		if (peer == peer_entry->link_peer) {
1890*5113495bSYour Name 			ml_peer->link_asresp_cnt++;
1891*5113495bSYour Name 			/* Free previous assoc resp buffer */
1892*5113495bSYour Name 			if (peer_entry->assoc_rsp_buf) {
1893*5113495bSYour Name 				qdf_nbuf_free(peer_entry->assoc_rsp_buf);
1894*5113495bSYour Name 				peer_entry->assoc_rsp_buf = NULL;
1895*5113495bSYour Name 			}
1896*5113495bSYour Name 
1897*5113495bSYour Name 			if (frm_buf)
1898*5113495bSYour Name 				peer_entry->assoc_rsp_buf = frm_buf;
1899*5113495bSYour Name 			else
1900*5113495bSYour Name 				peer_entry->assoc_rsp_buf = NULL;
1901*5113495bSYour Name 
1902*5113495bSYour Name 			break;
1903*5113495bSYour Name 		}
1904*5113495bSYour Name 	}
1905*5113495bSYour Name 
1906*5113495bSYour Name 	mlo_peer_lock_release(ml_peer);
1907*5113495bSYour Name 
1908*5113495bSYour Name 	return QDF_STATUS_SUCCESS;
1909*5113495bSYour Name }
1910*5113495bSYour Name 
wlan_mlo_link_peer_delete(struct wlan_objmgr_peer * peer)1911*5113495bSYour Name QDF_STATUS wlan_mlo_link_peer_delete(struct wlan_objmgr_peer *peer)
1912*5113495bSYour Name {
1913*5113495bSYour Name 	struct wlan_mlo_peer_context *ml_peer;
1914*5113495bSYour Name 
1915*5113495bSYour Name 	ml_peer = peer->mlo_peer_ctx;
1916*5113495bSYour Name 
1917*5113495bSYour Name 	if (!ml_peer)
1918*5113495bSYour Name 		return QDF_STATUS_E_NOENT;
1919*5113495bSYour Name 
1920*5113495bSYour Name 	if (ml_peer->mlpeer_state != ML_PEER_DISCONN_INITIATED)
1921*5113495bSYour Name 		wlan_mlo_peer_wsi_link_delete(ml_peer);
1922*5113495bSYour Name 
1923*5113495bSYour Name 	mlo_reset_link_peer(ml_peer, peer);
1924*5113495bSYour Name 	mlo_peer_detach_link_peer(ml_peer, peer);
1925*5113495bSYour Name 
1926*5113495bSYour Name 	if (ml_peer->mlpeer_state != ML_PEER_DISCONN_INITIATED)
1927*5113495bSYour Name 		wlan_mlo_peer_wsi_link_add(ml_peer);
1928*5113495bSYour Name 
1929*5113495bSYour Name 	wlan_mlo_peer_release_ref(ml_peer);
1930*5113495bSYour Name 
1931*5113495bSYour Name 	return QDF_STATUS_SUCCESS;
1932*5113495bSYour Name }
1933*5113495bSYour Name 
1934*5113495bSYour Name qdf_export_symbol(wlan_mlo_link_peer_delete);
1935*5113495bSYour Name 
mlo_peer_get_link_peer_assoc_req_buf(struct wlan_mlo_peer_context * ml_peer,uint8_t link_ix)1936*5113495bSYour Name qdf_nbuf_t mlo_peer_get_link_peer_assoc_req_buf(
1937*5113495bSYour Name 			struct wlan_mlo_peer_context *ml_peer,
1938*5113495bSYour Name 			uint8_t link_ix)
1939*5113495bSYour Name {
1940*5113495bSYour Name 	struct wlan_objmgr_peer *peer = NULL;
1941*5113495bSYour Name 	qdf_nbuf_t assocbuf = NULL;
1942*5113495bSYour Name 
1943*5113495bSYour Name 	if (!ml_peer)
1944*5113495bSYour Name 		return NULL;
1945*5113495bSYour Name 
1946*5113495bSYour Name 	peer = wlan_mlo_peer_get_assoc_peer(ml_peer);
1947*5113495bSYour Name 	if (!peer)
1948*5113495bSYour Name 		return NULL;
1949*5113495bSYour Name 
1950*5113495bSYour Name 	assocbuf = mlo_mlme_get_link_assoc_req(peer, link_ix);
1951*5113495bSYour Name 
1952*5113495bSYour Name 	return assocbuf;
1953*5113495bSYour Name }
1954*5113495bSYour Name 
wlan_mlo_peer_get_links_info(struct wlan_objmgr_peer * peer,struct mlo_tgt_partner_info * ml_links)1955*5113495bSYour Name void wlan_mlo_peer_get_links_info(struct wlan_objmgr_peer *peer,
1956*5113495bSYour Name 				  struct mlo_tgt_partner_info *ml_links)
1957*5113495bSYour Name {
1958*5113495bSYour Name 	struct wlan_mlo_peer_context *ml_peer;
1959*5113495bSYour Name 	struct wlan_mlo_link_peer_entry *peer_entry;
1960*5113495bSYour Name 	struct wlan_objmgr_peer *link_peer;
1961*5113495bSYour Name 	struct wlan_objmgr_vdev *link_vdev;
1962*5113495bSYour Name 	uint8_t i, ix, idx = 0;
1963*5113495bSYour Name 	struct wlan_mlo_eml_cap *ml_emlcap;
1964*5113495bSYour Name 
1965*5113495bSYour Name 	ml_peer = peer->mlo_peer_ctx;
1966*5113495bSYour Name 	ml_links->num_partner_links = 0;
1967*5113495bSYour Name 
1968*5113495bSYour Name 	if (!ml_peer)
1969*5113495bSYour Name 		return;
1970*5113495bSYour Name 
1971*5113495bSYour Name 	ml_emlcap = &ml_peer->mlpeer_emlcap;
1972*5113495bSYour Name 
1973*5113495bSYour Name 	mlo_peer_lock_acquire(ml_peer);
1974*5113495bSYour Name 
1975*5113495bSYour Name 	if ((ml_peer->mlpeer_state != ML_PEER_CREATED) &&
1976*5113495bSYour Name 	    (ml_peer->mlpeer_state != ML_PEER_ASSOC_DONE)) {
1977*5113495bSYour Name 		mlo_peer_lock_release(ml_peer);
1978*5113495bSYour Name 		return;
1979*5113495bSYour Name 	}
1980*5113495bSYour Name 
1981*5113495bSYour Name 	for (i = 0; i < MAX_MLO_LINK_PEERS; i++) {
1982*5113495bSYour Name 		peer_entry = &ml_peer->peer_list[i];
1983*5113495bSYour Name 		link_peer = peer_entry->link_peer;
1984*5113495bSYour Name 
1985*5113495bSYour Name 		if (!link_peer)
1986*5113495bSYour Name 			continue;
1987*5113495bSYour Name 		idx++;
1988*5113495bSYour Name 		if (link_peer == peer)
1989*5113495bSYour Name 			continue;
1990*5113495bSYour Name 		link_vdev = wlan_peer_get_vdev(link_peer);
1991*5113495bSYour Name 		if (!link_vdev)
1992*5113495bSYour Name 			continue;
1993*5113495bSYour Name 
1994*5113495bSYour Name 		if (ml_links->num_partner_links >= WLAN_UMAC_MLO_MAX_VDEVS)
1995*5113495bSYour Name 			break;
1996*5113495bSYour Name 
1997*5113495bSYour Name 		ix = ml_links->num_partner_links;
1998*5113495bSYour Name 		ml_links->link_info[ix].vdev_id = wlan_vdev_get_id(link_vdev);
1999*5113495bSYour Name 		ml_links->link_info[ix].hw_mld_link_id = peer_entry->hw_link_id;
2000*5113495bSYour Name 		ml_links->link_info[ix].mlo_enabled = 1;
2001*5113495bSYour Name 		ml_links->link_info[ix].mlo_assoc_link =
2002*5113495bSYour Name 			wlan_peer_mlme_is_assoc_peer(link_peer);
2003*5113495bSYour Name 		ml_links->link_info[ix].mlo_primary_umac =
2004*5113495bSYour Name 			peer_entry->is_primary;
2005*5113495bSYour Name 		ml_links->link_info[ix].mlo_logical_link_index_valid = 1;
2006*5113495bSYour Name 		ml_links->link_info[ix].emlsr_support = ml_emlcap->emlsr_supp;
2007*5113495bSYour Name 		ml_links->link_info[ix].logical_link_index = idx - 1;
2008*5113495bSYour Name 		ml_links->link_info[ix].mlo_bridge_peer = link_peer->mlo_bridge_peer;
2009*5113495bSYour Name 		ml_links->num_partner_links++;
2010*5113495bSYour Name 	}
2011*5113495bSYour Name 	mlo_peer_lock_release(ml_peer);
2012*5113495bSYour Name }
2013*5113495bSYour Name 
2014*5113495bSYour Name qdf_export_symbol(wlan_mlo_peer_get_links_info);
2015*5113495bSYour Name 
wlan_mlo_peer_get_primary_peer_link_id(struct wlan_objmgr_peer * peer)2016*5113495bSYour Name uint8_t wlan_mlo_peer_get_primary_peer_link_id(struct wlan_objmgr_peer *peer)
2017*5113495bSYour Name {
2018*5113495bSYour Name 	struct wlan_mlo_peer_context *ml_peer;
2019*5113495bSYour Name 
2020*5113495bSYour Name 	ml_peer = peer->mlo_peer_ctx;
2021*5113495bSYour Name 
2022*5113495bSYour Name 	if (!ml_peer) {
2023*5113495bSYour Name 		mlo_err("ml_peer is null");
2024*5113495bSYour Name 		return WLAN_LINK_ID_INVALID;
2025*5113495bSYour Name 	}
2026*5113495bSYour Name 
2027*5113495bSYour Name 	return wlan_mlo_peer_get_primary_peer_link_id_by_ml_peer(ml_peer);
2028*5113495bSYour Name }
2029*5113495bSYour Name 
2030*5113495bSYour Name qdf_export_symbol(wlan_mlo_peer_get_primary_peer_link_id);
2031*5113495bSYour Name 
wlan_mlo_peer_get_primary_peer_link_id_by_ml_peer(struct wlan_mlo_peer_context * ml_peer)2032*5113495bSYour Name uint8_t wlan_mlo_peer_get_primary_peer_link_id_by_ml_peer(
2033*5113495bSYour Name 				struct wlan_mlo_peer_context *ml_peer)
2034*5113495bSYour Name {
2035*5113495bSYour Name 	struct wlan_mlo_link_peer_entry *peer_entry;
2036*5113495bSYour Name 	struct wlan_objmgr_peer *link_peer;
2037*5113495bSYour Name 	struct wlan_objmgr_vdev *link_vdev;
2038*5113495bSYour Name 	uint8_t i, vdev_link_id;
2039*5113495bSYour Name 
2040*5113495bSYour Name 	if (!ml_peer) {
2041*5113495bSYour Name 		mlo_err("ml_peer is null");
2042*5113495bSYour Name 		return WLAN_LINK_ID_INVALID;
2043*5113495bSYour Name 	}
2044*5113495bSYour Name 	mlo_peer_lock_acquire(ml_peer);
2045*5113495bSYour Name 
2046*5113495bSYour Name 	if ((ml_peer->mlpeer_state != ML_PEER_CREATED) &&
2047*5113495bSYour Name 	    (ml_peer->mlpeer_state != ML_PEER_ASSOC_DONE)) {
2048*5113495bSYour Name 		mlo_peer_lock_release(ml_peer);
2049*5113495bSYour Name 		mlo_err("ml_peer is not created and association is not done");
2050*5113495bSYour Name 		return WLAN_LINK_ID_INVALID;
2051*5113495bSYour Name 	}
2052*5113495bSYour Name 
2053*5113495bSYour Name 	for (i = 0; i < MAX_MLO_LINK_PEERS; i++) {
2054*5113495bSYour Name 		peer_entry = &ml_peer->peer_list[i];
2055*5113495bSYour Name 		link_peer = peer_entry->link_peer;
2056*5113495bSYour Name 		if (!link_peer)
2057*5113495bSYour Name 			continue;
2058*5113495bSYour Name 
2059*5113495bSYour Name 		if (peer_entry->is_primary) {
2060*5113495bSYour Name 			link_vdev = wlan_peer_get_vdev(link_peer);
2061*5113495bSYour Name 			if (!link_vdev) {
2062*5113495bSYour Name 				mlo_peer_lock_release(ml_peer);
2063*5113495bSYour Name 				mlo_err("link vdev not found");
2064*5113495bSYour Name 				return WLAN_LINK_ID_INVALID;
2065*5113495bSYour Name 			}
2066*5113495bSYour Name 			vdev_link_id = wlan_vdev_get_link_id(link_vdev);
2067*5113495bSYour Name 			mlo_peer_lock_release(ml_peer);
2068*5113495bSYour Name 			return vdev_link_id;
2069*5113495bSYour Name 		}
2070*5113495bSYour Name 	}
2071*5113495bSYour Name 	mlo_peer_lock_release(ml_peer);
2072*5113495bSYour Name 	mlo_err("None of the peer is designated as primary");
2073*5113495bSYour Name 	return WLAN_LINK_ID_INVALID;
2074*5113495bSYour Name }
2075*5113495bSYour Name 
2076*5113495bSYour Name qdf_export_symbol(wlan_mlo_peer_get_primary_peer_link_id_by_ml_peer);
2077*5113495bSYour Name 
2078*5113495bSYour Name #ifdef WLAN_MLO_MULTI_CHIP
wlan_mlo_peer_get_str_capability(struct wlan_objmgr_peer * peer,uint8_t * str_capability)2079*5113495bSYour Name void wlan_mlo_peer_get_str_capability(struct wlan_objmgr_peer *peer,
2080*5113495bSYour Name 				      uint8_t *str_capability)
2081*5113495bSYour Name {
2082*5113495bSYour Name 	struct wlan_mlo_peer_context *ml_peer;
2083*5113495bSYour Name 	uint8_t i;
2084*5113495bSYour Name 
2085*5113495bSYour Name 	if (!str_capability)
2086*5113495bSYour Name 		return;
2087*5113495bSYour Name 
2088*5113495bSYour Name 	*str_capability = 1;
2089*5113495bSYour Name 	if (!peer)
2090*5113495bSYour Name 		return;
2091*5113495bSYour Name 	ml_peer = peer->mlo_peer_ctx;
2092*5113495bSYour Name 	if (!ml_peer)
2093*5113495bSYour Name 		return;
2094*5113495bSYour Name 
2095*5113495bSYour Name 	mlo_peer_lock_acquire(ml_peer);
2096*5113495bSYour Name 	if ((ml_peer->mlpeer_state != ML_PEER_CREATED) &&
2097*5113495bSYour Name 	    (ml_peer->mlpeer_state != ML_PEER_ASSOC_DONE)) {
2098*5113495bSYour Name 		mlo_peer_lock_release(ml_peer);
2099*5113495bSYour Name 		return;
2100*5113495bSYour Name 	}
2101*5113495bSYour Name 
2102*5113495bSYour Name 	for (i = 0; i < WLAN_UMAC_MLO_MAX_VDEVS; i++) {
2103*5113495bSYour Name 		if (ml_peer->mlpeer_nstrinfo[i].link_id >= MAX_MLO_LINKS)
2104*5113495bSYour Name 			continue;
2105*5113495bSYour Name 		if (ml_peer->mlpeer_nstrinfo[i].nstr_lp_present) {
2106*5113495bSYour Name 			*str_capability = 0;
2107*5113495bSYour Name 			break;
2108*5113495bSYour Name 		}
2109*5113495bSYour Name 	}
2110*5113495bSYour Name 	mlo_peer_lock_release(ml_peer);
2111*5113495bSYour Name }
2112*5113495bSYour Name 
wlan_mlo_peer_get_eml_capability(struct wlan_objmgr_peer * peer,uint8_t * is_emlsr_capable,uint8_t * is_emlmr_capable)2113*5113495bSYour Name void wlan_mlo_peer_get_eml_capability(struct wlan_objmgr_peer *peer,
2114*5113495bSYour Name 				      uint8_t *is_emlsr_capable,
2115*5113495bSYour Name 				      uint8_t *is_emlmr_capable)
2116*5113495bSYour Name {
2117*5113495bSYour Name 	struct wlan_mlo_peer_context *ml_peer;
2118*5113495bSYour Name 
2119*5113495bSYour Name 	if (!is_emlsr_capable || !is_emlmr_capable)
2120*5113495bSYour Name 		return;
2121*5113495bSYour Name 
2122*5113495bSYour Name 	*is_emlsr_capable = 0;
2123*5113495bSYour Name 	*is_emlmr_capable = 0;
2124*5113495bSYour Name 	if (!peer)
2125*5113495bSYour Name 		return;
2126*5113495bSYour Name 	ml_peer = peer->mlo_peer_ctx;
2127*5113495bSYour Name 	if (!ml_peer)
2128*5113495bSYour Name 		return;
2129*5113495bSYour Name 
2130*5113495bSYour Name 	mlo_peer_lock_acquire(ml_peer);
2131*5113495bSYour Name 	if ((ml_peer->mlpeer_state != ML_PEER_CREATED) &&
2132*5113495bSYour Name 	    (ml_peer->mlpeer_state != ML_PEER_ASSOC_DONE)) {
2133*5113495bSYour Name 		mlo_peer_lock_release(ml_peer);
2134*5113495bSYour Name 		return;
2135*5113495bSYour Name 	}
2136*5113495bSYour Name 	*is_emlsr_capable = ml_peer->mlpeer_emlcap.emlsr_supp;
2137*5113495bSYour Name 	*is_emlmr_capable = ml_peer->mlpeer_emlcap.emlmr_supp;
2138*5113495bSYour Name 	mlo_peer_lock_release(ml_peer);
2139*5113495bSYour Name }
2140*5113495bSYour Name #endif
2141*5113495bSYour Name 
wlan_mlo_peer_get_partner_links_info(struct wlan_objmgr_peer * peer,struct mlo_partner_info * ml_links)2142*5113495bSYour Name void wlan_mlo_peer_get_partner_links_info(struct wlan_objmgr_peer *peer,
2143*5113495bSYour Name 					  struct mlo_partner_info *ml_links)
2144*5113495bSYour Name {
2145*5113495bSYour Name 	struct wlan_mlo_peer_context *ml_peer;
2146*5113495bSYour Name 	struct wlan_mlo_link_peer_entry *peer_entry;
2147*5113495bSYour Name 	struct wlan_objmgr_peer *link_peer;
2148*5113495bSYour Name 	struct wlan_objmgr_vdev *link_vdev;
2149*5113495bSYour Name 	uint8_t i, ix;
2150*5113495bSYour Name 
2151*5113495bSYour Name 	ml_peer = peer->mlo_peer_ctx;
2152*5113495bSYour Name 	ml_links->num_partner_links = 0;
2153*5113495bSYour Name 
2154*5113495bSYour Name 	if (!ml_peer)
2155*5113495bSYour Name 		return;
2156*5113495bSYour Name 
2157*5113495bSYour Name 	mlo_peer_lock_acquire(ml_peer);
2158*5113495bSYour Name 
2159*5113495bSYour Name 	if ((ml_peer->mlpeer_state != ML_PEER_CREATED) &&
2160*5113495bSYour Name 	    (ml_peer->mlpeer_state != ML_PEER_ASSOC_DONE)) {
2161*5113495bSYour Name 		mlo_peer_lock_release(ml_peer);
2162*5113495bSYour Name 		return;
2163*5113495bSYour Name 	}
2164*5113495bSYour Name 
2165*5113495bSYour Name 	for (i = 0; i < MAX_MLO_LINK_PEERS; i++) {
2166*5113495bSYour Name 		peer_entry = &ml_peer->peer_list[i];
2167*5113495bSYour Name 		link_peer = peer_entry->link_peer;
2168*5113495bSYour Name 
2169*5113495bSYour Name 		if (!link_peer)
2170*5113495bSYour Name 			continue;
2171*5113495bSYour Name 
2172*5113495bSYour Name 		if (link_peer == peer)
2173*5113495bSYour Name 			continue;
2174*5113495bSYour Name 
2175*5113495bSYour Name 		link_vdev = wlan_peer_get_vdev(link_peer);
2176*5113495bSYour Name 		if (!link_vdev)
2177*5113495bSYour Name 			continue;
2178*5113495bSYour Name 
2179*5113495bSYour Name 		if (ml_links->num_partner_links >= WLAN_UMAC_MLO_MAX_VDEVS)
2180*5113495bSYour Name 			break;
2181*5113495bSYour Name 
2182*5113495bSYour Name 		ix = ml_links->num_partner_links;
2183*5113495bSYour Name 		ml_links->partner_link_info[ix].link_id = peer_entry->link_ix;
2184*5113495bSYour Name 		ml_links->partner_link_info[ix].is_bridge =
2185*5113495bSYour Name 		   (wlan_peer_get_peer_type(link_peer) == WLAN_PEER_MLO_BRIDGE);
2186*5113495bSYour Name 
2187*5113495bSYour Name 		qdf_copy_macaddr(&ml_links->partner_link_info[ix].link_addr,
2188*5113495bSYour Name 				 &peer_entry->link_addr);
2189*5113495bSYour Name 		ml_links->num_partner_links++;
2190*5113495bSYour Name 	}
2191*5113495bSYour Name 	mlo_peer_lock_release(ml_peer);
2192*5113495bSYour Name }
2193*5113495bSYour Name 
2194*5113495bSYour Name qdf_export_symbol(wlan_mlo_peer_get_partner_links_info);
2195*5113495bSYour Name 
2196*5113495bSYour Name #ifdef UMAC_SUPPORT_MLNAWDS
wlan_mlo_peer_is_nawds(struct wlan_mlo_peer_context * ml_peer)2197*5113495bSYour Name bool wlan_mlo_peer_is_nawds(struct wlan_mlo_peer_context *ml_peer)
2198*5113495bSYour Name {
2199*5113495bSYour Name 	bool status = false;
2200*5113495bSYour Name 
2201*5113495bSYour Name 	if (!ml_peer)
2202*5113495bSYour Name 		return status;
2203*5113495bSYour Name 
2204*5113495bSYour Name 	mlo_peer_lock_acquire(ml_peer);
2205*5113495bSYour Name 	if (ml_peer->is_nawds_ml_peer)
2206*5113495bSYour Name 		status = true;
2207*5113495bSYour Name 	mlo_peer_lock_release(ml_peer);
2208*5113495bSYour Name 
2209*5113495bSYour Name 	return status;
2210*5113495bSYour Name }
2211*5113495bSYour Name 
2212*5113495bSYour Name qdf_export_symbol(wlan_mlo_peer_is_nawds);
2213*5113495bSYour Name #endif
2214*5113495bSYour Name 
2215*5113495bSYour Name #ifdef MESH_MODE_SUPPORT
wlan_mlo_peer_is_mesh(struct wlan_mlo_peer_context * ml_peer)2216*5113495bSYour Name bool wlan_mlo_peer_is_mesh(struct wlan_mlo_peer_context *ml_peer)
2217*5113495bSYour Name {
2218*5113495bSYour Name 	bool status = false;
2219*5113495bSYour Name 
2220*5113495bSYour Name 	if (!ml_peer)
2221*5113495bSYour Name 		return status;
2222*5113495bSYour Name 
2223*5113495bSYour Name 	mlo_peer_lock_acquire(ml_peer);
2224*5113495bSYour Name 	if (ml_peer->is_mesh_ml_peer)
2225*5113495bSYour Name 		status = true;
2226*5113495bSYour Name 	mlo_peer_lock_release(ml_peer);
2227*5113495bSYour Name 
2228*5113495bSYour Name 	return status;
2229*5113495bSYour Name }
2230*5113495bSYour Name 
2231*5113495bSYour Name qdf_export_symbol(wlan_mlo_peer_is_mesh);
2232*5113495bSYour Name #endif
2233*5113495bSYour Name 
2234*5113495bSYour Name #ifdef UMAC_MLO_AUTH_DEFER
mlo_peer_free_auth_param(struct mlpeer_auth_params * auth_params)2235*5113495bSYour Name void mlo_peer_free_auth_param(struct mlpeer_auth_params *auth_params)
2236*5113495bSYour Name {
2237*5113495bSYour Name 	if (auth_params->rs)
2238*5113495bSYour Name 		qdf_mem_free(auth_params->rs);
2239*5113495bSYour Name 
2240*5113495bSYour Name 	if (auth_params->wbuf)
2241*5113495bSYour Name 		qdf_nbuf_free(auth_params->wbuf);
2242*5113495bSYour Name 
2243*5113495bSYour Name 	qdf_mem_free(auth_params);
2244*5113495bSYour Name }
2245*5113495bSYour Name 
mlo_peer_link_auth_defer(struct wlan_mlo_peer_context * ml_peer,struct qdf_mac_addr * link_mac,struct mlpeer_auth_params * auth_params)2246*5113495bSYour Name QDF_STATUS mlo_peer_link_auth_defer(struct wlan_mlo_peer_context *ml_peer,
2247*5113495bSYour Name 				    struct qdf_mac_addr *link_mac,
2248*5113495bSYour Name 				    struct mlpeer_auth_params *auth_params)
2249*5113495bSYour Name {
2250*5113495bSYour Name 	uint8_t i;
2251*5113495bSYour Name 	uint8_t free_entries = 0;
2252*5113495bSYour Name 	struct mlpeer_auth_params *recv_auth;
2253*5113495bSYour Name 	QDF_STATUS status = QDF_STATUS_E_FAILURE;
2254*5113495bSYour Name 
2255*5113495bSYour Name 	if (!ml_peer)
2256*5113495bSYour Name 		return status;
2257*5113495bSYour Name 
2258*5113495bSYour Name 	mlo_peer_lock_acquire(ml_peer);
2259*5113495bSYour Name 	for (i = 0; i < MAX_MLO_LINK_PEERS; i++) {
2260*5113495bSYour Name 		recv_auth = ml_peer->pending_auth[i];
2261*5113495bSYour Name 		if (!recv_auth) {
2262*5113495bSYour Name 			free_entries++;
2263*5113495bSYour Name 			continue;
2264*5113495bSYour Name 		}
2265*5113495bSYour Name 		/* overwrite the entry with latest entry */
2266*5113495bSYour Name 		if (qdf_is_macaddr_equal(link_mac, &recv_auth->link_addr)) {
2267*5113495bSYour Name 			mlo_peer_free_auth_param(recv_auth);
2268*5113495bSYour Name 			ml_peer->pending_auth[i] = auth_params;
2269*5113495bSYour Name 			mlo_peer_lock_release(ml_peer);
2270*5113495bSYour Name 
2271*5113495bSYour Name 			return QDF_STATUS_SUCCESS;
2272*5113495bSYour Name 		}
2273*5113495bSYour Name 	}
2274*5113495bSYour Name 
2275*5113495bSYour Name 	if (!free_entries) {
2276*5113495bSYour Name 		mlo_peer_lock_release(ml_peer);
2277*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
2278*5113495bSYour Name 	}
2279*5113495bSYour Name 
2280*5113495bSYour Name 	for (i = 0; i < MAX_MLO_LINK_PEERS; i++) {
2281*5113495bSYour Name 		recv_auth = ml_peer->pending_auth[i];
2282*5113495bSYour Name 		if (!recv_auth) {
2283*5113495bSYour Name 			ml_peer->pending_auth[i] = auth_params;
2284*5113495bSYour Name 			status = QDF_STATUS_SUCCESS;
2285*5113495bSYour Name 			break;
2286*5113495bSYour Name 		}
2287*5113495bSYour Name 	}
2288*5113495bSYour Name 	mlo_peer_lock_release(ml_peer);
2289*5113495bSYour Name 
2290*5113495bSYour Name 	return status;
2291*5113495bSYour Name }
2292*5113495bSYour Name 
wlan_mlo_partner_peer_delete_is_allowed(struct wlan_objmgr_peer * src_peer)2293*5113495bSYour Name bool wlan_mlo_partner_peer_delete_is_allowed(struct wlan_objmgr_peer *src_peer)
2294*5113495bSYour Name {
2295*5113495bSYour Name 	struct wlan_objmgr_vdev *vdev = NULL;
2296*5113495bSYour Name 	struct wlan_mlo_peer_context *ml_peer;
2297*5113495bSYour Name 
2298*5113495bSYour Name 	vdev = wlan_peer_get_vdev(src_peer);
2299*5113495bSYour Name 	if (!vdev)
2300*5113495bSYour Name 		return false;
2301*5113495bSYour Name 
2302*5113495bSYour Name 	ml_peer = src_peer->mlo_peer_ctx;
2303*5113495bSYour Name 	if (!wlan_peer_is_mlo(src_peer) || !ml_peer)
2304*5113495bSYour Name 		return false;
2305*5113495bSYour Name 
2306*5113495bSYour Name 	if (wlan_vdev_mlme_op_flags_get(vdev, WLAN_VDEV_OP_MLO_STOP_LINK_DEL) ||
2307*5113495bSYour Name 	    wlan_vdev_mlme_op_flags_get(vdev,
2308*5113495bSYour Name 					WLAN_VDEV_OP_MLO_LINK_TBTT_COMPLETE)) {
2309*5113495bSYour Name 		/* Single LINK MLO connection */
2310*5113495bSYour Name 		if (ml_peer->link_peer_cnt == 1)
2311*5113495bSYour Name 			return false;
2312*5113495bSYour Name 
2313*5113495bSYour Name 		/*
2314*5113495bSYour Name 		 * If this link is primary TQM and there is no ongoing migration
2315*5113495bSYour Name 		 * from this link, then issue full disconnect.
2316*5113495bSYour Name 		 */
2317*5113495bSYour Name 		if ((wlan_mlo_peer_get_primary_peer_link_id(src_peer) !=
2318*5113495bSYour Name 		    wlan_vdev_get_link_id(vdev)) ||
2319*5113495bSYour Name 		    ml_peer->primary_umac_migration_in_progress)
2320*5113495bSYour Name 			return false;
2321*5113495bSYour Name 	}
2322*5113495bSYour Name 
2323*5113495bSYour Name 	return true;
2324*5113495bSYour Name }
2325*5113495bSYour Name 
2326*5113495bSYour Name qdf_export_symbol(wlan_mlo_partner_peer_delete_is_allowed);
2327*5113495bSYour Name #endif
2328*5113495bSYour Name 
wlan_mlo_validate_reassocreq(struct wlan_mlo_peer_context * ml_peer)2329*5113495bSYour Name QDF_STATUS wlan_mlo_validate_reassocreq(struct wlan_mlo_peer_context *ml_peer)
2330*5113495bSYour Name {
2331*5113495bSYour Name 	uint16_t i;
2332*5113495bSYour Name 	struct wlan_mlo_link_peer_entry *peer_entry;
2333*5113495bSYour Name 	QDF_STATUS status = QDF_STATUS_SUCCESS;
2334*5113495bSYour Name 
2335*5113495bSYour Name 	if (!ml_peer) {
2336*5113495bSYour Name 		mlo_err(" ml peer is NULL");
2337*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
2338*5113495bSYour Name 	}
2339*5113495bSYour Name 
2340*5113495bSYour Name 	mlo_peer_lock_acquire(ml_peer);
2341*5113495bSYour Name 
2342*5113495bSYour Name 	for (i = 0; i < MAX_MLO_LINK_PEERS; i++) {
2343*5113495bSYour Name 		peer_entry = &ml_peer->peer_list[i];
2344*5113495bSYour Name 		if (!peer_entry->link_peer)
2345*5113495bSYour Name 			continue;
2346*5113495bSYour Name 
2347*5113495bSYour Name 		/* Check non-assoc link peer Assoc resp buf is valid
2348*5113495bSYour Name 		 * (exclude bridge peer)
2349*5113495bSYour Name 		 */
2350*5113495bSYour Name 		if (i && !peer_entry->assoc_rsp_buf &&
2351*5113495bSYour Name 		    (wlan_peer_get_peer_type(peer_entry->link_peer) !=
2352*5113495bSYour Name 						WLAN_PEER_MLO_BRIDGE)) {
2353*5113495bSYour Name 			status = QDF_STATUS_E_FAILURE;
2354*5113495bSYour Name 			break;
2355*5113495bSYour Name 		}
2356*5113495bSYour Name 	}
2357*5113495bSYour Name 
2358*5113495bSYour Name 	mlo_peer_lock_release(ml_peer);
2359*5113495bSYour Name 
2360*5113495bSYour Name 	return status;
2361*5113495bSYour Name }
2362*5113495bSYour Name 
2363*5113495bSYour Name #ifdef WLAN_WSI_STATS_SUPPORT
2364*5113495bSYour Name static uint32_t
wlan_mlo_psoc_get_mlo_grp_idx(struct mlo_mgr_context * mlo_mgr,uint32_t psoc_id)2365*5113495bSYour Name wlan_mlo_psoc_get_mlo_grp_idx(struct mlo_mgr_context *mlo_mgr,
2366*5113495bSYour Name 			      uint32_t psoc_id)
2367*5113495bSYour Name {
2368*5113495bSYour Name 	struct mlo_wsi_info *wsi_info = NULL;
2369*5113495bSYour Name 	struct mlo_wsi_psoc_grp *mlo_psoc_grp;
2370*5113495bSYour Name 	uint8_t grp_id, i;
2371*5113495bSYour Name 
2372*5113495bSYour Name 	if (!mlo_mgr)
2373*5113495bSYour Name 		return MLO_WSI_MAX_MLO_GRPS;
2374*5113495bSYour Name 
2375*5113495bSYour Name 	/* Retrieve the WSI link info structure */
2376*5113495bSYour Name 	wsi_info = mlo_mgr->wsi_info;
2377*5113495bSYour Name 	if (!wsi_info)
2378*5113495bSYour Name 		return MLO_WSI_MAX_MLO_GRPS;
2379*5113495bSYour Name 
2380*5113495bSYour Name 	for (grp_id = 0; grp_id < MLO_WSI_MAX_MLO_GRPS; grp_id++) {
2381*5113495bSYour Name 		mlo_psoc_grp = &wsi_info->mlo_psoc_grp[grp_id];
2382*5113495bSYour Name 		for (i = 0; i < mlo_psoc_grp->num_psoc; i++) {
2383*5113495bSYour Name 			if (mlo_psoc_grp->psoc_order[i] == psoc_id)
2384*5113495bSYour Name 				return grp_id;
2385*5113495bSYour Name 		}
2386*5113495bSYour Name 	}
2387*5113495bSYour Name 
2388*5113495bSYour Name 	return MLO_WSI_MAX_MLO_GRPS;
2389*5113495bSYour Name }
2390*5113495bSYour Name 
wlan_mlo_wsi_link_info_send_cmd(void)2391*5113495bSYour Name QDF_STATUS wlan_mlo_wsi_link_info_send_cmd(void)
2392*5113495bSYour Name {
2393*5113495bSYour Name 	struct mlo_mgr_context *mlo_mgr = NULL;
2394*5113495bSYour Name 	struct mlo_wsi_info *wsi_info = NULL;
2395*5113495bSYour Name 	struct wlan_lmac_if_mlo_tx_ops *mlo_tx_ops = NULL;
2396*5113495bSYour Name 	struct wlan_objmgr_psoc *psoc_objmgr = NULL;
2397*5113495bSYour Name 	struct wlan_objmgr_pdev *pdev = NULL;
2398*5113495bSYour Name 	QDF_STATUS error = QDF_STATUS_SUCCESS;
2399*5113495bSYour Name 	int i, j;
2400*5113495bSYour Name 
2401*5113495bSYour Name 	/* Retrieve the MLO manager context */
2402*5113495bSYour Name 	mlo_mgr = wlan_objmgr_get_mlo_ctx();
2403*5113495bSYour Name 	if (!mlo_mgr)
2404*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
2405*5113495bSYour Name 
2406*5113495bSYour Name 	/* Retrieve the WSI link info structure */
2407*5113495bSYour Name 	wsi_info = mlo_mgr->wsi_info;
2408*5113495bSYour Name 	if (!wsi_info)
2409*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
2410*5113495bSYour Name 
2411*5113495bSYour Name 	if (wsi_info->block_wmi_cmd) {
2412*5113495bSYour Name 		mlo_debug("WMI command is blocked");
2413*5113495bSYour Name 		return error;
2414*5113495bSYour Name 	}
2415*5113495bSYour Name 	/*
2416*5113495bSYour Name 	 * Check each PSOC if the WMI command needs to be sent
2417*5113495bSYour Name 	 * and send it for each PDEV in that PSOC
2418*5113495bSYour Name 	 */
2419*5113495bSYour Name 	for (i = 0; i < WLAN_OBJMGR_MAX_DEVICES; i++) {
2420*5113495bSYour Name 		if (!wsi_info->link_stats[i].send_wmi_cmd)
2421*5113495bSYour Name 			continue;
2422*5113495bSYour Name 
2423*5113495bSYour Name 		psoc_objmgr = wlan_objmgr_get_psoc_by_id(i, WLAN_MLO_MGR_ID);
2424*5113495bSYour Name 		if (!psoc_objmgr) {
2425*5113495bSYour Name 			mlo_err("Could not get PSOC obj for index %d", i);
2426*5113495bSYour Name 			continue;
2427*5113495bSYour Name 		}
2428*5113495bSYour Name 
2429*5113495bSYour Name 		mlo_tx_ops = &psoc_objmgr->soc_cb.tx_ops->mlo_ops;
2430*5113495bSYour Name 		if (!mlo_tx_ops || !mlo_tx_ops->send_wsi_link_info_cmd) {
2431*5113495bSYour Name 			mlo_err("mlo_tx_ops is null");
2432*5113495bSYour Name 			wlan_objmgr_psoc_release_ref(psoc_objmgr,
2433*5113495bSYour Name 						     WLAN_MLO_MGR_ID);
2434*5113495bSYour Name 			return QDF_STATUS_E_NULL_VALUE;
2435*5113495bSYour Name 		}
2436*5113495bSYour Name 
2437*5113495bSYour Name 		for (j = 0; j < psoc_objmgr->soc_objmgr.wlan_pdev_count; j++) {
2438*5113495bSYour Name 			pdev = psoc_objmgr->soc_objmgr.wlan_pdev_list[j];
2439*5113495bSYour Name 			if (!pdev)
2440*5113495bSYour Name 				continue;
2441*5113495bSYour Name 
2442*5113495bSYour Name 			if (mlo_tx_ops->send_wsi_link_info_cmd(
2443*5113495bSYour Name 					pdev, &wsi_info->link_stats[i]) !=
2444*5113495bSYour Name 						QDF_STATUS_SUCCESS) {
2445*5113495bSYour Name 				mlo_err("Could not send WMI command for PDEV %d in PSOC %d",
2446*5113495bSYour Name 					j, i);
2447*5113495bSYour Name 				error = QDF_STATUS_E_FAILURE;
2448*5113495bSYour Name 			} else {
2449*5113495bSYour Name 				wsi_info->link_stats[i].send_wmi_cmd = false;
2450*5113495bSYour Name 			}
2451*5113495bSYour Name 		}
2452*5113495bSYour Name 		wlan_objmgr_psoc_release_ref(psoc_objmgr, WLAN_MLO_MGR_ID);
2453*5113495bSYour Name 	}
2454*5113495bSYour Name 
2455*5113495bSYour Name 	return error;
2456*5113495bSYour Name }
2457*5113495bSYour Name 
wlan_mlo_psoc_get_ix_in_grp(struct mlo_mgr_context * mlo_mgr,uint32_t grp_id,uint32_t prim_psoc_id)2458*5113495bSYour Name static uint32_t wlan_mlo_psoc_get_ix_in_grp(struct mlo_mgr_context *mlo_mgr,
2459*5113495bSYour Name 					    uint32_t grp_id,
2460*5113495bSYour Name 					    uint32_t prim_psoc_id)
2461*5113495bSYour Name {
2462*5113495bSYour Name 	uint32_t i;
2463*5113495bSYour Name 
2464*5113495bSYour Name 	if (!mlo_mgr) {
2465*5113495bSYour Name 		mlo_err("NULL mlo_mgr");
2466*5113495bSYour Name 		return 0xFF;
2467*5113495bSYour Name 	}
2468*5113495bSYour Name 
2469*5113495bSYour Name 	/* Iterate through the PSOC order and find the ID */
2470*5113495bSYour Name 	for (i = 0; i < mlo_mgr->wsi_info->mlo_psoc_grp[grp_id].num_psoc; i++) {
2471*5113495bSYour Name 		if (mlo_mgr->wsi_info->mlo_psoc_grp[grp_id].psoc_order[i] ==
2472*5113495bSYour Name 		    prim_psoc_id) {
2473*5113495bSYour Name 			return i;
2474*5113495bSYour Name 		}
2475*5113495bSYour Name 	}
2476*5113495bSYour Name 
2477*5113495bSYour Name 	return 0xFF;
2478*5113495bSYour Name }
2479*5113495bSYour Name 
2480*5113495bSYour Name static uint32_t
wlan_mlo_get_wsi_next_psoc(struct mlo_wsi_psoc_grp * mlo_psoc_grp,uint32_t prim_psoc_id,uint32_t n)2481*5113495bSYour Name wlan_mlo_get_wsi_next_psoc(struct mlo_wsi_psoc_grp *mlo_psoc_grp,
2482*5113495bSYour Name 			   uint32_t prim_psoc_id, uint32_t n)
2483*5113495bSYour Name {
2484*5113495bSYour Name 	uint32_t i, j;
2485*5113495bSYour Name 	uint32_t psoc_index = MLO_WSI_PSOC_ID_MAX;
2486*5113495bSYour Name 
2487*5113495bSYour Name 	if (!n)
2488*5113495bSYour Name 		return psoc_index;
2489*5113495bSYour Name 
2490*5113495bSYour Name 	for (i = 0; i < mlo_psoc_grp->num_psoc; i++) {
2491*5113495bSYour Name 		if (mlo_psoc_grp->psoc_order[i] == prim_psoc_id) {
2492*5113495bSYour Name 			psoc_index = i;
2493*5113495bSYour Name 			break;
2494*5113495bSYour Name 		}
2495*5113495bSYour Name 	}
2496*5113495bSYour Name 
2497*5113495bSYour Name 	if (psoc_index == MLO_WSI_PSOC_ID_MAX)
2498*5113495bSYour Name 		return psoc_index;
2499*5113495bSYour Name 
2500*5113495bSYour Name 	for (i = 1; i <= WLAN_OBJMGR_MAX_DEVICES; i++) {
2501*5113495bSYour Name 		j = (psoc_index + i) % WLAN_OBJMGR_MAX_DEVICES;
2502*5113495bSYour Name 		if (mlo_psoc_grp->psoc_order[j] != MLO_WSI_PSOC_ID_MAX)
2503*5113495bSYour Name 			n--;
2504*5113495bSYour Name 		if (!n)
2505*5113495bSYour Name 			return mlo_psoc_grp->psoc_order[j];
2506*5113495bSYour Name 	}
2507*5113495bSYour Name 
2508*5113495bSYour Name 	return MLO_WSI_PSOC_ID_MAX;
2509*5113495bSYour Name }
2510*5113495bSYour Name 
2511*5113495bSYour Name static QDF_STATUS
wlan_mlo_peer_wsi_link_update(struct wlan_mlo_peer_context * ml_peer,bool add)2512*5113495bSYour Name wlan_mlo_peer_wsi_link_update(struct wlan_mlo_peer_context *ml_peer, bool add)
2513*5113495bSYour Name {
2514*5113495bSYour Name 	struct mlo_mgr_context *mlo_mgr = NULL;
2515*5113495bSYour Name 	struct mlo_wsi_info *wsi_info = NULL;
2516*5113495bSYour Name 	struct wlan_mlo_link_peer_entry *peer_entry = NULL;
2517*5113495bSYour Name 	uint32_t prim_psoc_id = 0xFF;
2518*5113495bSYour Name 	uint32_t sec_psoc_id[MAX_MLO_LINK_PEERS] = {0xFF};
2519*5113495bSYour Name 	uint32_t hops, hop_id;
2520*5113495bSYour Name 	uint32_t prim_grp_idx, sec_grp_idx;
2521*5113495bSYour Name 	uint32_t prim_psoc_ix_grp, sec_psoc_ix_grp;
2522*5113495bSYour Name 	uint32_t i, j, n;
2523*5113495bSYour Name 	struct mlo_wsi_psoc_grp *mlo_psoc_grp;
2524*5113495bSYour Name 	struct wlan_objmgr_psoc *psoc;
2525*5113495bSYour Name 
2526*5113495bSYour Name 	/* Check if ml_peer is valid */
2527*5113495bSYour Name 	if (!ml_peer) {
2528*5113495bSYour Name 		mlo_err("ML peer is null");
2529*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
2530*5113495bSYour Name 	}
2531*5113495bSYour Name 
2532*5113495bSYour Name 	/* Retrieve the MLO manager context */
2533*5113495bSYour Name 	mlo_mgr = wlan_objmgr_get_mlo_ctx();
2534*5113495bSYour Name 	if (!mlo_mgr) {
2535*5113495bSYour Name 		mlo_err("ML MGR is NULL for ML peer" QDF_MAC_ADDR_FMT,
2536*5113495bSYour Name 			QDF_MAC_ADDR_REF(ml_peer->peer_mld_addr.bytes));
2537*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
2538*5113495bSYour Name 	}
2539*5113495bSYour Name 
2540*5113495bSYour Name 	/* Retrieve the WSI link info structure */
2541*5113495bSYour Name 	wsi_info = mlo_mgr->wsi_info;
2542*5113495bSYour Name 	if (!wsi_info) {
2543*5113495bSYour Name 		mlo_err("WSI Info is NULL for ML peer" QDF_MAC_ADDR_FMT,
2544*5113495bSYour Name 			QDF_MAC_ADDR_REF(ml_peer->peer_mld_addr.bytes));
2545*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
2546*5113495bSYour Name 	}
2547*5113495bSYour Name 
2548*5113495bSYour Name 	prim_psoc_id = ml_peer->primary_umac_psoc_id;
2549*5113495bSYour Name 	/* Populate the primary PSOC ID of the respective group */
2550*5113495bSYour Name 	prim_grp_idx = wlan_mlo_psoc_get_mlo_grp_idx(mlo_mgr, prim_psoc_id);
2551*5113495bSYour Name 	if (prim_grp_idx == MLO_WSI_MAX_MLO_GRPS) {
2552*5113495bSYour Name 		mlo_err("Group index is invalid for ML peer" QDF_MAC_ADDR_FMT,
2553*5113495bSYour Name 			QDF_MAC_ADDR_REF(ml_peer->peer_mld_addr.bytes));
2554*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
2555*5113495bSYour Name 	}
2556*5113495bSYour Name 
2557*5113495bSYour Name 	/* Populate MLO primary and secondary link */
2558*5113495bSYour Name 	for (i = 0, j = 0; i < MAX_MLO_LINK_PEERS; i++) {
2559*5113495bSYour Name 		peer_entry = &ml_peer->peer_list[i];
2560*5113495bSYour Name 		if (!peer_entry->link_peer) {
2561*5113495bSYour Name 			mlo_debug("link peer is null");
2562*5113495bSYour Name 			continue;
2563*5113495bSYour Name 		}
2564*5113495bSYour Name 
2565*5113495bSYour Name 		psoc = wlan_peer_get_psoc(peer_entry->link_peer);
2566*5113495bSYour Name 		if (!mlo_get_wsi_stats_info_support(psoc)) {
2567*5113495bSYour Name 			mlo_debug("WSI stats support is not enabled on psoc %d",
2568*5113495bSYour Name 				  wlan_psoc_get_id(psoc));
2569*5113495bSYour Name 			return QDF_STATUS_E_INVAL;
2570*5113495bSYour Name 		}
2571*5113495bSYour Name 
2572*5113495bSYour Name 		/*
2573*5113495bSYour Name 		 * Consider all non-primary peers as secondary links.
2574*5113495bSYour Name 		 * Additionally, consider all active peers as secondary link if
2575*5113495bSYour Name 		 * the TQM is on another PSOC with bridge peer.
2576*5113495bSYour Name 		 */
2577*5113495bSYour Name 		if (!peer_entry->is_primary) {
2578*5113495bSYour Name 			sec_psoc_id[j] = wlan_vdev_get_psoc_id(
2579*5113495bSYour Name 						wlan_peer_get_vdev(
2580*5113495bSYour Name 						peer_entry->link_peer));
2581*5113495bSYour Name 
2582*5113495bSYour Name 			sec_grp_idx = wlan_mlo_psoc_get_mlo_grp_idx
2583*5113495bSYour Name 							(mlo_mgr,
2584*5113495bSYour Name 							 sec_psoc_id[j]);
2585*5113495bSYour Name 			if (sec_grp_idx != prim_grp_idx) {
2586*5113495bSYour Name 				mlo_err("Secondary link is not part of same MLO group as primary link");
2587*5113495bSYour Name 				continue;
2588*5113495bSYour Name 			}
2589*5113495bSYour Name 			j++;
2590*5113495bSYour Name 		}
2591*5113495bSYour Name 	}
2592*5113495bSYour Name 
2593*5113495bSYour Name 	/*
2594*5113495bSYour Name 	 * Logic for finding ingress and egress stats:
2595*5113495bSYour Name 	 * For a given MLO group, there is a PSOC order
2596*5113495bSYour Name 	 *
2597*5113495bSYour Name 	 * If there is secondary link, Increment the egress count for
2598*5113495bSYour Name 	 * the primary PSOC
2599*5113495bSYour Name 	 * (1) Iterate through each secondary link
2600*5113495bSYour Name 	 *      (1.1) Set the WMI command to true for that PSOC
2601*5113495bSYour Name 	 *      (1.2) Calculate the number of hops from the secondary link
2602*5113495bSYour Name 	 *            to that primary link within the group.
2603*5113495bSYour Name 	 *      (1.3) Iterate through a decrement sequence from the hop_count
2604*5113495bSYour Name 	 *            (1.3.1) Increment the ingress count for that PSOC index
2605*5113495bSYour Name 	 */
2606*5113495bSYour Name 	prim_psoc_ix_grp = wlan_mlo_psoc_get_ix_in_grp(mlo_mgr, prim_grp_idx,
2607*5113495bSYour Name 						       prim_psoc_id);
2608*5113495bSYour Name 
2609*5113495bSYour Name 	wsi_info->link_stats[prim_psoc_id].send_wmi_cmd = true;
2610*5113495bSYour Name 	mlo_psoc_grp = &wsi_info->mlo_psoc_grp[prim_grp_idx];
2611*5113495bSYour Name 
2612*5113495bSYour Name 	if (j) {
2613*5113495bSYour Name 		wsi_info->link_stats[prim_psoc_id].send_wmi_cmd = true;
2614*5113495bSYour Name 		if (add)
2615*5113495bSYour Name 			wsi_info->link_stats[prim_psoc_id].egress_cnt++;
2616*5113495bSYour Name 		else
2617*5113495bSYour Name 			wsi_info->link_stats[prim_psoc_id].egress_cnt--;
2618*5113495bSYour Name 	}
2619*5113495bSYour Name 
2620*5113495bSYour Name 	n = 1;
2621*5113495bSYour Name 	for (i = 0; i < j; i++) {
2622*5113495bSYour Name 		sec_psoc_ix_grp = wlan_mlo_psoc_get_ix_in_grp(mlo_mgr,
2623*5113495bSYour Name 							      prim_grp_idx,
2624*5113495bSYour Name 							      sec_psoc_id[i]);
2625*5113495bSYour Name 		hops = qdf_min(mlo_psoc_grp->num_psoc -
2626*5113495bSYour Name 			       (prim_psoc_ix_grp - sec_psoc_ix_grp),
2627*5113495bSYour Name 				(sec_psoc_ix_grp - prim_psoc_ix_grp));
2628*5113495bSYour Name 
2629*5113495bSYour Name 
2630*5113495bSYour Name 		if (hops > n) {
2631*5113495bSYour Name 			hop_id = wlan_mlo_get_wsi_next_psoc(mlo_psoc_grp,
2632*5113495bSYour Name 							    prim_psoc_id, n);
2633*5113495bSYour Name 			n++;
2634*5113495bSYour Name 			if (hop_id == MLO_WSI_PSOC_ID_MAX)
2635*5113495bSYour Name 				continue;
2636*5113495bSYour Name 
2637*5113495bSYour Name 			wsi_info->link_stats[hop_id].send_wmi_cmd = true;
2638*5113495bSYour Name 			if (add)
2639*5113495bSYour Name 				wsi_info->link_stats[hop_id].ingress_cnt++;
2640*5113495bSYour Name 			else
2641*5113495bSYour Name 				wsi_info->link_stats[hop_id].ingress_cnt--;
2642*5113495bSYour Name 		}
2643*5113495bSYour Name 	}
2644*5113495bSYour Name 
2645*5113495bSYour Name 	/* Check if WMI bit is set, if yes, then send the command */
2646*5113495bSYour Name 	if (wlan_mlo_wsi_link_info_send_cmd() != QDF_STATUS_SUCCESS) {
2647*5113495bSYour Name 		mlo_err("WSI link info not sent for ML peer" QDF_MAC_ADDR_FMT,
2648*5113495bSYour Name 			QDF_MAC_ADDR_REF(ml_peer->peer_mld_addr.bytes));
2649*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
2650*5113495bSYour Name 	}
2651*5113495bSYour Name 
2652*5113495bSYour Name 	return QDF_STATUS_SUCCESS;
2653*5113495bSYour Name }
2654*5113495bSYour Name 
wlan_mlo_peer_wsi_link_add(struct wlan_mlo_peer_context * ml_peer)2655*5113495bSYour Name QDF_STATUS wlan_mlo_peer_wsi_link_add(struct wlan_mlo_peer_context *ml_peer)
2656*5113495bSYour Name {
2657*5113495bSYour Name 	if (!ml_peer) {
2658*5113495bSYour Name 		mlo_err("Invalid peer");
2659*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
2660*5113495bSYour Name 	}
2661*5113495bSYour Name 
2662*5113495bSYour Name 	return wlan_mlo_peer_wsi_link_update(ml_peer, 1);
2663*5113495bSYour Name }
2664*5113495bSYour Name 
wlan_mlo_peer_wsi_link_delete(struct wlan_mlo_peer_context * ml_peer)2665*5113495bSYour Name QDF_STATUS wlan_mlo_peer_wsi_link_delete(struct wlan_mlo_peer_context *ml_peer)
2666*5113495bSYour Name {
2667*5113495bSYour Name 	if (!ml_peer) {
2668*5113495bSYour Name 		mlo_err("Invalid peer");
2669*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
2670*5113495bSYour Name 	}
2671*5113495bSYour Name 
2672*5113495bSYour Name 	return wlan_mlo_peer_wsi_link_update(ml_peer, 0);
2673*5113495bSYour Name }
2674*5113495bSYour Name 
wlan_mlo_wsi_stats_block_cmd(void)2675*5113495bSYour Name void wlan_mlo_wsi_stats_block_cmd(void)
2676*5113495bSYour Name {
2677*5113495bSYour Name 	struct mlo_mgr_context *mlo_mgr = NULL;
2678*5113495bSYour Name 	struct mlo_wsi_info *wsi_info = NULL;
2679*5113495bSYour Name 
2680*5113495bSYour Name 	/* Retrieve the MLO manager context */
2681*5113495bSYour Name 	mlo_mgr = wlan_objmgr_get_mlo_ctx();
2682*5113495bSYour Name 	if (!mlo_mgr)
2683*5113495bSYour Name 		return;
2684*5113495bSYour Name 
2685*5113495bSYour Name 	/* Retrieve the WSI link info structure */
2686*5113495bSYour Name 	wsi_info = mlo_mgr->wsi_info;
2687*5113495bSYour Name 	if (!wsi_info)
2688*5113495bSYour Name 		return;
2689*5113495bSYour Name 
2690*5113495bSYour Name 	wsi_info->block_wmi_cmd++;
2691*5113495bSYour Name }
2692*5113495bSYour Name 
wlan_mlo_wsi_stats_allow_cmd(void)2693*5113495bSYour Name void wlan_mlo_wsi_stats_allow_cmd(void)
2694*5113495bSYour Name {
2695*5113495bSYour Name 	struct mlo_mgr_context *mlo_mgr = NULL;
2696*5113495bSYour Name 	struct mlo_wsi_info *wsi_info = NULL;
2697*5113495bSYour Name 
2698*5113495bSYour Name 	/* Retrieve the MLO manager context */
2699*5113495bSYour Name 	mlo_mgr = wlan_objmgr_get_mlo_ctx();
2700*5113495bSYour Name 	if (!mlo_mgr)
2701*5113495bSYour Name 		return;
2702*5113495bSYour Name 
2703*5113495bSYour Name 	/* Retrieve the WSI link info structure */
2704*5113495bSYour Name 	wsi_info = mlo_mgr->wsi_info;
2705*5113495bSYour Name 	if (!wsi_info)
2706*5113495bSYour Name 		return;
2707*5113495bSYour Name 
2708*5113495bSYour Name 	if (wsi_info->block_wmi_cmd)
2709*5113495bSYour Name 		wsi_info->block_wmi_cmd--;
2710*5113495bSYour Name }
2711*5113495bSYour Name 
2712*5113495bSYour Name #else
wlan_mlo_wsi_stats_block_cmd(void)2713*5113495bSYour Name void wlan_mlo_wsi_stats_block_cmd(void)
2714*5113495bSYour Name {
2715*5113495bSYour Name }
2716*5113495bSYour Name 
wlan_mlo_wsi_stats_allow_cmd(void)2717*5113495bSYour Name void wlan_mlo_wsi_stats_allow_cmd(void)
2718*5113495bSYour Name {
2719*5113495bSYour Name }
2720*5113495bSYour Name 
wlan_mlo_wsi_link_info_send_cmd(void)2721*5113495bSYour Name QDF_STATUS wlan_mlo_wsi_link_info_send_cmd(void)
2722*5113495bSYour Name {
2723*5113495bSYour Name 	return QDF_STATUS_SUCCESS;
2724*5113495bSYour Name }
2725*5113495bSYour Name 
wlan_mlo_peer_wsi_link_add(struct wlan_mlo_peer_context * ml_peer)2726*5113495bSYour Name QDF_STATUS wlan_mlo_peer_wsi_link_add(struct wlan_mlo_peer_context *ml_peer)
2727*5113495bSYour Name {
2728*5113495bSYour Name 	return QDF_STATUS_SUCCESS;
2729*5113495bSYour Name }
2730*5113495bSYour Name 
wlan_mlo_peer_wsi_link_delete(struct wlan_mlo_peer_context * ml_peer)2731*5113495bSYour Name QDF_STATUS wlan_mlo_peer_wsi_link_delete(struct wlan_mlo_peer_context *ml_peer)
2732*5113495bSYour Name {
2733*5113495bSYour Name 	return QDF_STATUS_SUCCESS;
2734*5113495bSYour Name }
2735*5113495bSYour Name #endif
2736*5113495bSYour Name 
wlan_mlo_ap_vdev_add_assoc_entry(struct wlan_objmgr_vdev * vdev,struct qdf_mac_addr * mld_addr)2737*5113495bSYour Name void wlan_mlo_ap_vdev_add_assoc_entry(struct wlan_objmgr_vdev *vdev,
2738*5113495bSYour Name 				      struct qdf_mac_addr *mld_addr)
2739*5113495bSYour Name {
2740*5113495bSYour Name 	struct wlan_mlo_dev_context *mld_ctx = vdev->mlo_dev_ctx;
2741*5113495bSYour Name 	struct wlan_mlo_sta_assoc_pending_list *assoc_list;
2742*5113495bSYour Name 	struct wlan_mlo_sta_entry *sta_entry = NULL;
2743*5113495bSYour Name 
2744*5113495bSYour Name 	if (!mld_ctx || !wlan_vdev_mlme_is_mlo_ap(vdev))
2745*5113495bSYour Name 		return;
2746*5113495bSYour Name 
2747*5113495bSYour Name 	assoc_list = &mld_ctx->ap_ctx->assoc_list;
2748*5113495bSYour Name 
2749*5113495bSYour Name 	sta_entry = wlan_mlo_ap_vdev_find_assoc_entry(vdev, mld_addr);
2750*5113495bSYour Name 	if (sta_entry) {
2751*5113495bSYour Name 		mlo_err("Duplicate entry " QDF_MAC_ADDR_FMT,
2752*5113495bSYour Name 			QDF_MAC_ADDR_REF(mld_addr->bytes));
2753*5113495bSYour Name 		return;
2754*5113495bSYour Name 	}
2755*5113495bSYour Name 
2756*5113495bSYour Name 	sta_entry = qdf_mem_malloc(sizeof(*sta_entry));
2757*5113495bSYour Name 	if (!sta_entry)
2758*5113495bSYour Name 		return;
2759*5113495bSYour Name 
2760*5113495bSYour Name 	qdf_copy_macaddr((struct qdf_mac_addr *)&sta_entry->peer_mld_addr,
2761*5113495bSYour Name 			 (struct qdf_mac_addr *)&mld_addr[0]);
2762*5113495bSYour Name 
2763*5113495bSYour Name 	qdf_spin_lock_bh(&assoc_list->list_lock);
2764*5113495bSYour Name 	qdf_list_insert_back(&assoc_list->peer_list, &sta_entry->mac_node);
2765*5113495bSYour Name 	qdf_spin_unlock_bh(&assoc_list->list_lock);
2766*5113495bSYour Name }
2767*5113495bSYour Name 
wlan_mlo_ap_vdev_del_assoc_entry(struct wlan_objmgr_vdev * vdev,struct qdf_mac_addr * mld_addr)2768*5113495bSYour Name void wlan_mlo_ap_vdev_del_assoc_entry(struct wlan_objmgr_vdev *vdev,
2769*5113495bSYour Name 				      struct qdf_mac_addr *mld_addr)
2770*5113495bSYour Name {
2771*5113495bSYour Name 	struct wlan_mlo_dev_context *mld_ctx = vdev->mlo_dev_ctx;
2772*5113495bSYour Name 	struct wlan_mlo_sta_assoc_pending_list *assoc_list;
2773*5113495bSYour Name 	struct wlan_mlo_sta_entry *sta_entry = NULL;
2774*5113495bSYour Name 
2775*5113495bSYour Name 	if (!mld_ctx || !wlan_vdev_mlme_is_mlo_ap(vdev))
2776*5113495bSYour Name 		return;
2777*5113495bSYour Name 
2778*5113495bSYour Name 	assoc_list = &mld_ctx->ap_ctx->assoc_list;
2779*5113495bSYour Name 	sta_entry = wlan_mlo_ap_vdev_find_assoc_entry(vdev, mld_addr);
2780*5113495bSYour Name 	if (!sta_entry)
2781*5113495bSYour Name 		return;
2782*5113495bSYour Name 
2783*5113495bSYour Name 	qdf_spin_lock_bh(&assoc_list->list_lock);
2784*5113495bSYour Name 	qdf_list_remove_node(&assoc_list->peer_list, &sta_entry->mac_node);
2785*5113495bSYour Name 	qdf_spin_unlock_bh(&assoc_list->list_lock);
2786*5113495bSYour Name 
2787*5113495bSYour Name 	qdf_mem_free(sta_entry);
2788*5113495bSYour Name }
2789*5113495bSYour Name 
2790*5113495bSYour Name static inline struct wlan_mlo_sta_entry *
wlan_mlo_assoc_list_peek_head(qdf_list_t * assoc_list)2791*5113495bSYour Name wlan_mlo_assoc_list_peek_head(qdf_list_t *assoc_list)
2792*5113495bSYour Name {
2793*5113495bSYour Name 	struct wlan_mlo_sta_entry *sta_entry = NULL;
2794*5113495bSYour Name 	qdf_list_node_t *list_node = NULL;
2795*5113495bSYour Name 
2796*5113495bSYour Name 	/* This API is invoked with lock acquired, do not add log prints */
2797*5113495bSYour Name 	if (qdf_list_peek_front(assoc_list, &list_node) != QDF_STATUS_SUCCESS)
2798*5113495bSYour Name 		return NULL;
2799*5113495bSYour Name 
2800*5113495bSYour Name 	sta_entry = qdf_container_of(list_node,
2801*5113495bSYour Name 				     struct wlan_mlo_sta_entry, mac_node);
2802*5113495bSYour Name 	return sta_entry;
2803*5113495bSYour Name }
2804*5113495bSYour Name 
2805*5113495bSYour Name static inline struct wlan_mlo_sta_entry *
wlan_mlo_sta_get_next_sta_entry(qdf_list_t * assoc_list,struct wlan_mlo_sta_entry * sta_entry)2806*5113495bSYour Name wlan_mlo_sta_get_next_sta_entry(qdf_list_t *assoc_list,
2807*5113495bSYour Name 				struct wlan_mlo_sta_entry *sta_entry)
2808*5113495bSYour Name {
2809*5113495bSYour Name 	struct wlan_mlo_sta_entry *next_sta_entry = NULL;
2810*5113495bSYour Name 	qdf_list_node_t *node = &sta_entry->mac_node;
2811*5113495bSYour Name 	qdf_list_node_t *next_node = NULL;
2812*5113495bSYour Name 
2813*5113495bSYour Name 	/* This API is invoked with lock acquired, do not add log prints */
2814*5113495bSYour Name 	if (!node)
2815*5113495bSYour Name 		return NULL;
2816*5113495bSYour Name 
2817*5113495bSYour Name 	if (qdf_list_peek_next(assoc_list, node, &next_node) !=
2818*5113495bSYour Name 				QDF_STATUS_SUCCESS)
2819*5113495bSYour Name 		return NULL;
2820*5113495bSYour Name 
2821*5113495bSYour Name 	next_sta_entry = qdf_container_of(next_node,
2822*5113495bSYour Name 					  struct wlan_mlo_sta_entry, mac_node);
2823*5113495bSYour Name 	return next_sta_entry;
2824*5113495bSYour Name }
2825*5113495bSYour Name 
2826*5113495bSYour Name struct wlan_mlo_sta_entry *
wlan_mlo_ap_vdev_find_assoc_entry(struct wlan_objmgr_vdev * vdev,struct qdf_mac_addr * mld_addr)2827*5113495bSYour Name wlan_mlo_ap_vdev_find_assoc_entry(struct wlan_objmgr_vdev *vdev,
2828*5113495bSYour Name 				  struct qdf_mac_addr *mld_addr)
2829*5113495bSYour Name {
2830*5113495bSYour Name 	struct wlan_mlo_dev_context *mld_ctx = vdev->mlo_dev_ctx;
2831*5113495bSYour Name 	struct wlan_mlo_sta_assoc_pending_list *assoc_list;
2832*5113495bSYour Name 	struct wlan_mlo_sta_entry *sta_entry = NULL;
2833*5113495bSYour Name 	struct wlan_mlo_sta_entry *next_sta_entry = NULL;
2834*5113495bSYour Name 
2835*5113495bSYour Name 	if (!mld_ctx || !wlan_vdev_mlme_is_mlo_ap(vdev))
2836*5113495bSYour Name 		return NULL;
2837*5113495bSYour Name 
2838*5113495bSYour Name 	assoc_list = &mld_ctx->ap_ctx->assoc_list;
2839*5113495bSYour Name 	if (qdf_list_empty(&assoc_list->peer_list)) {
2840*5113495bSYour Name 		mlo_info("list is empty");
2841*5113495bSYour Name 		return NULL;
2842*5113495bSYour Name 	}
2843*5113495bSYour Name 	qdf_spin_lock_bh(&assoc_list->list_lock);
2844*5113495bSYour Name 
2845*5113495bSYour Name 	sta_entry = wlan_mlo_assoc_list_peek_head(&assoc_list->peer_list);
2846*5113495bSYour Name 	while (sta_entry) {
2847*5113495bSYour Name 		if (qdf_is_macaddr_equal(&sta_entry->peer_mld_addr, mld_addr)) {
2848*5113495bSYour Name 			qdf_spin_unlock_bh(&assoc_list->list_lock);
2849*5113495bSYour Name 			return sta_entry;
2850*5113495bSYour Name 		}
2851*5113495bSYour Name 
2852*5113495bSYour Name 		next_sta_entry =
2853*5113495bSYour Name 		wlan_mlo_sta_get_next_sta_entry(&assoc_list->peer_list,
2854*5113495bSYour Name 						sta_entry);
2855*5113495bSYour Name 		sta_entry = next_sta_entry;
2856*5113495bSYour Name 	}
2857*5113495bSYour Name 	qdf_spin_unlock_bh(&assoc_list->list_lock);
2858*5113495bSYour Name 
2859*5113495bSYour Name 	return NULL;
2860*5113495bSYour Name }
2861*5113495bSYour Name 
2862