xref: /wlan-driver/qca-wifi-host-cmn/umac/mlo_mgr/src/wlan_mlo_mgr_sta.c (revision 5113495b16420b49004c444715d2daae2066e7dc) !
1*5113495bSYour Name /*
2*5113495bSYour Name  * Copyright (c) 2021, The Linux Foundation. All rights reserved.
3*5113495bSYour Name  * Copyright (c) 2021-2024 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 /*
19*5113495bSYour Name  * DOC: contains MLO manager STA related api's
20*5113495bSYour Name  */
21*5113495bSYour Name 
22*5113495bSYour Name #include <wlan_cmn.h>
23*5113495bSYour Name #include <wlan_mlo_mgr_sta.h>
24*5113495bSYour Name #include <wlan_cm_public_struct.h>
25*5113495bSYour Name #include <wlan_mlo_mgr_main.h>
26*5113495bSYour Name #include <wlan_cm_api.h>
27*5113495bSYour Name #include <wlan_mlo_mgr_cmn.h>
28*5113495bSYour Name #include <wlan_scan_api.h>
29*5113495bSYour Name #include <scheduler_api.h>
30*5113495bSYour Name #include <wlan_crypto_global_api.h>
31*5113495bSYour Name #include <utils_mlo.h>
32*5113495bSYour Name #include <wlan_mlme_cmn.h>
33*5113495bSYour Name #include <wlan_scan_utils_api.h>
34*5113495bSYour Name #include <qdf_time.h>
35*5113495bSYour Name #include <wlan_objmgr_peer_obj.h>
36*5113495bSYour Name #include <wlan_scan_api.h>
37*5113495bSYour Name #include <wlan_mlo_mgr_peer.h>
38*5113495bSYour Name #include <qdf_module.h>
39*5113495bSYour Name #include <wlan_mlo_mgr_public_api.h>
40*5113495bSYour Name 
41*5113495bSYour Name #ifdef WLAN_FEATURE_11BE_MLO
42*5113495bSYour Name static QDF_STATUS mlo_disconnect_req(struct wlan_objmgr_vdev *vdev,
43*5113495bSYour Name 				     enum wlan_cm_source source,
44*5113495bSYour Name 				     enum wlan_reason_code reason_code,
45*5113495bSYour Name 				     struct qdf_mac_addr *bssid,
46*5113495bSYour Name 				     bool validate_req);
47*5113495bSYour Name 
48*5113495bSYour Name void
mlo_allocate_and_copy_ies(struct wlan_cm_connect_req * target,struct wlan_cm_connect_req * source)49*5113495bSYour Name mlo_allocate_and_copy_ies(struct wlan_cm_connect_req *target,
50*5113495bSYour Name 			  struct wlan_cm_connect_req *source)
51*5113495bSYour Name {
52*5113495bSYour Name 	target->assoc_ie.ptr = NULL;
53*5113495bSYour Name 	target->scan_ie.ptr = NULL;
54*5113495bSYour Name 	target->crypto.wep_keys.key = NULL;
55*5113495bSYour Name 	target->crypto.wep_keys.seq = NULL;
56*5113495bSYour Name 	target->crypto.wep_keys.key_len = 0;
57*5113495bSYour Name 	target->crypto.wep_keys.seq_len = 0;
58*5113495bSYour Name 
59*5113495bSYour Name 	if (source->scan_ie.ptr) {
60*5113495bSYour Name 		target->scan_ie.ptr = qdf_mem_malloc(source->scan_ie.len);
61*5113495bSYour Name 		if (!target->scan_ie.ptr)
62*5113495bSYour Name 			target->scan_ie.len = 0;
63*5113495bSYour Name 		else
64*5113495bSYour Name 			qdf_mem_copy(target->scan_ie.ptr,
65*5113495bSYour Name 				     source->scan_ie.ptr, source->scan_ie.len);
66*5113495bSYour Name 	}
67*5113495bSYour Name 
68*5113495bSYour Name 	if (source->assoc_ie.ptr) {
69*5113495bSYour Name 		target->assoc_ie.ptr = qdf_mem_malloc(source->assoc_ie.len);
70*5113495bSYour Name 		if (!target->assoc_ie.ptr)
71*5113495bSYour Name 			target->assoc_ie.len = 0;
72*5113495bSYour Name 		else
73*5113495bSYour Name 			qdf_mem_copy(target->assoc_ie.ptr, source->assoc_ie.ptr,
74*5113495bSYour Name 				     source->assoc_ie.len);
75*5113495bSYour Name 	}
76*5113495bSYour Name }
77*5113495bSYour Name 
78*5113495bSYour Name /*
79*5113495bSYour Name  * mlo_get_tdls_link_vdev() - API to get tdls link vdev
80*5113495bSYour Name  * @mlo_dev_ctx: pointer to mlo dev context
81*5113495bSYour Name  *
82*5113495bSYour Name  * Return: MLD tdls link vdev
83*5113495bSYour Name  */
84*5113495bSYour Name static inline struct wlan_objmgr_vdev *
mlo_get_tdls_link_vdev(struct wlan_mlo_dev_context * mlo_dev_ctx)85*5113495bSYour Name mlo_get_tdls_link_vdev(struct wlan_mlo_dev_context *mlo_dev_ctx)
86*5113495bSYour Name {
87*5113495bSYour Name 	uint8_t i = 0;
88*5113495bSYour Name 
89*5113495bSYour Name 	if (!mlo_dev_ctx)
90*5113495bSYour Name 		return NULL;
91*5113495bSYour Name 
92*5113495bSYour Name 	for (i =  0; i < WLAN_UMAC_MLO_MAX_VDEVS; i++) {
93*5113495bSYour Name 		if (!mlo_dev_ctx->wlan_vdev_list[i])
94*5113495bSYour Name 			continue;
95*5113495bSYour Name 
96*5113495bSYour Name 		if (wlan_vdev_mlme_is_tdls_vdev(mlo_dev_ctx->wlan_vdev_list[i]))
97*5113495bSYour Name 			return mlo_dev_ctx->wlan_vdev_list[i];
98*5113495bSYour Name 	}
99*5113495bSYour Name 	return NULL;
100*5113495bSYour Name }
101*5113495bSYour Name 
102*5113495bSYour Name struct wlan_objmgr_vdev *
wlan_mlo_get_tdls_link_vdev(struct wlan_objmgr_vdev * vdev)103*5113495bSYour Name wlan_mlo_get_tdls_link_vdev(struct wlan_objmgr_vdev *vdev)
104*5113495bSYour Name {
105*5113495bSYour Name 	struct wlan_mlo_dev_context *mlo_dev_ctx = vdev->mlo_dev_ctx;
106*5113495bSYour Name 
107*5113495bSYour Name 	if (!mlo_dev_ctx || !wlan_vdev_mlme_is_mlo_vdev(vdev))
108*5113495bSYour Name 		return NULL;
109*5113495bSYour Name 
110*5113495bSYour Name 	return mlo_get_tdls_link_vdev(mlo_dev_ctx);
111*5113495bSYour Name }
112*5113495bSYour Name 
113*5113495bSYour Name /*
114*5113495bSYour Name  * mlo_get_assoc_link_vdev - API to get assoc link vdev
115*5113495bSYour Name  *
116*5113495bSYour Name  * @mlo_dev_ctx: pointer to mlo dev context
117*5113495bSYour Name  *
118*5113495bSYour Name  * Return: MLD assoc link vdev
119*5113495bSYour Name  */
120*5113495bSYour Name static inline struct wlan_objmgr_vdev *
mlo_get_assoc_link_vdev(struct wlan_mlo_dev_context * mlo_dev_ctx)121*5113495bSYour Name mlo_get_assoc_link_vdev(struct wlan_mlo_dev_context *mlo_dev_ctx)
122*5113495bSYour Name {
123*5113495bSYour Name 	uint8_t i = 0;
124*5113495bSYour Name 
125*5113495bSYour Name 	if (!mlo_dev_ctx)
126*5113495bSYour Name 		return NULL;
127*5113495bSYour Name 
128*5113495bSYour Name 	for (i =  0; i < WLAN_UMAC_MLO_MAX_VDEVS; i++) {
129*5113495bSYour Name 		if (!mlo_dev_ctx->wlan_vdev_list[i])
130*5113495bSYour Name 			continue;
131*5113495bSYour Name 
132*5113495bSYour Name 		if (wlan_vdev_mlme_is_mlo_vdev(mlo_dev_ctx->wlan_vdev_list[i]) &&
133*5113495bSYour Name 		    !wlan_vdev_mlme_is_mlo_link_vdev(mlo_dev_ctx->wlan_vdev_list[i]))
134*5113495bSYour Name 			return mlo_dev_ctx->wlan_vdev_list[i];
135*5113495bSYour Name 	}
136*5113495bSYour Name 	return NULL;
137*5113495bSYour Name }
138*5113495bSYour Name 
139*5113495bSYour Name struct wlan_objmgr_vdev *
wlan_mlo_get_assoc_link_vdev(struct wlan_objmgr_vdev * vdev)140*5113495bSYour Name wlan_mlo_get_assoc_link_vdev(struct wlan_objmgr_vdev *vdev)
141*5113495bSYour Name {
142*5113495bSYour Name 	struct wlan_mlo_dev_context *mlo_dev_ctx = vdev->mlo_dev_ctx;
143*5113495bSYour Name 
144*5113495bSYour Name 	if (!mlo_dev_ctx || !wlan_vdev_mlme_is_mlo_vdev(vdev))
145*5113495bSYour Name 		return NULL;
146*5113495bSYour Name 
147*5113495bSYour Name 	return mlo_get_assoc_link_vdev(mlo_dev_ctx);
148*5113495bSYour Name }
149*5113495bSYour Name 
150*5113495bSYour Name struct wlan_objmgr_vdev *
ucfg_mlo_get_assoc_link_vdev(struct wlan_objmgr_vdev * vdev)151*5113495bSYour Name ucfg_mlo_get_assoc_link_vdev(struct wlan_objmgr_vdev *vdev)
152*5113495bSYour Name {
153*5113495bSYour Name 	return wlan_mlo_get_assoc_link_vdev(vdev);
154*5113495bSYour Name }
155*5113495bSYour Name 
156*5113495bSYour Name /**
157*5113495bSYour Name  * mlo_is_mld_disconnected - Check whether MLD is disconnected
158*5113495bSYour Name  *
159*5113495bSYour Name  * @vdev: pointer to vdev
160*5113495bSYour Name  *
161*5113495bSYour Name  * Return: true if mld is disconnected, false otherwise
162*5113495bSYour Name  */
163*5113495bSYour Name static inline
mlo_is_mld_disconnected(struct wlan_objmgr_vdev * vdev)164*5113495bSYour Name bool mlo_is_mld_disconnected(struct wlan_objmgr_vdev *vdev)
165*5113495bSYour Name {
166*5113495bSYour Name 	struct wlan_mlo_dev_context *mlo_dev_ctx = vdev->mlo_dev_ctx;
167*5113495bSYour Name 	uint8_t i = 0;
168*5113495bSYour Name 
169*5113495bSYour Name 	if (!mlo_dev_ctx || !wlan_vdev_mlme_is_mlo_vdev(vdev))
170*5113495bSYour Name 		return true;
171*5113495bSYour Name 
172*5113495bSYour Name 	for (i =  0; i < WLAN_UMAC_MLO_MAX_VDEVS; i++) {
173*5113495bSYour Name 		if (!mlo_dev_ctx->wlan_vdev_list[i])
174*5113495bSYour Name 			continue;
175*5113495bSYour Name 
176*5113495bSYour Name 		if (!wlan_cm_is_vdev_disconnected(mlo_dev_ctx->wlan_vdev_list[i]))
177*5113495bSYour Name 			return false;
178*5113495bSYour Name 	}
179*5113495bSYour Name 	return true;
180*5113495bSYour Name }
181*5113495bSYour Name 
mlo_is_mld_disconnecting_connecting(struct wlan_objmgr_vdev * vdev)182*5113495bSYour Name bool mlo_is_mld_disconnecting_connecting(struct wlan_objmgr_vdev *vdev)
183*5113495bSYour Name {
184*5113495bSYour Name 	struct wlan_mlo_dev_context *mlo_dev_ctx = vdev->mlo_dev_ctx;
185*5113495bSYour Name 	uint8_t i = 0;
186*5113495bSYour Name 
187*5113495bSYour Name 	if (!mlo_dev_ctx || !wlan_vdev_mlme_is_mlo_vdev(vdev))
188*5113495bSYour Name 		return false;
189*5113495bSYour Name 
190*5113495bSYour Name 	for (i =  0; i < WLAN_UMAC_MLO_MAX_VDEVS; i++) {
191*5113495bSYour Name 		if (!mlo_dev_ctx->wlan_vdev_list[i])
192*5113495bSYour Name 			continue;
193*5113495bSYour Name 		if (wlan_cm_is_vdev_disconnecting(mlo_dev_ctx->wlan_vdev_list[i]) ||
194*5113495bSYour Name 		    wlan_cm_is_vdev_connecting(mlo_dev_ctx->wlan_vdev_list[i]))
195*5113495bSYour Name 			return true;
196*5113495bSYour Name 	}
197*5113495bSYour Name 	return false;
198*5113495bSYour Name }
199*5113495bSYour Name 
mlo_is_ml_connection_in_progress(struct wlan_objmgr_psoc * psoc,uint8_t vdev_id)200*5113495bSYour Name bool mlo_is_ml_connection_in_progress(struct wlan_objmgr_psoc *psoc,
201*5113495bSYour Name 				      uint8_t vdev_id)
202*5113495bSYour Name {
203*5113495bSYour Name 	struct wlan_objmgr_vdev *vdev;
204*5113495bSYour Name 	struct wlan_mlo_dev_context *mlo_dev_ctx;
205*5113495bSYour Name 	uint8_t i = 0;
206*5113495bSYour Name 	bool val = false;
207*5113495bSYour Name 
208*5113495bSYour Name 	vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, vdev_id,
209*5113495bSYour Name 						    WLAN_MLO_MGR_ID);
210*5113495bSYour Name 
211*5113495bSYour Name 	if (!vdev) {
212*5113495bSYour Name 		mlo_err("Invalid vdev");
213*5113495bSYour Name 		return false;
214*5113495bSYour Name 	}
215*5113495bSYour Name 
216*5113495bSYour Name 	mlo_dev_ctx = vdev->mlo_dev_ctx;
217*5113495bSYour Name 	if (!mlo_dev_ctx || !wlan_vdev_mlme_is_mlo_vdev(vdev))
218*5113495bSYour Name 		goto end;
219*5113495bSYour Name 
220*5113495bSYour Name 	for (i =  0; i < WLAN_UMAC_MLO_MAX_VDEVS; i++) {
221*5113495bSYour Name 		if (!mlo_dev_ctx->wlan_vdev_list[i])
222*5113495bSYour Name 			continue;
223*5113495bSYour Name 		if (qdf_test_bit(i, mlo_dev_ctx->sta_ctx->wlan_connected_links)) {
224*5113495bSYour Name 			if (!wlan_cm_is_vdev_connected(mlo_dev_ctx->wlan_vdev_list[i])) {
225*5113495bSYour Name 				val = true;
226*5113495bSYour Name 				goto end;
227*5113495bSYour Name 			}
228*5113495bSYour Name 		}
229*5113495bSYour Name 	}
230*5113495bSYour Name 
231*5113495bSYour Name end:
232*5113495bSYour Name 	wlan_objmgr_vdev_release_ref(vdev, WLAN_MLO_MGR_ID);
233*5113495bSYour Name 	return val;
234*5113495bSYour Name }
235*5113495bSYour Name 
ucfg_mlo_is_mld_disconnected(struct wlan_objmgr_vdev * vdev)236*5113495bSYour Name bool ucfg_mlo_is_mld_disconnected(struct wlan_objmgr_vdev *vdev)
237*5113495bSYour Name {
238*5113495bSYour Name 	return mlo_is_mld_disconnected(vdev);
239*5113495bSYour Name }
240*5113495bSYour Name 
241*5113495bSYour Name /**
242*5113495bSYour Name  * mlo_send_link_disconnect- Issue the disconnect request on MLD links
243*5113495bSYour Name  *
244*5113495bSYour Name  * @vdev: pointer to vdev
245*5113495bSYour Name  * @source: disconnect source
246*5113495bSYour Name  * @reason_code: disconnect reason
247*5113495bSYour Name  * @bssid: bssid of AP to disconnect, can be null if not known
248*5113495bSYour Name  *
249*5113495bSYour Name  * Return: QDF_STATUS
250*5113495bSYour Name  */
251*5113495bSYour Name static QDF_STATUS
mlo_send_link_disconnect(struct wlan_objmgr_vdev * vdev,enum wlan_cm_source source,enum wlan_reason_code reason_code,struct qdf_mac_addr * bssid)252*5113495bSYour Name mlo_send_link_disconnect(struct wlan_objmgr_vdev *vdev,
253*5113495bSYour Name 			 enum wlan_cm_source source,
254*5113495bSYour Name 			 enum wlan_reason_code reason_code,
255*5113495bSYour Name 			 struct qdf_mac_addr *bssid)
256*5113495bSYour Name {
257*5113495bSYour Name 	uint8_t i = 0;
258*5113495bSYour Name 	enum wlan_cm_source link_source = source;
259*5113495bSYour Name 	struct wlan_objmgr_vdev *assoc_vdev =
260*5113495bSYour Name 			mlo_get_assoc_link_vdev(vdev->mlo_dev_ctx);
261*5113495bSYour Name 	struct wlan_objmgr_vdev *wlan_vdev_list[WLAN_UMAC_MLO_MAX_VDEVS];
262*5113495bSYour Name 	uint16_t vdev_count = 0;
263*5113495bSYour Name 	struct wlan_mlo_sta *sta_ctx = NULL;
264*5113495bSYour Name 
265*5113495bSYour Name 	sta_ctx = vdev->mlo_dev_ctx->sta_ctx;
266*5113495bSYour Name 	if (!sta_ctx) {
267*5113495bSYour Name 		mlo_err("Invalid sta_ctx");
268*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
269*5113495bSYour Name 	}
270*5113495bSYour Name 
271*5113495bSYour Name 	if (!assoc_vdev && mlo_mgr_is_link_switch_supported(vdev)) {
272*5113495bSYour Name 		if (!wlan_mlo_mgr_is_link_switch_on_assoc_vdev(vdev))
273*5113495bSYour Name 			return QDF_STATUS_E_FAILURE;
274*5113495bSYour Name 
275*5113495bSYour Name 		assoc_vdev = wlan_mlo_mgr_link_switch_get_assoc_vdev(vdev);
276*5113495bSYour Name 		mlo_release_vdev_ref(assoc_vdev);
277*5113495bSYour Name 	}
278*5113495bSYour Name 
279*5113495bSYour Name 	/*
280*5113495bSYour Name 	 * Change the source for the link vdev to make sure it's handled as a
281*5113495bSYour Name 	 * Northbound disconnect in VDEV/PEER state machine.
282*5113495bSYour Name 	 */
283*5113495bSYour Name 	if (source != CM_OSIF_DISCONNECT)
284*5113495bSYour Name 		link_source = CM_MLO_LINK_VDEV_DISCONNECT;
285*5113495bSYour Name 
286*5113495bSYour Name 	mlo_sta_get_vdev_list(vdev, &vdev_count, wlan_vdev_list);
287*5113495bSYour Name 	for (i =  0; i < vdev_count; i++) {
288*5113495bSYour Name 		if ((wlan_vdev_list[i] != assoc_vdev) &&
289*5113495bSYour Name 		    (qdf_test_bit(i, sta_ctx->wlan_connected_links) ||
290*5113495bSYour Name 		    (wlan_cm_is_vdev_connected(wlan_vdev_list[i]) &&
291*5113495bSYour Name 		    !wlan_peer_is_mlo(wlan_vdev_get_bsspeer(wlan_vdev_list[i]))) ||
292*5113495bSYour Name 		    wlan_cm_is_vdev_idle_due_to_link_switch(wlan_vdev_list[i])))
293*5113495bSYour Name 			wlan_cm_disconnect(wlan_vdev_list[i],
294*5113495bSYour Name 					   link_source, reason_code,
295*5113495bSYour Name 					   NULL);
296*5113495bSYour Name 		mlo_release_vdev_ref(wlan_vdev_list[i]);
297*5113495bSYour Name 	}
298*5113495bSYour Name 
299*5113495bSYour Name 	if (assoc_vdev)
300*5113495bSYour Name 		wlan_cm_disconnect(assoc_vdev, source, reason_code, NULL);
301*5113495bSYour Name 
302*5113495bSYour Name 	return QDF_STATUS_SUCCESS;
303*5113495bSYour Name }
304*5113495bSYour Name 
mlo_free_copied_conn_req(struct wlan_mlo_sta * sta_ctx)305*5113495bSYour Name static void mlo_free_copied_conn_req(struct wlan_mlo_sta *sta_ctx)
306*5113495bSYour Name {
307*5113495bSYour Name 	if (sta_ctx) {
308*5113495bSYour Name 		mlo_debug("enter");
309*5113495bSYour Name 		copied_conn_req_lock_acquire(sta_ctx);
310*5113495bSYour Name 		if (sta_ctx->copied_conn_req) {
311*5113495bSYour Name 			wlan_cm_free_connect_req(sta_ctx->copied_conn_req);
312*5113495bSYour Name 			sta_ctx->copied_conn_req = NULL;
313*5113495bSYour Name 		}
314*5113495bSYour Name 		copied_conn_req_lock_release(sta_ctx);
315*5113495bSYour Name 	}
316*5113495bSYour Name }
317*5113495bSYour Name 
318*5113495bSYour Name #ifdef WLAN_FEATURE_11BE_MLO_ADV_FEATURE
mlo_mgr_get_per_link_chan_info(struct wlan_objmgr_vdev * vdev,int link_id,struct wlan_channel * chan_info)319*5113495bSYour Name int mlo_mgr_get_per_link_chan_info(struct wlan_objmgr_vdev *vdev, int link_id,
320*5113495bSYour Name 				   struct wlan_channel *chan_info)
321*5113495bSYour Name {
322*5113495bSYour Name 	struct mlo_link_info *ml_link_info;
323*5113495bSYour Name 
324*5113495bSYour Name 	ml_link_info = mlo_mgr_get_ap_link_by_link_id(vdev->mlo_dev_ctx,
325*5113495bSYour Name 						      link_id);
326*5113495bSYour Name 	if (!ml_link_info) {
327*5113495bSYour Name 		mlo_debug("ml_link_info null for link_id: %d", link_id);
328*5113495bSYour Name 		return -EINVAL;
329*5113495bSYour Name 	}
330*5113495bSYour Name 
331*5113495bSYour Name 	qdf_mem_copy(chan_info, ml_link_info->link_chan_info,
332*5113495bSYour Name 		     sizeof(*chan_info));
333*5113495bSYour Name 
334*5113495bSYour Name 	return 0;
335*5113495bSYour Name }
336*5113495bSYour Name 
337*5113495bSYour Name static QDF_STATUS
mlo_validate_connect_req(struct wlan_objmgr_vdev * vdev,struct wlan_mlo_dev_context * mlo_dev_ctx,struct wlan_cm_connect_req * req)338*5113495bSYour Name mlo_validate_connect_req(struct wlan_objmgr_vdev *vdev,
339*5113495bSYour Name 			 struct wlan_mlo_dev_context *mlo_dev_ctx,
340*5113495bSYour Name 			 struct wlan_cm_connect_req *req)
341*5113495bSYour Name {
342*5113495bSYour Name /* check back to back connect handling */
343*5113495bSYour Name 	return QDF_STATUS_SUCCESS;
344*5113495bSYour Name }
345*5113495bSYour Name 
346*5113495bSYour Name static QDF_STATUS
mlo_validate_disconn_req(struct wlan_objmgr_vdev * vdev,enum wlan_cm_source source,enum wlan_reason_code reason_code,struct qdf_mac_addr * bssid)347*5113495bSYour Name mlo_validate_disconn_req(struct wlan_objmgr_vdev *vdev,
348*5113495bSYour Name 			 enum wlan_cm_source source,
349*5113495bSYour Name 			 enum wlan_reason_code reason_code,
350*5113495bSYour Name 			 struct qdf_mac_addr *bssid)
351*5113495bSYour Name {
352*5113495bSYour Name 	return QDF_STATUS_SUCCESS;
353*5113495bSYour Name }
354*5113495bSYour Name 
mlo_validate_mlo_cap(struct wlan_objmgr_vdev * vdev)355*5113495bSYour Name static QDF_STATUS mlo_validate_mlo_cap(struct wlan_objmgr_vdev *vdev)
356*5113495bSYour Name {
357*5113495bSYour Name 	return QDF_STATUS_SUCCESS;
358*5113495bSYour Name }
359*5113495bSYour Name 
360*5113495bSYour Name static inline
mlo_mld_clear_mlo_cap(struct wlan_objmgr_vdev * vdev)361*5113495bSYour Name void mlo_mld_clear_mlo_cap(struct wlan_objmgr_vdev *vdev)
362*5113495bSYour Name { }
363*5113495bSYour Name #else
364*5113495bSYour Name /**
365*5113495bSYour Name  * mlo_is_mld_connected - Check whether MLD is connected
366*5113495bSYour Name  *
367*5113495bSYour Name  * @vdev: pointer to vdev
368*5113495bSYour Name  *
369*5113495bSYour Name  * Return: true if mld is connected, false otherwise
370*5113495bSYour Name  */
371*5113495bSYour Name static inline
mlo_is_mld_connected(struct wlan_objmgr_vdev * vdev)372*5113495bSYour Name bool mlo_is_mld_connected(struct wlan_objmgr_vdev *vdev)
373*5113495bSYour Name {
374*5113495bSYour Name 	struct wlan_mlo_dev_context *mlo_dev_ctx = vdev->mlo_dev_ctx;
375*5113495bSYour Name 	uint8_t i = 0;
376*5113495bSYour Name 
377*5113495bSYour Name 	if (!mlo_dev_ctx || !wlan_vdev_mlme_is_mlo_vdev(vdev))
378*5113495bSYour Name 		return true;
379*5113495bSYour Name 
380*5113495bSYour Name 	for (i =  0; i < WLAN_UMAC_MLO_MAX_VDEVS; i++) {
381*5113495bSYour Name 		if (!mlo_dev_ctx->wlan_vdev_list[i])
382*5113495bSYour Name 			continue;
383*5113495bSYour Name 
384*5113495bSYour Name 		if (qdf_test_bit(i, mlo_dev_ctx->sta_ctx->wlan_connected_links)) {
385*5113495bSYour Name 			if (!wlan_cm_is_vdev_connected(mlo_dev_ctx->wlan_vdev_list[i]))
386*5113495bSYour Name 				return false;
387*5113495bSYour Name 		}
388*5113495bSYour Name 	}
389*5113495bSYour Name 	return true;
390*5113495bSYour Name }
391*5113495bSYour Name 
ucfg_mlo_is_mld_connected(struct wlan_objmgr_vdev * vdev)392*5113495bSYour Name bool ucfg_mlo_is_mld_connected(struct wlan_objmgr_vdev *vdev)
393*5113495bSYour Name {
394*5113495bSYour Name 	return mlo_is_mld_connected(vdev);
395*5113495bSYour Name }
396*5113495bSYour Name 
397*5113495bSYour Name static inline
mlo_mld_clear_mlo_cap(struct wlan_objmgr_vdev * vdev)398*5113495bSYour Name void mlo_mld_clear_mlo_cap(struct wlan_objmgr_vdev *vdev)
399*5113495bSYour Name {
400*5113495bSYour Name 	struct wlan_mlo_dev_context *mlo_dev_ctx = vdev->mlo_dev_ctx;
401*5113495bSYour Name 	uint8_t i = 0;
402*5113495bSYour Name 
403*5113495bSYour Name 	if (!mlo_dev_ctx || !wlan_vdev_mlme_is_mlo_vdev(vdev))
404*5113495bSYour Name 		return;
405*5113495bSYour Name 
406*5113495bSYour Name 	for (i =  0; i < WLAN_UMAC_MLO_MAX_VDEVS; i++) {
407*5113495bSYour Name 		if (!mlo_dev_ctx->wlan_vdev_list[i])
408*5113495bSYour Name 			continue;
409*5113495bSYour Name 		wlan_vdev_mlme_clear_mlo_vdev(mlo_dev_ctx->wlan_vdev_list[i]);
410*5113495bSYour Name 		wlan_vdev_mlme_clear_mlo_link_vdev(mlo_dev_ctx->wlan_vdev_list[i]);
411*5113495bSYour Name 	}
412*5113495bSYour Name 	mlo_clear_bridge_sta_ctx(vdev);
413*5113495bSYour Name }
414*5113495bSYour Name 
ucfg_mlo_mld_clear_mlo_cap(struct wlan_objmgr_vdev * vdev)415*5113495bSYour Name void ucfg_mlo_mld_clear_mlo_cap(struct wlan_objmgr_vdev *vdev)
416*5113495bSYour Name {
417*5113495bSYour Name 	mlo_mld_clear_mlo_cap(vdev);
418*5113495bSYour Name }
419*5113495bSYour Name 
420*5113495bSYour Name static void
mlo_cm_handle_connect_in_disconnection_state(struct wlan_objmgr_vdev * vdev,struct wlan_cm_connect_req * req)421*5113495bSYour Name mlo_cm_handle_connect_in_disconnection_state(struct wlan_objmgr_vdev *vdev,
422*5113495bSYour Name 					     struct wlan_cm_connect_req *req)
423*5113495bSYour Name {
424*5113495bSYour Name 	struct wlan_mlo_dev_context *mlo_dev_ctx = vdev->mlo_dev_ctx;
425*5113495bSYour Name 	struct wlan_mlo_sta *sta_ctx;
426*5113495bSYour Name 
427*5113495bSYour Name 	if (!mlo_dev_ctx) {
428*5113495bSYour Name 		mlo_err("ML dev ctx is NULL");
429*5113495bSYour Name 		return;
430*5113495bSYour Name 	}
431*5113495bSYour Name 
432*5113495bSYour Name 	sta_ctx = mlo_dev_ctx->sta_ctx;
433*5113495bSYour Name 	if (!sta_ctx->connect_req)
434*5113495bSYour Name 		sta_ctx->connect_req = qdf_mem_malloc(
435*5113495bSYour Name 					sizeof(struct wlan_cm_connect_req));
436*5113495bSYour Name 
437*5113495bSYour Name 	if (sta_ctx->connect_req) {
438*5113495bSYour Name 		qdf_mem_copy(sta_ctx->connect_req, req,
439*5113495bSYour Name 			     sizeof(struct wlan_cm_connect_req));
440*5113495bSYour Name 		mlo_allocate_and_copy_ies(sta_ctx->connect_req, req);
441*5113495bSYour Name 	} else {
442*5113495bSYour Name 		mlo_err("Failed to allocate connect req");
443*5113495bSYour Name 	}
444*5113495bSYour Name }
445*5113495bSYour Name 
446*5113495bSYour Name static QDF_STATUS
mlo_validate_disconn_req(struct wlan_objmgr_vdev * vdev,enum wlan_cm_source source,enum wlan_reason_code reason_code,struct qdf_mac_addr * bssid)447*5113495bSYour Name mlo_validate_disconn_req(struct wlan_objmgr_vdev *vdev,
448*5113495bSYour Name 			 enum wlan_cm_source source,
449*5113495bSYour Name 			 enum wlan_reason_code reason_code,
450*5113495bSYour Name 			 struct qdf_mac_addr *bssid)
451*5113495bSYour Name {
452*5113495bSYour Name 	struct wlan_mlo_dev_context *mlo_dev = vdev->mlo_dev_ctx;
453*5113495bSYour Name 	struct wlan_mlo_sta *sta_ctx = mlo_dev->sta_ctx;
454*5113495bSYour Name 	uint8_t i = 0;
455*5113495bSYour Name 
456*5113495bSYour Name 	for (i = 0; i < WLAN_UMAC_MLO_MAX_VDEVS; i++) {
457*5113495bSYour Name 		if (!mlo_dev->wlan_vdev_list[i])
458*5113495bSYour Name 			continue;
459*5113495bSYour Name 
460*5113495bSYour Name 		if (wlan_cm_is_vdev_connecting(mlo_dev->wlan_vdev_list[i])) {
461*5113495bSYour Name 			if (!wlan_vdev_mlme_is_mlo_link_vdev(
462*5113495bSYour Name 						mlo_dev->wlan_vdev_list[i]))
463*5113495bSYour Name 				return QDF_STATUS_SUCCESS;
464*5113495bSYour Name 
465*5113495bSYour Name 			if (!sta_ctx->disconn_req)
466*5113495bSYour Name 				sta_ctx->disconn_req =
467*5113495bSYour Name 					qdf_mem_malloc(
468*5113495bSYour Name 					sizeof(struct wlan_cm_disconnect_req));
469*5113495bSYour Name 
470*5113495bSYour Name 			if (!sta_ctx->disconn_req)
471*5113495bSYour Name 				return QDF_STATUS_SUCCESS;
472*5113495bSYour Name 
473*5113495bSYour Name 			sta_ctx->disconn_req->vdev_id =
474*5113495bSYour Name 						wlan_vdev_get_id(vdev);
475*5113495bSYour Name 			sta_ctx->disconn_req->source = source;
476*5113495bSYour Name 			sta_ctx->disconn_req->reason_code = reason_code;
477*5113495bSYour Name 			if (bssid)
478*5113495bSYour Name 				qdf_copy_macaddr(&sta_ctx->disconn_req->bssid,
479*5113495bSYour Name 						 bssid);
480*5113495bSYour Name 			return QDF_STATUS_E_BUSY;
481*5113495bSYour Name 		} else if (wlan_cm_is_vdev_connected(mlo_dev->wlan_vdev_list[i]) &&
482*5113495bSYour Name 			   !wlan_vdev_mlme_is_mlo_link_vdev(
483*5113495bSYour Name 				mlo_dev->wlan_vdev_list[i]) &&
484*5113495bSYour Name 			   wlan_peer_is_mlo(wlan_vdev_get_bsspeer(
485*5113495bSYour Name 						mlo_dev->wlan_vdev_list[i]))) {
486*5113495bSYour Name 				/* If the vdev is moved to connected state but
487*5113495bSYour Name 				 * MLO mgr is not yet notified, defer disconnect
488*5113495bSYour Name 				 * as it can cause race between connect complete
489*5113495bSYour Name 				 * and disconnect initiation
490*5113495bSYour Name 				 */
491*5113495bSYour Name 			if (!qdf_test_bit(i, sta_ctx->wlan_connected_links)) {
492*5113495bSYour Name 				if (!sta_ctx->disconn_req)
493*5113495bSYour Name 					sta_ctx->disconn_req =
494*5113495bSYour Name 						qdf_mem_malloc(
495*5113495bSYour Name 						sizeof(struct wlan_cm_disconnect_req));
496*5113495bSYour Name 
497*5113495bSYour Name 				if (!sta_ctx->disconn_req)
498*5113495bSYour Name 					return QDF_STATUS_SUCCESS;
499*5113495bSYour Name 
500*5113495bSYour Name 				sta_ctx->disconn_req->vdev_id =
501*5113495bSYour Name 					wlan_vdev_get_id(vdev);
502*5113495bSYour Name 				sta_ctx->disconn_req->source = source;
503*5113495bSYour Name 				sta_ctx->disconn_req->reason_code = reason_code;
504*5113495bSYour Name 				if (bssid)
505*5113495bSYour Name 					qdf_copy_macaddr(&sta_ctx->disconn_req->bssid,
506*5113495bSYour Name 							 bssid);
507*5113495bSYour Name 
508*5113495bSYour Name 				return QDF_STATUS_E_BUSY;
509*5113495bSYour Name 			}
510*5113495bSYour Name 		}
511*5113495bSYour Name 	}
512*5113495bSYour Name 	return QDF_STATUS_SUCCESS;
513*5113495bSYour Name }
514*5113495bSYour Name 
mlo_disconnect_no_lock(struct wlan_objmgr_vdev * vdev,enum wlan_cm_source source,enum wlan_reason_code reason_code,struct qdf_mac_addr * bssid)515*5113495bSYour Name static QDF_STATUS mlo_disconnect_no_lock(struct wlan_objmgr_vdev *vdev,
516*5113495bSYour Name 					 enum wlan_cm_source source,
517*5113495bSYour Name 					 enum wlan_reason_code reason_code,
518*5113495bSYour Name 					 struct qdf_mac_addr *bssid)
519*5113495bSYour Name {
520*5113495bSYour Name 	struct wlan_mlo_dev_context *mlo_dev_ctx = vdev->mlo_dev_ctx;
521*5113495bSYour Name 	struct wlan_mlo_sta *sta_ctx = NULL;
522*5113495bSYour Name 	QDF_STATUS status = QDF_STATUS_SUCCESS;
523*5113495bSYour Name 	struct wlan_objmgr_vdev *assoc_vdev = NULL;
524*5113495bSYour Name 	uint8_t i = 0;
525*5113495bSYour Name 
526*5113495bSYour Name 	if (mlo_dev_ctx)
527*5113495bSYour Name 		sta_ctx = mlo_dev_ctx->sta_ctx;
528*5113495bSYour Name 	if (sta_ctx) {
529*5113495bSYour Name 		mlo_free_copied_conn_req(sta_ctx);
530*5113495bSYour Name 	} else {
531*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
532*5113495bSYour Name 	}
533*5113495bSYour Name 
534*5113495bSYour Name 	if (wlan_vdev_mlme_is_mlo_vdev(vdev)) {
535*5113495bSYour Name 		sta_ctx = mlo_dev_ctx->sta_ctx;
536*5113495bSYour Name 		if (!sta_ctx)
537*5113495bSYour Name 			return QDF_STATUS_E_FAILURE;
538*5113495bSYour Name 
539*5113495bSYour Name 		assoc_vdev = mlo_get_assoc_link_vdev(mlo_dev_ctx);
540*5113495bSYour Name 
541*5113495bSYour Name 		if (sta_ctx->connect_req) {
542*5113495bSYour Name 			wlan_cm_free_connect_req(sta_ctx->connect_req);
543*5113495bSYour Name 			sta_ctx->connect_req = NULL;
544*5113495bSYour Name 		}
545*5113495bSYour Name 
546*5113495bSYour Name 		status = mlo_validate_disconn_req(vdev, source,
547*5113495bSYour Name 						  reason_code, bssid);
548*5113495bSYour Name 		if (QDF_IS_STATUS_ERROR(status)) {
549*5113495bSYour Name 			mlo_err("Connect in progress, deferring disconnect");
550*5113495bSYour Name 			return status;
551*5113495bSYour Name 		}
552*5113495bSYour Name 
553*5113495bSYour Name 		for (i =  0; i < WLAN_UMAC_MLO_MAX_VDEVS; i++) {
554*5113495bSYour Name 			if (!mlo_dev_ctx->wlan_vdev_list[i])
555*5113495bSYour Name 				continue;
556*5113495bSYour Name 
557*5113495bSYour Name 			if ((mlo_dev_ctx->wlan_vdev_list[i] != assoc_vdev) &&
558*5113495bSYour Name 			    (qdf_test_bit(i, mlo_dev_ctx->sta_ctx->wlan_connected_links) ||
559*5113495bSYour Name 			    (wlan_cm_is_vdev_connected(mlo_dev_ctx->wlan_vdev_list[i]) &&
560*5113495bSYour Name 			     !wlan_peer_is_mlo(wlan_vdev_get_bsspeer(mlo_dev_ctx->wlan_vdev_list[i])))))
561*5113495bSYour Name 				wlan_cm_disconnect(mlo_dev_ctx->wlan_vdev_list[i],
562*5113495bSYour Name 						   source, reason_code,
563*5113495bSYour Name 						   NULL);
564*5113495bSYour Name 		}
565*5113495bSYour Name 
566*5113495bSYour Name 		if (assoc_vdev)
567*5113495bSYour Name 			wlan_cm_disconnect(assoc_vdev, source,
568*5113495bSYour Name 					   reason_code, NULL);
569*5113495bSYour Name 	}
570*5113495bSYour Name 
571*5113495bSYour Name 	return status;
572*5113495bSYour Name }
573*5113495bSYour Name 
574*5113495bSYour Name static void
mlo_cm_handle_connect_in_connection_state(struct wlan_objmgr_vdev * vdev,struct wlan_cm_connect_req * req)575*5113495bSYour Name mlo_cm_handle_connect_in_connection_state(struct wlan_objmgr_vdev *vdev,
576*5113495bSYour Name 					  struct wlan_cm_connect_req *req)
577*5113495bSYour Name {
578*5113495bSYour Name 	mlo_disconnect_no_lock(vdev, CM_INTERNAL_DISCONNECT,
579*5113495bSYour Name 			       REASON_UNSPEC_FAILURE, NULL);
580*5113495bSYour Name 	mlo_cm_handle_connect_in_disconnection_state(vdev, req);
581*5113495bSYour Name }
582*5113495bSYour Name 
583*5113495bSYour Name static QDF_STATUS
mlo_validate_connect_req(struct wlan_objmgr_vdev * vdev,struct wlan_mlo_dev_context * mlo_dev_ctx,struct wlan_cm_connect_req * req)584*5113495bSYour Name mlo_validate_connect_req(struct wlan_objmgr_vdev *vdev,
585*5113495bSYour Name 			 struct wlan_mlo_dev_context *mlo_dev_ctx,
586*5113495bSYour Name 			 struct wlan_cm_connect_req *req)
587*5113495bSYour Name {
588*5113495bSYour Name 	uint8_t i = 0;
589*5113495bSYour Name 	QDF_STATUS status = QDF_STATUS_SUCCESS;
590*5113495bSYour Name 
591*5113495bSYour Name 	if (!wlan_vdev_mlme_is_mlo_vdev(vdev))
592*5113495bSYour Name 		return QDF_STATUS_SUCCESS;
593*5113495bSYour Name 
594*5113495bSYour Name 	// Handle connect in various states
595*5113495bSYour Name 	for (i = 0; i < WLAN_UMAC_MLO_MAX_VDEVS; i++) {
596*5113495bSYour Name 		if (!mlo_dev_ctx->wlan_vdev_list[i])
597*5113495bSYour Name 			continue;
598*5113495bSYour Name 
599*5113495bSYour Name 		if ((wlan_cm_is_vdev_connected(mlo_dev_ctx->wlan_vdev_list[i])) ||
600*5113495bSYour Name 		    (wlan_cm_is_vdev_connecting(mlo_dev_ctx->wlan_vdev_list[i])) ||
601*5113495bSYour Name 		    (wlan_cm_is_vdev_roaming(mlo_dev_ctx->wlan_vdev_list[i]))) {
602*5113495bSYour Name 			mlo_cm_handle_connect_in_connection_state(mlo_dev_ctx->wlan_vdev_list[i], req);
603*5113495bSYour Name 			return QDF_STATUS_E_BUSY;
604*5113495bSYour Name 		} else if (wlan_cm_is_vdev_disconnecting(mlo_dev_ctx->wlan_vdev_list[i])) {
605*5113495bSYour Name 			mlo_cm_handle_connect_in_disconnection_state(mlo_dev_ctx->wlan_vdev_list[i], req);
606*5113495bSYour Name 			return QDF_STATUS_E_BUSY;
607*5113495bSYour Name 		}
608*5113495bSYour Name 
609*5113495bSYour Name 		/*
610*5113495bSYour Name 		 * mlo_connect: update wlan_connect_req_links in
611*5113495bSYour Name 		 * wlan_cfg80211_conect on osif_cm_connect,
612*5113495bSYour Name 		 * Validate pre checks for connection
613*5113495bSYour Name 		 */
614*5113495bSYour Name 		if (qdf_test_bit(i, mlo_dev_ctx->sta_ctx->wlan_connect_req_links)) {
615*5113495bSYour Name 			status = mlo_mlme_validate_conn_req(
616*5113495bSYour Name 					mlo_dev_ctx->wlan_vdev_list[i], NULL);
617*5113495bSYour Name 			if (status != QDF_STATUS_SUCCESS)
618*5113495bSYour Name 				return status;
619*5113495bSYour Name 			/*
620*5113495bSYour Name 			 * clone security params in all partner sta vaps
621*5113495bSYour Name 			 */
622*5113495bSYour Name 			mlo_mlme_clone_sta_security(
623*5113495bSYour Name 				mlo_dev_ctx->wlan_vdev_list[i], req);
624*5113495bSYour Name 		}
625*5113495bSYour Name 	}
626*5113495bSYour Name 	return status;
627*5113495bSYour Name }
628*5113495bSYour Name 
mlo_validate_mlo_cap(struct wlan_objmgr_vdev * vdev)629*5113495bSYour Name static QDF_STATUS mlo_validate_mlo_cap(struct wlan_objmgr_vdev *vdev)
630*5113495bSYour Name {
631*5113495bSYour Name 	if (wlan_vdev_mlme_is_mlo_vdev(vdev))
632*5113495bSYour Name 		return QDF_STATUS_SUCCESS;
633*5113495bSYour Name 
634*5113495bSYour Name 	return QDF_STATUS_E_FAILURE;
635*5113495bSYour Name }
636*5113495bSYour Name #endif
637*5113495bSYour Name 
mlo_set_cu_bpcc(struct wlan_objmgr_vdev * vdev,uint8_t vdev_id,uint8_t bpcc)638*5113495bSYour Name QDF_STATUS mlo_set_cu_bpcc(struct wlan_objmgr_vdev *vdev,
639*5113495bSYour Name 			   uint8_t vdev_id, uint8_t bpcc)
640*5113495bSYour Name {
641*5113495bSYour Name 	struct wlan_mlo_dev_context *mlo_dev_ctx;
642*5113495bSYour Name 	struct mlo_sta_cu_params *cu_param;
643*5113495bSYour Name 	uint8_t i;
644*5113495bSYour Name 
645*5113495bSYour Name 	mlo_dev_ctx = vdev->mlo_dev_ctx;
646*5113495bSYour Name 	if (!mlo_dev_ctx) {
647*5113495bSYour Name 		mlo_err("ML dev ctx is NULL");
648*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
649*5113495bSYour Name 	}
650*5113495bSYour Name 
651*5113495bSYour Name 	cu_param = &mlo_dev_ctx->sta_ctx->mlo_cu_param[0];
652*5113495bSYour Name 	for (i = 0; i < WLAN_UMAC_MLO_MAX_VDEVS; i++) {
653*5113495bSYour Name 		if (cu_param[i].initialized && cu_param[i].vdev_id == vdev_id) {
654*5113495bSYour Name 			cu_param[i].bpcc = bpcc;
655*5113495bSYour Name 			return QDF_STATUS_SUCCESS;
656*5113495bSYour Name 		}
657*5113495bSYour Name 	}
658*5113495bSYour Name 
659*5113495bSYour Name 	return QDF_STATUS_E_INVAL;
660*5113495bSYour Name }
661*5113495bSYour Name 
mlo_get_cu_bpcc(struct wlan_objmgr_vdev * vdev,uint8_t vdev_id,uint8_t * bpcc)662*5113495bSYour Name QDF_STATUS mlo_get_cu_bpcc(struct wlan_objmgr_vdev *vdev,
663*5113495bSYour Name 			   uint8_t vdev_id, uint8_t *bpcc)
664*5113495bSYour Name {
665*5113495bSYour Name 	struct wlan_mlo_dev_context *mlo_dev_ctx;
666*5113495bSYour Name 	struct mlo_sta_cu_params *cu_param;
667*5113495bSYour Name 	uint8_t i;
668*5113495bSYour Name 
669*5113495bSYour Name 	mlo_dev_ctx = vdev->mlo_dev_ctx;
670*5113495bSYour Name 	if (!mlo_dev_ctx) {
671*5113495bSYour Name 		mlo_err("ML dev ctx is NULL");
672*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
673*5113495bSYour Name 	}
674*5113495bSYour Name 
675*5113495bSYour Name 	cu_param = &mlo_dev_ctx->sta_ctx->mlo_cu_param[0];
676*5113495bSYour Name 	for (i = 0; i < WLAN_UMAC_MLO_MAX_VDEVS; i++) {
677*5113495bSYour Name 		if (cu_param[i].initialized &&
678*5113495bSYour Name 		    cu_param[i].vdev_id == vdev_id) {
679*5113495bSYour Name 			*bpcc = cu_param[i].bpcc;
680*5113495bSYour Name 			return QDF_STATUS_SUCCESS;
681*5113495bSYour Name 		}
682*5113495bSYour Name 	}
683*5113495bSYour Name 
684*5113495bSYour Name 	return QDF_STATUS_E_INVAL;
685*5113495bSYour Name }
686*5113495bSYour Name 
mlo_init_cu_bpcc(struct wlan_mlo_dev_context * mlo_dev_ctx,uint8_t vdev_id)687*5113495bSYour Name void mlo_init_cu_bpcc(struct wlan_mlo_dev_context *mlo_dev_ctx,
688*5113495bSYour Name 		      uint8_t vdev_id)
689*5113495bSYour Name {
690*5113495bSYour Name 	uint8_t i;
691*5113495bSYour Name 	struct mlo_sta_cu_params *cu_param;
692*5113495bSYour Name 	uint8_t empty_slot = 0xff;
693*5113495bSYour Name 
694*5113495bSYour Name 	cu_param = &mlo_dev_ctx->sta_ctx->mlo_cu_param[0];
695*5113495bSYour Name 
696*5113495bSYour Name 	for (i = 0; i < WLAN_UMAC_MLO_MAX_VDEVS; i++) {
697*5113495bSYour Name 		if (cu_param[i].initialized &&
698*5113495bSYour Name 		    cu_param[i].vdev_id == vdev_id) {
699*5113495bSYour Name 			cu_param[i].bpcc = 0;
700*5113495bSYour Name 			return;
701*5113495bSYour Name 		}
702*5113495bSYour Name 
703*5113495bSYour Name 		if (!cu_param[i].initialized && empty_slot == 0xff)
704*5113495bSYour Name 			empty_slot = i;
705*5113495bSYour Name 	}
706*5113495bSYour Name 
707*5113495bSYour Name 	if (empty_slot != 0xff) {
708*5113495bSYour Name 		cu_param[empty_slot].bpcc = 0;
709*5113495bSYour Name 		cu_param[empty_slot].vdev_id = vdev_id;
710*5113495bSYour Name 		cu_param[empty_slot].initialized = true;
711*5113495bSYour Name 		mlo_debug("init cu bpcc idx %d, vdev_id %d",
712*5113495bSYour Name 			  empty_slot, vdev_id);
713*5113495bSYour Name 	} else {
714*5113495bSYour Name 		mlo_debug("No bpcc idx for vdev_id %d", vdev_id);
715*5113495bSYour Name 	}
716*5113495bSYour Name }
717*5113495bSYour Name 
mlo_clear_cu_bpcc(struct wlan_objmgr_vdev * vdev)718*5113495bSYour Name void mlo_clear_cu_bpcc(struct wlan_objmgr_vdev *vdev)
719*5113495bSYour Name {
720*5113495bSYour Name 	struct wlan_mlo_dev_context *mlo_dev_ctx = NULL;
721*5113495bSYour Name 	struct wlan_mlo_sta *sta_ctx = NULL;
722*5113495bSYour Name 	uint32_t size;
723*5113495bSYour Name 
724*5113495bSYour Name 	if (!vdev)
725*5113495bSYour Name 		return;
726*5113495bSYour Name 
727*5113495bSYour Name 	mlo_dev_ctx = vdev->mlo_dev_ctx;
728*5113495bSYour Name 	if (!mlo_dev_ctx)
729*5113495bSYour Name 		return;
730*5113495bSYour Name 
731*5113495bSYour Name 	sta_ctx = mlo_dev_ctx->sta_ctx;
732*5113495bSYour Name 	if (!sta_ctx)
733*5113495bSYour Name 		return;
734*5113495bSYour Name 
735*5113495bSYour Name 	size = sizeof(sta_ctx->mlo_cu_param);
736*5113495bSYour Name 	qdf_mem_zero(sta_ctx->mlo_cu_param, size);
737*5113495bSYour Name }
738*5113495bSYour Name 
739*5113495bSYour Name #ifdef WLAN_FEATURE_11BE_MLO_ADV_FEATURE
mlo_clear_sta_key_mgmt(struct wlan_objmgr_vdev * vdev)740*5113495bSYour Name static void mlo_clear_sta_key_mgmt(struct wlan_objmgr_vdev *vdev)
741*5113495bSYour Name {
742*5113495bSYour Name 	struct wlan_mlo_dev_context *mlo_dev_ctx = NULL;
743*5113495bSYour Name 	struct wlan_mlo_sta *sta_ctx = NULL;
744*5113495bSYour Name 
745*5113495bSYour Name 	if (!vdev)
746*5113495bSYour Name 		return;
747*5113495bSYour Name 
748*5113495bSYour Name 	mlo_dev_ctx = vdev->mlo_dev_ctx;
749*5113495bSYour Name 	if (!mlo_dev_ctx)
750*5113495bSYour Name 		return;
751*5113495bSYour Name 
752*5113495bSYour Name 	sta_ctx = mlo_dev_ctx->sta_ctx;
753*5113495bSYour Name 	if (!sta_ctx)
754*5113495bSYour Name 		return;
755*5113495bSYour Name 
756*5113495bSYour Name 	qdf_mem_zero(sta_ctx->key_mgmt, sizeof(sta_ctx->key_mgmt));
757*5113495bSYour Name 
758*5113495bSYour Name 	mlo_debug("clear sta_key_mgmt");
759*5113495bSYour Name }
760*5113495bSYour Name 
761*5113495bSYour Name #else
mlo_clear_sta_key_mgmt(struct wlan_objmgr_vdev * vdev)762*5113495bSYour Name static void mlo_clear_sta_key_mgmt(struct wlan_objmgr_vdev *vdev)
763*5113495bSYour Name {
764*5113495bSYour Name }
765*5113495bSYour Name #endif
766*5113495bSYour Name 
mlo_connect(struct wlan_objmgr_vdev * vdev,struct wlan_cm_connect_req * req)767*5113495bSYour Name QDF_STATUS mlo_connect(struct wlan_objmgr_vdev *vdev,
768*5113495bSYour Name 		       struct wlan_cm_connect_req *req)
769*5113495bSYour Name {
770*5113495bSYour Name 	struct wlan_mlo_dev_context *mlo_dev_ctx;
771*5113495bSYour Name 	struct wlan_mlo_sta *sta_ctx = NULL;
772*5113495bSYour Name 	QDF_STATUS status = QDF_STATUS_SUCCESS;
773*5113495bSYour Name 
774*5113495bSYour Name 	mlo_dev_ctx = vdev->mlo_dev_ctx;
775*5113495bSYour Name 	if (mlo_dev_ctx)
776*5113495bSYour Name 		sta_ctx = mlo_dev_ctx->sta_ctx;
777*5113495bSYour Name 	if (sta_ctx) {
778*5113495bSYour Name 		status = mlo_validate_mlo_cap(vdev);
779*5113495bSYour Name 		if (QDF_IS_STATUS_ERROR(status))
780*5113495bSYour Name 			return wlan_cm_start_connect(vdev, req);
781*5113495bSYour Name 
782*5113495bSYour Name 		mlo_dev_lock_acquire(mlo_dev_ctx);
783*5113495bSYour Name 		status = mlo_validate_connect_req(vdev, mlo_dev_ctx, req);
784*5113495bSYour Name 		copied_conn_req_lock_acquire(sta_ctx);
785*5113495bSYour Name 		if (!sta_ctx->copied_conn_req)
786*5113495bSYour Name 			sta_ctx->copied_conn_req = qdf_mem_malloc(
787*5113495bSYour Name 					sizeof(struct wlan_cm_connect_req));
788*5113495bSYour Name 		else
789*5113495bSYour Name 			wlan_cm_free_connect_req_param(sta_ctx->copied_conn_req);
790*5113495bSYour Name 
791*5113495bSYour Name 		if (sta_ctx->copied_conn_req) {
792*5113495bSYour Name 			qdf_mem_copy(sta_ctx->copied_conn_req, req,
793*5113495bSYour Name 				     sizeof(struct wlan_cm_connect_req));
794*5113495bSYour Name 			mlo_allocate_and_copy_ies(sta_ctx->copied_conn_req,
795*5113495bSYour Name 						  req);
796*5113495bSYour Name 			copied_conn_req_lock_release(sta_ctx);
797*5113495bSYour Name 		} else {
798*5113495bSYour Name 			mlo_err("Failed to allocate orig connect req");
799*5113495bSYour Name 			copied_conn_req_lock_release(sta_ctx);
800*5113495bSYour Name 			mlo_dev_lock_release(mlo_dev_ctx);
801*5113495bSYour Name 
802*5113495bSYour Name 			return QDF_STATUS_E_NOMEM;
803*5113495bSYour Name 		}
804*5113495bSYour Name 
805*5113495bSYour Name 		if (QDF_IS_STATUS_SUCCESS(status)) {
806*5113495bSYour Name 			mlo_clear_cu_bpcc(vdev);
807*5113495bSYour Name 			mlo_clear_connected_links_bmap(vdev);
808*5113495bSYour Name 			mlo_clear_sta_key_mgmt(vdev);
809*5113495bSYour Name 			mlo_dev_lock_release(mlo_dev_ctx);
810*5113495bSYour Name 
811*5113495bSYour Name 			status = wlan_cm_start_connect(vdev, req);
812*5113495bSYour Name 			if (QDF_IS_STATUS_ERROR(status))
813*5113495bSYour Name 				mlo_mld_clear_mlo_cap(vdev);
814*5113495bSYour Name 			return status;
815*5113495bSYour Name 		}
816*5113495bSYour Name 
817*5113495bSYour Name 		mlo_dev_lock_release(mlo_dev_ctx);
818*5113495bSYour Name 
819*5113495bSYour Name 		return status;
820*5113495bSYour Name 	}
821*5113495bSYour Name 
822*5113495bSYour Name 	return wlan_cm_start_connect(vdev, req);
823*5113495bSYour Name }
824*5113495bSYour Name 
825*5113495bSYour Name static inline void
mlo_update_connect_req_chan_info(struct wlan_cm_connect_req * req)826*5113495bSYour Name mlo_update_connect_req_chan_info(struct wlan_cm_connect_req *req)
827*5113495bSYour Name {
828*5113495bSYour Name 	req->chan_freq = 0;
829*5113495bSYour Name 	req->chan_freq_hint = 0;
830*5113495bSYour Name }
831*5113495bSYour Name 
832*5113495bSYour Name /**
833*5113495bSYour Name  * mlo_prepare_and_send_connect- Prepare and send the connect req
834*5113495bSYour Name  *
835*5113495bSYour Name  * @vdev: vdev pointer
836*5113495bSYour Name  * @ml_parnter_info: ml partner link info
837*5113495bSYour Name  * @link_info: link info on which connect req will be sent
838*5113495bSYour Name  * @ssid: ssid to connect
839*5113495bSYour Name  * @mld_addr: MLD address for connect request.
840*5113495bSYour Name  *
841*5113495bSYour Name  * Return: none
842*5113495bSYour Name  */
843*5113495bSYour Name 
844*5113495bSYour Name static void
mlo_prepare_and_send_connect(struct wlan_objmgr_vdev * vdev,struct mlo_partner_info ml_parnter_info,struct mlo_link_info link_info,struct wlan_ssid ssid,struct qdf_mac_addr * mld_addr)845*5113495bSYour Name mlo_prepare_and_send_connect(struct wlan_objmgr_vdev *vdev,
846*5113495bSYour Name 			     struct mlo_partner_info ml_parnter_info,
847*5113495bSYour Name 			     struct mlo_link_info link_info,
848*5113495bSYour Name 			     struct wlan_ssid ssid,
849*5113495bSYour Name 			     struct qdf_mac_addr *mld_addr)
850*5113495bSYour Name {
851*5113495bSYour Name 	struct wlan_cm_connect_req req = {0};
852*5113495bSYour Name 	struct wlan_mlo_dev_context *mlo_dev_ctx = vdev->mlo_dev_ctx;
853*5113495bSYour Name 	struct wlan_mlo_sta *sta_ctx;
854*5113495bSYour Name 
855*5113495bSYour Name 	if (!mlo_dev_ctx) {
856*5113495bSYour Name 		mlo_err("ML dev ctx is NULL");
857*5113495bSYour Name 		return;
858*5113495bSYour Name 	}
859*5113495bSYour Name 
860*5113495bSYour Name 	sta_ctx = mlo_dev_ctx->sta_ctx;
861*5113495bSYour Name 
862*5113495bSYour Name 	mlo_debug("Partner link connect mac:" QDF_MAC_ADDR_FMT
863*5113495bSYour Name 		  " bssid:" QDF_MAC_ADDR_FMT " vdev_id:%d",
864*5113495bSYour Name 		  QDF_MAC_ADDR_REF(wlan_vdev_mlme_get_macaddr(vdev)),
865*5113495bSYour Name 		  QDF_MAC_ADDR_REF(link_info.link_addr.bytes),
866*5113495bSYour Name 		  wlan_vdev_get_id(vdev));
867*5113495bSYour Name 
868*5113495bSYour Name 	if (sta_ctx->copied_conn_req)
869*5113495bSYour Name 		qdf_mem_copy(&req, sta_ctx->copied_conn_req,
870*5113495bSYour Name 			     sizeof(struct wlan_cm_connect_req));
871*5113495bSYour Name 	else
872*5113495bSYour Name 		mlo_err("Invalid copied_conn_req");
873*5113495bSYour Name 
874*5113495bSYour Name 	mlo_update_connect_req_chan_info(&req);
875*5113495bSYour Name 
876*5113495bSYour Name 	qdf_mem_copy(req.bssid.bytes,
877*5113495bSYour Name 		     link_info.link_addr.bytes,
878*5113495bSYour Name 		     QDF_MAC_ADDR_SIZE);
879*5113495bSYour Name 
880*5113495bSYour Name 	qdf_mem_copy(&req.ml_parnter_info,
881*5113495bSYour Name 		     &ml_parnter_info,
882*5113495bSYour Name 		     sizeof(struct mlo_partner_info));
883*5113495bSYour Name 
884*5113495bSYour Name 	req.vdev_id = wlan_vdev_get_id(vdev);
885*5113495bSYour Name 	req.ssid.length = ssid.length;
886*5113495bSYour Name 	qdf_mem_copy(&req.ssid.ssid, &ssid.ssid, ssid.length);
887*5113495bSYour Name 	if (mld_addr)
888*5113495bSYour Name 		qdf_copy_macaddr(&req.mld_addr, mld_addr);
889*5113495bSYour Name 
890*5113495bSYour Name 	if (sta_ctx->copied_conn_req)
891*5113495bSYour Name 		mlo_allocate_and_copy_ies(&req, sta_ctx->copied_conn_req);
892*5113495bSYour Name 
893*5113495bSYour Name 	if (!req.assoc_ie.ptr)
894*5113495bSYour Name 		mlo_err("Failed to allocate assoc IEs");
895*5113495bSYour Name 
896*5113495bSYour Name 	if (!req.scan_ie.ptr)
897*5113495bSYour Name 		mlo_err("Failed to allocate scan IEs");
898*5113495bSYour Name 
899*5113495bSYour Name 	/* Reset crypto auth type for partner link.
900*5113495bSYour Name 	 * It will be set based on partner scan cache entry
901*5113495bSYour Name 	 */
902*5113495bSYour Name 	req.crypto.auth_type = 0;
903*5113495bSYour Name 
904*5113495bSYour Name 	wlan_cm_start_connect(vdev, &req);
905*5113495bSYour Name 	wlan_cm_free_connect_req_param(&req);
906*5113495bSYour Name }
907*5113495bSYour Name 
908*5113495bSYour Name /**
909*5113495bSYour Name  * mlo_send_link_connect- Create/Issue the connection on secondary link
910*5113495bSYour Name  *
911*5113495bSYour Name  * @vdev: vdev pointer
912*5113495bSYour Name  * @resp: Connection resp of assoc VDEV
913*5113495bSYour Name  *
914*5113495bSYour Name  * Return: none
915*5113495bSYour Name  */
916*5113495bSYour Name #ifdef WLAN_FEATURE_11BE_MLO_ADV_FEATURE
mlo_send_link_connect(struct wlan_objmgr_vdev * vdev,struct wlan_cm_connect_resp * resp)917*5113495bSYour Name static void mlo_send_link_connect(struct wlan_objmgr_vdev *vdev,
918*5113495bSYour Name 				  struct wlan_cm_connect_resp *resp)
919*5113495bSYour Name {
920*5113495bSYour Name 	/* Create the secondary interface, Send keys if the last link */
921*5113495bSYour Name 	uint8_t i, partner_idx = 0;
922*5113495bSYour Name 	struct wlan_ssid ssid = {0};
923*5113495bSYour Name 	struct wlan_objmgr_vdev *wlan_vdev_list[WLAN_UMAC_MLO_MAX_VDEVS];
924*5113495bSYour Name 	uint16_t vdev_count = 0;
925*5113495bSYour Name 	struct wlan_mlo_dev_context *mlo_dev_ctx = vdev->mlo_dev_ctx;
926*5113495bSYour Name 	struct mlo_partner_info *ml_parnter_info = &resp->ml_parnter_info;
927*5113495bSYour Name 
928*5113495bSYour Name 	mlo_debug("Sending link connect on partner interface");
929*5113495bSYour Name 	wlan_vdev_mlme_get_ssid(
930*5113495bSYour Name 			vdev, ssid.ssid,
931*5113495bSYour Name 			&ssid.length);
932*5113495bSYour Name 
933*5113495bSYour Name 	if (!ml_parnter_info->num_partner_links) {
934*5113495bSYour Name 		mlo_err("No partner info in connect resp");
935*5113495bSYour Name 		return;
936*5113495bSYour Name 	}
937*5113495bSYour Name 
938*5113495bSYour Name 	if(wlan_vdev_mlme_is_mlo_link_vdev(vdev))
939*5113495bSYour Name 		return;
940*5113495bSYour Name 
941*5113495bSYour Name 	copied_conn_req_lock_acquire(mlo_dev_ctx->sta_ctx);
942*5113495bSYour Name 	if (!mlo_dev_ctx->sta_ctx->copied_conn_req) {
943*5113495bSYour Name 		mlo_dev_ctx->sta_ctx->copied_conn_req =
944*5113495bSYour Name 			qdf_mem_malloc(sizeof(struct wlan_cm_connect_req));
945*5113495bSYour Name 		if (mlo_dev_ctx->sta_ctx->copied_conn_req) {
946*5113495bSYour Name 			wlan_cm_get_active_connect_req_param(vdev,
947*5113495bSYour Name 							     mlo_dev_ctx->sta_ctx->copied_conn_req);
948*5113495bSYour Name 		}
949*5113495bSYour Name 	}
950*5113495bSYour Name 	copied_conn_req_lock_release(mlo_dev_ctx->sta_ctx);
951*5113495bSYour Name 
952*5113495bSYour Name 	mlo_sta_get_vdev_list(vdev, &vdev_count, wlan_vdev_list);
953*5113495bSYour Name 	for (i = 0; i < vdev_count; i++) {
954*5113495bSYour Name 		if (wlan_vdev_list[i] == vdev) {
955*5113495bSYour Name 			mlo_release_vdev_ref(wlan_vdev_list[i]);
956*5113495bSYour Name 			continue;
957*5113495bSYour Name 		}
958*5113495bSYour Name 		wlan_vdev_mlme_set_mlo_vdev(mlo_dev_ctx->wlan_vdev_list[i]);
959*5113495bSYour Name 		wlan_vdev_mlme_set_mlo_link_vdev(mlo_dev_ctx->wlan_vdev_list[i]);
960*5113495bSYour Name 		wlan_vdev_set_link_id(
961*5113495bSYour Name 		      wlan_vdev_list[i],
962*5113495bSYour Name 		      ml_parnter_info->partner_link_info[partner_idx].link_id);
963*5113495bSYour Name 		ml_parnter_info->partner_link_info[partner_idx].vdev_id =
964*5113495bSYour Name 			       wlan_vdev_get_id(mlo_dev_ctx->wlan_vdev_list[i]);
965*5113495bSYour Name 		wlan_crypto_free_vdev_key(wlan_vdev_list[i]);
966*5113495bSYour Name 		mlo_prepare_and_send_connect(
967*5113495bSYour Name 				wlan_vdev_list[i],
968*5113495bSYour Name 				*ml_parnter_info,
969*5113495bSYour Name 				ml_parnter_info->partner_link_info[partner_idx],
970*5113495bSYour Name 				ssid, &resp->mld_addr);
971*5113495bSYour Name 		mlo_update_connected_links(wlan_vdev_list[i], 1);
972*5113495bSYour Name 		partner_idx++;
973*5113495bSYour Name 		mlo_release_vdev_ref(wlan_vdev_list[i]);
974*5113495bSYour Name 	}
975*5113495bSYour Name }
976*5113495bSYour Name #else
mlo_send_link_connect(struct wlan_objmgr_vdev * vdev,struct wlan_cm_connect_resp * resp)977*5113495bSYour Name static void mlo_send_link_connect(struct wlan_objmgr_vdev *vdev,
978*5113495bSYour Name 				  struct wlan_cm_connect_resp *resp)
979*5113495bSYour Name {
980*5113495bSYour Name 	struct wlan_ssid ssid = {0};
981*5113495bSYour Name 	uint8_t i = 0;
982*5113495bSYour Name 	uint8_t j = 0;
983*5113495bSYour Name 	struct wlan_mlo_dev_context *mlo_dev_ctx = vdev->mlo_dev_ctx;
984*5113495bSYour Name 	struct mlo_partner_info *ml_parnter_info = &resp->ml_parnter_info;
985*5113495bSYour Name 
986*5113495bSYour Name 	if (!ml_parnter_info->num_partner_links) {
987*5113495bSYour Name 		mlo_err("No partner info in connect resp");
988*5113495bSYour Name 		return;
989*5113495bSYour Name 	}
990*5113495bSYour Name 
991*5113495bSYour Name 	mlo_dev_lock_acquire(mlo_dev_ctx);
992*5113495bSYour Name 	if (!wlan_cm_is_vdev_connected(vdev)) {
993*5113495bSYour Name 		mlo_dev_lock_release(mlo_dev_ctx);
994*5113495bSYour Name 		return;
995*5113495bSYour Name 	}
996*5113495bSYour Name 
997*5113495bSYour Name 	for (j = 0; j < ml_parnter_info->num_partner_links; j++) {
998*5113495bSYour Name 		for (i =  0; i < WLAN_UMAC_MLO_MAX_VDEVS; i++) {
999*5113495bSYour Name 			if (!mlo_dev_ctx->wlan_vdev_list[i])
1000*5113495bSYour Name 				continue;
1001*5113495bSYour Name 			/*
1002*5113495bSYour Name 			* mlo_connect: update wlan_connected_links bitmap from
1003*5113495bSYour Name 			* assoc resp parsing
1004*5113495bSYour Name 			*/
1005*5113495bSYour Name 			if (qdf_test_bit(i, mlo_dev_ctx->sta_ctx->wlan_connected_links)) {
1006*5113495bSYour Name 				if (wlan_cm_is_vdev_disconnected(
1007*5113495bSYour Name 					mlo_dev_ctx->wlan_vdev_list[i])) {
1008*5113495bSYour Name 					if (mlo_dev_ctx->wlan_vdev_list[i]->vdev_mlme.mlo_link_id
1009*5113495bSYour Name 						== ml_parnter_info->partner_link_info[j].link_id) {
1010*5113495bSYour Name 						wlan_vdev_mlme_get_ssid(
1011*5113495bSYour Name 							vdev, ssid.ssid,
1012*5113495bSYour Name 							&ssid.length);
1013*5113495bSYour Name 						mlo_prepare_and_send_connect(
1014*5113495bSYour Name 							mlo_dev_ctx->wlan_vdev_list[i],
1015*5113495bSYour Name 							*ml_parnter_info,
1016*5113495bSYour Name 							ml_parnter_info->partner_link_info[j],
1017*5113495bSYour Name 							ssid, NULL);
1018*5113495bSYour Name 						mlo_dev_lock_release(mlo_dev_ctx);
1019*5113495bSYour Name 						return;
1020*5113495bSYour Name 					}
1021*5113495bSYour Name 				}
1022*5113495bSYour Name 			}
1023*5113495bSYour Name 		}
1024*5113495bSYour Name 	}
1025*5113495bSYour Name 	mlo_dev_lock_release(mlo_dev_ctx);
1026*5113495bSYour Name }
1027*5113495bSYour Name #endif
1028*5113495bSYour Name 
1029*5113495bSYour Name void
mlo_update_connected_links_bmap(struct wlan_mlo_dev_context * mlo_dev_ctx,struct mlo_partner_info ml_parnter_info)1030*5113495bSYour Name mlo_update_connected_links_bmap(struct wlan_mlo_dev_context *mlo_dev_ctx,
1031*5113495bSYour Name 				struct mlo_partner_info ml_parnter_info)
1032*5113495bSYour Name {
1033*5113495bSYour Name 	uint8_t i = 0;
1034*5113495bSYour Name 	uint8_t j = 0;
1035*5113495bSYour Name 
1036*5113495bSYour Name 	if (!mlo_dev_ctx) {
1037*5113495bSYour Name 		mlo_err("ML dev ctx is NULL");
1038*5113495bSYour Name 		return;
1039*5113495bSYour Name 	}
1040*5113495bSYour Name 
1041*5113495bSYour Name 	for (i = 0; i < WLAN_UMAC_MLO_MAX_VDEVS; i++) {
1042*5113495bSYour Name 		if (!mlo_dev_ctx->wlan_vdev_list[i])
1043*5113495bSYour Name 			continue;
1044*5113495bSYour Name 
1045*5113495bSYour Name 		for (j = 0; j < ml_parnter_info.num_partner_links; j++) {
1046*5113495bSYour Name 			if (wlan_vdev_get_link_id(mlo_dev_ctx->wlan_vdev_list[i]) ==
1047*5113495bSYour Name 			    ml_parnter_info.partner_link_info[j].link_id)
1048*5113495bSYour Name 				mlo_update_connected_links(
1049*5113495bSYour Name 					mlo_dev_ctx->wlan_vdev_list[i], 1);
1050*5113495bSYour Name 		}
1051*5113495bSYour Name 	}
1052*5113495bSYour Name }
1053*5113495bSYour Name 
mlo_clear_connected_links_bmap(struct wlan_objmgr_vdev * vdev)1054*5113495bSYour Name void mlo_clear_connected_links_bmap(struct wlan_objmgr_vdev *vdev)
1055*5113495bSYour Name {
1056*5113495bSYour Name 	struct wlan_mlo_dev_context *mlo_dev_ctx = NULL;
1057*5113495bSYour Name 	struct wlan_mlo_sta *sta_ctx = NULL;
1058*5113495bSYour Name 
1059*5113495bSYour Name 	if (!vdev)
1060*5113495bSYour Name 		return;
1061*5113495bSYour Name 
1062*5113495bSYour Name 	mlo_dev_ctx = vdev->mlo_dev_ctx;
1063*5113495bSYour Name 	if (!mlo_dev_ctx)
1064*5113495bSYour Name 		return;
1065*5113495bSYour Name 
1066*5113495bSYour Name 	sta_ctx = mlo_dev_ctx->sta_ctx;
1067*5113495bSYour Name 	if (!sta_ctx)
1068*5113495bSYour Name 		return;
1069*5113495bSYour Name 
1070*5113495bSYour Name 	qdf_mem_zero(sta_ctx->wlan_connected_links,
1071*5113495bSYour Name 		     sizeof(sta_ctx->wlan_connected_links));
1072*5113495bSYour Name }
1073*5113495bSYour Name 
ml_activate_disconnect_req_sched_cb(struct scheduler_msg * msg)1074*5113495bSYour Name static QDF_STATUS ml_activate_disconnect_req_sched_cb(struct scheduler_msg *msg)
1075*5113495bSYour Name {
1076*5113495bSYour Name 	struct wlan_objmgr_vdev *vdev = msg->bodyptr;
1077*5113495bSYour Name 
1078*5113495bSYour Name 	if (!vdev) {
1079*5113495bSYour Name 		mlme_err("Null input vdev");
1080*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
1081*5113495bSYour Name 	}
1082*5113495bSYour Name 
1083*5113495bSYour Name 	mlo_disconnect(vdev, CM_OSIF_DISCONNECT,
1084*5113495bSYour Name 		       REASON_UNSPEC_FAILURE, NULL);
1085*5113495bSYour Name 
1086*5113495bSYour Name 	wlan_objmgr_vdev_release_ref(vdev, WLAN_MLO_MGR_ID);
1087*5113495bSYour Name 	return QDF_STATUS_SUCCESS;
1088*5113495bSYour Name }
1089*5113495bSYour Name 
ml_activate_disconnect_req_flush_cb(struct scheduler_msg * msg)1090*5113495bSYour Name static QDF_STATUS ml_activate_disconnect_req_flush_cb(struct scheduler_msg *msg)
1091*5113495bSYour Name {
1092*5113495bSYour Name 	struct wlan_objmgr_vdev *vdev = msg->bodyptr;
1093*5113495bSYour Name 
1094*5113495bSYour Name 	if (!vdev) {
1095*5113495bSYour Name 		mlme_err("Null input vdev");
1096*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
1097*5113495bSYour Name 	}
1098*5113495bSYour Name 
1099*5113495bSYour Name 	wlan_objmgr_vdev_release_ref(vdev, WLAN_MLO_MGR_ID);
1100*5113495bSYour Name 	return QDF_STATUS_SUCCESS;
1101*5113495bSYour Name }
1102*5113495bSYour Name 
ml_activate_pend_disconn_req_cb(struct scheduler_msg * msg)1103*5113495bSYour Name static QDF_STATUS ml_activate_pend_disconn_req_cb(struct scheduler_msg *msg)
1104*5113495bSYour Name {
1105*5113495bSYour Name 	struct wlan_objmgr_vdev *vdev = msg->bodyptr;
1106*5113495bSYour Name 	struct wlan_mlo_dev_context *mlo_dev_ctx = NULL;
1107*5113495bSYour Name 	struct wlan_mlo_sta *sta_ctx = NULL;
1108*5113495bSYour Name 
1109*5113495bSYour Name 	if (!vdev) {
1110*5113495bSYour Name 		mlme_err("Null input vdev");
1111*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
1112*5113495bSYour Name 	}
1113*5113495bSYour Name 
1114*5113495bSYour Name 	mlo_dev_ctx = vdev->mlo_dev_ctx;
1115*5113495bSYour Name 	sta_ctx = mlo_dev_ctx->sta_ctx;
1116*5113495bSYour Name 	if (!sta_ctx || !sta_ctx->disconn_req)
1117*5113495bSYour Name 		goto release_ref;
1118*5113495bSYour Name 
1119*5113495bSYour Name 	mlo_disconnect_req(vdev, sta_ctx->disconn_req->source,
1120*5113495bSYour Name 			   sta_ctx->disconn_req->reason_code,
1121*5113495bSYour Name 			   &sta_ctx->disconn_req->bssid, false);
1122*5113495bSYour Name 
1123*5113495bSYour Name 	qdf_mem_free(sta_ctx->disconn_req);
1124*5113495bSYour Name 	sta_ctx->disconn_req = NULL;
1125*5113495bSYour Name 
1126*5113495bSYour Name release_ref:
1127*5113495bSYour Name 	wlan_objmgr_vdev_release_ref(vdev, WLAN_MLO_MGR_ID);
1128*5113495bSYour Name 
1129*5113495bSYour Name 	return QDF_STATUS_SUCCESS;
1130*5113495bSYour Name }
1131*5113495bSYour Name 
ml_activate_pend_disconn_req_flush_cb(struct scheduler_msg * msg)1132*5113495bSYour Name static QDF_STATUS ml_activate_pend_disconn_req_flush_cb(
1133*5113495bSYour Name 					struct scheduler_msg *msg)
1134*5113495bSYour Name {
1135*5113495bSYour Name 	struct wlan_objmgr_vdev *vdev = msg->bodyptr;
1136*5113495bSYour Name 
1137*5113495bSYour Name 	if (!vdev) {
1138*5113495bSYour Name 		mlme_err("Null input vdev");
1139*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
1140*5113495bSYour Name 	}
1141*5113495bSYour Name 
1142*5113495bSYour Name 	wlan_objmgr_vdev_release_ref(vdev, WLAN_MLO_MGR_ID);
1143*5113495bSYour Name 	return QDF_STATUS_SUCCESS;
1144*5113495bSYour Name }
1145*5113495bSYour Name 
1146*5113495bSYour Name #ifdef WLAN_FEATURE_11BE_MLO_ADV_FEATURE
1147*5113495bSYour Name static inline
mlo_post_disconnect_msg(struct scheduler_msg * msg)1148*5113495bSYour Name QDF_STATUS mlo_post_disconnect_msg(struct scheduler_msg *msg)
1149*5113495bSYour Name {
1150*5113495bSYour Name 	return scheduler_post_message(
1151*5113495bSYour Name 			QDF_MODULE_ID_OS_IF,
1152*5113495bSYour Name 			QDF_MODULE_ID_SCAN,
1153*5113495bSYour Name 			QDF_MODULE_ID_OS_IF,
1154*5113495bSYour Name 			msg);
1155*5113495bSYour Name }
1156*5113495bSYour Name #else
1157*5113495bSYour Name static inline
mlo_post_disconnect_msg(struct scheduler_msg * msg)1158*5113495bSYour Name QDF_STATUS mlo_post_disconnect_msg(struct scheduler_msg *msg)
1159*5113495bSYour Name {
1160*5113495bSYour Name 	return scheduler_post_message(
1161*5113495bSYour Name 			QDF_MODULE_ID_MLME,
1162*5113495bSYour Name 			QDF_MODULE_ID_MLME,
1163*5113495bSYour Name 			QDF_MODULE_ID_MLME,
1164*5113495bSYour Name 			msg);
1165*5113495bSYour Name }
1166*5113495bSYour Name #endif
1167*5113495bSYour Name 
mlo_handle_sta_link_connect_failure(struct wlan_objmgr_vdev * vdev,struct wlan_cm_connect_resp * rsp)1168*5113495bSYour Name void mlo_handle_sta_link_connect_failure(struct wlan_objmgr_vdev *vdev,
1169*5113495bSYour Name 					 struct wlan_cm_connect_resp *rsp)
1170*5113495bSYour Name {
1171*5113495bSYour Name 	struct wlan_mlo_dev_context *mlo_dev_ctx = vdev->mlo_dev_ctx;
1172*5113495bSYour Name 	struct scheduler_msg msg = {0};
1173*5113495bSYour Name 	QDF_STATUS ret;
1174*5113495bSYour Name 	struct wlan_objmgr_vdev *assoc_vdev;
1175*5113495bSYour Name 
1176*5113495bSYour Name 	if (!mlo_dev_ctx) {
1177*5113495bSYour Name 		mlo_err("ML dev ctx is NULL");
1178*5113495bSYour Name 		return;
1179*5113495bSYour Name 	}
1180*5113495bSYour Name 
1181*5113495bSYour Name 	assoc_vdev = mlo_get_assoc_link_vdev(mlo_dev_ctx);
1182*5113495bSYour Name 	if (!assoc_vdev) {
1183*5113495bSYour Name 		mlo_err("Assoc Vdev is NULL");
1184*5113495bSYour Name 		return;
1185*5113495bSYour Name 	}
1186*5113495bSYour Name 
1187*5113495bSYour Name 	if (vdev != assoc_vdev) {
1188*5113495bSYour Name 		mlo_update_connected_links(vdev, 0);
1189*5113495bSYour Name 		if (rsp->reason == CM_NO_CANDIDATE_FOUND ||
1190*5113495bSYour Name 		    rsp->reason == CM_HW_MODE_FAILURE ||
1191*5113495bSYour Name 		    rsp->reason == CM_SER_FAILURE) {
1192*5113495bSYour Name 			ret = wlan_objmgr_vdev_try_get_ref(
1193*5113495bSYour Name 					assoc_vdev, WLAN_MLO_MGR_ID);
1194*5113495bSYour Name 			if (QDF_IS_STATUS_ERROR(ret)) {
1195*5113495bSYour Name 				mlo_err("Failed to get ref vdev_id %d",
1196*5113495bSYour Name 					wlan_vdev_get_id(assoc_vdev));
1197*5113495bSYour Name 				return;
1198*5113495bSYour Name 			}
1199*5113495bSYour Name 			/* Since these failures happen in same context. use
1200*5113495bSYour Name 			 * scheduler to avoid deadlock by deferring context
1201*5113495bSYour Name 			 */
1202*5113495bSYour Name 			msg.bodyptr = assoc_vdev;
1203*5113495bSYour Name 			msg.callback = ml_activate_disconnect_req_sched_cb;
1204*5113495bSYour Name 			msg.flush_callback =
1205*5113495bSYour Name 				ml_activate_disconnect_req_flush_cb;
1206*5113495bSYour Name 			ret = mlo_post_disconnect_msg(&msg);
1207*5113495bSYour Name 			if (QDF_IS_STATUS_ERROR(ret)) {
1208*5113495bSYour Name 				wlan_objmgr_vdev_release_ref(
1209*5113495bSYour Name 						assoc_vdev,
1210*5113495bSYour Name 						WLAN_MLO_MGR_ID);
1211*5113495bSYour Name 				return;
1212*5113495bSYour Name 			}
1213*5113495bSYour Name 		} else {
1214*5113495bSYour Name 			mlo_disconnect(vdev, CM_OSIF_DISCONNECT,
1215*5113495bSYour Name 				       REASON_UNSPEC_FAILURE, NULL);
1216*5113495bSYour Name 		}
1217*5113495bSYour Name 	}
1218*5113495bSYour Name }
1219*5113495bSYour Name 
mlo_handle_pending_disconnect(struct wlan_objmgr_vdev * vdev)1220*5113495bSYour Name void mlo_handle_pending_disconnect(struct wlan_objmgr_vdev *vdev)
1221*5113495bSYour Name {
1222*5113495bSYour Name 	struct scheduler_msg msg = {0};
1223*5113495bSYour Name 	QDF_STATUS ret;
1224*5113495bSYour Name 
1225*5113495bSYour Name 	ret = wlan_objmgr_vdev_try_get_ref(
1226*5113495bSYour Name 			vdev, WLAN_MLO_MGR_ID);
1227*5113495bSYour Name 	if (QDF_IS_STATUS_ERROR(ret)) {
1228*5113495bSYour Name 		mlo_err("Failed to get ref vdev_id %d",
1229*5113495bSYour Name 			wlan_vdev_get_id(vdev));
1230*5113495bSYour Name 		return;
1231*5113495bSYour Name 	}
1232*5113495bSYour Name 
1233*5113495bSYour Name 	msg.bodyptr = vdev;
1234*5113495bSYour Name 	msg.callback = ml_activate_pend_disconn_req_cb;
1235*5113495bSYour Name 	msg.flush_callback =
1236*5113495bSYour Name 		ml_activate_pend_disconn_req_flush_cb;
1237*5113495bSYour Name 	ret = mlo_post_disconnect_msg(&msg);
1238*5113495bSYour Name 	if (QDF_IS_STATUS_ERROR(ret)) {
1239*5113495bSYour Name 		mlo_err("Failed to post scheduler msg");
1240*5113495bSYour Name 		wlan_objmgr_vdev_release_ref(
1241*5113495bSYour Name 				vdev,
1242*5113495bSYour Name 				WLAN_MLO_MGR_ID);
1243*5113495bSYour Name 		QDF_BUG(0);
1244*5113495bSYour Name 		return;
1245*5113495bSYour Name 	}
1246*5113495bSYour Name }
1247*5113495bSYour Name 
1248*5113495bSYour Name #ifdef WLAN_FEATURE_11BE_MLO_ADV_FEATURE
1249*5113495bSYour Name static bool
mlo_sta_ignore_link_connect_fail(struct wlan_objmgr_vdev * vdev)1250*5113495bSYour Name mlo_sta_ignore_link_connect_fail(struct wlan_objmgr_vdev *vdev)
1251*5113495bSYour Name {
1252*5113495bSYour Name 	if (wlan_cm_is_vdev_disconnected(vdev)) {
1253*5113495bSYour Name 		if (!wlan_vdev_mlme_is_mlo_link_vdev(vdev))
1254*5113495bSYour Name 			return false;
1255*5113495bSYour Name 		else
1256*5113495bSYour Name 			return true;
1257*5113495bSYour Name 	}
1258*5113495bSYour Name 
1259*5113495bSYour Name 	return false;
1260*5113495bSYour Name }
1261*5113495bSYour Name #else
1262*5113495bSYour Name static inline bool
mlo_sta_ignore_link_connect_fail(struct wlan_objmgr_vdev * vdev)1263*5113495bSYour Name mlo_sta_ignore_link_connect_fail(struct wlan_objmgr_vdev *vdev)
1264*5113495bSYour Name {
1265*5113495bSYour Name 	return false;
1266*5113495bSYour Name }
1267*5113495bSYour Name #endif
1268*5113495bSYour Name 
mlo_sta_link_connect_notify(struct wlan_objmgr_vdev * vdev,struct wlan_cm_connect_resp * rsp)1269*5113495bSYour Name void mlo_sta_link_connect_notify(struct wlan_objmgr_vdev *vdev,
1270*5113495bSYour Name 				 struct wlan_cm_connect_resp *rsp)
1271*5113495bSYour Name {
1272*5113495bSYour Name 	struct wlan_mlo_dev_context *mlo_dev_ctx = vdev->mlo_dev_ctx;
1273*5113495bSYour Name 	struct wlan_mlo_sta *sta_ctx = NULL;
1274*5113495bSYour Name 
1275*5113495bSYour Name 	if (mlo_dev_ctx) {
1276*5113495bSYour Name 		sta_ctx = mlo_dev_ctx->sta_ctx;
1277*5113495bSYour Name 	} else {
1278*5113495bSYour Name 		mlo_debug_rl("mlo_dev_ctx is NULL");
1279*5113495bSYour Name 		return;
1280*5113495bSYour Name 	}
1281*5113495bSYour Name 
1282*5113495bSYour Name 	if (sta_ctx && sta_ctx->disconn_req) {
1283*5113495bSYour Name 		mlo_debug("Handle pending disocnnect for vdev %d",
1284*5113495bSYour Name 			  wlan_vdev_get_id(vdev));
1285*5113495bSYour Name 		mlo_handle_pending_disconnect(vdev);
1286*5113495bSYour Name 		return;
1287*5113495bSYour Name 	}
1288*5113495bSYour Name 
1289*5113495bSYour Name 	if (wlan_cm_is_link_switch_connect_resp(rsp)) {
1290*5113495bSYour Name 		mlo_info("Skip for link switch connect request");
1291*5113495bSYour Name 		return;
1292*5113495bSYour Name 	}
1293*5113495bSYour Name 
1294*5113495bSYour Name 	if (mlo_sta_ignore_link_connect_fail(vdev))
1295*5113495bSYour Name 		return;
1296*5113495bSYour Name 
1297*5113495bSYour Name 	if (wlan_cm_is_vdev_disconnected(vdev))
1298*5113495bSYour Name 		mlo_free_copied_conn_req(sta_ctx);
1299*5113495bSYour Name 
1300*5113495bSYour Name 	if (wlan_vdev_mlme_is_mlo_vdev(vdev)) {
1301*5113495bSYour Name 		mlo_debug("Vdev: %d", wlan_vdev_get_id(vdev));
1302*5113495bSYour Name 		if (wlan_cm_is_vdev_disconnected(vdev)) {
1303*5113495bSYour Name 			mlo_handle_sta_link_connect_failure(vdev, rsp);
1304*5113495bSYour Name 			return;
1305*5113495bSYour Name 		} else if (!wlan_cm_is_vdev_connected(vdev)) {
1306*5113495bSYour Name 			/* If vdev is not in disconnected or connected state,
1307*5113495bSYour Name 			 * then the event is received due to connect req being
1308*5113495bSYour Name 			 * flushed. Hence, ignore this event
1309*5113495bSYour Name 			 */
1310*5113495bSYour Name 			return;
1311*5113495bSYour Name 		}
1312*5113495bSYour Name 
1313*5113495bSYour Name 		if (!wlan_vdev_mlme_is_mlo_link_vdev(vdev) && sta_ctx) {
1314*5113495bSYour Name 			if (sta_ctx->assoc_rsp.ptr) {
1315*5113495bSYour Name 				qdf_mem_free(sta_ctx->assoc_rsp.ptr);
1316*5113495bSYour Name 				sta_ctx->assoc_rsp.ptr = NULL;
1317*5113495bSYour Name 			}
1318*5113495bSYour Name 			sta_ctx->assoc_rsp.len = rsp->connect_ies.assoc_rsp.len;
1319*5113495bSYour Name 			sta_ctx->assoc_rsp.ptr =
1320*5113495bSYour Name 				qdf_mem_malloc(rsp->connect_ies.assoc_rsp.len);
1321*5113495bSYour Name 			if (!sta_ctx->assoc_rsp.ptr) {
1322*5113495bSYour Name 				QDF_ASSERT(0);
1323*5113495bSYour Name 				return;
1324*5113495bSYour Name 			}
1325*5113495bSYour Name 			if (rsp->connect_ies.assoc_rsp.ptr)
1326*5113495bSYour Name 				qdf_mem_copy(sta_ctx->assoc_rsp.ptr,
1327*5113495bSYour Name 					     rsp->connect_ies.assoc_rsp.ptr,
1328*5113495bSYour Name 					     rsp->connect_ies.assoc_rsp.len);
1329*5113495bSYour Name 			sta_ctx->ml_partner_info = rsp->ml_parnter_info;
1330*5113495bSYour Name 			/* Update connected_links_bmap for all vdev taking
1331*5113495bSYour Name 			 * part in association
1332*5113495bSYour Name 			 */
1333*5113495bSYour Name 			mlo_update_connected_links(vdev, 1);
1334*5113495bSYour Name 			mlo_update_connected_links_bmap(mlo_dev_ctx,
1335*5113495bSYour Name 							rsp->ml_parnter_info);
1336*5113495bSYour Name 		}
1337*5113495bSYour Name 		mlo_send_link_connect(vdev, rsp);
1338*5113495bSYour Name 	}
1339*5113495bSYour Name }
1340*5113495bSYour Name 
1341*5113495bSYour Name /**
1342*5113495bSYour Name  * mlo_send_link_disconnect_sync- Issue sync the disconnect request on MLD links
1343*5113495bSYour Name  *
1344*5113495bSYour Name  * @mlo_dev_ctx: pointer to mlo dev context
1345*5113495bSYour Name  * @source: disconnect source
1346*5113495bSYour Name  * @reason_code: disconnect reason
1347*5113495bSYour Name  * @bssid: bssid of AP to disconnect, can be null if not known
1348*5113495bSYour Name  *
1349*5113495bSYour Name  * Return: QDF_STATUS
1350*5113495bSYour Name  */
1351*5113495bSYour Name static QDF_STATUS
mlo_send_link_disconnect_sync(struct wlan_mlo_dev_context * mlo_dev_ctx,enum wlan_cm_source source,enum wlan_reason_code reason_code,struct qdf_mac_addr * bssid)1352*5113495bSYour Name mlo_send_link_disconnect_sync(struct wlan_mlo_dev_context *mlo_dev_ctx,
1353*5113495bSYour Name 			      enum wlan_cm_source source,
1354*5113495bSYour Name 			      enum wlan_reason_code reason_code,
1355*5113495bSYour Name 			      struct qdf_mac_addr *bssid)
1356*5113495bSYour Name {
1357*5113495bSYour Name 	uint8_t i;
1358*5113495bSYour Name 	struct wlan_objmgr_vdev *sync_vdev =
1359*5113495bSYour Name 		mlo_get_assoc_link_vdev(mlo_dev_ctx);
1360*5113495bSYour Name 
1361*5113495bSYour Name 	for (i = 0; i < WLAN_UMAC_MLO_MAX_VDEVS; i++) {
1362*5113495bSYour Name 		if (!mlo_dev_ctx->wlan_vdev_list[i] ||
1363*5113495bSYour Name 		    mlo_dev_ctx->wlan_vdev_list[i] == sync_vdev) {
1364*5113495bSYour Name 			continue;
1365*5113495bSYour Name 		}
1366*5113495bSYour Name 
1367*5113495bSYour Name 		/**
1368*5113495bSYour Name 		 * If the assoc vdev isn't present, use the first link dev as
1369*5113495bSYour Name 		 * sync candidate.
1370*5113495bSYour Name 		 */
1371*5113495bSYour Name 		if (!sync_vdev) {
1372*5113495bSYour Name 			sync_vdev = mlo_dev_ctx->wlan_vdev_list[i];
1373*5113495bSYour Name 			continue;
1374*5113495bSYour Name 		}
1375*5113495bSYour Name 
1376*5113495bSYour Name 		/**
1377*5113495bSYour Name 		 * To initiate disconnect on all links at once, no need to use
1378*5113495bSYour Name 		 * sync API for all link vdevs.
1379*5113495bSYour Name 		 */
1380*5113495bSYour Name 		wlan_cm_disconnect(mlo_dev_ctx->wlan_vdev_list[i],
1381*5113495bSYour Name 				   source, reason_code, NULL);
1382*5113495bSYour Name 	}
1383*5113495bSYour Name 
1384*5113495bSYour Name 	if (sync_vdev)
1385*5113495bSYour Name 		wlan_cm_disconnect_sync(sync_vdev, source, reason_code);
1386*5113495bSYour Name 
1387*5113495bSYour Name 	return QDF_STATUS_SUCCESS;
1388*5113495bSYour Name }
1389*5113495bSYour Name 
mlo_disconnect_req(struct wlan_objmgr_vdev * vdev,enum wlan_cm_source source,enum wlan_reason_code reason_code,struct qdf_mac_addr * bssid,bool validate_req)1390*5113495bSYour Name static QDF_STATUS mlo_disconnect_req(struct wlan_objmgr_vdev *vdev,
1391*5113495bSYour Name 				     enum wlan_cm_source source,
1392*5113495bSYour Name 				     enum wlan_reason_code reason_code,
1393*5113495bSYour Name 				     struct qdf_mac_addr *bssid,
1394*5113495bSYour Name 				     bool validate_req)
1395*5113495bSYour Name {
1396*5113495bSYour Name 	struct wlan_mlo_dev_context *mlo_dev_ctx = NULL;
1397*5113495bSYour Name 	struct wlan_mlo_sta *sta_ctx = NULL;
1398*5113495bSYour Name 	QDF_STATUS status = QDF_STATUS_SUCCESS;
1399*5113495bSYour Name 
1400*5113495bSYour Name 	if (!vdev)
1401*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
1402*5113495bSYour Name 
1403*5113495bSYour Name 	mlo_dev_ctx = vdev->mlo_dev_ctx;
1404*5113495bSYour Name 	if (mlo_dev_ctx)
1405*5113495bSYour Name 		sta_ctx = mlo_dev_ctx->sta_ctx;
1406*5113495bSYour Name 	if (mlo_dev_ctx && wlan_vdev_mlme_is_mlo_vdev(vdev)) {
1407*5113495bSYour Name 		mlo_dev_lock_acquire(mlo_dev_ctx);
1408*5113495bSYour Name 		if (sta_ctx && sta_ctx->connect_req &&
1409*5113495bSYour Name 		    source != CM_INTERNAL_DISCONNECT) {
1410*5113495bSYour Name 			wlan_cm_free_connect_req(sta_ctx->connect_req);
1411*5113495bSYour Name 			sta_ctx->connect_req = NULL;
1412*5113495bSYour Name 		}
1413*5113495bSYour Name 
1414*5113495bSYour Name 		if (validate_req) {
1415*5113495bSYour Name 			status = mlo_validate_disconn_req(vdev, source,
1416*5113495bSYour Name 							  reason_code, bssid);
1417*5113495bSYour Name 			if (QDF_IS_STATUS_ERROR(status)) {
1418*5113495bSYour Name 				mlo_err("Connect in progress, deferring disconnect");
1419*5113495bSYour Name 				mlo_dev_lock_release(mlo_dev_ctx);
1420*5113495bSYour Name 				return status;
1421*5113495bSYour Name 			}
1422*5113495bSYour Name 		}
1423*5113495bSYour Name 
1424*5113495bSYour Name 		mlo_dev_lock_release(mlo_dev_ctx);
1425*5113495bSYour Name 
1426*5113495bSYour Name 		status = mlo_send_link_disconnect(vdev, source,
1427*5113495bSYour Name 						  reason_code, bssid);
1428*5113495bSYour Name 		if (QDF_IS_STATUS_SUCCESS(status))
1429*5113495bSYour Name 			mlo_free_copied_conn_req(sta_ctx);
1430*5113495bSYour Name 
1431*5113495bSYour Name 		return status;
1432*5113495bSYour Name 	}
1433*5113495bSYour Name 	status = wlan_cm_disconnect(vdev, source,
1434*5113495bSYour Name 				    reason_code, NULL);
1435*5113495bSYour Name 	if (QDF_IS_STATUS_SUCCESS(status))
1436*5113495bSYour Name 		mlo_free_copied_conn_req(sta_ctx);
1437*5113495bSYour Name 
1438*5113495bSYour Name 	return status;
1439*5113495bSYour Name }
1440*5113495bSYour Name 
mlo_disconnect(struct wlan_objmgr_vdev * vdev,enum wlan_cm_source source,enum wlan_reason_code reason_code,struct qdf_mac_addr * bssid)1441*5113495bSYour Name QDF_STATUS mlo_disconnect(struct wlan_objmgr_vdev *vdev,
1442*5113495bSYour Name 			  enum wlan_cm_source source,
1443*5113495bSYour Name 			  enum wlan_reason_code reason_code,
1444*5113495bSYour Name 			  struct qdf_mac_addr *bssid)
1445*5113495bSYour Name {
1446*5113495bSYour Name 	return mlo_disconnect_req(vdev, source, reason_code, bssid, true);
1447*5113495bSYour Name }
1448*5113495bSYour Name 
1449*5113495bSYour Name #ifdef WLAN_FEATURE_11BE_MLO_ADV_FEATURE
1450*5113495bSYour Name /**
1451*5113495bSYour Name  * mlo_wait_for_mld_disconnection - API to wait for sync mld disconnection
1452*5113495bSYour Name  * @vdev: pointer to vdev
1453*5113495bSYour Name  *
1454*5113495bSYour Name  * Return: none
1455*5113495bSYour Name  */
1456*5113495bSYour Name static inline
mlo_wait_for_mld_disconnection(struct wlan_objmgr_vdev * vdev)1457*5113495bSYour Name void mlo_wait_for_mld_disconnection(struct wlan_objmgr_vdev *vdev)
1458*5113495bSYour Name { }
1459*5113495bSYour Name #else
1460*5113495bSYour Name #define ML_DISCONNECT_CMD_TIMEOUT 1000
1461*5113495bSYour Name #define ML_DISCONNECT_CMD_TIMEOUT_CNT 30 /* 30*1000 ms */
1462*5113495bSYour Name 
mlo_wait_for_mld_disconnection(struct wlan_objmgr_vdev * vdev)1463*5113495bSYour Name static void mlo_wait_for_mld_disconnection(struct wlan_objmgr_vdev *vdev)
1464*5113495bSYour Name {
1465*5113495bSYour Name 	int waitcnt = 0;
1466*5113495bSYour Name 	qdf_event_t wait_event;
1467*5113495bSYour Name 
1468*5113495bSYour Name 	qdf_mem_zero(&wait_event, sizeof(wait_event));
1469*5113495bSYour Name 	qdf_event_create(&wait_event);
1470*5113495bSYour Name 	qdf_event_reset(&wait_event);
1471*5113495bSYour Name 
1472*5113495bSYour Name 	while (!mlo_is_mld_disconnected(vdev) &&
1473*5113495bSYour Name 	       waitcnt < ML_DISCONNECT_CMD_TIMEOUT_CNT) {
1474*5113495bSYour Name 		qdf_wait_single_event(&wait_event, ML_DISCONNECT_CMD_TIMEOUT);
1475*5113495bSYour Name 		waitcnt++;
1476*5113495bSYour Name 	}
1477*5113495bSYour Name 	qdf_event_destroy(&wait_event);
1478*5113495bSYour Name }
1479*5113495bSYour Name #endif
mlo_sync_disconnect(struct wlan_objmgr_vdev * vdev,enum wlan_cm_source source,enum wlan_reason_code reason_code,struct qdf_mac_addr * bssid)1480*5113495bSYour Name QDF_STATUS mlo_sync_disconnect(struct wlan_objmgr_vdev *vdev,
1481*5113495bSYour Name 			       enum wlan_cm_source source,
1482*5113495bSYour Name 			       enum wlan_reason_code reason_code,
1483*5113495bSYour Name 			       struct qdf_mac_addr *bssid)
1484*5113495bSYour Name {
1485*5113495bSYour Name 	struct wlan_mlo_dev_context *mlo_dev_ctx = NULL;
1486*5113495bSYour Name 	struct wlan_mlo_sta *sta_ctx = NULL;
1487*5113495bSYour Name 	QDF_STATUS status = QDF_STATUS_SUCCESS;
1488*5113495bSYour Name 
1489*5113495bSYour Name 	if (!vdev)
1490*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
1491*5113495bSYour Name 
1492*5113495bSYour Name 	mlo_dev_ctx = vdev->mlo_dev_ctx;
1493*5113495bSYour Name 	if (mlo_dev_ctx)
1494*5113495bSYour Name 		sta_ctx = mlo_dev_ctx->sta_ctx;
1495*5113495bSYour Name 	if (mlo_dev_ctx && wlan_vdev_mlme_is_mlo_vdev(vdev)) {
1496*5113495bSYour Name 		if (sta_ctx && sta_ctx->connect_req) {
1497*5113495bSYour Name 			wlan_cm_free_connect_req(sta_ctx->connect_req);
1498*5113495bSYour Name 			sta_ctx->connect_req = NULL;
1499*5113495bSYour Name 		}
1500*5113495bSYour Name 
1501*5113495bSYour Name 		status = mlo_validate_disconn_req(vdev, source,
1502*5113495bSYour Name 						  reason_code, bssid);
1503*5113495bSYour Name 		if (QDF_IS_STATUS_ERROR(status)) {
1504*5113495bSYour Name 			mlo_err("Connect in progress, deferring disconnect");
1505*5113495bSYour Name 			return status;
1506*5113495bSYour Name 		}
1507*5113495bSYour Name 
1508*5113495bSYour Name 		status = mlo_send_link_disconnect_sync(mlo_dev_ctx, source,
1509*5113495bSYour Name 						       reason_code, bssid);
1510*5113495bSYour Name 		if (QDF_IS_STATUS_SUCCESS(status)) {
1511*5113495bSYour Name 			mlo_free_copied_conn_req(sta_ctx);
1512*5113495bSYour Name 			mlo_wait_for_mld_disconnection(vdev);
1513*5113495bSYour Name 		}
1514*5113495bSYour Name 
1515*5113495bSYour Name 		return status;
1516*5113495bSYour Name 	}
1517*5113495bSYour Name 	status = wlan_cm_disconnect_sync(vdev, source,
1518*5113495bSYour Name 					 reason_code);
1519*5113495bSYour Name 	if (QDF_IS_STATUS_SUCCESS(status))
1520*5113495bSYour Name 		mlo_free_copied_conn_req(sta_ctx);
1521*5113495bSYour Name 
1522*5113495bSYour Name 	return status;
1523*5113495bSYour Name }
1524*5113495bSYour Name 
1525*5113495bSYour Name /**
1526*5113495bSYour Name  * mlo_handle_disconnect_resp- Issue desired actions on partner link vdev
1527*5113495bSYour Name  *
1528*5113495bSYour Name  * @vdev: pointer to vdev
1529*5113495bSYour Name  * @resp: disconnect resp
1530*5113495bSYour Name  *
1531*5113495bSYour Name  * Return: none
1532*5113495bSYour Name  */
1533*5113495bSYour Name #ifdef WLAN_FEATURE_11BE_MLO_ADV_FEATURE
1534*5113495bSYour Name static
mlo_handle_disconnect_resp(struct wlan_objmgr_vdev * vdev,struct wlan_cm_discon_rsp * resp)1535*5113495bSYour Name void mlo_handle_disconnect_resp(struct wlan_objmgr_vdev *vdev,
1536*5113495bSYour Name 				struct wlan_cm_discon_rsp *resp)
1537*5113495bSYour Name {
1538*5113495bSYour Name /* If it is secondary link then delete vdev object from mlo device. */
1539*5113495bSYour Name 	enum wlan_cm_source source;
1540*5113495bSYour Name 	enum wlan_reason_code reason_code;
1541*5113495bSYour Name 	uint8_t i = 0;
1542*5113495bSYour Name 	struct wlan_objmgr_vdev *wlan_vdev_list[WLAN_UMAC_MLO_MAX_VDEVS];
1543*5113495bSYour Name 	uint16_t vdev_count = 0;
1544*5113495bSYour Name 
1545*5113495bSYour Name 	mlo_sta_get_vdev_list(vdev, &vdev_count, wlan_vdev_list);
1546*5113495bSYour Name 	for (i =  0; i < vdev_count; i++) {
1547*5113495bSYour Name 		if (wlan_cm_is_vdev_connected(wlan_vdev_list[i])) {
1548*5113495bSYour Name 			if (wlan_vdev_mlme_is_mlo_link_vdev(
1549*5113495bSYour Name 					wlan_vdev_list[i])) {
1550*5113495bSYour Name 				source = resp->req.req.source;
1551*5113495bSYour Name 				reason_code = resp->req.req.reason_code;
1552*5113495bSYour Name 				wlan_cm_disconnect(
1553*5113495bSYour Name 						wlan_vdev_list[i],
1554*5113495bSYour Name 						source, reason_code, NULL);
1555*5113495bSYour Name 			}
1556*5113495bSYour Name 		}
1557*5113495bSYour Name 		mlo_release_vdev_ref(wlan_vdev_list[i]);
1558*5113495bSYour Name 	}
1559*5113495bSYour Name }
1560*5113495bSYour Name #else
1561*5113495bSYour Name static
mlo_handle_disconnect_resp(struct wlan_objmgr_vdev * vdev,struct wlan_cm_discon_rsp * resp)1562*5113495bSYour Name void mlo_handle_disconnect_resp(struct wlan_objmgr_vdev *vdev,
1563*5113495bSYour Name 				struct wlan_cm_discon_rsp *resp)
1564*5113495bSYour Name { }
1565*5113495bSYour Name 
ml_activate_connect_req_sched_cb(struct scheduler_msg * msg)1566*5113495bSYour Name static QDF_STATUS ml_activate_connect_req_sched_cb(struct scheduler_msg *msg)
1567*5113495bSYour Name {
1568*5113495bSYour Name 	struct wlan_objmgr_vdev *vdev = msg->bodyptr;
1569*5113495bSYour Name 	struct wlan_mlo_dev_context *mlo_dev_ctx = NULL;
1570*5113495bSYour Name 	struct wlan_mlo_sta *sta_ctx = NULL;
1571*5113495bSYour Name 	uint8_t i = 0;
1572*5113495bSYour Name 	struct mlo_partner_info partner_info;
1573*5113495bSYour Name 	struct mlo_link_info partner_link_info;
1574*5113495bSYour Name 	struct wlan_objmgr_vdev *tmp_vdev;
1575*5113495bSYour Name 
1576*5113495bSYour Name 	if (!vdev) {
1577*5113495bSYour Name 		mlme_err("Null input vdev");
1578*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
1579*5113495bSYour Name 	}
1580*5113495bSYour Name 
1581*5113495bSYour Name 	mlo_dev_ctx = vdev->mlo_dev_ctx;
1582*5113495bSYour Name 	if (!mlo_dev_ctx) {
1583*5113495bSYour Name 		wlan_objmgr_vdev_release_ref(vdev, WLAN_MLO_MGR_ID);
1584*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
1585*5113495bSYour Name 	}
1586*5113495bSYour Name 
1587*5113495bSYour Name 	sta_ctx = mlo_dev_ctx->sta_ctx;
1588*5113495bSYour Name 	if (!sta_ctx || !sta_ctx->connect_req) {
1589*5113495bSYour Name 		wlan_objmgr_vdev_release_ref(vdev, WLAN_MLO_MGR_ID);
1590*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
1591*5113495bSYour Name 	}
1592*5113495bSYour Name 
1593*5113495bSYour Name 	if (sta_ctx->connect_req->ml_parnter_info.num_partner_links) {
1594*5113495bSYour Name 		partner_info = sta_ctx->connect_req->ml_parnter_info;
1595*5113495bSYour Name 		wlan_vdev_mlme_set_mlo_vdev(vdev);
1596*5113495bSYour Name 		wlan_vdev_mlme_clear_mlo_link_vdev(vdev);
1597*5113495bSYour Name 		mlo_clear_connect_req_links_bmap(vdev);
1598*5113495bSYour Name 		mlo_update_connect_req_links(vdev, 1);
1599*5113495bSYour Name 		for (i = 0; i < partner_info.num_partner_links; i++) {
1600*5113495bSYour Name 			partner_link_info = partner_info.partner_link_info[i];
1601*5113495bSYour Name 			tmp_vdev = mlo_get_ml_vdev_by_mac(
1602*5113495bSYour Name 					vdev,
1603*5113495bSYour Name 					&partner_link_info.link_addr);
1604*5113495bSYour Name 			if (tmp_vdev) {
1605*5113495bSYour Name 				mlo_update_connect_req_links(tmp_vdev, 1);
1606*5113495bSYour Name 				wlan_vdev_mlme_set_mlo_vdev(tmp_vdev);
1607*5113495bSYour Name 				wlan_vdev_mlme_set_mlo_link_vdev(tmp_vdev);
1608*5113495bSYour Name 				wlan_vdev_set_link_id(
1609*5113495bSYour Name 					tmp_vdev,
1610*5113495bSYour Name 					partner_link_info.link_id);
1611*5113495bSYour Name 			}
1612*5113495bSYour Name 		}
1613*5113495bSYour Name 	}
1614*5113495bSYour Name 
1615*5113495bSYour Name 	mlo_connect(vdev, sta_ctx->connect_req);
1616*5113495bSYour Name 	wlan_cm_free_connect_req(sta_ctx->connect_req);
1617*5113495bSYour Name 	sta_ctx->connect_req = NULL;
1618*5113495bSYour Name 
1619*5113495bSYour Name 	wlan_objmgr_vdev_release_ref(vdev, WLAN_MLO_MGR_ID);
1620*5113495bSYour Name 	return QDF_STATUS_SUCCESS;
1621*5113495bSYour Name }
1622*5113495bSYour Name 
ml_activate_connect_req_flush_cb(struct scheduler_msg * msg)1623*5113495bSYour Name static QDF_STATUS ml_activate_connect_req_flush_cb(struct scheduler_msg *msg)
1624*5113495bSYour Name {
1625*5113495bSYour Name 	struct wlan_objmgr_vdev *vdev = msg->bodyptr;
1626*5113495bSYour Name 
1627*5113495bSYour Name 	if (!vdev) {
1628*5113495bSYour Name 		mlme_err("Null input vdev");
1629*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
1630*5113495bSYour Name 	}
1631*5113495bSYour Name 
1632*5113495bSYour Name 	wlan_objmgr_vdev_release_ref(vdev, WLAN_MLO_MGR_ID);
1633*5113495bSYour Name 	return QDF_STATUS_SUCCESS;
1634*5113495bSYour Name }
1635*5113495bSYour Name #endif
1636*5113495bSYour Name 
1637*5113495bSYour Name #ifdef WLAN_FEATURE_11BE_MLO_ADV_FEATURE
1638*5113495bSYour Name static inline
mlo_sta_link_handle_pending_connect(struct wlan_objmgr_vdev * vdev)1639*5113495bSYour Name void mlo_sta_link_handle_pending_connect(struct wlan_objmgr_vdev *vdev)
1640*5113495bSYour Name { }
1641*5113495bSYour Name #else
1642*5113495bSYour Name static inline
mlo_sta_link_handle_pending_connect(struct wlan_objmgr_vdev * vdev)1643*5113495bSYour Name void mlo_sta_link_handle_pending_connect(struct wlan_objmgr_vdev *vdev)
1644*5113495bSYour Name {
1645*5113495bSYour Name 	struct wlan_mlo_dev_context *mlo_dev_ctx = vdev->mlo_dev_ctx;
1646*5113495bSYour Name 	struct scheduler_msg msg = {0};
1647*5113495bSYour Name 	QDF_STATUS ret;
1648*5113495bSYour Name 	struct wlan_mlo_sta *sta_ctx = NULL;
1649*5113495bSYour Name 
1650*5113495bSYour Name 	if (!mlo_dev_ctx) {
1651*5113495bSYour Name 		mlo_err("ML dev ctx is null");
1652*5113495bSYour Name 		return;
1653*5113495bSYour Name 	}
1654*5113495bSYour Name 	sta_ctx = mlo_dev_ctx->sta_ctx;
1655*5113495bSYour Name 	ret = wlan_objmgr_vdev_try_get_ref(
1656*5113495bSYour Name 			vdev,
1657*5113495bSYour Name 			WLAN_MLO_MGR_ID);
1658*5113495bSYour Name 	if (QDF_IS_STATUS_ERROR(ret)) {
1659*5113495bSYour Name 		wlan_cm_free_connect_req(sta_ctx->connect_req);
1660*5113495bSYour Name 		sta_ctx->connect_req = NULL;
1661*5113495bSYour Name 		return;
1662*5113495bSYour Name 	}
1663*5113495bSYour Name 	msg.bodyptr = vdev;
1664*5113495bSYour Name 	msg.callback = ml_activate_connect_req_sched_cb;
1665*5113495bSYour Name 	msg.flush_callback = ml_activate_connect_req_flush_cb;
1666*5113495bSYour Name 
1667*5113495bSYour Name 	ret = scheduler_post_message(QDF_MODULE_ID_MLME,
1668*5113495bSYour Name 				     QDF_MODULE_ID_MLME,
1669*5113495bSYour Name 				     QDF_MODULE_ID_MLME, &msg);
1670*5113495bSYour Name 	if (QDF_IS_STATUS_ERROR(ret)) {
1671*5113495bSYour Name 		wlan_cm_free_connect_req(sta_ctx->connect_req);
1672*5113495bSYour Name 		sta_ctx->connect_req = NULL;
1673*5113495bSYour Name 		wlan_objmgr_vdev_release_ref(vdev,
1674*5113495bSYour Name 					     WLAN_MLO_MGR_ID);
1675*5113495bSYour Name 		return;
1676*5113495bSYour Name 	}
1677*5113495bSYour Name }
1678*5113495bSYour Name #endif
1679*5113495bSYour Name 
mlo_sta_link_disconn_notify(struct wlan_objmgr_vdev * vdev,struct wlan_cm_discon_rsp * resp)1680*5113495bSYour Name void mlo_sta_link_disconn_notify(struct wlan_objmgr_vdev *vdev,
1681*5113495bSYour Name 				 struct wlan_cm_discon_rsp *resp)
1682*5113495bSYour Name {
1683*5113495bSYour Name 	struct wlan_mlo_dev_context *mlo_dev_ctx = vdev->mlo_dev_ctx;
1684*5113495bSYour Name 	struct wlan_mlo_sta *sta_ctx = NULL;
1685*5113495bSYour Name 	struct wlan_objmgr_vdev *assoc_vdev = NULL;
1686*5113495bSYour Name 
1687*5113495bSYour Name 	if (!mlo_dev_ctx || !(wlan_vdev_mlme_is_mlo_vdev(vdev)))
1688*5113495bSYour Name 		return;
1689*5113495bSYour Name 
1690*5113495bSYour Name 	sta_ctx = mlo_dev_ctx->sta_ctx;
1691*5113495bSYour Name 	if (!sta_ctx)
1692*5113495bSYour Name 		return;
1693*5113495bSYour Name 
1694*5113495bSYour Name 	if (!wlan_cm_is_vdev_disconnected(vdev))
1695*5113495bSYour Name 		return;
1696*5113495bSYour Name 
1697*5113495bSYour Name 	mlo_update_connected_links(vdev, 0);
1698*5113495bSYour Name 	if (mlo_is_mld_disconnected(vdev)) {
1699*5113495bSYour Name 		if (sta_ctx->connect_req) {
1700*5113495bSYour Name 			assoc_vdev = mlo_get_assoc_link_vdev(mlo_dev_ctx);
1701*5113495bSYour Name 			if (!assoc_vdev)
1702*5113495bSYour Name 				return;
1703*5113495bSYour Name 			mlo_sta_link_handle_pending_connect(assoc_vdev);
1704*5113495bSYour Name 		}
1705*5113495bSYour Name 	}
1706*5113495bSYour Name 
1707*5113495bSYour Name 	if (!wlan_cm_is_link_switch_disconnect_resp(resp))
1708*5113495bSYour Name 		mlo_handle_disconnect_resp(vdev, resp);
1709*5113495bSYour Name }
1710*5113495bSYour Name 
mlo_is_mld_sta(struct wlan_objmgr_vdev * vdev)1711*5113495bSYour Name bool mlo_is_mld_sta(struct wlan_objmgr_vdev *vdev)
1712*5113495bSYour Name {
1713*5113495bSYour Name 	if ((wlan_vdev_mlme_get_opmode(vdev) == QDF_STA_MODE) &&
1714*5113495bSYour Name 	    wlan_vdev_mlme_is_mlo_vdev(vdev))
1715*5113495bSYour Name 		return true;
1716*5113495bSYour Name 
1717*5113495bSYour Name 	return false;
1718*5113495bSYour Name }
1719*5113495bSYour Name 
1720*5113495bSYour Name qdf_export_symbol(mlo_is_mld_sta);
1721*5113495bSYour Name #ifndef WLAN_FEATURE_11BE_MLO_ADV_FEATURE
1722*5113495bSYour Name struct wlan_objmgr_vdev *
mlo_get_ml_vdev_by_mac(struct wlan_objmgr_vdev * vdev,struct qdf_mac_addr * macaddr)1723*5113495bSYour Name mlo_get_ml_vdev_by_mac(struct wlan_objmgr_vdev *vdev,
1724*5113495bSYour Name 		       struct qdf_mac_addr *macaddr)
1725*5113495bSYour Name {
1726*5113495bSYour Name 	struct wlan_mlo_dev_context *mlo_dev_ctx = vdev->mlo_dev_ctx;
1727*5113495bSYour Name 	uint8_t i = 0;
1728*5113495bSYour Name 
1729*5113495bSYour Name 	if (!mlo_dev_ctx)
1730*5113495bSYour Name 		return NULL;
1731*5113495bSYour Name 
1732*5113495bSYour Name 	for (i = 0; i < WLAN_UMAC_MLO_MAX_VDEVS; i++) {
1733*5113495bSYour Name 		if (!mlo_dev_ctx->wlan_vdev_list[i])
1734*5113495bSYour Name 			continue;
1735*5113495bSYour Name 
1736*5113495bSYour Name 		if(qdf_mem_cmp(macaddr,
1737*5113495bSYour Name 			       wlan_vdev_mlme_get_macaddr(mlo_dev_ctx->wlan_vdev_list[i]),
1738*5113495bSYour Name 			       QDF_MAC_ADDR_SIZE) == 0) {
1739*5113495bSYour Name 			return mlo_dev_ctx->wlan_vdev_list[i];
1740*5113495bSYour Name 		}
1741*5113495bSYour Name 	}
1742*5113495bSYour Name 	return NULL;
1743*5113495bSYour Name }
1744*5113495bSYour Name #endif
1745*5113495bSYour Name 
1746*5113495bSYour Name qdf_freq_t
mlo_get_chan_freq_by_bssid(struct wlan_objmgr_pdev * pdev,struct qdf_mac_addr * bssid)1747*5113495bSYour Name mlo_get_chan_freq_by_bssid(struct wlan_objmgr_pdev *pdev,
1748*5113495bSYour Name 			   struct qdf_mac_addr *bssid)
1749*5113495bSYour Name {
1750*5113495bSYour Name 	struct scan_filter *scan_filter;
1751*5113495bSYour Name 	int8_t ch_freq = 0;
1752*5113495bSYour Name 	qdf_list_t *list = NULL;
1753*5113495bSYour Name 	struct scan_cache_node *first_node = NULL;
1754*5113495bSYour Name 	qdf_list_node_t *cur_node = NULL;
1755*5113495bSYour Name 
1756*5113495bSYour Name 	scan_filter = qdf_mem_malloc(sizeof(*scan_filter));
1757*5113495bSYour Name 	if (!scan_filter)
1758*5113495bSYour Name 		return ch_freq;
1759*5113495bSYour Name 
1760*5113495bSYour Name 	scan_filter->num_of_bssid = 1;
1761*5113495bSYour Name 	qdf_mem_copy(scan_filter->bssid_list[0].bytes,
1762*5113495bSYour Name 		     bssid, sizeof(struct qdf_mac_addr));
1763*5113495bSYour Name 	list = wlan_scan_get_result(pdev, scan_filter);
1764*5113495bSYour Name 	qdf_mem_free(scan_filter);
1765*5113495bSYour Name 
1766*5113495bSYour Name 	if (!list || (list && !qdf_list_size(list))) {
1767*5113495bSYour Name 		mlo_debug("scan list empty");
1768*5113495bSYour Name 		goto error;
1769*5113495bSYour Name 	}
1770*5113495bSYour Name 
1771*5113495bSYour Name 	qdf_list_peek_front(list, &cur_node);
1772*5113495bSYour Name 	first_node = qdf_container_of(cur_node,
1773*5113495bSYour Name 				      struct scan_cache_node,
1774*5113495bSYour Name 				      node);
1775*5113495bSYour Name 	if (first_node && first_node->entry)
1776*5113495bSYour Name 		ch_freq = first_node->entry->channel.chan_freq;
1777*5113495bSYour Name error:
1778*5113495bSYour Name 	if (list)
1779*5113495bSYour Name 		wlan_scan_purge_results(list);
1780*5113495bSYour Name 
1781*5113495bSYour Name 	return ch_freq;
1782*5113495bSYour Name }
1783*5113495bSYour Name 
1784*5113495bSYour Name #ifdef WLAN_FEATURE_ROAM_OFFLOAD
1785*5113495bSYour Name /**
1786*5113495bSYour Name  * mlo_get_reassoc_rsp() - To get reassoc response
1787*5113495bSYour Name  * @vdev: objmgr vdev
1788*5113495bSYour Name  * @reassoc_rsp_frame: reassoc rsp
1789*5113495bSYour Name  *
1790*5113495bSYour Name  * Return: NA
1791*5113495bSYour Name  */
1792*5113495bSYour Name static
mlo_get_reassoc_rsp(struct wlan_objmgr_vdev * vdev,struct element_info ** reassoc_rsp_frame)1793*5113495bSYour Name void mlo_get_reassoc_rsp(struct wlan_objmgr_vdev *vdev,
1794*5113495bSYour Name 			 struct element_info **reassoc_rsp_frame)
1795*5113495bSYour Name {
1796*5113495bSYour Name 	struct wlan_mlo_dev_context *mlo_dev_ctx = vdev->mlo_dev_ctx;
1797*5113495bSYour Name 	struct wlan_mlo_sta *sta_ctx = NULL;
1798*5113495bSYour Name 
1799*5113495bSYour Name 	if (!mlo_dev_ctx || !mlo_dev_ctx->sta_ctx)
1800*5113495bSYour Name 		return;
1801*5113495bSYour Name 
1802*5113495bSYour Name 	sta_ctx = mlo_dev_ctx->sta_ctx;
1803*5113495bSYour Name 	if (!sta_ctx->copied_reassoc_rsp) {
1804*5113495bSYour Name 		mlo_err("Reassoc rsp not present for vdev_id %d",
1805*5113495bSYour Name 			wlan_vdev_get_id(vdev));
1806*5113495bSYour Name 		*reassoc_rsp_frame = NULL;
1807*5113495bSYour Name 		return;
1808*5113495bSYour Name 	}
1809*5113495bSYour Name 
1810*5113495bSYour Name 	if (!sta_ctx->copied_reassoc_rsp->connect_ies.assoc_rsp.len ||
1811*5113495bSYour Name 	    !sta_ctx->copied_reassoc_rsp->connect_ies.assoc_rsp.ptr) {
1812*5113495bSYour Name 		mlo_err("Reassoc Resp info empty vdev_id %d assoc len %d",
1813*5113495bSYour Name 			wlan_vdev_get_id(vdev),
1814*5113495bSYour Name 			sta_ctx->copied_reassoc_rsp->connect_ies.assoc_rsp.len);
1815*5113495bSYour Name 		*reassoc_rsp_frame = NULL;
1816*5113495bSYour Name 		return;
1817*5113495bSYour Name 	}
1818*5113495bSYour Name 
1819*5113495bSYour Name 	*reassoc_rsp_frame =
1820*5113495bSYour Name 		&sta_ctx->copied_reassoc_rsp->connect_ies.assoc_rsp;
1821*5113495bSYour Name }
1822*5113495bSYour Name #else
1823*5113495bSYour Name static inline
mlo_get_reassoc_rsp(struct wlan_objmgr_vdev * vdev,struct element_info ** reassoc_rsp_frame)1824*5113495bSYour Name void mlo_get_reassoc_rsp(struct wlan_objmgr_vdev *vdev,
1825*5113495bSYour Name 			 struct element_info **reassoc_rsp_frame)
1826*5113495bSYour Name {
1827*5113495bSYour Name 	*reassoc_rsp_frame = NULL;
1828*5113495bSYour Name }
1829*5113495bSYour Name #endif
1830*5113495bSYour Name 
mlo_get_assoc_rsp(struct wlan_objmgr_vdev * vdev,struct element_info * assoc_rsp_frame)1831*5113495bSYour Name void mlo_get_assoc_rsp(struct wlan_objmgr_vdev *vdev,
1832*5113495bSYour Name 		       struct element_info *assoc_rsp_frame)
1833*5113495bSYour Name {
1834*5113495bSYour Name 	struct wlan_mlo_dev_context *mlo_dev_ctx = vdev->mlo_dev_ctx;
1835*5113495bSYour Name 	struct wlan_mlo_sta *sta_ctx = NULL;
1836*5113495bSYour Name 	struct element_info *mlo_reassoc_rsp = NULL;
1837*5113495bSYour Name 
1838*5113495bSYour Name 	if (!mlo_dev_ctx || !mlo_dev_ctx->sta_ctx)
1839*5113495bSYour Name 		return;
1840*5113495bSYour Name 
1841*5113495bSYour Name 	sta_ctx = mlo_dev_ctx->sta_ctx;
1842*5113495bSYour Name 	if (sta_ctx->assoc_rsp.len && sta_ctx->assoc_rsp.ptr) {
1843*5113495bSYour Name 		*assoc_rsp_frame = sta_ctx->assoc_rsp;
1844*5113495bSYour Name 		return;
1845*5113495bSYour Name 	}
1846*5113495bSYour Name 	mlo_get_reassoc_rsp(vdev, &mlo_reassoc_rsp);
1847*5113495bSYour Name 	if (mlo_reassoc_rsp)
1848*5113495bSYour Name 		*assoc_rsp_frame = *mlo_reassoc_rsp;
1849*5113495bSYour Name }
1850*5113495bSYour Name 
mlo_sta_save_quiet_status(struct wlan_mlo_dev_context * mlo_dev_ctx,uint8_t link_id,bool quiet_status)1851*5113495bSYour Name QDF_STATUS mlo_sta_save_quiet_status(struct wlan_mlo_dev_context *mlo_dev_ctx,
1852*5113495bSYour Name 				     uint8_t link_id,
1853*5113495bSYour Name 				     bool quiet_status)
1854*5113495bSYour Name {
1855*5113495bSYour Name 	struct wlan_mlo_sta *sta_ctx;
1856*5113495bSYour Name 	int i;
1857*5113495bSYour Name 	bool find_free_buffer = false;
1858*5113495bSYour Name 	int free_idx;
1859*5113495bSYour Name 
1860*5113495bSYour Name 	if (!mlo_dev_ctx) {
1861*5113495bSYour Name 		mlo_err("invalid mlo_dev_ctx");
1862*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
1863*5113495bSYour Name 	}
1864*5113495bSYour Name 
1865*5113495bSYour Name 	mlo_dev_lock_acquire(mlo_dev_ctx);
1866*5113495bSYour Name 	sta_ctx = mlo_dev_ctx->sta_ctx;
1867*5113495bSYour Name 	if (!sta_ctx) {
1868*5113495bSYour Name 		mlo_err("invalid sta_ctx");
1869*5113495bSYour Name 		mlo_dev_lock_release(mlo_dev_ctx);
1870*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
1871*5113495bSYour Name 	}
1872*5113495bSYour Name 	for (i = 0; i < QDF_ARRAY_SIZE(sta_ctx->mlo_quiet_status); i++) {
1873*5113495bSYour Name 		if (!sta_ctx->mlo_quiet_status[i].valid_status) {
1874*5113495bSYour Name 			if (!find_free_buffer) {
1875*5113495bSYour Name 				free_idx = i;
1876*5113495bSYour Name 				find_free_buffer = true;
1877*5113495bSYour Name 			}
1878*5113495bSYour Name 		} else if (link_id == sta_ctx->mlo_quiet_status[i].link_id) {
1879*5113495bSYour Name 			sta_ctx->mlo_quiet_status[i].quiet_status =
1880*5113495bSYour Name 							quiet_status;
1881*5113495bSYour Name 			mlo_debug("mld mac " QDF_MAC_ADDR_FMT " link id %d quiet status update %d",
1882*5113495bSYour Name 				  QDF_MAC_ADDR_REF(mlo_dev_ctx->mld_addr.bytes),
1883*5113495bSYour Name 				  link_id, quiet_status);
1884*5113495bSYour Name 			mlo_dev_lock_release(mlo_dev_ctx);
1885*5113495bSYour Name 			return QDF_STATUS_SUCCESS;
1886*5113495bSYour Name 		}
1887*5113495bSYour Name 	}
1888*5113495bSYour Name 	if (!find_free_buffer) {
1889*5113495bSYour Name 		mlo_err("no free buffer for link id %d to save quiet_status",
1890*5113495bSYour Name 			link_id);
1891*5113495bSYour Name 		mlo_dev_lock_release(mlo_dev_ctx);
1892*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
1893*5113495bSYour Name 	}
1894*5113495bSYour Name 	sta_ctx->mlo_quiet_status[free_idx].quiet_status = quiet_status;
1895*5113495bSYour Name 	sta_ctx->mlo_quiet_status[free_idx].link_id = link_id;
1896*5113495bSYour Name 	sta_ctx->mlo_quiet_status[free_idx].valid_status = true;
1897*5113495bSYour Name 
1898*5113495bSYour Name 	mlo_debug("mld mac " QDF_MAC_ADDR_FMT " link id %d in quiet status %d",
1899*5113495bSYour Name 		  QDF_MAC_ADDR_REF(mlo_dev_ctx->mld_addr.bytes),
1900*5113495bSYour Name 		  link_id, quiet_status);
1901*5113495bSYour Name 	mlo_dev_lock_release(mlo_dev_ctx);
1902*5113495bSYour Name 
1903*5113495bSYour Name 	return QDF_STATUS_SUCCESS;
1904*5113495bSYour Name }
1905*5113495bSYour Name 
mlo_is_sta_in_quiet_status(struct wlan_mlo_dev_context * mlo_dev_ctx,uint8_t link_id)1906*5113495bSYour Name bool mlo_is_sta_in_quiet_status(struct wlan_mlo_dev_context *mlo_dev_ctx,
1907*5113495bSYour Name 				uint8_t link_id)
1908*5113495bSYour Name {
1909*5113495bSYour Name 	struct wlan_mlo_sta *sta_ctx;
1910*5113495bSYour Name 	int i;
1911*5113495bSYour Name 	bool quiet_status = false;
1912*5113495bSYour Name 
1913*5113495bSYour Name 	if (!mlo_dev_ctx) {
1914*5113495bSYour Name 		mlo_err("invalid mlo_dev_ctx");
1915*5113495bSYour Name 		return quiet_status;
1916*5113495bSYour Name 	}
1917*5113495bSYour Name 
1918*5113495bSYour Name 	mlo_dev_lock_acquire(mlo_dev_ctx);
1919*5113495bSYour Name 	sta_ctx = mlo_dev_ctx->sta_ctx;
1920*5113495bSYour Name 	if (!sta_ctx) {
1921*5113495bSYour Name 		mlo_err("invalid sta_ctx");
1922*5113495bSYour Name 		mlo_dev_lock_release(mlo_dev_ctx);
1923*5113495bSYour Name 		return quiet_status;
1924*5113495bSYour Name 	}
1925*5113495bSYour Name 	for (i = 0; i < QDF_ARRAY_SIZE(sta_ctx->mlo_quiet_status); i++) {
1926*5113495bSYour Name 		if (sta_ctx->mlo_quiet_status[i].valid_status &&
1927*5113495bSYour Name 		    link_id == sta_ctx->mlo_quiet_status[i].link_id) {
1928*5113495bSYour Name 			quiet_status =
1929*5113495bSYour Name 				sta_ctx->mlo_quiet_status[i].quiet_status;
1930*5113495bSYour Name 			break;
1931*5113495bSYour Name 		}
1932*5113495bSYour Name 	}
1933*5113495bSYour Name 	mlo_dev_lock_release(mlo_dev_ctx);
1934*5113495bSYour Name 
1935*5113495bSYour Name 	return quiet_status;
1936*5113495bSYour Name }
1937*5113495bSYour Name 
mlo_is_sta_inactivity_allowed_with_quiet(struct wlan_objmgr_psoc * psoc,uint8_t * vdev_id_list,uint8_t num_mlo,uint8_t * mlo_idx,uint8_t affected_links,uint8_t * affected_list)1938*5113495bSYour Name bool mlo_is_sta_inactivity_allowed_with_quiet(struct wlan_objmgr_psoc *psoc,
1939*5113495bSYour Name 					      uint8_t *vdev_id_list,
1940*5113495bSYour Name 					      uint8_t num_mlo, uint8_t *mlo_idx,
1941*5113495bSYour Name 					      uint8_t affected_links,
1942*5113495bSYour Name 					      uint8_t *affected_list)
1943*5113495bSYour Name {
1944*5113495bSYour Name 	uint8_t i, j;
1945*5113495bSYour Name 	struct wlan_objmgr_vdev *vdev;
1946*5113495bSYour Name 	bool allowed = false;
1947*5113495bSYour Name 
1948*5113495bSYour Name 	for (i = 0; i < num_mlo; i++) {
1949*5113495bSYour Name 		for (j = 0; j < affected_links; j++) {
1950*5113495bSYour Name 			if (vdev_id_list[mlo_idx[i]] == affected_list[j])
1951*5113495bSYour Name 				break;
1952*5113495bSYour Name 		}
1953*5113495bSYour Name 		if (j != affected_links)
1954*5113495bSYour Name 			continue;
1955*5113495bSYour Name 		/* find vdev not in affected_list */
1956*5113495bSYour Name 		vdev = wlan_objmgr_get_vdev_by_id_from_psoc(
1957*5113495bSYour Name 				psoc, vdev_id_list[mlo_idx[i]],
1958*5113495bSYour Name 				WLAN_IF_MGR_ID);
1959*5113495bSYour Name 		if (!vdev) {
1960*5113495bSYour Name 			mlo_err("invalid vdev for id %d",
1961*5113495bSYour Name 				vdev_id_list[mlo_idx[i]]);
1962*5113495bSYour Name 			continue;
1963*5113495bSYour Name 		}
1964*5113495bSYour Name 
1965*5113495bSYour Name 		/* for not affected vdev, check the vdev is in quiet or not*/
1966*5113495bSYour Name 		allowed = !mlo_is_sta_in_quiet_status(
1967*5113495bSYour Name 				vdev->mlo_dev_ctx, wlan_vdev_get_link_id(vdev));
1968*5113495bSYour Name 		wlan_objmgr_vdev_release_ref(vdev, WLAN_IF_MGR_ID);
1969*5113495bSYour Name 		if (allowed) {
1970*5113495bSYour Name 			mlo_debug("vdev id %d link id %d is not in quiet, allow partner link to trigger inactivity",
1971*5113495bSYour Name 				  wlan_vdev_get_id(vdev),
1972*5113495bSYour Name 				  wlan_vdev_get_link_id(vdev));
1973*5113495bSYour Name 			break;
1974*5113495bSYour Name 		}
1975*5113495bSYour Name 	}
1976*5113495bSYour Name 
1977*5113495bSYour Name 	return allowed;
1978*5113495bSYour Name }
1979*5113495bSYour Name 
mlo_is_sta_csa_synced(struct wlan_mlo_dev_context * mlo_dev_ctx,uint8_t link_id)1980*5113495bSYour Name bool mlo_is_sta_csa_synced(struct wlan_mlo_dev_context *mlo_dev_ctx,
1981*5113495bSYour Name 			   uint8_t link_id)
1982*5113495bSYour Name {
1983*5113495bSYour Name 	struct wlan_mlo_sta *sta_ctx;
1984*5113495bSYour Name 	int i;
1985*5113495bSYour Name 	bool sta_csa_synced = false;
1986*5113495bSYour Name 
1987*5113495bSYour Name 	if (!mlo_dev_ctx) {
1988*5113495bSYour Name 		mlo_err("invalid mlo_dev_ctx");
1989*5113495bSYour Name 		return sta_csa_synced;
1990*5113495bSYour Name 	}
1991*5113495bSYour Name 
1992*5113495bSYour Name 	mlo_dev_lock_acquire(mlo_dev_ctx);
1993*5113495bSYour Name 	sta_ctx = mlo_dev_ctx->sta_ctx;
1994*5113495bSYour Name 	if (!sta_ctx) {
1995*5113495bSYour Name 		mlo_err("invalid sta_ctx");
1996*5113495bSYour Name 		mlo_dev_lock_release(mlo_dev_ctx);
1997*5113495bSYour Name 		return sta_csa_synced;
1998*5113495bSYour Name 	}
1999*5113495bSYour Name 	for (i = 0; i < QDF_ARRAY_SIZE(sta_ctx->mlo_csa_param); i++) {
2000*5113495bSYour Name 		if (link_id == sta_ctx->mlo_csa_param[i].link_id &&
2001*5113495bSYour Name 		    (sta_ctx->mlo_csa_param[i].valid_csa_param ||
2002*5113495bSYour Name 		     sta_ctx->mlo_csa_param[i].mlo_csa_synced)) {
2003*5113495bSYour Name 			sta_csa_synced =
2004*5113495bSYour Name 				sta_ctx->mlo_csa_param[i].mlo_csa_synced;
2005*5113495bSYour Name 			break;
2006*5113495bSYour Name 		}
2007*5113495bSYour Name 	}
2008*5113495bSYour Name 	mlo_dev_lock_release(mlo_dev_ctx);
2009*5113495bSYour Name 
2010*5113495bSYour Name 	return sta_csa_synced;
2011*5113495bSYour Name }
2012*5113495bSYour Name 
2013*5113495bSYour Name #ifdef WLAN_FEATURE_11BE_MLO_ADV_FEATURE
mlo_sta_handle_csa_standby_link(struct wlan_mlo_dev_context * mlo_dev_ctx,uint8_t link_id,struct csa_offload_params * csa_param,struct wlan_objmgr_vdev * vdev)2014*5113495bSYour Name QDF_STATUS mlo_sta_handle_csa_standby_link(
2015*5113495bSYour Name 			struct wlan_mlo_dev_context *mlo_dev_ctx,
2016*5113495bSYour Name 			uint8_t link_id,
2017*5113495bSYour Name 			struct csa_offload_params *csa_param,
2018*5113495bSYour Name 			struct wlan_objmgr_vdev *vdev)
2019*5113495bSYour Name {
2020*5113495bSYour Name 	QDF_STATUS status = QDF_STATUS_SUCCESS;
2021*5113495bSYour Name 	struct wlan_lmac_if_mlo_tx_ops *mlo_tx_ops;
2022*5113495bSYour Name 	struct mlo_link_info *link_info;
2023*5113495bSYour Name 	struct mlo_link_bss_params params = {0};
2024*5113495bSYour Name 	struct wlan_objmgr_psoc *psoc;
2025*5113495bSYour Name 	struct wlan_objmgr_pdev *pdev;
2026*5113495bSYour Name 
2027*5113495bSYour Name 	if (!mlo_dev_ctx) {
2028*5113495bSYour Name 		mlo_err("invalid mlo_dev_ctx");
2029*5113495bSYour Name 		return QDF_STATUS_E_NULL_VALUE;
2030*5113495bSYour Name 	}
2031*5113495bSYour Name 
2032*5113495bSYour Name 	pdev = wlan_vdev_get_pdev(vdev);
2033*5113495bSYour Name 	if (!pdev) {
2034*5113495bSYour Name 		mlo_err("null pdev");
2035*5113495bSYour Name 		return QDF_STATUS_E_NULL_VALUE;
2036*5113495bSYour Name 	}
2037*5113495bSYour Name 
2038*5113495bSYour Name 	psoc = wlan_vdev_get_psoc(vdev);
2039*5113495bSYour Name 	if (!psoc) {
2040*5113495bSYour Name 		mlo_err("null psoc");
2041*5113495bSYour Name 		return QDF_STATUS_E_NULL_VALUE;
2042*5113495bSYour Name 	}
2043*5113495bSYour Name 
2044*5113495bSYour Name 	mlo_tx_ops = &psoc->soc_cb.tx_ops->mlo_ops;
2045*5113495bSYour Name 
2046*5113495bSYour Name 	link_info = mlo_mgr_get_ap_link_by_link_id(mlo_dev_ctx, link_id);
2047*5113495bSYour Name 	if (!link_info) {
2048*5113495bSYour Name 		mlo_err("link info null");
2049*5113495bSYour Name 		return QDF_STATUS_E_NULL_VALUE;
2050*5113495bSYour Name 	}
2051*5113495bSYour Name 
2052*5113495bSYour Name 	if (link_info->vdev_id != WLAN_INVALID_VDEV_ID) {
2053*5113495bSYour Name 		mlo_debug("vdev id %d link id %d ", link_info->vdev_id,
2054*5113495bSYour Name 			  link_id);
2055*5113495bSYour Name 		return QDF_STATUS_E_NULL_VALUE;
2056*5113495bSYour Name 	}
2057*5113495bSYour Name 
2058*5113495bSYour Name 	mlo_mgr_update_csa_link_info(pdev, mlo_dev_ctx, csa_param, link_id);
2059*5113495bSYour Name 
2060*5113495bSYour Name 	params.link_id = link_info->link_id;
2061*5113495bSYour Name 	params.chan = qdf_mem_malloc(sizeof(struct wlan_channel));
2062*5113495bSYour Name 	if (!params.chan) {
2063*5113495bSYour Name 		mlo_err("no mem allocated");
2064*5113495bSYour Name 		return QDF_STATUS_E_NOMEM;
2065*5113495bSYour Name 	}
2066*5113495bSYour Name 
2067*5113495bSYour Name 	wlan_vdev_get_bss_peer_mld_mac(
2068*5113495bSYour Name 				vdev,
2069*5113495bSYour Name 				(struct qdf_mac_addr *)&params.ap_mld_mac[0]);
2070*5113495bSYour Name 
2071*5113495bSYour Name 	params.chan->ch_freq = link_info->link_chan_info->ch_freq;
2072*5113495bSYour Name 	params.chan->ch_cfreq1 = link_info->link_chan_info->ch_cfreq1;
2073*5113495bSYour Name 	params.chan->ch_cfreq2 = link_info->link_chan_info->ch_cfreq2;
2074*5113495bSYour Name 	params.chan->ch_phymode = link_info->link_chan_info->ch_phymode;
2075*5113495bSYour Name 
2076*5113495bSYour Name 	mlo_debug("link id %d chan freq %d cfreq1 %d cfreq2 %d host phymode %d ap mld mac " QDF_MAC_ADDR_FMT,
2077*5113495bSYour Name 		  link_info->link_id, link_info->link_chan_info->ch_freq,
2078*5113495bSYour Name 		  link_info->link_chan_info->ch_cfreq1,
2079*5113495bSYour Name 		  link_info->link_chan_info->ch_cfreq2,
2080*5113495bSYour Name 		  link_info->link_chan_info->ch_phymode,
2081*5113495bSYour Name 		  QDF_MAC_ADDR_REF(&params.ap_mld_mac[0]));
2082*5113495bSYour Name 
2083*5113495bSYour Name 	if (!mlo_tx_ops->send_link_set_bss_params_cmd) {
2084*5113495bSYour Name 		mlo_err("handler is not registered");
2085*5113495bSYour Name 		qdf_mem_free(params.chan);
2086*5113495bSYour Name 		return QDF_STATUS_E_NULL_VALUE;
2087*5113495bSYour Name 	}
2088*5113495bSYour Name 
2089*5113495bSYour Name 	status = mlo_tx_ops->send_link_set_bss_params_cmd(psoc, &params);
2090*5113495bSYour Name 
2091*5113495bSYour Name 	if (QDF_IS_STATUS_ERROR(status)) {
2092*5113495bSYour Name 		mlo_err("failed to send link set bss request command to FW");
2093*5113495bSYour Name 		qdf_mem_free(params.chan);
2094*5113495bSYour Name 		return QDF_STATUS_E_NULL_VALUE;
2095*5113495bSYour Name 	}
2096*5113495bSYour Name 	qdf_mem_free(params.chan);
2097*5113495bSYour Name 	return status;
2098*5113495bSYour Name }
2099*5113495bSYour Name 
mlo_sta_handle_link_reconfig_standby_link(struct wlan_objmgr_vdev * vdev,struct ml_rv_info * reconfig_info)2100*5113495bSYour Name static void mlo_sta_handle_link_reconfig_standby_link(
2101*5113495bSYour Name 			struct wlan_objmgr_vdev *vdev,
2102*5113495bSYour Name 			struct ml_rv_info *reconfig_info)
2103*5113495bSYour Name {
2104*5113495bSYour Name 	struct vdev_mlme_obj *vdev_mlme;
2105*5113495bSYour Name 
2106*5113495bSYour Name 	vdev_mlme = wlan_vdev_mlme_get_cmpt_obj(vdev);
2107*5113495bSYour Name 	if (!vdev_mlme)
2108*5113495bSYour Name 		return;
2109*5113495bSYour Name 	if (vdev_mlme->ops &&
2110*5113495bSYour Name 	    vdev_mlme->ops->mlme_vdev_reconfig_notify_standby) {
2111*5113495bSYour Name 		vdev_mlme->ops->mlme_vdev_reconfig_notify_standby(
2112*5113495bSYour Name 				vdev_mlme,
2113*5113495bSYour Name 				reconfig_info);
2114*5113495bSYour Name 	}
2115*5113495bSYour Name }
2116*5113495bSYour Name #else
mlo_sta_handle_link_reconfig_standby_link(struct wlan_objmgr_vdev * vdev,struct ml_rv_info * reconfig_info)2117*5113495bSYour Name static void mlo_sta_handle_link_reconfig_standby_link(
2118*5113495bSYour Name 			struct wlan_objmgr_vdev *vdev,
2119*5113495bSYour Name 			struct ml_rv_info *reconfig_info)
2120*5113495bSYour Name {
2121*5113495bSYour Name }
2122*5113495bSYour Name #endif
2123*5113495bSYour Name 
mlo_sta_csa_save_params(struct wlan_mlo_dev_context * mlo_dev_ctx,uint8_t link_id,struct csa_offload_params * csa_param)2124*5113495bSYour Name QDF_STATUS mlo_sta_csa_save_params(struct wlan_mlo_dev_context *mlo_dev_ctx,
2125*5113495bSYour Name 				   uint8_t link_id,
2126*5113495bSYour Name 				   struct csa_offload_params *csa_param)
2127*5113495bSYour Name {
2128*5113495bSYour Name 	struct wlan_mlo_sta *sta_ctx;
2129*5113495bSYour Name 	int i;
2130*5113495bSYour Name 	bool find_free_buffer = false;
2131*5113495bSYour Name 	int free_idx;
2132*5113495bSYour Name 	QDF_STATUS status = QDF_STATUS_SUCCESS;
2133*5113495bSYour Name 
2134*5113495bSYour Name 	if (!mlo_dev_ctx) {
2135*5113495bSYour Name 		mlo_err("invalid mlo_dev_ctx");
2136*5113495bSYour Name 		status = QDF_STATUS_E_INVAL;
2137*5113495bSYour Name 		goto done;
2138*5113495bSYour Name 	}
2139*5113495bSYour Name 
2140*5113495bSYour Name 	mlo_dev_lock_acquire(mlo_dev_ctx);
2141*5113495bSYour Name 	sta_ctx = mlo_dev_ctx->sta_ctx;
2142*5113495bSYour Name 	if (!sta_ctx) {
2143*5113495bSYour Name 		mlo_err("invalid sta_ctx");
2144*5113495bSYour Name 		status = QDF_STATUS_E_INVAL;
2145*5113495bSYour Name 		goto rel_lock;
2146*5113495bSYour Name 	}
2147*5113495bSYour Name 	for (i = 0; i < QDF_ARRAY_SIZE(sta_ctx->mlo_csa_param); i++) {
2148*5113495bSYour Name 		if (!sta_ctx->mlo_csa_param[i].valid_csa_param &&
2149*5113495bSYour Name 		    !sta_ctx->mlo_csa_param[i].mlo_csa_synced) {
2150*5113495bSYour Name 			if (!find_free_buffer) {
2151*5113495bSYour Name 				free_idx = i;
2152*5113495bSYour Name 				find_free_buffer = true;
2153*5113495bSYour Name 			}
2154*5113495bSYour Name 		} else if (link_id == sta_ctx->mlo_csa_param[i].link_id) {
2155*5113495bSYour Name 			qdf_mem_copy(&sta_ctx->mlo_csa_param[i].csa_param,
2156*5113495bSYour Name 				     csa_param, sizeof(*csa_param));
2157*5113495bSYour Name 			mlo_debug("mld mac " QDF_MAC_ADDR_FMT " link id %d update csa",
2158*5113495bSYour Name 				  QDF_MAC_ADDR_REF(mlo_dev_ctx->mld_addr.bytes),
2159*5113495bSYour Name 				  link_id);
2160*5113495bSYour Name 			goto rel_lock;
2161*5113495bSYour Name 		}
2162*5113495bSYour Name 	}
2163*5113495bSYour Name 	if (!find_free_buffer) {
2164*5113495bSYour Name 		mlo_err("no free buffer of csa param for link %d in sta_ctx",
2165*5113495bSYour Name 			link_id);
2166*5113495bSYour Name 		status = QDF_STATUS_E_INVAL;
2167*5113495bSYour Name 		goto rel_lock;
2168*5113495bSYour Name 	}
2169*5113495bSYour Name 	qdf_mem_copy(&sta_ctx->mlo_csa_param[free_idx].csa_param,
2170*5113495bSYour Name 		     csa_param, sizeof(*csa_param));
2171*5113495bSYour Name 	sta_ctx->mlo_csa_param[free_idx].link_id = link_id;
2172*5113495bSYour Name 	sta_ctx->mlo_csa_param[free_idx].valid_csa_param = true;
2173*5113495bSYour Name 	mlo_debug("mld mac " QDF_MAC_ADDR_FMT " link id %d RX csa",
2174*5113495bSYour Name 		  QDF_MAC_ADDR_REF(mlo_dev_ctx->mld_addr.bytes),
2175*5113495bSYour Name 		  link_id);
2176*5113495bSYour Name 
2177*5113495bSYour Name rel_lock:
2178*5113495bSYour Name 	mlo_dev_lock_release(mlo_dev_ctx);
2179*5113495bSYour Name 
2180*5113495bSYour Name done:
2181*5113495bSYour Name 
2182*5113495bSYour Name 	return status;
2183*5113495bSYour Name }
2184*5113495bSYour Name 
mlo_sta_up_active_notify(struct wlan_objmgr_vdev * vdev)2185*5113495bSYour Name QDF_STATUS mlo_sta_up_active_notify(struct wlan_objmgr_vdev *vdev)
2186*5113495bSYour Name {
2187*5113495bSYour Name 	struct wlan_mlo_sta *sta_ctx;
2188*5113495bSYour Name 	struct wlan_mlo_dev_context *mlo_dev_ctx;
2189*5113495bSYour Name 	uint8_t link_id;
2190*5113495bSYour Name 	int i;
2191*5113495bSYour Name 	bool find_free_buffer = false;
2192*5113495bSYour Name 	int free_idx;
2193*5113495bSYour Name 	struct csa_offload_params csa_param;
2194*5113495bSYour Name 	struct wlan_channel *chan;
2195*5113495bSYour Name 	QDF_STATUS status = QDF_STATUS_SUCCESS;
2196*5113495bSYour Name 
2197*5113495bSYour Name 	if (!vdev) {
2198*5113495bSYour Name 		mlo_err("invalid vdev");
2199*5113495bSYour Name 		status = QDF_STATUS_E_INVAL;
2200*5113495bSYour Name 		goto done;
2201*5113495bSYour Name 	}
2202*5113495bSYour Name 	link_id = wlan_vdev_get_link_id(vdev);
2203*5113495bSYour Name 	mlo_dev_ctx = vdev->mlo_dev_ctx;
2204*5113495bSYour Name 	if (!mlo_dev_ctx) {
2205*5113495bSYour Name 		mlo_err("invalid mlo_dev_ctx");
2206*5113495bSYour Name 		status = QDF_STATUS_E_INVAL;
2207*5113495bSYour Name 		goto done;
2208*5113495bSYour Name 	}
2209*5113495bSYour Name 	mlo_dev_lock_acquire(mlo_dev_ctx);
2210*5113495bSYour Name 	sta_ctx = mlo_dev_ctx->sta_ctx;
2211*5113495bSYour Name 	if (!sta_ctx) {
2212*5113495bSYour Name 		mlo_err("invalid sta_ctx");
2213*5113495bSYour Name 		status = QDF_STATUS_E_INVAL;
2214*5113495bSYour Name 		goto rel_lock;
2215*5113495bSYour Name 	}
2216*5113495bSYour Name 
2217*5113495bSYour Name 	for (i = 0; i < QDF_ARRAY_SIZE(sta_ctx->mlo_csa_param); i++) {
2218*5113495bSYour Name 		if (!sta_ctx->mlo_csa_param[i].valid_csa_param &&
2219*5113495bSYour Name 		    !sta_ctx->mlo_csa_param[i].mlo_csa_synced) {
2220*5113495bSYour Name 			if (!find_free_buffer) {
2221*5113495bSYour Name 				free_idx = i;
2222*5113495bSYour Name 				find_free_buffer = true;
2223*5113495bSYour Name 			}
2224*5113495bSYour Name 		} else if (link_id == sta_ctx->mlo_csa_param[i].link_id) {
2225*5113495bSYour Name 			if (sta_ctx->mlo_csa_param[i].valid_csa_param &&
2226*5113495bSYour Name 			    !sta_ctx->mlo_csa_param[i].mlo_csa_synced) {
2227*5113495bSYour Name 				mlo_debug("mld mac " QDF_MAC_ADDR_FMT " vdev id %d link id %d handle csa",
2228*5113495bSYour Name 					  QDF_MAC_ADDR_REF(
2229*5113495bSYour Name 						mlo_dev_ctx->mld_addr.bytes),
2230*5113495bSYour Name 					  wlan_vdev_get_id(vdev), link_id);
2231*5113495bSYour Name 				csa_param = sta_ctx->mlo_csa_param[i].csa_param;
2232*5113495bSYour Name 				sta_ctx->mlo_csa_param[i].mlo_csa_synced = true;
2233*5113495bSYour Name 				mlo_dev_lock_release(mlo_dev_ctx);
2234*5113495bSYour Name 				chan = wlan_vdev_mlme_get_bss_chan(vdev);
2235*5113495bSYour Name 				if (csa_param.csa_chan_freq && chan &&
2236*5113495bSYour Name 				    csa_param.csa_chan_freq != chan->ch_freq)
2237*5113495bSYour Name 					mlo_mlme_handle_sta_csa_param(
2238*5113495bSYour Name 						vdev, &csa_param);
2239*5113495bSYour Name 				goto done;
2240*5113495bSYour Name 			}
2241*5113495bSYour Name 			sta_ctx->mlo_csa_param[i].mlo_csa_synced = true;
2242*5113495bSYour Name 			goto rel_lock;
2243*5113495bSYour Name 		}
2244*5113495bSYour Name 	}
2245*5113495bSYour Name 	if (!find_free_buffer) {
2246*5113495bSYour Name 		mlo_err("no free buffer of csa param for link %d in sta_ctx",
2247*5113495bSYour Name 			link_id);
2248*5113495bSYour Name 		goto rel_lock;
2249*5113495bSYour Name 	}
2250*5113495bSYour Name 	sta_ctx->mlo_csa_param[free_idx].mlo_csa_synced = true;
2251*5113495bSYour Name 	sta_ctx->mlo_csa_param[free_idx].link_id = link_id;
2252*5113495bSYour Name 	mlo_debug("mld mac " QDF_MAC_ADDR_FMT " link id %d UP Active",
2253*5113495bSYour Name 		  QDF_MAC_ADDR_REF(mlo_dev_ctx->mld_addr.bytes),
2254*5113495bSYour Name 		  link_id);
2255*5113495bSYour Name 
2256*5113495bSYour Name rel_lock:
2257*5113495bSYour Name 	mlo_dev_lock_release(mlo_dev_ctx);
2258*5113495bSYour Name 
2259*5113495bSYour Name done:
2260*5113495bSYour Name 
2261*5113495bSYour Name 	return status;
2262*5113495bSYour Name }
2263*5113495bSYour Name 
mlo_is_sta_csa_param_handled(struct wlan_objmgr_vdev * vdev,struct csa_offload_params * csa_param)2264*5113495bSYour Name bool mlo_is_sta_csa_param_handled(struct wlan_objmgr_vdev *vdev,
2265*5113495bSYour Name 				  struct csa_offload_params *csa_param)
2266*5113495bSYour Name {
2267*5113495bSYour Name 	struct wlan_mlo_sta *sta_ctx;
2268*5113495bSYour Name 	struct wlan_mlo_dev_context *mlo_dev_ctx;
2269*5113495bSYour Name 	uint8_t link_id;
2270*5113495bSYour Name 	int i;
2271*5113495bSYour Name 	bool handled = false;
2272*5113495bSYour Name 
2273*5113495bSYour Name 	if (!vdev) {
2274*5113495bSYour Name 		mlo_err("invalid vdev");
2275*5113495bSYour Name 		goto done;
2276*5113495bSYour Name 	}
2277*5113495bSYour Name 	link_id = wlan_vdev_get_link_id(vdev);
2278*5113495bSYour Name 	mlo_dev_ctx = vdev->mlo_dev_ctx;
2279*5113495bSYour Name 	if (!mlo_dev_ctx) {
2280*5113495bSYour Name 		mlo_err("invalid mlo_dev_ctx");
2281*5113495bSYour Name 		goto done;
2282*5113495bSYour Name 	}
2283*5113495bSYour Name 	mlo_dev_lock_acquire(mlo_dev_ctx);
2284*5113495bSYour Name 	sta_ctx = mlo_dev_ctx->sta_ctx;
2285*5113495bSYour Name 	if (!sta_ctx) {
2286*5113495bSYour Name 		mlo_err("invalid sta_ctx");
2287*5113495bSYour Name 		goto rel_lock;
2288*5113495bSYour Name 	}
2289*5113495bSYour Name 
2290*5113495bSYour Name 	for (i = 0; i < QDF_ARRAY_SIZE(sta_ctx->mlo_csa_param); i++) {
2291*5113495bSYour Name 		if (link_id == sta_ctx->mlo_csa_param[i].link_id &&
2292*5113495bSYour Name 		    (sta_ctx->mlo_csa_param[i].valid_csa_param ||
2293*5113495bSYour Name 		     sta_ctx->mlo_csa_param[i].mlo_csa_synced))
2294*5113495bSYour Name 			break;
2295*5113495bSYour Name 	}
2296*5113495bSYour Name 
2297*5113495bSYour Name 	if (i >= QDF_ARRAY_SIZE(sta_ctx->mlo_csa_param)) {
2298*5113495bSYour Name 		mlo_debug("mlo csa synced does not happen before csa FW event");
2299*5113495bSYour Name 		goto rel_lock;
2300*5113495bSYour Name 	}
2301*5113495bSYour Name 	if (!sta_ctx->mlo_csa_param[i].csa_offload_event_recvd) {
2302*5113495bSYour Name 		sta_ctx->mlo_csa_param[i].csa_offload_event_recvd = true;
2303*5113495bSYour Name 		if (sta_ctx->mlo_csa_param[i].valid_csa_param &&
2304*5113495bSYour Name 		    !qdf_mem_cmp(&sta_ctx->mlo_csa_param[i].csa_param,
2305*5113495bSYour Name 				 csa_param, sizeof(*csa_param)))
2306*5113495bSYour Name 			handled = true;
2307*5113495bSYour Name 	}
2308*5113495bSYour Name 
2309*5113495bSYour Name rel_lock:
2310*5113495bSYour Name 	mlo_dev_lock_release(mlo_dev_ctx);
2311*5113495bSYour Name 
2312*5113495bSYour Name done:
2313*5113495bSYour Name 
2314*5113495bSYour Name 	return handled;
2315*5113495bSYour Name }
2316*5113495bSYour Name 
2317*5113495bSYour Name #ifdef WLAN_FEATURE_11BE_MLO_ADV_FEATURE
mlo_internal_disconnect_links(struct wlan_objmgr_vdev * vdev)2318*5113495bSYour Name void mlo_internal_disconnect_links(struct wlan_objmgr_vdev *vdev)
2319*5113495bSYour Name {
2320*5113495bSYour Name 	struct wlan_mlo_dev_context *mlo_dev_ctx = NULL;
2321*5113495bSYour Name 	struct wlan_mlo_sta *sta_ctx = NULL;
2322*5113495bSYour Name 	uint8_t i;
2323*5113495bSYour Name 	struct wlan_objmgr_vdev *assoc_vdev;
2324*5113495bSYour Name 	struct wlan_objmgr_vdev *wlan_vdev_list[WLAN_UMAC_MLO_MAX_VDEVS];
2325*5113495bSYour Name 	uint16_t vdev_count = 0;
2326*5113495bSYour Name 
2327*5113495bSYour Name 	if (!vdev)
2328*5113495bSYour Name 		return;
2329*5113495bSYour Name 
2330*5113495bSYour Name 	if (!wlan_vdev_mlme_is_assoc_sta_vdev(vdev) &&
2331*5113495bSYour Name 	    !wlan_mlo_mgr_is_link_switch_on_assoc_vdev(vdev)) {
2332*5113495bSYour Name 		mlo_debug("Not an assoc vdev, so ignore disconnect req");
2333*5113495bSYour Name 		return;
2334*5113495bSYour Name 	}
2335*5113495bSYour Name 
2336*5113495bSYour Name 	mlo_dev_ctx = vdev->mlo_dev_ctx;
2337*5113495bSYour Name 	if (mlo_dev_ctx) {
2338*5113495bSYour Name 		sta_ctx = mlo_dev_ctx->sta_ctx;
2339*5113495bSYour Name 	} else {
2340*5113495bSYour Name 		mlo_err("Invalid mlo_dev_ctx");
2341*5113495bSYour Name 		return;
2342*5113495bSYour Name 	}
2343*5113495bSYour Name 
2344*5113495bSYour Name 	if (sta_ctx) {
2345*5113495bSYour Name 		mlo_free_copied_conn_req(sta_ctx);
2346*5113495bSYour Name 	} else {
2347*5113495bSYour Name 		mlo_err("Invalid sta_ctx");
2348*5113495bSYour Name 		return;
2349*5113495bSYour Name 	}
2350*5113495bSYour Name 
2351*5113495bSYour Name 	if (sta_ctx->connect_req) {
2352*5113495bSYour Name 		wlan_cm_free_connect_req(sta_ctx->connect_req);
2353*5113495bSYour Name 		sta_ctx->connect_req = NULL;
2354*5113495bSYour Name 	}
2355*5113495bSYour Name 
2356*5113495bSYour Name 	assoc_vdev = mlo_get_assoc_link_vdev(mlo_dev_ctx);
2357*5113495bSYour Name 	if (!assoc_vdev) {
2358*5113495bSYour Name 		assoc_vdev = wlan_mlo_mgr_link_switch_get_assoc_vdev(vdev);
2359*5113495bSYour Name 		if (!assoc_vdev) {
2360*5113495bSYour Name 			mlo_debug("Couldn't get assoc vdev");
2361*5113495bSYour Name 			return;
2362*5113495bSYour Name 		}
2363*5113495bSYour Name 		mlo_release_vdev_ref(assoc_vdev);
2364*5113495bSYour Name 	}
2365*5113495bSYour Name 
2366*5113495bSYour Name 	mlo_sta_get_vdev_list(vdev, &vdev_count, wlan_vdev_list);
2367*5113495bSYour Name 	for (i =  0; i < vdev_count; i++) {
2368*5113495bSYour Name 		if (wlan_vdev_list[i] != assoc_vdev &&
2369*5113495bSYour Name 		    (wlan_cm_is_vdev_connected(wlan_vdev_list[i]) ||
2370*5113495bSYour Name 		     wlan_cm_is_vdev_connecting(wlan_vdev_list[i]) ||
2371*5113495bSYour Name 		     wlan_cm_is_vdev_idle_due_to_link_switch(wlan_vdev_list[i])))
2372*5113495bSYour Name 			wlan_cm_disconnect(wlan_vdev_list[i],
2373*5113495bSYour Name 					   CM_MLO_LINK_VDEV_DISCONNECT,
2374*5113495bSYour Name 					   REASON_UNSPEC_FAILURE,
2375*5113495bSYour Name 					   NULL);
2376*5113495bSYour Name 		mlo_release_vdev_ref(wlan_vdev_list[i]);
2377*5113495bSYour Name 	}
2378*5113495bSYour Name }
2379*5113495bSYour Name #else
mlo_internal_disconnect_links(struct wlan_objmgr_vdev * vdev)2380*5113495bSYour Name void mlo_internal_disconnect_links(struct wlan_objmgr_vdev *vdev)
2381*5113495bSYour Name {
2382*5113495bSYour Name }
2383*5113495bSYour Name #endif /* WLAN_FEATURE_11BE_MLO_ADV_FEATURE */
2384*5113495bSYour Name 
mlo_sta_get_vdev_list(struct wlan_objmgr_vdev * vdev,uint16_t * vdev_count,struct wlan_objmgr_vdev ** wlan_vdev_list)2385*5113495bSYour Name void mlo_sta_get_vdev_list(struct wlan_objmgr_vdev *vdev, uint16_t *vdev_count,
2386*5113495bSYour Name 			   struct wlan_objmgr_vdev **wlan_vdev_list)
2387*5113495bSYour Name {
2388*5113495bSYour Name 	struct wlan_mlo_dev_context *dev_ctx;
2389*5113495bSYour Name 	int i;
2390*5113495bSYour Name 	QDF_STATUS status;
2391*5113495bSYour Name 
2392*5113495bSYour Name 	*vdev_count = 0;
2393*5113495bSYour Name 
2394*5113495bSYour Name 	if (!vdev || !vdev->mlo_dev_ctx) {
2395*5113495bSYour Name 		mlo_err("Invalid input");
2396*5113495bSYour Name 		return;
2397*5113495bSYour Name 	}
2398*5113495bSYour Name 
2399*5113495bSYour Name 	dev_ctx = vdev->mlo_dev_ctx;
2400*5113495bSYour Name 
2401*5113495bSYour Name 	mlo_dev_lock_acquire(dev_ctx);
2402*5113495bSYour Name 	*vdev_count = 0;
2403*5113495bSYour Name 	for (i = 0; i < QDF_ARRAY_SIZE(dev_ctx->wlan_vdev_list); i++) {
2404*5113495bSYour Name 		if (dev_ctx->wlan_vdev_list[i]) {
2405*5113495bSYour Name 			status =
2406*5113495bSYour Name 			wlan_objmgr_vdev_try_get_ref(dev_ctx->wlan_vdev_list[i],
2407*5113495bSYour Name 						     WLAN_MLO_MGR_ID);
2408*5113495bSYour Name 			if (QDF_IS_STATUS_ERROR(status))
2409*5113495bSYour Name 				break;
2410*5113495bSYour Name 			wlan_vdev_list[*vdev_count] =
2411*5113495bSYour Name 				dev_ctx->wlan_vdev_list[i];
2412*5113495bSYour Name 			(*vdev_count) += 1;
2413*5113495bSYour Name 		}
2414*5113495bSYour Name 	}
2415*5113495bSYour Name 	mlo_dev_lock_release(dev_ctx);
2416*5113495bSYour Name }
2417*5113495bSYour Name 
mlo_sta_vdev_get_reconfig_timer_state(struct wlan_objmgr_vdev * vdev)2418*5113495bSYour Name bool mlo_sta_vdev_get_reconfig_timer_state(struct wlan_objmgr_vdev *vdev)
2419*5113495bSYour Name {
2420*5113495bSYour Name 	struct vdev_mlme_obj *vdev_mlme;
2421*5113495bSYour Name 
2422*5113495bSYour Name 	if (!vdev || !mlo_is_mld_sta(vdev))
2423*5113495bSYour Name 		return false;
2424*5113495bSYour Name 
2425*5113495bSYour Name 	vdev_mlme = wlan_vdev_mlme_get_cmpt_obj(vdev);
2426*5113495bSYour Name 	if (!vdev_mlme) {
2427*5113495bSYour Name 		mlo_err("vdev mlme is null");
2428*5113495bSYour Name 		return false;
2429*5113495bSYour Name 	}
2430*5113495bSYour Name 
2431*5113495bSYour Name 	return vdev_mlme->ml_reconfig_started;
2432*5113495bSYour Name }
2433*5113495bSYour Name 
mlo_sta_stop_reconfig_timer_by_vdev(struct wlan_objmgr_vdev * vdev)2434*5113495bSYour Name void mlo_sta_stop_reconfig_timer_by_vdev(struct wlan_objmgr_vdev *vdev)
2435*5113495bSYour Name {
2436*5113495bSYour Name 	struct vdev_mlme_obj *vdev_mlme;
2437*5113495bSYour Name 
2438*5113495bSYour Name 	if (!vdev || !mlo_is_mld_sta(vdev))
2439*5113495bSYour Name 		return;
2440*5113495bSYour Name 
2441*5113495bSYour Name 	vdev_mlme = wlan_vdev_mlme_get_cmpt_obj(vdev);
2442*5113495bSYour Name 	if (!vdev_mlme) {
2443*5113495bSYour Name 		mlo_err("vdev mlme is null");
2444*5113495bSYour Name 		return;
2445*5113495bSYour Name 	}
2446*5113495bSYour Name 
2447*5113495bSYour Name 	if (!vdev_mlme->ml_reconfig_started)
2448*5113495bSYour Name 		return;
2449*5113495bSYour Name 
2450*5113495bSYour Name 	qdf_timer_stop(&vdev_mlme->ml_reconfig_timer);
2451*5113495bSYour Name 
2452*5113495bSYour Name 	mlo_debug("vdev %d reconfig timer active to stop",
2453*5113495bSYour Name 		  wlan_vdev_get_id(vdev));
2454*5113495bSYour Name 	vdev_mlme->ml_reconfig_started = false;
2455*5113495bSYour Name }
2456*5113495bSYour Name 
mlo_sta_stop_reconfig_timer(struct wlan_objmgr_vdev * vdev)2457*5113495bSYour Name void mlo_sta_stop_reconfig_timer(struct wlan_objmgr_vdev *vdev)
2458*5113495bSYour Name {
2459*5113495bSYour Name 	struct wlan_objmgr_vdev *wlan_vdev_list[WLAN_UMAC_MLO_MAX_VDEVS] = {0};
2460*5113495bSYour Name 	uint16_t vdev_count = 0;
2461*5113495bSYour Name 	uint8_t i;
2462*5113495bSYour Name 
2463*5113495bSYour Name 	if (!vdev || !mlo_is_mld_sta(vdev))
2464*5113495bSYour Name 		return;
2465*5113495bSYour Name 
2466*5113495bSYour Name 	mlo_get_ml_vdev_list(vdev, &vdev_count, wlan_vdev_list);
2467*5113495bSYour Name 	if (!vdev_count) {
2468*5113495bSYour Name 		mlo_err("vdev num 0 in mld dev");
2469*5113495bSYour Name 		return;
2470*5113495bSYour Name 	}
2471*5113495bSYour Name 
2472*5113495bSYour Name 	for (i = 0; i < vdev_count; i++) {
2473*5113495bSYour Name 		if (!wlan_vdev_list[i]) {
2474*5113495bSYour Name 			mlo_err("vdev is null in mld");
2475*5113495bSYour Name 			goto release_ref;
2476*5113495bSYour Name 		}
2477*5113495bSYour Name 		mlo_sta_stop_reconfig_timer_by_vdev(wlan_vdev_list[i]);
2478*5113495bSYour Name 	}
2479*5113495bSYour Name 
2480*5113495bSYour Name release_ref:
2481*5113495bSYour Name 	for (i = 0; i < vdev_count; i++)
2482*5113495bSYour Name 		mlo_release_vdev_ref(wlan_vdev_list[i]);
2483*5113495bSYour Name }
2484*5113495bSYour Name 
2485*5113495bSYour Name #ifdef WLAN_FEATURE_11BE_MLO_ADV_FEATURE
mlo_defer_set_keys(struct wlan_objmgr_vdev * vdev,uint8_t link_id,bool value)2486*5113495bSYour Name void mlo_defer_set_keys(struct wlan_objmgr_vdev *vdev,
2487*5113495bSYour Name 			uint8_t link_id, bool value)
2488*5113495bSYour Name {
2489*5113495bSYour Name 	struct wlan_mlo_sta *sta_ctx;
2490*5113495bSYour Name 	uint8_t link_iter;
2491*5113495bSYour Name 
2492*5113495bSYour Name 	if (!vdev || !vdev->mlo_dev_ctx)
2493*5113495bSYour Name 		return;
2494*5113495bSYour Name 
2495*5113495bSYour Name 	sta_ctx = vdev->mlo_dev_ctx->sta_ctx;
2496*5113495bSYour Name 	if (!sta_ctx)
2497*5113495bSYour Name 		return;
2498*5113495bSYour Name 	if (value) {
2499*5113495bSYour Name 		for (link_iter = 0; link_iter < WLAN_MAX_ML_BSS_LINKS;
2500*5113495bSYour Name 		     link_iter++) {
2501*5113495bSYour Name 			if (sta_ctx->key_mgmt[link_iter].keys_saved &&
2502*5113495bSYour Name 			    sta_ctx->key_mgmt[link_iter].link_id == link_id)
2503*5113495bSYour Name 				return;
2504*5113495bSYour Name 		}
2505*5113495bSYour Name 
2506*5113495bSYour Name 		for (link_iter = 0; link_iter < WLAN_MAX_ML_BSS_LINKS;
2507*5113495bSYour Name 		     link_iter++) {
2508*5113495bSYour Name 			if (!sta_ctx->key_mgmt[link_iter].keys_saved) {
2509*5113495bSYour Name 				sta_ctx->key_mgmt[link_iter].link_id = link_id;
2510*5113495bSYour Name 				sta_ctx->key_mgmt[link_iter].keys_saved = true;
2511*5113495bSYour Name 				mlo_debug("set key link id %d value %d iter %d",
2512*5113495bSYour Name 					  link_id, value, link_iter);
2513*5113495bSYour Name 				return;
2514*5113495bSYour Name 			}
2515*5113495bSYour Name 		}
2516*5113495bSYour Name 	} else {
2517*5113495bSYour Name 		for (link_iter = 0; link_iter < WLAN_MAX_ML_BSS_LINKS;
2518*5113495bSYour Name 		     link_iter++) {
2519*5113495bSYour Name 			if (sta_ctx->key_mgmt[link_iter].link_id == link_id) {
2520*5113495bSYour Name 				sta_ctx->key_mgmt[link_iter].keys_saved = false;
2521*5113495bSYour Name 				mlo_debug("set key link id %d value %d iter %d",
2522*5113495bSYour Name 					  link_id, value, link_iter);
2523*5113495bSYour Name 				return;
2524*5113495bSYour Name 			}
2525*5113495bSYour Name 		}
2526*5113495bSYour Name 	}
2527*5113495bSYour Name }
2528*5113495bSYour Name 
mlo_is_set_key_defered(struct wlan_objmgr_vdev * vdev,uint8_t link_id)2529*5113495bSYour Name bool mlo_is_set_key_defered(struct wlan_objmgr_vdev *vdev,
2530*5113495bSYour Name 			    uint8_t link_id)
2531*5113495bSYour Name {
2532*5113495bSYour Name 	struct wlan_mlo_sta *sta_ctx;
2533*5113495bSYour Name 	uint8_t link_iter;
2534*5113495bSYour Name 
2535*5113495bSYour Name 	if (!vdev || !vdev->mlo_dev_ctx)
2536*5113495bSYour Name 		return false;
2537*5113495bSYour Name 
2538*5113495bSYour Name 	sta_ctx = vdev->mlo_dev_ctx->sta_ctx;
2539*5113495bSYour Name 	if (!sta_ctx)
2540*5113495bSYour Name 		return false;
2541*5113495bSYour Name 
2542*5113495bSYour Name 	for (link_iter = 0; link_iter < WLAN_MAX_ML_BSS_LINKS;
2543*5113495bSYour Name 	     link_iter++) {
2544*5113495bSYour Name 		if (sta_ctx->key_mgmt[link_iter].link_id == link_id)
2545*5113495bSYour Name 			return sta_ctx->key_mgmt[link_iter].keys_saved;
2546*5113495bSYour Name 	}
2547*5113495bSYour Name 	return false;
2548*5113495bSYour Name }
2549*5113495bSYour Name #endif
2550*5113495bSYour Name 
2551*5113495bSYour Name static uint16_t
mlo_get_bcn_interval_by_bssid(struct wlan_objmgr_pdev * pdev,uint8_t * bssid)2552*5113495bSYour Name mlo_get_bcn_interval_by_bssid(struct wlan_objmgr_pdev *pdev,
2553*5113495bSYour Name 			      uint8_t *bssid)
2554*5113495bSYour Name {
2555*5113495bSYour Name 	struct scan_filter *scan_filter;
2556*5113495bSYour Name 	uint16_t bcn_int = 0;
2557*5113495bSYour Name 	qdf_list_t *list = NULL;
2558*5113495bSYour Name 	struct scan_cache_node *first_node = NULL;
2559*5113495bSYour Name 	qdf_list_node_t *cur_node = NULL;
2560*5113495bSYour Name 
2561*5113495bSYour Name 	scan_filter = qdf_mem_malloc(sizeof(*scan_filter));
2562*5113495bSYour Name 	if (!scan_filter)
2563*5113495bSYour Name 		return bcn_int;
2564*5113495bSYour Name 
2565*5113495bSYour Name 	scan_filter->num_of_bssid = 1;
2566*5113495bSYour Name 	qdf_mem_copy(scan_filter->bssid_list[0].bytes,
2567*5113495bSYour Name 		     bssid, sizeof(struct qdf_mac_addr));
2568*5113495bSYour Name 	list = wlan_scan_get_result(pdev, scan_filter);
2569*5113495bSYour Name 	qdf_mem_free(scan_filter);
2570*5113495bSYour Name 
2571*5113495bSYour Name 	if (!list || (list && !qdf_list_size(list))) {
2572*5113495bSYour Name 		mlo_debug("scan list empty");
2573*5113495bSYour Name 		goto error;
2574*5113495bSYour Name 	}
2575*5113495bSYour Name 
2576*5113495bSYour Name 	qdf_list_peek_front(list, &cur_node);
2577*5113495bSYour Name 	first_node = qdf_container_of(cur_node,
2578*5113495bSYour Name 				      struct scan_cache_node,
2579*5113495bSYour Name 				      node);
2580*5113495bSYour Name 	if (first_node && first_node->entry)
2581*5113495bSYour Name 		bcn_int = first_node->entry->bcn_int;
2582*5113495bSYour Name error:
2583*5113495bSYour Name 	if (list)
2584*5113495bSYour Name 		wlan_scan_purge_results(list);
2585*5113495bSYour Name 
2586*5113495bSYour Name 	return bcn_int;
2587*5113495bSYour Name }
2588*5113495bSYour Name 
2589*5113495bSYour Name #ifdef QCA_SUPPORT_PRIMARY_LINK_MIGRATE
2590*5113495bSYour Name static QDF_STATUS
mlo_sta_handle_ptqm_migration(struct wlan_objmgr_vdev * removal_vdev)2591*5113495bSYour Name mlo_sta_handle_ptqm_migration(struct wlan_objmgr_vdev *removal_vdev)
2592*5113495bSYour Name {
2593*5113495bSYour Name 	struct wlan_objmgr_peer *bss_peer;
2594*5113495bSYour Name 
2595*5113495bSYour Name 	if (!wlan_cm_is_vdev_connected(removal_vdev))
2596*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
2597*5113495bSYour Name 
2598*5113495bSYour Name 	bss_peer = wlan_vdev_get_bsspeer(removal_vdev);
2599*5113495bSYour Name 	if (!bss_peer)
2600*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
2601*5113495bSYour Name 
2602*5113495bSYour Name 	/* Invoke migration only if the link being removed is the primary */
2603*5113495bSYour Name 	if (wlan_mlo_peer_get_primary_peer_link_id(bss_peer)
2604*5113495bSYour Name 		!= wlan_vdev_get_link_id(removal_vdev))
2605*5113495bSYour Name 		return QDF_STATUS_SUCCESS;
2606*5113495bSYour Name 
2607*5113495bSYour Name 	return wlan_mlo_set_ptqm_migration(removal_vdev, bss_peer->mlo_peer_ctx,
2608*5113495bSYour Name 					   false, WLAN_LINK_ID_INVALID, true);
2609*5113495bSYour Name }
2610*5113495bSYour Name #else
2611*5113495bSYour Name static QDF_STATUS
mlo_sta_handle_ptqm_migration(struct wlan_objmgr_vdev * removal_vdev)2612*5113495bSYour Name mlo_sta_handle_ptqm_migration(struct wlan_objmgr_vdev *removal_vdev)
2613*5113495bSYour Name {
2614*5113495bSYour Name 	return QDF_STATUS_SUCCESS;
2615*5113495bSYour Name }
2616*5113495bSYour Name #endif
2617*5113495bSYour Name 
mlo_process_link_remove(struct wlan_objmgr_vdev * vdev,struct ml_rv_partner_link_info * link_info)2618*5113495bSYour Name static void mlo_process_link_remove(struct wlan_objmgr_vdev *vdev,
2619*5113495bSYour Name 				    struct ml_rv_partner_link_info *link_info)
2620*5113495bSYour Name {
2621*5113495bSYour Name 	struct vdev_mlme_obj *vdev_mlme = NULL;
2622*5113495bSYour Name 	struct wlan_objmgr_peer *bss_peer = NULL;
2623*5113495bSYour Name 	uint16_t bcn_int = 0;
2624*5113495bSYour Name 	uint16_t tbtt_count = 0;
2625*5113495bSYour Name 	QDF_STATUS status;
2626*5113495bSYour Name 
2627*5113495bSYour Name 	vdev_mlme = wlan_vdev_mlme_get_cmpt_obj(vdev);
2628*5113495bSYour Name 	if (!vdev_mlme)
2629*5113495bSYour Name 		return;
2630*5113495bSYour Name 
2631*5113495bSYour Name 	bss_peer = wlan_vdev_get_bsspeer(vdev);
2632*5113495bSYour Name 	if (!bss_peer)
2633*5113495bSYour Name 		return;
2634*5113495bSYour Name 
2635*5113495bSYour Name 	/* Link delete triggered from AP,
2636*5113495bSYour Name 	 * start timer with tbtt count * beacon interval
2637*5113495bSYour Name 	 */
2638*5113495bSYour Name 	tbtt_count = link_info->ap_removal_timer;
2639*5113495bSYour Name 	bcn_int = mlo_get_bcn_interval_by_bssid(
2640*5113495bSYour Name 			wlan_vdev_get_pdev(vdev),
2641*5113495bSYour Name 			wlan_peer_get_macaddr(bss_peer));
2642*5113495bSYour Name 	if (!bcn_int)
2643*5113495bSYour Name 		return;
2644*5113495bSYour Name 
2645*5113495bSYour Name 	if (vdev_mlme->ops &&
2646*5113495bSYour Name 	    vdev_mlme->ops->mlme_vdev_reconfig_notify) {
2647*5113495bSYour Name 		status = vdev_mlme->ops->mlme_vdev_reconfig_notify(
2648*5113495bSYour Name 				vdev_mlme, &tbtt_count, bcn_int);
2649*5113495bSYour Name 		if (QDF_IS_STATUS_ERROR(status))
2650*5113495bSYour Name 			return;
2651*5113495bSYour Name 	}
2652*5113495bSYour Name 
2653*5113495bSYour Name 	/* Handle PTQM migration upon seeing AP removal for the first time */
2654*5113495bSYour Name 	if (!vdev_mlme->ml_reconfig_started)
2655*5113495bSYour Name 		mlo_sta_handle_ptqm_migration(vdev);
2656*5113495bSYour Name 
2657*5113495bSYour Name 	vdev_mlme->ml_reconfig_started = true;
2658*5113495bSYour Name 	qdf_timer_mod(&vdev_mlme->ml_reconfig_timer,
2659*5113495bSYour Name 		      qdf_time_uint_to_ms(tbtt_count * bcn_int));
2660*5113495bSYour Name }
2661*5113495bSYour Name 
2662*5113495bSYour Name #ifdef WLAN_FEATURE_11BE_MLO_ADV_FEATURE
2663*5113495bSYour Name static inline
mlo_process_link_add(struct wlan_objmgr_psoc * psoc,struct wlan_objmgr_vdev * vdev,struct mlo_partner_info * cache_partner_info,struct mlo_partner_info * partner_info,uint16_t vdev_count)2664*5113495bSYour Name QDF_STATUS mlo_process_link_add(struct wlan_objmgr_psoc *psoc,
2665*5113495bSYour Name 				struct wlan_objmgr_vdev *vdev,
2666*5113495bSYour Name 				struct mlo_partner_info *cache_partner_info,
2667*5113495bSYour Name 				struct mlo_partner_info *partner_info,
2668*5113495bSYour Name 				uint16_t vdev_count)
2669*5113495bSYour Name {
2670*5113495bSYour Name 	return QDF_STATUS_E_INVAL;
2671*5113495bSYour Name }
2672*5113495bSYour Name #else
2673*5113495bSYour Name static
mlo_process_link_add(struct wlan_objmgr_psoc * psoc,struct wlan_objmgr_vdev * vdev,struct mlo_partner_info * cache_partner_info,struct mlo_partner_info * partner_info,uint16_t vdev_count)2674*5113495bSYour Name QDF_STATUS mlo_process_link_add(struct wlan_objmgr_psoc *psoc,
2675*5113495bSYour Name 				struct wlan_objmgr_vdev *vdev,
2676*5113495bSYour Name 				struct mlo_partner_info *cache_partner_info,
2677*5113495bSYour Name 				struct mlo_partner_info *partner_info,
2678*5113495bSYour Name 				uint16_t vdev_count)
2679*5113495bSYour Name {
2680*5113495bSYour Name 	struct wlan_mlo_dev_context *ml_ctx = vdev->mlo_dev_ctx;
2681*5113495bSYour Name 
2682*5113495bSYour Name 	/* Check if ini to support dynamic link add is enable
2683*5113495bSYour Name 	 * or not
2684*5113495bSYour Name 	 */
2685*5113495bSYour Name 	if (!mlme_mlo_is_reconfig_reassoc_enable(psoc)) {
2686*5113495bSYour Name 		mlo_debug("ML Reconfig link add support disabled");
2687*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
2688*5113495bSYour Name 	}
2689*5113495bSYour Name 
2690*5113495bSYour Name 	if (vdev_count == ml_ctx->wlan_vdev_count) {
2691*5113495bSYour Name 		/* All links are participating in current ML connection */
2692*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
2693*5113495bSYour Name 	}
2694*5113495bSYour Name 
2695*5113495bSYour Name 	/* check if any new link in scan entry */
2696*5113495bSYour Name 	if (partner_info->num_partner_links ==
2697*5113495bSYour Name 	    cache_partner_info->num_partner_links) {
2698*5113495bSYour Name 		if (!qdf_mem_cmp(cache_partner_info, partner_info,
2699*5113495bSYour Name 				 sizeof(struct mlo_partner_info))) {
2700*5113495bSYour Name 			mlo_debug("No new link found");
2701*5113495bSYour Name 			return QDF_STATUS_E_INVAL;
2702*5113495bSYour Name 		}
2703*5113495bSYour Name 	}
2704*5113495bSYour Name 
2705*5113495bSYour Name 	/* mlo connected on all links already */
2706*5113495bSYour Name 	if (partner_info->num_partner_links <= (vdev_count - 1))
2707*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
2708*5113495bSYour Name 
2709*5113495bSYour Name 	/* Partner info changed compared to the cached scan entry.
2710*5113495bSYour Name 	 * Process link add
2711*5113495bSYour Name 	 */
2712*5113495bSYour Name 	mlo_err("Link addition detected, issue disconnect");
2713*5113495bSYour Name 	mlo_disconnect(vdev, CM_SB_DISCONNECT,
2714*5113495bSYour Name 		       REASON_UNSPEC_FAILURE, NULL);
2715*5113495bSYour Name 	return QDF_STATUS_SUCCESS;
2716*5113495bSYour Name }
2717*5113495bSYour Name #endif
2718*5113495bSYour Name 
mlo_process_ml_reconfig_ie(struct wlan_objmgr_vdev * vdev,struct scan_cache_entry * scan_entry,uint8_t * ml_ie,qdf_size_t ml_ie_len,struct mlo_partner_info * partner_info)2719*5113495bSYour Name void mlo_process_ml_reconfig_ie(struct wlan_objmgr_vdev *vdev,
2720*5113495bSYour Name 				struct scan_cache_entry *scan_entry,
2721*5113495bSYour Name 				uint8_t *ml_ie, qdf_size_t ml_ie_len,
2722*5113495bSYour Name 				struct mlo_partner_info *partner_info)
2723*5113495bSYour Name {
2724*5113495bSYour Name 	struct wlan_objmgr_psoc *psoc = NULL;
2725*5113495bSYour Name 	struct wlan_objmgr_pdev *pdev = NULL;
2726*5113495bSYour Name 	struct wlan_objmgr_vdev *co_mld_vdev = NULL;
2727*5113495bSYour Name 	struct wlan_objmgr_vdev *wlan_vdev_list[WLAN_UMAC_MLO_MAX_VDEVS] = {NULL};
2728*5113495bSYour Name 	uint16_t vdev_count = 0;
2729*5113495bSYour Name 	uint8_t idx = 0;
2730*5113495bSYour Name 	uint8_t i = 0;
2731*5113495bSYour Name 	uint8_t link_ix = 0;
2732*5113495bSYour Name 	struct ml_rv_info reconfig_info = {0};
2733*5113495bSYour Name 	struct mlo_partner_info ml_partner_info = {0};
2734*5113495bSYour Name 	uint8_t *ml_rv_ie = NULL;
2735*5113495bSYour Name 	qdf_size_t ml_rv_ie_len = 0;
2736*5113495bSYour Name 	QDF_STATUS status = QDF_STATUS_SUCCESS;
2737*5113495bSYour Name 
2738*5113495bSYour Name 	if (!vdev || !mlo_is_mld_sta(vdev))
2739*5113495bSYour Name 		return;
2740*5113495bSYour Name 
2741*5113495bSYour Name 	pdev = wlan_vdev_get_pdev(vdev);
2742*5113495bSYour Name 	if (!pdev)
2743*5113495bSYour Name 		return;
2744*5113495bSYour Name 
2745*5113495bSYour Name 	psoc = wlan_pdev_get_psoc(pdev);
2746*5113495bSYour Name 	if (!psoc)
2747*5113495bSYour Name 		return;
2748*5113495bSYour Name 
2749*5113495bSYour Name 	mlo_get_ml_vdev_list(vdev, &vdev_count, wlan_vdev_list);
2750*5113495bSYour Name 	if (!vdev_count) {
2751*5113495bSYour Name 		mlo_debug("Number of VDEVs under MLD is reported as 0");
2752*5113495bSYour Name 		return;
2753*5113495bSYour Name 	}
2754*5113495bSYour Name 
2755*5113495bSYour Name 	if (!scan_entry ||
2756*5113495bSYour Name 	    QDF_IS_STATUS_ERROR(util_scan_get_ml_partner_info(scan_entry,
2757*5113495bSYour Name 							      &ml_partner_info))) {
2758*5113495bSYour Name 		mlo_debug("Unable to fetch the partner info in scan db");
2759*5113495bSYour Name 		goto check_ml_rv;
2760*5113495bSYour Name 	}
2761*5113495bSYour Name 
2762*5113495bSYour Name 	/* Processing for link add */
2763*5113495bSYour Name 	if (QDF_IS_STATUS_SUCCESS(mlo_process_link_add(psoc, vdev,
2764*5113495bSYour Name 						       partner_info,
2765*5113495bSYour Name 						       &ml_partner_info,
2766*5113495bSYour Name 						       vdev_count))) {
2767*5113495bSYour Name 		mlo_err("Issued MLD disconnect for link add");
2768*5113495bSYour Name 		goto err_release_refs;
2769*5113495bSYour Name 	}
2770*5113495bSYour Name 
2771*5113495bSYour Name check_ml_rv:
2772*5113495bSYour Name 	/* Processing for ML Reconfig IE */
2773*5113495bSYour Name 	if (vdev_count == 1) {
2774*5113495bSYour Name 		/* Single link MLO, no need to process link delete */
2775*5113495bSYour Name 		goto err_release_refs;
2776*5113495bSYour Name 	}
2777*5113495bSYour Name 
2778*5113495bSYour Name 	status = util_find_mlie_by_variant(ml_ie,
2779*5113495bSYour Name 					   ml_ie_len,
2780*5113495bSYour Name 					   &ml_rv_ie,
2781*5113495bSYour Name 					   &ml_rv_ie_len,
2782*5113495bSYour Name 					   WLAN_ML_VARIANT_RECONFIG);
2783*5113495bSYour Name 	if (QDF_IS_STATUS_ERROR(status) || !ml_rv_ie) {
2784*5113495bSYour Name 		mlo_debug("ML IE for reconfig variant not found");
2785*5113495bSYour Name 		goto err_release_refs;
2786*5113495bSYour Name 	}
2787*5113495bSYour Name 
2788*5113495bSYour Name 	status = util_get_rvmlie_persta_link_info(ml_rv_ie, ml_rv_ie_len,
2789*5113495bSYour Name 						  &reconfig_info);
2790*5113495bSYour Name 	if (QDF_IS_STATUS_ERROR(status)) {
2791*5113495bSYour Name 		mlo_err("Unable to get persta link info from ML RV IE");
2792*5113495bSYour Name 		goto err_release_refs;
2793*5113495bSYour Name 	}
2794*5113495bSYour Name 
2795*5113495bSYour Name 	if (!reconfig_info.num_links) {
2796*5113495bSYour Name 		mlo_err("No. of links is 0 in ML reconfig IE");
2797*5113495bSYour Name 		goto err_release_refs;
2798*5113495bSYour Name 	}
2799*5113495bSYour Name 
2800*5113495bSYour Name 	for (idx = 0; idx < vdev_count; idx++) {
2801*5113495bSYour Name 		co_mld_vdev = wlan_vdev_list[idx];
2802*5113495bSYour Name 		if (!co_mld_vdev) {
2803*5113495bSYour Name 			mlo_debug("VDEV in MLD VDEV list is NULL");
2804*5113495bSYour Name 			goto err_release_refs;
2805*5113495bSYour Name 		}
2806*5113495bSYour Name 
2807*5113495bSYour Name 		link_ix = wlan_vdev_get_link_id(co_mld_vdev);
2808*5113495bSYour Name 		for (i = 0; i < reconfig_info.num_links; i++) {
2809*5113495bSYour Name 			if (link_ix == reconfig_info.link_info[i].link_id)
2810*5113495bSYour Name 				mlo_process_link_remove(co_mld_vdev,
2811*5113495bSYour Name 							&reconfig_info.link_info[i]);
2812*5113495bSYour Name 		}
2813*5113495bSYour Name 	}
2814*5113495bSYour Name 
2815*5113495bSYour Name 	mlo_sta_handle_link_reconfig_standby_link(vdev, &reconfig_info);
2816*5113495bSYour Name 
2817*5113495bSYour Name err_release_refs:
2818*5113495bSYour Name 
2819*5113495bSYour Name 	for (i = 0; i < vdev_count; i++)
2820*5113495bSYour Name 		mlo_release_vdev_ref(wlan_vdev_list[i]);
2821*5113495bSYour Name }
2822*5113495bSYour Name 
2823*5113495bSYour Name QDF_STATUS
mlo_get_link_state_context(struct wlan_objmgr_psoc * psoc,get_ml_link_state_cb * resp_cb,void ** context,uint8_t vdev_id)2824*5113495bSYour Name mlo_get_link_state_context(struct wlan_objmgr_psoc *psoc,
2825*5113495bSYour Name 			   get_ml_link_state_cb *resp_cb,
2826*5113495bSYour Name 			   void **context, uint8_t vdev_id)
2827*5113495bSYour Name {
2828*5113495bSYour Name 	struct wlan_mlo_dev_context *mlo_ctx;
2829*5113495bSYour Name 	struct wlan_mlo_sta *sta_ctx = NULL;
2830*5113495bSYour Name 	struct wlan_objmgr_vdev *vdev;
2831*5113495bSYour Name 
2832*5113495bSYour Name 	vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, vdev_id,
2833*5113495bSYour Name 						    WLAN_MLO_MGR_ID);
2834*5113495bSYour Name 	if (!vdev)
2835*5113495bSYour Name 		return QDF_STATUS_E_NULL_VALUE;
2836*5113495bSYour Name 
2837*5113495bSYour Name 	if (!wlan_vdev_mlme_is_mlo_vdev(vdev)) {
2838*5113495bSYour Name 		wlan_objmgr_vdev_release_ref(vdev, WLAN_MLO_MGR_ID);
2839*5113495bSYour Name 		return QDF_STATUS_E_NULL_VALUE;
2840*5113495bSYour Name 	}
2841*5113495bSYour Name 
2842*5113495bSYour Name 	mlo_ctx = vdev->mlo_dev_ctx;
2843*5113495bSYour Name 
2844*5113495bSYour Name 	if (!mlo_ctx) {
2845*5113495bSYour Name 		mlo_err("null mlo_dev_ctx");
2846*5113495bSYour Name 		wlan_objmgr_vdev_release_ref(vdev, WLAN_MLO_MGR_ID);
2847*5113495bSYour Name 		return QDF_STATUS_E_NULL_VALUE;
2848*5113495bSYour Name 	}
2849*5113495bSYour Name 
2850*5113495bSYour Name 	sta_ctx = mlo_ctx->sta_ctx;
2851*5113495bSYour Name 
2852*5113495bSYour Name 	if (!sta_ctx) {
2853*5113495bSYour Name 		wlan_objmgr_vdev_release_ref(vdev, WLAN_MLO_MGR_ID);
2854*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
2855*5113495bSYour Name 	}
2856*5113495bSYour Name 
2857*5113495bSYour Name 	mlo_dev_lock_acquire(mlo_ctx);
2858*5113495bSYour Name 	*resp_cb = sta_ctx->ml_link_state.ml_link_state_resp_cb;
2859*5113495bSYour Name 	*context = sta_ctx->ml_link_state.ml_link_state_req_context;
2860*5113495bSYour Name 
2861*5113495bSYour Name 	mlo_dev_lock_release(mlo_ctx);
2862*5113495bSYour Name 	wlan_objmgr_vdev_release_ref(vdev, WLAN_MLO_MGR_ID);
2863*5113495bSYour Name 	return QDF_STATUS_SUCCESS;
2864*5113495bSYour Name }
2865*5113495bSYour Name 
2866*5113495bSYour Name void
wlan_mlo_send_vdev_pause(struct wlan_objmgr_psoc * psoc,struct wlan_objmgr_vdev * vdev,uint16_t session_id,uint16_t vdev_pause_dur)2867*5113495bSYour Name wlan_mlo_send_vdev_pause(struct wlan_objmgr_psoc *psoc,
2868*5113495bSYour Name 			 struct wlan_objmgr_vdev *vdev,
2869*5113495bSYour Name 			 uint16_t session_id,
2870*5113495bSYour Name 			 uint16_t vdev_pause_dur)
2871*5113495bSYour Name {
2872*5113495bSYour Name 	struct wlan_lmac_if_mlo_tx_ops *mlo_tx_ops;
2873*5113495bSYour Name 	struct mlo_vdev_pause vdev_pause_info;
2874*5113495bSYour Name 	QDF_STATUS status = QDF_STATUS_E_FAILURE;
2875*5113495bSYour Name 
2876*5113495bSYour Name 	mlo_tx_ops = &psoc->soc_cb.tx_ops->mlo_ops;
2877*5113495bSYour Name 	if (!mlo_tx_ops) {
2878*5113495bSYour Name 		mlo_err("tx_ops is null!");
2879*5113495bSYour Name 		return;
2880*5113495bSYour Name 	}
2881*5113495bSYour Name 
2882*5113495bSYour Name 	if (!mlo_tx_ops->send_vdev_pause) {
2883*5113495bSYour Name 		mlo_err("send_vdev_pause is null");
2884*5113495bSYour Name 		return;
2885*5113495bSYour Name 	}
2886*5113495bSYour Name 
2887*5113495bSYour Name 	vdev_pause_info.vdev_id = session_id;
2888*5113495bSYour Name 	vdev_pause_info.vdev_pause_duration = vdev_pause_dur;
2889*5113495bSYour Name 	status = mlo_tx_ops->send_vdev_pause(psoc, &vdev_pause_info);
2890*5113495bSYour Name 	if (QDF_IS_STATUS_ERROR(status))
2891*5113495bSYour Name 		mlo_err("Failed to send vdev pause to FW");
2892*5113495bSYour Name }
2893*5113495bSYour Name 
2894*5113495bSYour Name #ifdef WLAN_FEATURE_11BE_MLO_ADV_FEATURE
mlo_is_any_link_disconnecting(struct wlan_objmgr_vdev * vdev)2895*5113495bSYour Name bool mlo_is_any_link_disconnecting(struct wlan_objmgr_vdev *vdev)
2896*5113495bSYour Name {
2897*5113495bSYour Name 	struct wlan_objmgr_vdev *wlan_vdev_list[WLAN_UMAC_MLO_MAX_VDEVS];
2898*5113495bSYour Name 	uint16_t vdev_count = 0, i;
2899*5113495bSYour Name 	bool status = false;
2900*5113495bSYour Name 
2901*5113495bSYour Name 	if (!vdev)
2902*5113495bSYour Name 		return status;
2903*5113495bSYour Name 
2904*5113495bSYour Name 	mlo_sta_get_vdev_list(vdev, &vdev_count, wlan_vdev_list);
2905*5113495bSYour Name 	for (i =  0; i < vdev_count; i++) {
2906*5113495bSYour Name 		if (!status && wlan_cm_is_vdev_disconnecting(wlan_vdev_list[i]))
2907*5113495bSYour Name 			status = true;
2908*5113495bSYour Name 		mlo_release_vdev_ref(wlan_vdev_list[i]);
2909*5113495bSYour Name 	}
2910*5113495bSYour Name 
2911*5113495bSYour Name 	return status;
2912*5113495bSYour Name }
2913*5113495bSYour Name 
2914*5113495bSYour Name QDF_STATUS
mlo_set_chan_switch_in_progress(struct wlan_objmgr_vdev * vdev,bool val)2915*5113495bSYour Name mlo_set_chan_switch_in_progress(struct wlan_objmgr_vdev *vdev, bool val)
2916*5113495bSYour Name {
2917*5113495bSYour Name 	struct wlan_mlo_dev_context *mlo_dev_ctx = vdev->mlo_dev_ctx;
2918*5113495bSYour Name 
2919*5113495bSYour Name 	if (!mlo_dev_ctx || !mlo_dev_ctx->sta_ctx)
2920*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
2921*5113495bSYour Name 
2922*5113495bSYour Name 	mlo_dev_ctx->sta_ctx->ml_chan_switch_in_progress = val;
2923*5113495bSYour Name 	mlo_debug("Set ml_chan_switch_in_progress: %d vdev %d",
2924*5113495bSYour Name 		  val, wlan_vdev_get_id(vdev));
2925*5113495bSYour Name 
2926*5113495bSYour Name 	return QDF_STATUS_SUCCESS;
2927*5113495bSYour Name }
2928*5113495bSYour Name 
mlo_is_chan_switch_in_progress(struct wlan_objmgr_vdev * vdev)2929*5113495bSYour Name bool mlo_is_chan_switch_in_progress(struct wlan_objmgr_vdev *vdev)
2930*5113495bSYour Name {
2931*5113495bSYour Name 	struct wlan_mlo_dev_context *mlo_dev_ctx = vdev->mlo_dev_ctx;
2932*5113495bSYour Name 
2933*5113495bSYour Name 	if (!mlo_dev_ctx || !mlo_dev_ctx->sta_ctx)
2934*5113495bSYour Name 		return false;
2935*5113495bSYour Name 
2936*5113495bSYour Name 	return mlo_dev_ctx->sta_ctx->ml_chan_switch_in_progress;
2937*5113495bSYour Name }
2938*5113495bSYour Name #endif
2939*5113495bSYour Name #endif
2940