xref: /wlan-driver/qca-wifi-host-cmn/umac/mlo_mgr/src/wlan_mlo_mgr_main.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 init/deinit api's
20*5113495bSYour Name  */
21*5113495bSYour Name #include "wlan_cmn.h"
22*5113495bSYour Name #include <wlan_objmgr_cmn.h>
23*5113495bSYour Name #include <wlan_objmgr_global_obj.h>
24*5113495bSYour Name #include "wlan_mlo_mgr_cmn.h"
25*5113495bSYour Name #include "wlan_mlo_mgr_main.h"
26*5113495bSYour Name #include <wlan_mlo_mgr_ap.h>
27*5113495bSYour Name #include <wlan_mlo_mgr_peer.h>
28*5113495bSYour Name #include <wlan_mlo_mgr_setup.h>
29*5113495bSYour Name #include <wlan_cm_public_struct.h>
30*5113495bSYour Name #include "wlan_mlo_mgr_msgq.h"
31*5113495bSYour Name #include <target_if_mlo_mgr.h>
32*5113495bSYour Name #include <wlan_mlo_t2lm.h>
33*5113495bSYour Name #include <wlan_cm_api.h>
34*5113495bSYour Name #include <wlan_mlo_mgr_public_api.h>
35*5113495bSYour Name #include "cdp_txrx_cmn.h"
36*5113495bSYour Name 
37*5113495bSYour Name #ifdef WLAN_WSI_STATS_SUPPORT
38*5113495bSYour Name /*
39*5113495bSYour Name  * wlan_mlo_wsi_get_num_psocs() - Get the number of attached PSOCs
40*5113495bSYour Name  * @psoc: Pointer to psoc
41*5113495bSYour Name  * @arg: Pointer to variable to store count
42*5113495bSYour Name  * @index: Index for iteration function
43*5113495bSYour Name  */
wlan_mlo_wsi_get_num_psocs(struct wlan_objmgr_psoc * psoc,void * arg,uint8_t index)44*5113495bSYour Name static void wlan_mlo_wsi_get_num_psocs(struct wlan_objmgr_psoc *psoc,
45*5113495bSYour Name 				       void *arg, uint8_t index)
46*5113495bSYour Name {
47*5113495bSYour Name 	/* If arg is NULL then skip increment */
48*5113495bSYour Name 	if (!arg)
49*5113495bSYour Name 		return;
50*5113495bSYour Name 
51*5113495bSYour Name 	(*(uint32_t *)arg)++;
52*5113495bSYour Name }
53*5113495bSYour Name 
mlo_wsi_link_info_deinit(struct mlo_mgr_context * mlo_mgr)54*5113495bSYour Name static void mlo_wsi_link_info_deinit(struct mlo_mgr_context *mlo_mgr)
55*5113495bSYour Name {
56*5113495bSYour Name 	if (!mlo_mgr)
57*5113495bSYour Name 		return;
58*5113495bSYour Name 
59*5113495bSYour Name 	if (mlo_mgr->wsi_info) {
60*5113495bSYour Name 		qdf_mem_free(mlo_mgr->wsi_info);
61*5113495bSYour Name 		mlo_mgr->wsi_info = NULL;
62*5113495bSYour Name 	}
63*5113495bSYour Name }
64*5113495bSYour Name 
65*5113495bSYour Name #ifdef WLAN_MLO_MULTI_CHIP
mlo_wsi_link_info_update_soc(struct wlan_objmgr_psoc * psoc,uint8_t grp_id)66*5113495bSYour Name void mlo_wsi_link_info_update_soc(struct wlan_objmgr_psoc *psoc,
67*5113495bSYour Name 				  uint8_t grp_id)
68*5113495bSYour Name {
69*5113495bSYour Name 	struct mlo_mgr_context *mlo_ctx = wlan_objmgr_get_mlo_ctx();
70*5113495bSYour Name 	struct mlo_wsi_psoc_grp *mlo_grp_info;
71*5113495bSYour Name 	uint8_t i, j;
72*5113495bSYour Name 
73*5113495bSYour Name 	if (!mlo_ctx) {
74*5113495bSYour Name 		mlo_err("Invalid mlo_mgr_ctx");
75*5113495bSYour Name 		return;
76*5113495bSYour Name 	}
77*5113495bSYour Name 
78*5113495bSYour Name 	mlo_grp_info = &mlo_ctx->wsi_info->mlo_psoc_grp[grp_id];
79*5113495bSYour Name 	if (!mlo_grp_info) {
80*5113495bSYour Name 		mlo_err("mlo_grp_info is invalid for ix %d", i);
81*5113495bSYour Name 		return;
82*5113495bSYour Name 	}
83*5113495bSYour Name 
84*5113495bSYour Name 	mlo_ctx->wsi_info->num_psoc++;
85*5113495bSYour Name 
86*5113495bSYour Name 	/* Set the PSOC order for the MLO group */
87*5113495bSYour Name 	for (j = 0; j < WLAN_OBJMGR_MAX_DEVICES; j++) {
88*5113495bSYour Name 		if (mlo_grp_info->psoc_order[j] == MLO_WSI_PSOC_ID_MAX) {
89*5113495bSYour Name 			mlo_grp_info->psoc_order[j] = wlan_psoc_get_id(psoc);
90*5113495bSYour Name 			mlo_grp_info->num_psoc++;
91*5113495bSYour Name 			break;
92*5113495bSYour Name 		}
93*5113495bSYour Name 	}
94*5113495bSYour Name }
95*5113495bSYour Name #endif
96*5113495bSYour Name 
97*5113495bSYour Name static void
mlo_wsi_link_info_setup_mlo_grps(struct mlo_mgr_context * mlo_mgr)98*5113495bSYour Name mlo_wsi_link_info_setup_mlo_grps(struct mlo_mgr_context *mlo_mgr)
99*5113495bSYour Name {
100*5113495bSYour Name 	struct mlo_wsi_psoc_grp *mlo_grp_info;
101*5113495bSYour Name 	uint8_t i, j;
102*5113495bSYour Name 
103*5113495bSYour Name 	if (!mlo_mgr) {
104*5113495bSYour Name 		mlo_err("Invalid mlo_mgr");
105*5113495bSYour Name 		return;
106*5113495bSYour Name 	}
107*5113495bSYour Name 
108*5113495bSYour Name 	if (!mlo_mgr->wsi_info) {
109*5113495bSYour Name 		mlo_err("Invalid wsi_info");
110*5113495bSYour Name 		return;
111*5113495bSYour Name 	}
112*5113495bSYour Name 
113*5113495bSYour Name 	wlan_objmgr_iterate_psoc_list(wlan_mlo_wsi_get_num_psocs,
114*5113495bSYour Name 				      &mlo_mgr->wsi_info->num_psoc,
115*5113495bSYour Name 				      WLAN_MLO_MGR_ID);
116*5113495bSYour Name 	if (!mlo_mgr->wsi_info->num_psoc)
117*5113495bSYour Name 		mlo_info("Could not find active PSOCs");
118*5113495bSYour Name 
119*5113495bSYour Name 	for (i = 0; i < MLO_WSI_MAX_MLO_GRPS; i++) {
120*5113495bSYour Name 		mlo_grp_info =
121*5113495bSYour Name 			&mlo_mgr->wsi_info->mlo_psoc_grp[i];
122*5113495bSYour Name 		if (!mlo_grp_info) {
123*5113495bSYour Name 			mlo_err("mlo_grp_info is invalid for ix %d", i);
124*5113495bSYour Name 			continue;
125*5113495bSYour Name 		}
126*5113495bSYour Name 
127*5113495bSYour Name 		/* Set the PSOC order for the MLO group */
128*5113495bSYour Name 		for (j = 0; j < WLAN_OBJMGR_MAX_DEVICES; j++) {
129*5113495bSYour Name 			/*
130*5113495bSYour Name 			 * NOTE: Inclusion of more MLO groups will require
131*5113495bSYour Name 			 * changes to this block where rvalue will need
132*5113495bSYour Name 			 * to be checked against the group they need to
133*5113495bSYour Name 			 * be assigned to.
134*5113495bSYour Name 			 */
135*5113495bSYour Name 			if (j < mlo_mgr->wsi_info->num_psoc) {
136*5113495bSYour Name 				mlo_grp_info->psoc_order[j] = j;
137*5113495bSYour Name 				mlo_grp_info->num_psoc++;
138*5113495bSYour Name 			} else {
139*5113495bSYour Name 				mlo_grp_info->psoc_order[j] =
140*5113495bSYour Name 							MLO_WSI_PSOC_ID_MAX;
141*5113495bSYour Name 			}
142*5113495bSYour Name 			mlo_err("PSOC order %d, index %d",
143*5113495bSYour Name 				mlo_grp_info->psoc_order[j], j);
144*5113495bSYour Name 		}
145*5113495bSYour Name 	}
146*5113495bSYour Name }
147*5113495bSYour Name 
mlo_wsi_link_info_init(struct mlo_mgr_context * mlo_mgr)148*5113495bSYour Name static void mlo_wsi_link_info_init(struct mlo_mgr_context *mlo_mgr)
149*5113495bSYour Name {
150*5113495bSYour Name 	uint8_t i;
151*5113495bSYour Name 
152*5113495bSYour Name 	if (!mlo_mgr)
153*5113495bSYour Name 		return;
154*5113495bSYour Name 
155*5113495bSYour Name 	/* Initialize the mlo_wsi_link_info structure */
156*5113495bSYour Name 	mlo_mgr->wsi_info = qdf_mem_malloc(
157*5113495bSYour Name 					sizeof(struct mlo_wsi_info));
158*5113495bSYour Name 	if (!mlo_mgr->wsi_info) {
159*5113495bSYour Name 		mlo_err("Could not allocate memory for wsi_link_info");
160*5113495bSYour Name 		return;
161*5113495bSYour Name 	}
162*5113495bSYour Name 
163*5113495bSYour Name 	/* Initialize the MLO group context in the WSI stats */
164*5113495bSYour Name 	for (i = 0; i < MLO_WSI_MAX_MLO_GRPS; i++)
165*5113495bSYour Name 		mlo_wsi_link_info_setup_mlo_grps(mlo_mgr);
166*5113495bSYour Name }
167*5113495bSYour Name #else
mlo_wsi_link_info_init(struct mlo_mgr_context * mlo_mgr)168*5113495bSYour Name static void mlo_wsi_link_info_init(struct mlo_mgr_context *mlo_mgr)
169*5113495bSYour Name {
170*5113495bSYour Name }
171*5113495bSYour Name 
mlo_wsi_link_info_deinit(struct mlo_mgr_context * mlo_mgr)172*5113495bSYour Name static void mlo_wsi_link_info_deinit(struct mlo_mgr_context *mlo_mgr)
173*5113495bSYour Name {
174*5113495bSYour Name }
175*5113495bSYour Name #endif
176*5113495bSYour Name 
mlo_global_ctx_deinit(void)177*5113495bSYour Name static void mlo_global_ctx_deinit(void)
178*5113495bSYour Name {
179*5113495bSYour Name 	struct mlo_mgr_context *mlo_mgr_ctx = wlan_objmgr_get_mlo_ctx();
180*5113495bSYour Name 
181*5113495bSYour Name 	if (!mlo_mgr_ctx)
182*5113495bSYour Name 		return;
183*5113495bSYour Name 
184*5113495bSYour Name 	if (qdf_list_empty(&mlo_mgr_ctx->ml_dev_list))
185*5113495bSYour Name 		mlo_debug("ML dev list is not empty");
186*5113495bSYour Name 
187*5113495bSYour Name 	/* Deallocation of the WSI link information */
188*5113495bSYour Name 	mlo_wsi_link_info_deinit(mlo_mgr_ctx);
189*5113495bSYour Name 
190*5113495bSYour Name 	mlo_setup_deinit();
191*5113495bSYour Name 	mlo_msgq_free();
192*5113495bSYour Name 	ml_peerid_lock_destroy(mlo_mgr_ctx);
193*5113495bSYour Name 	ml_link_lock_destroy(mlo_mgr_ctx);
194*5113495bSYour Name 	ml_aid_lock_destroy(mlo_mgr_ctx);
195*5113495bSYour Name 	qdf_list_destroy(&mlo_mgr_ctx->ml_dev_list);
196*5113495bSYour Name 
197*5113495bSYour Name 	qdf_mem_free(mlo_mgr_ctx);
198*5113495bSYour Name 	wlan_objmgr_set_mlo_ctx(NULL);
199*5113495bSYour Name }
200*5113495bSYour Name 
mlo_global_ctx_init(void)201*5113495bSYour Name static void mlo_global_ctx_init(void)
202*5113495bSYour Name {
203*5113495bSYour Name 	struct mlo_mgr_context *mlo_mgr_ctx;
204*5113495bSYour Name 
205*5113495bSYour Name 	/* If it is already created, ignore */
206*5113495bSYour Name 	if (wlan_objmgr_get_mlo_ctx()) {
207*5113495bSYour Name 		mlo_err("Global object is already created");
208*5113495bSYour Name 		return;
209*5113495bSYour Name 	}
210*5113495bSYour Name 
211*5113495bSYour Name 	/* Allocation of memory for Global object */
212*5113495bSYour Name 	mlo_mgr_ctx = (struct mlo_mgr_context *)
213*5113495bSYour Name 			qdf_mem_malloc(sizeof(*mlo_mgr_ctx));
214*5113495bSYour Name 	if (!mlo_mgr_ctx)
215*5113495bSYour Name 		return;
216*5113495bSYour Name 
217*5113495bSYour Name 	wlan_objmgr_set_mlo_ctx(mlo_mgr_ctx);
218*5113495bSYour Name 
219*5113495bSYour Name 	qdf_list_create(&mlo_mgr_ctx->ml_dev_list, WLAN_UMAC_MLO_MAX_DEV);
220*5113495bSYour Name 	mlo_mgr_ctx->max_mlo_peer_id = MAX_MLO_PEER_ID;
221*5113495bSYour Name 	mlo_mgr_ctx->last_mlo_peer_id = 0;
222*5113495bSYour Name 	ml_peerid_lock_create(mlo_mgr_ctx);
223*5113495bSYour Name 	ml_link_lock_create(mlo_mgr_ctx);
224*5113495bSYour Name 	ml_aid_lock_create(mlo_mgr_ctx);
225*5113495bSYour Name 	mlo_mgr_ctx->mlo_is_force_primary_umac = 0;
226*5113495bSYour Name 	mlo_mgr_ctx->force_non_assoc_prim_umac = 0;
227*5113495bSYour Name 	mlo_msgq_init();
228*5113495bSYour Name 
229*5113495bSYour Name 	/* Allocation of the WSI link information */
230*5113495bSYour Name 	mlo_wsi_link_info_init(mlo_mgr_ctx);
231*5113495bSYour Name }
232*5113495bSYour Name 
233*5113495bSYour Name /**
234*5113495bSYour Name  * wlan_mlo_check_psoc_capable() - Check if psoc is mlo capable
235*5113495bSYour Name  * @psoc: psoc pointer
236*5113495bSYour Name  *
237*5113495bSYour Name  * API to check if psoc is mlo capable
238*5113495bSYour Name  *
239*5113495bSYour Name  * Return: bool, true if capable else false
240*5113495bSYour Name  */
241*5113495bSYour Name #ifdef WLAN_MLO_MULTI_CHIP
wlan_mlo_check_psoc_capable(struct wlan_objmgr_psoc * psoc)242*5113495bSYour Name static bool wlan_mlo_check_psoc_capable(struct wlan_objmgr_psoc *psoc)
243*5113495bSYour Name {
244*5113495bSYour Name 	return wlan_mlo_get_psoc_capable(psoc);
245*5113495bSYour Name }
246*5113495bSYour Name #else
wlan_mlo_check_psoc_capable(struct wlan_objmgr_psoc * psoc)247*5113495bSYour Name static bool wlan_mlo_check_psoc_capable(struct wlan_objmgr_psoc *psoc)
248*5113495bSYour Name {
249*5113495bSYour Name 	return true;
250*5113495bSYour Name }
251*5113495bSYour Name #endif
252*5113495bSYour Name 
wlan_mlo_mgr_psoc_enable(struct wlan_objmgr_psoc * psoc)253*5113495bSYour Name QDF_STATUS wlan_mlo_mgr_psoc_enable(struct wlan_objmgr_psoc *psoc)
254*5113495bSYour Name {
255*5113495bSYour Name 	struct wlan_lmac_if_mlo_tx_ops *mlo_tx_ops;
256*5113495bSYour Name 
257*5113495bSYour Name 	if (!psoc) {
258*5113495bSYour Name 		mlo_err("psoc is null");
259*5113495bSYour Name 		return QDF_STATUS_E_NULL_VALUE;
260*5113495bSYour Name 	}
261*5113495bSYour Name 
262*5113495bSYour Name 	if (!wlan_mlo_check_psoc_capable(psoc))
263*5113495bSYour Name 		return QDF_STATUS_SUCCESS;
264*5113495bSYour Name 
265*5113495bSYour Name 	mlo_tx_ops = target_if_mlo_get_tx_ops(psoc);
266*5113495bSYour Name 	if (!mlo_tx_ops) {
267*5113495bSYour Name 		mlo_err("tx_ops is null!");
268*5113495bSYour Name 		return QDF_STATUS_E_NULL_VALUE;
269*5113495bSYour Name 	}
270*5113495bSYour Name 
271*5113495bSYour Name 	if (!mlo_tx_ops->register_events) {
272*5113495bSYour Name 		mlo_err("register_events function is null!");
273*5113495bSYour Name 		return QDF_STATUS_E_NULL_VALUE;
274*5113495bSYour Name 	}
275*5113495bSYour Name 
276*5113495bSYour Name 	return mlo_tx_ops->register_events(psoc);
277*5113495bSYour Name }
278*5113495bSYour Name 
wlan_mlo_mgr_psoc_disable(struct wlan_objmgr_psoc * psoc)279*5113495bSYour Name QDF_STATUS wlan_mlo_mgr_psoc_disable(struct wlan_objmgr_psoc *psoc)
280*5113495bSYour Name {
281*5113495bSYour Name 	struct wlan_lmac_if_mlo_tx_ops *mlo_tx_ops;
282*5113495bSYour Name 
283*5113495bSYour Name 	if (!psoc) {
284*5113495bSYour Name 		mlo_err("psoc is null");
285*5113495bSYour Name 		return QDF_STATUS_E_NULL_VALUE;
286*5113495bSYour Name 	}
287*5113495bSYour Name 
288*5113495bSYour Name 	mlo_tx_ops = target_if_mlo_get_tx_ops(psoc);
289*5113495bSYour Name 	if (!mlo_tx_ops) {
290*5113495bSYour Name 		mlo_err("tx_ops is null!");
291*5113495bSYour Name 		return QDF_STATUS_E_NULL_VALUE;
292*5113495bSYour Name 	}
293*5113495bSYour Name 
294*5113495bSYour Name 	if (!mlo_tx_ops->unregister_events) {
295*5113495bSYour Name 		mlo_err("unregister_events function is null!");
296*5113495bSYour Name 		return QDF_STATUS_E_NULL_VALUE;
297*5113495bSYour Name 	}
298*5113495bSYour Name 
299*5113495bSYour Name 	return mlo_tx_ops->unregister_events(psoc);
300*5113495bSYour Name }
301*5113495bSYour Name 
302*5113495bSYour Name #ifdef WLAN_FEATURE_11BE_MLO_ADV_FEATURE
303*5113495bSYour Name QDF_STATUS
mlo_mgr_register_link_switch_notifier(enum wlan_umac_comp_id comp_id,mlo_mgr_link_switch_notifier_cb cb)304*5113495bSYour Name mlo_mgr_register_link_switch_notifier(enum wlan_umac_comp_id comp_id,
305*5113495bSYour Name 				      mlo_mgr_link_switch_notifier_cb cb)
306*5113495bSYour Name {
307*5113495bSYour Name 	struct mlo_mgr_context *g_mlo_mgr_ctx = wlan_objmgr_get_mlo_ctx();
308*5113495bSYour Name 
309*5113495bSYour Name 	if (!g_mlo_mgr_ctx) {
310*5113495bSYour Name 		mlo_err("global mlo mgr not initialized");
311*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
312*5113495bSYour Name 	}
313*5113495bSYour Name 
314*5113495bSYour Name 	if (!cb || comp_id >= WLAN_UMAC_COMP_ID_MAX) {
315*5113495bSYour Name 		mlo_err("Invalid component");
316*5113495bSYour Name 		QDF_ASSERT(0);
317*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
318*5113495bSYour Name 	}
319*5113495bSYour Name 
320*5113495bSYour Name 	if (g_mlo_mgr_ctx->lswitch_notifier[comp_id].in_use)
321*5113495bSYour Name 		return QDF_STATUS_E_ALREADY;
322*5113495bSYour Name 
323*5113495bSYour Name 	g_mlo_mgr_ctx->lswitch_notifier[comp_id].in_use = true;
324*5113495bSYour Name 	g_mlo_mgr_ctx->lswitch_notifier[comp_id].cb = cb;
325*5113495bSYour Name 	return QDF_STATUS_SUCCESS;
326*5113495bSYour Name }
327*5113495bSYour Name 
328*5113495bSYour Name QDF_STATUS
mlo_mgr_unregister_link_switch_notifier(enum wlan_umac_comp_id comp_id)329*5113495bSYour Name mlo_mgr_unregister_link_switch_notifier(enum wlan_umac_comp_id comp_id)
330*5113495bSYour Name {
331*5113495bSYour Name 	struct mlo_mgr_context *g_mlo_mgr_ctx = wlan_objmgr_get_mlo_ctx();
332*5113495bSYour Name 
333*5113495bSYour Name 	if (!g_mlo_mgr_ctx) {
334*5113495bSYour Name 		mlo_err("global mlo mgr not initialized");
335*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
336*5113495bSYour Name 	}
337*5113495bSYour Name 
338*5113495bSYour Name 	if (comp_id >= WLAN_UMAC_COMP_ID_MAX) {
339*5113495bSYour Name 		mlo_err("Invalid component");
340*5113495bSYour Name 		QDF_ASSERT(0);
341*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
342*5113495bSYour Name 	}
343*5113495bSYour Name 
344*5113495bSYour Name 	if (!g_mlo_mgr_ctx->lswitch_notifier[comp_id].in_use)
345*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
346*5113495bSYour Name 
347*5113495bSYour Name 	g_mlo_mgr_ctx->lswitch_notifier[comp_id].in_use = false;
348*5113495bSYour Name 	g_mlo_mgr_ctx->lswitch_notifier[comp_id].cb = NULL;
349*5113495bSYour Name 	return QDF_STATUS_SUCCESS;
350*5113495bSYour Name }
351*5113495bSYour Name 
mlo_mgr_init_link_switch_notifier(void)352*5113495bSYour Name static QDF_STATUS mlo_mgr_init_link_switch_notifier(void)
353*5113495bSYour Name {
354*5113495bSYour Name 	int i;
355*5113495bSYour Name 	struct mlo_mgr_context *g_mlo_mgr_ctx = wlan_objmgr_get_mlo_ctx();
356*5113495bSYour Name 
357*5113495bSYour Name 	if (!g_mlo_mgr_ctx)
358*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
359*5113495bSYour Name 
360*5113495bSYour Name 	for (i = 0; i < WLAN_UMAC_COMP_ID_MAX; i++) {
361*5113495bSYour Name 		g_mlo_mgr_ctx->lswitch_notifier[i].in_use = false;
362*5113495bSYour Name 		g_mlo_mgr_ctx->lswitch_notifier[i].cb = NULL;
363*5113495bSYour Name 	}
364*5113495bSYour Name 
365*5113495bSYour Name 	return QDF_STATUS_SUCCESS;
366*5113495bSYour Name }
367*5113495bSYour Name #else
mlo_mgr_init_link_switch_notifier(void)368*5113495bSYour Name static inline QDF_STATUS mlo_mgr_init_link_switch_notifier(void)
369*5113495bSYour Name {
370*5113495bSYour Name 	return QDF_STATUS_E_NOSUPPORT;
371*5113495bSYour Name }
372*5113495bSYour Name #endif /* WLAN_FEATURE_11BE_MLO_ADV_FEATURE */
373*5113495bSYour Name 
wlan_mlo_mgr_init(void)374*5113495bSYour Name QDF_STATUS wlan_mlo_mgr_init(void)
375*5113495bSYour Name {
376*5113495bSYour Name 	QDF_STATUS status;
377*5113495bSYour Name 
378*5113495bSYour Name 	mlo_global_ctx_init();
379*5113495bSYour Name 
380*5113495bSYour Name 	status = wlan_objmgr_register_vdev_create_handler(
381*5113495bSYour Name 		WLAN_UMAC_COMP_MLO_MGR,
382*5113495bSYour Name 		wlan_mlo_mgr_vdev_created_notification, NULL);
383*5113495bSYour Name 	if (QDF_IS_STATUS_ERROR(status)) {
384*5113495bSYour Name 		mlo_err("Failed to register vdev create handler");
385*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
386*5113495bSYour Name 	}
387*5113495bSYour Name 
388*5113495bSYour Name 	status = wlan_objmgr_register_vdev_destroy_handler(WLAN_UMAC_COMP_MLO_MGR,
389*5113495bSYour Name 		wlan_mlo_mgr_vdev_destroyed_notification, NULL);
390*5113495bSYour Name 	if (QDF_IS_STATUS_ERROR(status)) {
391*5113495bSYour Name 		mlo_debug("Failed to register VDEV destroy handler");
392*5113495bSYour Name 		wlan_objmgr_unregister_vdev_create_handler(WLAN_UMAC_COMP_MLO_MGR,
393*5113495bSYour Name 					wlan_mlo_mgr_vdev_created_notification, NULL);
394*5113495bSYour Name 		return status;
395*5113495bSYour Name 	}
396*5113495bSYour Name 
397*5113495bSYour Name 	status = mlo_mgr_init_link_switch_notifier();
398*5113495bSYour Name 	if (QDF_IS_STATUS_SUCCESS(status)) {
399*5113495bSYour Name 		status = mlo_mgr_register_link_switch_notifier(WLAN_UMAC_COMP_MLO_MGR,
400*5113495bSYour Name 							       mlo_mgr_link_switch_notification);
401*5113495bSYour Name 		return status;
402*5113495bSYour Name 	}
403*5113495bSYour Name 	if (status == QDF_STATUS_E_NOSUPPORT)
404*5113495bSYour Name 		status = QDF_STATUS_SUCCESS;
405*5113495bSYour Name 
406*5113495bSYour Name 	return status;
407*5113495bSYour Name }
408*5113495bSYour Name 
wlan_mlo_mgr_deinit(void)409*5113495bSYour Name QDF_STATUS wlan_mlo_mgr_deinit(void)
410*5113495bSYour Name {
411*5113495bSYour Name 	QDF_STATUS status;
412*5113495bSYour Name 	struct mlo_mgr_context *mlo_mgr_ctx = wlan_objmgr_get_mlo_ctx();
413*5113495bSYour Name 
414*5113495bSYour Name 	if (!mlo_mgr_ctx) {
415*5113495bSYour Name 		mlo_err("MLO global object is not allocated");
416*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
417*5113495bSYour Name 	}
418*5113495bSYour Name 
419*5113495bSYour Name 	wlan_mlo_mgr_unregister_link_switch_notifier(WLAN_UMAC_COMP_MLO_MGR);
420*5113495bSYour Name 
421*5113495bSYour Name 	mlo_global_ctx_deinit();
422*5113495bSYour Name 
423*5113495bSYour Name 	status = wlan_objmgr_unregister_vdev_create_handler(
424*5113495bSYour Name 		WLAN_UMAC_COMP_MLO_MGR,
425*5113495bSYour Name 		wlan_mlo_mgr_vdev_created_notification, NULL);
426*5113495bSYour Name 	if (status != QDF_STATUS_SUCCESS)
427*5113495bSYour Name 		mlo_err("Failed to unregister vdev create handler");
428*5113495bSYour Name 
429*5113495bSYour Name 	status = wlan_objmgr_unregister_vdev_destroy_handler(
430*5113495bSYour Name 			WLAN_UMAC_COMP_MLO_MGR,
431*5113495bSYour Name 			wlan_mlo_mgr_vdev_destroyed_notification, NULL);
432*5113495bSYour Name 	if (status != QDF_STATUS_SUCCESS)
433*5113495bSYour Name 		mlo_err("Failed to unregister vdev delete handler");
434*5113495bSYour Name 
435*5113495bSYour Name 	return status;
436*5113495bSYour Name }
437*5113495bSYour Name 
wlan_mlo_list_peek_head(qdf_list_t * ml_list)438*5113495bSYour Name struct wlan_mlo_dev_context *wlan_mlo_list_peek_head(
439*5113495bSYour Name 					qdf_list_t *ml_list)
440*5113495bSYour Name {
441*5113495bSYour Name 	struct wlan_mlo_dev_context *mld_ctx;
442*5113495bSYour Name 	qdf_list_node_t *ml_node = NULL;
443*5113495bSYour Name 
444*5113495bSYour Name 	/* This API is invoked with lock acquired, do not add log prints */
445*5113495bSYour Name 	if (qdf_list_peek_front(ml_list, &ml_node) != QDF_STATUS_SUCCESS)
446*5113495bSYour Name 		return NULL;
447*5113495bSYour Name 
448*5113495bSYour Name 	mld_ctx = qdf_container_of(ml_node, struct wlan_mlo_dev_context,
449*5113495bSYour Name 				   node);
450*5113495bSYour Name 
451*5113495bSYour Name 	return mld_ctx;
452*5113495bSYour Name }
453*5113495bSYour Name 
wlan_mlo_get_next_mld_ctx(qdf_list_t * ml_list,struct wlan_mlo_dev_context * mld_cur)454*5113495bSYour Name struct wlan_mlo_dev_context *wlan_mlo_get_next_mld_ctx(qdf_list_t *ml_list,
455*5113495bSYour Name 					struct wlan_mlo_dev_context *mld_cur)
456*5113495bSYour Name {
457*5113495bSYour Name 	struct wlan_mlo_dev_context *mld_next;
458*5113495bSYour Name 	qdf_list_node_t *node = &mld_cur->node;
459*5113495bSYour Name 	qdf_list_node_t *next_node = NULL;
460*5113495bSYour Name 
461*5113495bSYour Name 	/* This API is invoked with lock acquired, do not add log prints */
462*5113495bSYour Name 	if (!node)
463*5113495bSYour Name 		return NULL;
464*5113495bSYour Name 
465*5113495bSYour Name 	if (qdf_list_peek_next(ml_list, node, &next_node) !=
466*5113495bSYour Name 						QDF_STATUS_SUCCESS)
467*5113495bSYour Name 		return NULL;
468*5113495bSYour Name 
469*5113495bSYour Name 	mld_next = qdf_container_of(next_node, struct wlan_mlo_dev_context,
470*5113495bSYour Name 				    node);
471*5113495bSYour Name 	return mld_next;
472*5113495bSYour Name }
473*5113495bSYour Name 
wlan_mlo_get_sta_mld_ctx_count(void)474*5113495bSYour Name uint8_t wlan_mlo_get_sta_mld_ctx_count(void)
475*5113495bSYour Name {
476*5113495bSYour Name 	struct wlan_mlo_dev_context *mld_cur;
477*5113495bSYour Name 	struct wlan_mlo_dev_context *mld_next;
478*5113495bSYour Name 	qdf_list_t *ml_list;
479*5113495bSYour Name 	struct mlo_mgr_context *mlo_mgr_ctx = wlan_objmgr_get_mlo_ctx();
480*5113495bSYour Name 	uint8_t count = 0;
481*5113495bSYour Name 
482*5113495bSYour Name 	if (!mlo_mgr_ctx)
483*5113495bSYour Name 		return count;
484*5113495bSYour Name 
485*5113495bSYour Name 	ml_link_lock_acquire(mlo_mgr_ctx);
486*5113495bSYour Name 	ml_list = &mlo_mgr_ctx->ml_dev_list;
487*5113495bSYour Name 	/* Get first mld context */
488*5113495bSYour Name 	mld_cur = wlan_mlo_list_peek_head(ml_list);
489*5113495bSYour Name 
490*5113495bSYour Name 	while (mld_cur) {
491*5113495bSYour Name 		/* get next mld node */
492*5113495bSYour Name 		if (mld_cur->sta_ctx)
493*5113495bSYour Name 			count++;
494*5113495bSYour Name 		mld_next = wlan_mlo_get_next_mld_ctx(ml_list, mld_cur);
495*5113495bSYour Name 		mld_cur = mld_next;
496*5113495bSYour Name 	}
497*5113495bSYour Name 	ml_link_lock_release(mlo_mgr_ctx);
498*5113495bSYour Name 
499*5113495bSYour Name 	return count;
500*5113495bSYour Name }
501*5113495bSYour Name 
502*5113495bSYour Name struct wlan_mlo_dev_context
wlan_mlo_get_mld_ctx_by_mldaddr(struct qdf_mac_addr * mldaddr)503*5113495bSYour Name *wlan_mlo_get_mld_ctx_by_mldaddr(struct qdf_mac_addr *mldaddr)
504*5113495bSYour Name {
505*5113495bSYour Name 	struct wlan_mlo_dev_context *mld_cur;
506*5113495bSYour Name 	struct wlan_mlo_dev_context *mld_next;
507*5113495bSYour Name 	qdf_list_t *ml_list;
508*5113495bSYour Name 	struct mlo_mgr_context *mlo_mgr_ctx = wlan_objmgr_get_mlo_ctx();
509*5113495bSYour Name 
510*5113495bSYour Name 	if (!mlo_mgr_ctx)
511*5113495bSYour Name 		return NULL;
512*5113495bSYour Name 
513*5113495bSYour Name 	ml_link_lock_acquire(mlo_mgr_ctx);
514*5113495bSYour Name 	ml_list = &mlo_mgr_ctx->ml_dev_list;
515*5113495bSYour Name 	/* Get first mld context */
516*5113495bSYour Name 	mld_cur = wlan_mlo_list_peek_head(ml_list);
517*5113495bSYour Name 	/**
518*5113495bSYour Name 	 * Iterate through ml list, till ml mldaddr matches with
519*5113495bSYour Name 	 * entry of list
520*5113495bSYour Name 	 */
521*5113495bSYour Name 	while (mld_cur) {
522*5113495bSYour Name 		if (QDF_IS_STATUS_SUCCESS(WLAN_ADDR_EQ(&mld_cur->mld_addr,
523*5113495bSYour Name 					  mldaddr))) {
524*5113495bSYour Name 			ml_link_lock_release(mlo_mgr_ctx);
525*5113495bSYour Name 			return mld_cur;
526*5113495bSYour Name 		}
527*5113495bSYour Name 		/* get next mld node */
528*5113495bSYour Name 		mld_next = wlan_mlo_get_next_mld_ctx(ml_list, mld_cur);
529*5113495bSYour Name 		mld_cur = mld_next;
530*5113495bSYour Name 	}
531*5113495bSYour Name 	ml_link_lock_release(mlo_mgr_ctx);
532*5113495bSYour Name 
533*5113495bSYour Name 	return NULL;
534*5113495bSYour Name }
535*5113495bSYour Name 
wlan_mlo_is_mld_ctx_exist(struct qdf_mac_addr * mldaddr)536*5113495bSYour Name bool wlan_mlo_is_mld_ctx_exist(struct qdf_mac_addr *mldaddr)
537*5113495bSYour Name {
538*5113495bSYour Name 	struct wlan_mlo_dev_context *mld_ctx = NULL;
539*5113495bSYour Name 
540*5113495bSYour Name 	mld_ctx = wlan_mlo_get_mld_ctx_by_mldaddr(mldaddr);
541*5113495bSYour Name 	if (mld_ctx)
542*5113495bSYour Name 		return true;
543*5113495bSYour Name 
544*5113495bSYour Name 	return false;
545*5113495bSYour Name }
546*5113495bSYour Name 
547*5113495bSYour Name #ifdef WLAN_MLO_MULTI_CHIP
mlo_mgr_is_mld_has_active_link(bool * is_active)548*5113495bSYour Name QDF_STATUS mlo_mgr_is_mld_has_active_link(bool *is_active)
549*5113495bSYour Name {
550*5113495bSYour Name 	qdf_list_t *ml_list;
551*5113495bSYour Name 	uint32_t idx, count;
552*5113495bSYour Name 	struct wlan_mlo_dev_context *mld_cur, *mld_next;
553*5113495bSYour Name 	struct wlan_objmgr_vdev *vdev;
554*5113495bSYour Name 	struct mlo_mgr_context *g_mlo_ctx = wlan_objmgr_get_mlo_ctx();
555*5113495bSYour Name 	QDF_STATUS status;
556*5113495bSYour Name 
557*5113495bSYour Name 	if (!g_mlo_ctx || !is_active)
558*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
559*5113495bSYour Name 
560*5113495bSYour Name 	ml_link_lock_acquire(g_mlo_ctx);
561*5113495bSYour Name 	ml_list = &g_mlo_ctx->ml_dev_list;
562*5113495bSYour Name 	if (!qdf_list_size(ml_list)) {
563*5113495bSYour Name 		ml_link_lock_release(g_mlo_ctx);
564*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
565*5113495bSYour Name 	}
566*5113495bSYour Name 
567*5113495bSYour Name 	*is_active = false;
568*5113495bSYour Name 	mld_cur = wlan_mlo_list_peek_head(ml_list);
569*5113495bSYour Name 	while (mld_cur) {
570*5113495bSYour Name 		mlo_dev_lock_acquire(mld_cur);
571*5113495bSYour Name 		count = QDF_ARRAY_SIZE(mld_cur->wlan_vdev_list);
572*5113495bSYour Name 		for (idx = 0; idx < count; idx++) {
573*5113495bSYour Name 			vdev = mld_cur->wlan_vdev_list[idx];
574*5113495bSYour Name 			if (!vdev)
575*5113495bSYour Name 				continue;
576*5113495bSYour Name 
577*5113495bSYour Name 			status = wlan_vdev_mlme_is_init_state(vdev);
578*5113495bSYour Name 			if (QDF_STATUS_SUCCESS == status)
579*5113495bSYour Name 				continue;
580*5113495bSYour Name 
581*5113495bSYour Name 			qdf_err("VDEV [vdev_id %u, pdev_id %u, psoc_id %u, state %u] is still active",
582*5113495bSYour Name 				wlan_vdev_get_id(vdev),
583*5113495bSYour Name 				wlan_objmgr_pdev_get_pdev_id(wlan_vdev_get_pdev(vdev)),
584*5113495bSYour Name 				wlan_vdev_get_psoc_id(vdev),
585*5113495bSYour Name 				wlan_vdev_mlme_get_state(vdev));
586*5113495bSYour Name 			*is_active = true;
587*5113495bSYour Name 			mlo_dev_lock_release(mld_cur);
588*5113495bSYour Name 			ml_link_lock_release(g_mlo_ctx);
589*5113495bSYour Name 			return QDF_STATUS_SUCCESS;
590*5113495bSYour Name 		}
591*5113495bSYour Name 		mld_next = wlan_mlo_get_next_mld_ctx(ml_list, mld_cur);
592*5113495bSYour Name 		mlo_dev_lock_release(mld_cur);
593*5113495bSYour Name 		mld_cur = mld_next;
594*5113495bSYour Name 	}
595*5113495bSYour Name 	ml_link_lock_release(g_mlo_ctx);
596*5113495bSYour Name 
597*5113495bSYour Name 	return QDF_STATUS_SUCCESS;
598*5113495bSYour Name }
599*5113495bSYour Name 
600*5113495bSYour Name qdf_export_symbol(mlo_mgr_is_mld_has_active_link);
601*5113495bSYour Name #endif
602*5113495bSYour Name 
603*5113495bSYour Name #ifdef WLAN_FEATURE_11BE_MLO
mlo_mgr_ml_peer_exist_on_diff_ml_ctx(uint8_t * peer_addr,uint8_t * peer_vdev_id)604*5113495bSYour Name bool mlo_mgr_ml_peer_exist_on_diff_ml_ctx(uint8_t *peer_addr,
605*5113495bSYour Name 					  uint8_t *peer_vdev_id)
606*5113495bSYour Name {
607*5113495bSYour Name 	qdf_list_t *ml_list;
608*5113495bSYour Name 	uint32_t idx, count;
609*5113495bSYour Name 	struct wlan_mlo_dev_context *mld_cur, *mld_next;
610*5113495bSYour Name 	struct wlan_mlo_peer_list *mlo_peer_list;
611*5113495bSYour Name 	struct wlan_objmgr_vdev *vdev;
612*5113495bSYour Name 	bool ret_status = false, same_ml_ctx = false;
613*5113495bSYour Name 	struct mlo_mgr_context *g_mlo_ctx = wlan_objmgr_get_mlo_ctx();
614*5113495bSYour Name 
615*5113495bSYour Name 	if (!g_mlo_ctx || !peer_addr ||
616*5113495bSYour Name 	    qdf_is_macaddr_zero((struct qdf_mac_addr *)peer_addr))
617*5113495bSYour Name 		return ret_status;
618*5113495bSYour Name 
619*5113495bSYour Name 	ml_link_lock_acquire(g_mlo_ctx);
620*5113495bSYour Name 	ml_list = &g_mlo_ctx->ml_dev_list;
621*5113495bSYour Name 	if (!qdf_list_size(ml_list))
622*5113495bSYour Name 		goto g_ml_ref;
623*5113495bSYour Name 
624*5113495bSYour Name 	mld_cur = wlan_mlo_list_peek_head(ml_list);
625*5113495bSYour Name 	while (mld_cur) {
626*5113495bSYour Name 		mlo_dev_lock_acquire(mld_cur);
627*5113495bSYour Name 		if (qdf_is_macaddr_equal(&mld_cur->mld_addr,
628*5113495bSYour Name 					 (struct qdf_mac_addr *)peer_addr)) {
629*5113495bSYour Name 			/* For self peer, the address passed will match the
630*5113495bSYour Name 			 * MLD address of its own ML dev context, so allow
631*5113495bSYour Name 			 * peer creation in this scenario as both are in
632*5113495bSYour Name 			 * same ML dev context.
633*5113495bSYour Name 			 */
634*5113495bSYour Name 			if (peer_vdev_id) {
635*5113495bSYour Name 				count = QDF_ARRAY_SIZE(mld_cur->wlan_vdev_list);
636*5113495bSYour Name 				for (idx = 0; idx < count; idx++) {
637*5113495bSYour Name 					vdev = mld_cur->wlan_vdev_list[idx];
638*5113495bSYour Name 					if (!vdev)
639*5113495bSYour Name 						continue;
640*5113495bSYour Name 					if (*peer_vdev_id ==
641*5113495bSYour Name 					    wlan_vdev_get_id(vdev)) {
642*5113495bSYour Name 						same_ml_ctx = true;
643*5113495bSYour Name 						break;
644*5113495bSYour Name 					}
645*5113495bSYour Name 				}
646*5113495bSYour Name 			}
647*5113495bSYour Name 			mlo_dev_lock_release(mld_cur);
648*5113495bSYour Name 			mlo_err("MLD ID %d exists with mac " QDF_MAC_ADDR_FMT,
649*5113495bSYour Name 				mld_cur->mld_id, QDF_MAC_ADDR_REF(peer_addr));
650*5113495bSYour Name 			ret_status = true;
651*5113495bSYour Name 			goto check_same_ml_ctx;
652*5113495bSYour Name 		}
653*5113495bSYour Name 
654*5113495bSYour Name 		/* Check the peer list for a MAC address match */
655*5113495bSYour Name 		mlo_peer_list = &mld_cur->mlo_peer_list;
656*5113495bSYour Name 		ml_peerlist_lock_acquire(mlo_peer_list);
657*5113495bSYour Name 		if (mlo_get_mlpeer(mld_cur, (struct qdf_mac_addr *)peer_addr)) {
658*5113495bSYour Name 			/* If peer_vdev_id is NULL, then API will treat any
659*5113495bSYour Name 			 * match as happening on another dev context
660*5113495bSYour Name 			 */
661*5113495bSYour Name 			if (peer_vdev_id) {
662*5113495bSYour Name 				count = QDF_ARRAY_SIZE(mld_cur->wlan_vdev_list);
663*5113495bSYour Name 				for (idx = 0; idx < count; idx++) {
664*5113495bSYour Name 					vdev = mld_cur->wlan_vdev_list[idx];
665*5113495bSYour Name 					if (!vdev)
666*5113495bSYour Name 						continue;
667*5113495bSYour Name 					if (*peer_vdev_id ==
668*5113495bSYour Name 					    wlan_vdev_get_id(vdev)) {
669*5113495bSYour Name 						same_ml_ctx = true;
670*5113495bSYour Name 						break;
671*5113495bSYour Name 					}
672*5113495bSYour Name 				}
673*5113495bSYour Name 			}
674*5113495bSYour Name 			ml_peerlist_lock_release(mlo_peer_list);
675*5113495bSYour Name 			mlo_dev_lock_release(mld_cur);
676*5113495bSYour Name 			mlo_err("MLD ID %d ML Peer exists with mac " QDF_MAC_ADDR_FMT,
677*5113495bSYour Name 				mld_cur->mld_id, QDF_MAC_ADDR_REF(peer_addr));
678*5113495bSYour Name 			ret_status = true;
679*5113495bSYour Name 			goto check_same_ml_ctx;
680*5113495bSYour Name 		}
681*5113495bSYour Name 		ml_peerlist_lock_release(mlo_peer_list);
682*5113495bSYour Name 
683*5113495bSYour Name 		mld_next = wlan_mlo_get_next_mld_ctx(ml_list, mld_cur);
684*5113495bSYour Name 		mlo_dev_lock_release(mld_cur);
685*5113495bSYour Name 		mld_cur = mld_next;
686*5113495bSYour Name 	}
687*5113495bSYour Name 
688*5113495bSYour Name check_same_ml_ctx:
689*5113495bSYour Name 	if (same_ml_ctx)
690*5113495bSYour Name 		ret_status = false;
691*5113495bSYour Name 
692*5113495bSYour Name g_ml_ref:
693*5113495bSYour Name 	ml_link_lock_release(g_mlo_ctx);
694*5113495bSYour Name 	return ret_status;
695*5113495bSYour Name }
696*5113495bSYour Name 
697*5113495bSYour Name #define WLAN_HDD_MGMT_FRAME_DA_OFFSET 4
698*5113495bSYour Name #define WLAN_HDD_MGMT_FRAME_SA_OFFSET (WLAN_HDD_MGMT_FRAME_DA_OFFSET + 6)
699*5113495bSYour Name #define WLAN_HDD_MGMT_FRAME_BSSID_OFFSET (WLAN_HDD_MGMT_FRAME_SA_OFFSET + 6)
700*5113495bSYour Name #define WLAN_HDD_MGMT_FRAME_ACTION_CATEGORY_OFFSET \
701*5113495bSYour Name 				(WLAN_HDD_MGMT_FRAME_BSSID_OFFSET + 6 + 2)
702*5113495bSYour Name #define WLAN_HDD_MGMT_FRAME_ACTION_TYPE_OFFSET \
703*5113495bSYour Name 				(WLAN_HDD_MGMT_FRAME_ACTION_CATEGORY_OFFSET + 1)
704*5113495bSYour Name #define WLAN_HDD_ACTION_FRAME_CATEGORY_PUBLIC 0x04
705*5113495bSYour Name 
706*5113495bSYour Name /*
707*5113495bSYour Name  * Typical 802.11 Action Frame Format
708*5113495bSYour Name  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-
709*5113495bSYour Name  * | FC | DUR |  DA  |   SA  | BSSID |Seq.|Cat.|Act|   Elements   | FCS |
710*5113495bSYour Name  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-
711*5113495bSYour Name  *    2    2     6       6       6     2    1    1   Variable Len    4
712*5113495bSYour Name  */
wlan_mlo_update_action_frame_from_user(struct wlan_objmgr_vdev * vdev,uint8_t * frame,uint32_t frame_len)713*5113495bSYour Name void wlan_mlo_update_action_frame_from_user(struct wlan_objmgr_vdev *vdev,
714*5113495bSYour Name 					    uint8_t *frame,
715*5113495bSYour Name 					    uint32_t frame_len)
716*5113495bSYour Name {
717*5113495bSYour Name 	struct wlan_objmgr_peer *peer;
718*5113495bSYour Name 	uint8_t *da, *sa, *bssid;
719*5113495bSYour Name 
720*5113495bSYour Name 	if (!wlan_vdev_mlme_is_mlo_vdev(vdev) ||
721*5113495bSYour Name 	    (wlan_vdev_mlme_get_opmode(vdev) != QDF_STA_MODE))
722*5113495bSYour Name 		return;
723*5113495bSYour Name 
724*5113495bSYour Name 	if (frame_len <= WLAN_HDD_MGMT_FRAME_ACTION_TYPE_OFFSET) {
725*5113495bSYour Name 		mlo_debug("Not a valid Action frame len: %d", frame_len);
726*5113495bSYour Name 		return;
727*5113495bSYour Name 	}
728*5113495bSYour Name 
729*5113495bSYour Name 	/* Translate address only for action frames
730*5113495bSYour Name 	 * which are not of public category.
731*5113495bSYour Name 	 * Reference: 802.11-2012, Subclause: 8.5
732*5113495bSYour Name 	 */
733*5113495bSYour Name 
734*5113495bSYour Name 	if (frame[WLAN_HDD_MGMT_FRAME_ACTION_CATEGORY_OFFSET] ==
735*5113495bSYour Name 				WLAN_HDD_ACTION_FRAME_CATEGORY_PUBLIC)
736*5113495bSYour Name 		return;
737*5113495bSYour Name 
738*5113495bSYour Name 	da = frame + WLAN_HDD_MGMT_FRAME_DA_OFFSET;
739*5113495bSYour Name 	sa = frame + WLAN_HDD_MGMT_FRAME_SA_OFFSET;
740*5113495bSYour Name 	bssid = frame + WLAN_HDD_MGMT_FRAME_BSSID_OFFSET;
741*5113495bSYour Name 
742*5113495bSYour Name 	peer = wlan_objmgr_vdev_try_get_bsspeer(vdev, WLAN_MLO_MGR_ID);
743*5113495bSYour Name 	if (!peer) {
744*5113495bSYour Name 		mlo_debug("Peer not found");
745*5113495bSYour Name 		return;
746*5113495bSYour Name 	}
747*5113495bSYour Name 
748*5113495bSYour Name 	mlo_debug("Change MLD addr to link addr for non-Public action frame");
749*5113495bSYour Name 	/* DA = VDEV's BSS peer's link address.
750*5113495bSYour Name 	 * SA = VDEV's link address.
751*5113495bSYour Name 	 * BSSID = VDEV's BSS peer's link address.
752*5113495bSYour Name 	 */
753*5113495bSYour Name 
754*5113495bSYour Name 	qdf_ether_addr_copy(da, wlan_peer_get_macaddr(peer));
755*5113495bSYour Name 	qdf_ether_addr_copy(sa, wlan_vdev_mlme_get_macaddr(vdev));
756*5113495bSYour Name 	qdf_ether_addr_copy(bssid, wlan_peer_get_macaddr(peer));
757*5113495bSYour Name 
758*5113495bSYour Name 	wlan_objmgr_peer_release_ref(peer, WLAN_MLO_MGR_ID);
759*5113495bSYour Name }
760*5113495bSYour Name 
wlan_mlo_update_action_frame_to_user(struct wlan_objmgr_vdev * vdev,uint8_t * frame,uint32_t frame_len)761*5113495bSYour Name void wlan_mlo_update_action_frame_to_user(struct wlan_objmgr_vdev *vdev,
762*5113495bSYour Name 					  uint8_t *frame,
763*5113495bSYour Name 					  uint32_t frame_len)
764*5113495bSYour Name {
765*5113495bSYour Name 	struct wlan_objmgr_peer *peer;
766*5113495bSYour Name 	uint8_t *da, *sa, *bssid;
767*5113495bSYour Name 
768*5113495bSYour Name 	if (!wlan_vdev_mlme_is_mlo_vdev(vdev) ||
769*5113495bSYour Name 	    (wlan_vdev_mlme_get_opmode(vdev) != QDF_STA_MODE))
770*5113495bSYour Name 		return;
771*5113495bSYour Name 
772*5113495bSYour Name 	if (frame_len <= WLAN_HDD_MGMT_FRAME_ACTION_TYPE_OFFSET) {
773*5113495bSYour Name 		mlo_debug("Not a valid Action frame len: %d", frame_len);
774*5113495bSYour Name 		return;
775*5113495bSYour Name 	}
776*5113495bSYour Name 
777*5113495bSYour Name 	/* Translate address only for action frames
778*5113495bSYour Name 	 * which are not of public category.
779*5113495bSYour Name 	 * Reference: 802.11-2012, Subclause: 8.5
780*5113495bSYour Name 	 */
781*5113495bSYour Name 
782*5113495bSYour Name 	if (frame[WLAN_HDD_MGMT_FRAME_ACTION_CATEGORY_OFFSET] ==
783*5113495bSYour Name 				WLAN_HDD_ACTION_FRAME_CATEGORY_PUBLIC)
784*5113495bSYour Name 		return;
785*5113495bSYour Name 
786*5113495bSYour Name 	da = frame + WLAN_HDD_MGMT_FRAME_DA_OFFSET;
787*5113495bSYour Name 	sa = frame + WLAN_HDD_MGMT_FRAME_SA_OFFSET;
788*5113495bSYour Name 	bssid = frame + WLAN_HDD_MGMT_FRAME_BSSID_OFFSET;
789*5113495bSYour Name 
790*5113495bSYour Name 	peer = wlan_objmgr_vdev_try_get_bsspeer(vdev, WLAN_MLO_MGR_ID);
791*5113495bSYour Name 	if (!peer) {
792*5113495bSYour Name 		mlo_debug("Peer not found");
793*5113495bSYour Name 		return;
794*5113495bSYour Name 	}
795*5113495bSYour Name 
796*5113495bSYour Name 	mlo_debug("Change link addr to MLD addr for non-Public action frame");
797*5113495bSYour Name 	/* DA = VDEV's MLD address.
798*5113495bSYour Name 	 * SA = VDEV's BSS peer's MLD address.
799*5113495bSYour Name 	 * BSSID = VDEV's BSS peer's MLD address.
800*5113495bSYour Name 	 */
801*5113495bSYour Name 
802*5113495bSYour Name 	qdf_ether_addr_copy(da, wlan_vdev_mlme_get_mldaddr(vdev));
803*5113495bSYour Name 	qdf_ether_addr_copy(sa, wlan_peer_mlme_get_mldaddr(peer));
804*5113495bSYour Name 	qdf_ether_addr_copy(bssid, wlan_peer_mlme_get_mldaddr(peer));
805*5113495bSYour Name 
806*5113495bSYour Name 	wlan_objmgr_peer_release_ref(peer, WLAN_MLO_MGR_ID);
807*5113495bSYour Name }
808*5113495bSYour Name #endif
809*5113495bSYour Name 
mlo_ap_ctx_deinit(struct wlan_mlo_dev_context * ml_dev)810*5113495bSYour Name static QDF_STATUS mlo_ap_ctx_deinit(struct wlan_mlo_dev_context *ml_dev)
811*5113495bSYour Name {
812*5113495bSYour Name 	wlan_mlo_vdev_aid_mgr_deinit(ml_dev);
813*5113495bSYour Name 	mlo_ap_lock_destroy(ml_dev->ap_ctx);
814*5113495bSYour Name 	qdf_mem_free(ml_dev->ap_ctx);
815*5113495bSYour Name 	ml_dev->ap_ctx = NULL;
816*5113495bSYour Name 
817*5113495bSYour Name 	return QDF_STATUS_SUCCESS;
818*5113495bSYour Name }
819*5113495bSYour Name 
mlo_ap_ctx_init(struct wlan_mlo_dev_context * ml_dev)820*5113495bSYour Name static QDF_STATUS mlo_ap_ctx_init(struct wlan_mlo_dev_context *ml_dev)
821*5113495bSYour Name {
822*5113495bSYour Name 	struct wlan_mlo_ap *ap_ctx;
823*5113495bSYour Name 
824*5113495bSYour Name 	ap_ctx = qdf_mem_malloc(sizeof(*ap_ctx));
825*5113495bSYour Name 	if (!ap_ctx) {
826*5113495bSYour Name 		mlo_err("MLO AP ctx alloc failure");
827*5113495bSYour Name 		return QDF_STATUS_E_NOMEM;
828*5113495bSYour Name 	}
829*5113495bSYour Name 
830*5113495bSYour Name 	ml_dev->ap_ctx = ap_ctx;
831*5113495bSYour Name 	mlo_ap_lock_create(ml_dev->ap_ctx);
832*5113495bSYour Name 	if (wlan_mlo_vdev_aid_mgr_init(ml_dev) != QDF_STATUS_SUCCESS) {
833*5113495bSYour Name 		mlo_ap_ctx_deinit(ml_dev);
834*5113495bSYour Name 		return QDF_STATUS_E_NOMEM;
835*5113495bSYour Name 	}
836*5113495bSYour Name 
837*5113495bSYour Name 	return QDF_STATUS_SUCCESS;
838*5113495bSYour Name }
839*5113495bSYour Name 
840*5113495bSYour Name #ifdef CONFIG_AP_PLATFORM
841*5113495bSYour Name static inline
wlan_mlo_check_grp_id(uint8_t ref_id,struct wlan_objmgr_vdev * vdev)842*5113495bSYour Name QDF_STATUS wlan_mlo_check_grp_id(uint8_t ref_id,
843*5113495bSYour Name 				 struct wlan_objmgr_vdev *vdev)
844*5113495bSYour Name {
845*5113495bSYour Name 	struct wlan_objmgr_psoc *psoc;
846*5113495bSYour Name 	uint8_t grp_id = 0;
847*5113495bSYour Name 
848*5113495bSYour Name 	psoc = wlan_vdev_get_psoc(vdev);
849*5113495bSYour Name 	if (!mlo_psoc_get_grp_id(psoc, &grp_id)) {
850*5113495bSYour Name 		mlo_err("Unable to get mlo group id");
851*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
852*5113495bSYour Name 	}
853*5113495bSYour Name 
854*5113495bSYour Name 	if (grp_id != ref_id) {
855*5113495bSYour Name 		mlo_err("Error : MLD VAP Configuration with different WSI/MLD Groups");
856*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
857*5113495bSYour Name 	}
858*5113495bSYour Name 
859*5113495bSYour Name 	return QDF_STATUS_SUCCESS;
860*5113495bSYour Name }
861*5113495bSYour Name 
862*5113495bSYour Name static inline
wlan_mlo_pdev_check(struct wlan_objmgr_pdev * ref_pdev,struct wlan_objmgr_vdev * vdev)863*5113495bSYour Name QDF_STATUS wlan_mlo_pdev_check(struct wlan_objmgr_pdev *ref_pdev,
864*5113495bSYour Name 			       struct wlan_objmgr_vdev *vdev)
865*5113495bSYour Name {
866*5113495bSYour Name 	struct wlan_objmgr_pdev *pdev;
867*5113495bSYour Name 	struct wlan_objmgr_psoc *psoc;
868*5113495bSYour Name 	uint8_t grp_id = 0;
869*5113495bSYour Name 
870*5113495bSYour Name 	pdev = wlan_vdev_get_pdev(vdev);
871*5113495bSYour Name 
872*5113495bSYour Name 	psoc = wlan_pdev_get_psoc(ref_pdev);
873*5113495bSYour Name 	if (!mlo_psoc_get_grp_id(psoc, &grp_id)) {
874*5113495bSYour Name 		mlo_err("Unable to get the MLO Group ID for the vdev");
875*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
876*5113495bSYour Name 	}
877*5113495bSYour Name 
878*5113495bSYour Name 	if (mlo_check_all_pdev_state(psoc, grp_id, MLO_LINK_SETUP_DONE)) {
879*5113495bSYour Name 		mlo_err("Pdev link is not in ready state, initial link setup failed");
880*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
881*5113495bSYour Name 	}
882*5113495bSYour Name 
883*5113495bSYour Name 	if (ref_pdev == pdev) {
884*5113495bSYour Name 		mlo_err("MLD vdev for this pdev already found, investigate config");
885*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
886*5113495bSYour Name 	}
887*5113495bSYour Name 
888*5113495bSYour Name 	if (wlan_mlo_check_grp_id(grp_id, vdev))
889*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
890*5113495bSYour Name 
891*5113495bSYour Name 	return QDF_STATUS_SUCCESS;
892*5113495bSYour Name }
893*5113495bSYour Name 
894*5113495bSYour Name static inline
mlo_dev_config_check(struct wlan_mlo_dev_context * ml_dev,struct wlan_objmgr_vdev * vdev)895*5113495bSYour Name QDF_STATUS mlo_dev_config_check(struct wlan_mlo_dev_context *ml_dev,
896*5113495bSYour Name 				struct wlan_objmgr_vdev *vdev)
897*5113495bSYour Name {
898*5113495bSYour Name 	return QDF_STATUS_SUCCESS;
899*5113495bSYour Name }
900*5113495bSYour Name 
901*5113495bSYour Name #else
902*5113495bSYour Name static inline
mlo_dev_config_check(struct wlan_mlo_dev_context * ml_dev,struct wlan_objmgr_vdev * vdev)903*5113495bSYour Name QDF_STATUS mlo_dev_config_check(struct wlan_mlo_dev_context *ml_dev,
904*5113495bSYour Name 				struct wlan_objmgr_vdev *vdev)
905*5113495bSYour Name {
906*5113495bSYour Name 	enum QDF_OPMODE opmode = wlan_vdev_mlme_get_opmode(vdev);
907*5113495bSYour Name 
908*5113495bSYour Name 	if (wlan_mlo_check_valid_config(ml_dev, wlan_vdev_get_pdev(vdev),
909*5113495bSYour Name 					opmode) != QDF_STATUS_SUCCESS)
910*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
911*5113495bSYour Name 
912*5113495bSYour Name 	return QDF_STATUS_SUCCESS;
913*5113495bSYour Name }
914*5113495bSYour Name 
915*5113495bSYour Name static inline
wlan_mlo_pdev_check(struct wlan_objmgr_pdev * ref_pdev,struct wlan_objmgr_vdev * vdev)916*5113495bSYour Name QDF_STATUS wlan_mlo_pdev_check(struct wlan_objmgr_pdev *ref_pdev,
917*5113495bSYour Name 			       struct wlan_objmgr_vdev *vdev)
918*5113495bSYour Name {
919*5113495bSYour Name 	return QDF_STATUS_SUCCESS;
920*5113495bSYour Name }
921*5113495bSYour Name #endif
922*5113495bSYour Name 
wlan_mlo_check_valid_config(struct wlan_mlo_dev_context * ml_dev,struct wlan_objmgr_pdev * pdev,enum QDF_OPMODE opmode)923*5113495bSYour Name QDF_STATUS wlan_mlo_check_valid_config(struct wlan_mlo_dev_context *ml_dev,
924*5113495bSYour Name 				       struct wlan_objmgr_pdev *pdev,
925*5113495bSYour Name 				       enum QDF_OPMODE opmode)
926*5113495bSYour Name {
927*5113495bSYour Name 	uint32_t id = 0;
928*5113495bSYour Name 	struct wlan_objmgr_vdev *vdev;
929*5113495bSYour Name 
930*5113495bSYour Name 	if (!ml_dev)
931*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
932*5113495bSYour Name 
933*5113495bSYour Name 	if (!pdev)
934*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
935*5113495bSYour Name 
936*5113495bSYour Name 	mlo_dev_lock_acquire(ml_dev);
937*5113495bSYour Name 	while (id < WLAN_UMAC_MLO_MAX_VDEVS) {
938*5113495bSYour Name 		vdev = ml_dev->wlan_vdev_list[id];
939*5113495bSYour Name 		if (vdev) {
940*5113495bSYour Name 			if (wlan_mlo_pdev_check(pdev, vdev)) {
941*5113495bSYour Name 				mlo_dev_lock_release(ml_dev);
942*5113495bSYour Name 				return QDF_STATUS_E_FAILURE;
943*5113495bSYour Name 			}
944*5113495bSYour Name 
945*5113495bSYour Name 			if (wlan_vdev_mlme_get_opmode(vdev) != opmode) {
946*5113495bSYour Name 				mlo_err("Invalid opmode %d type found expected %d, investigate config",
947*5113495bSYour Name 					wlan_vdev_mlme_get_opmode(vdev),
948*5113495bSYour Name 					opmode);
949*5113495bSYour Name 				mlo_dev_lock_release(ml_dev);
950*5113495bSYour Name 				return QDF_STATUS_E_FAILURE;
951*5113495bSYour Name 			}
952*5113495bSYour Name 		}
953*5113495bSYour Name 		id++;
954*5113495bSYour Name 	}
955*5113495bSYour Name 
956*5113495bSYour Name 	mlo_dev_lock_release(ml_dev);
957*5113495bSYour Name 	return QDF_STATUS_SUCCESS;
958*5113495bSYour Name }
959*5113495bSYour Name 
960*5113495bSYour Name /**
961*5113495bSYour Name  * mlo_t2lm_ctx_init() - API to initialize the t2lm context with the default
962*5113495bSYour Name  * values.
963*5113495bSYour Name  * @ml_dev: Pointer to ML Dev context
964*5113495bSYour Name  * @vdev: Pointer to vdev structure
965*5113495bSYour Name  *
966*5113495bSYour Name  * Return: None
967*5113495bSYour Name  */
mlo_t2lm_ctx_init(struct wlan_mlo_dev_context * ml_dev,struct wlan_objmgr_vdev * vdev)968*5113495bSYour Name static inline void mlo_t2lm_ctx_init(struct wlan_mlo_dev_context *ml_dev,
969*5113495bSYour Name 				     struct wlan_objmgr_vdev *vdev)
970*5113495bSYour Name {
971*5113495bSYour Name 	struct wlan_t2lm_info *t2lm;
972*5113495bSYour Name 
973*5113495bSYour Name 	t2lm = &ml_dev->t2lm_ctx.established_t2lm.t2lm;
974*5113495bSYour Name 
975*5113495bSYour Name 	qdf_mem_zero(&ml_dev->t2lm_ctx, sizeof(struct wlan_t2lm_context));
976*5113495bSYour Name 
977*5113495bSYour Name 	t2lm->direction = WLAN_T2LM_BIDI_DIRECTION;
978*5113495bSYour Name 	t2lm->default_link_mapping = 1;
979*5113495bSYour Name 	t2lm->link_mapping_size = 0;
980*5113495bSYour Name 
981*5113495bSYour Name 	wlan_mlo_t2lm_timer_init(vdev);
982*5113495bSYour Name 	wlan_mlo_t2lm_register_link_update_notify_handler(ml_dev);
983*5113495bSYour Name }
984*5113495bSYour Name 
985*5113495bSYour Name /**
986*5113495bSYour Name  * mlo_epcs_ctx_init() - API to initialize the epcs context with the
987*5113495bSYour Name  * default values.
988*5113495bSYour Name  * @ml_dev: Pointer to ML Dev context
989*5113495bSYour Name  *
990*5113495bSYour Name  * Return: None
991*5113495bSYour Name  */
mlo_epcs_ctx_init(struct wlan_mlo_dev_context * ml_dev)992*5113495bSYour Name static inline void mlo_epcs_ctx_init(struct wlan_mlo_dev_context *ml_dev)
993*5113495bSYour Name {
994*5113495bSYour Name 	struct wlan_epcs_context *epcs_ctx;
995*5113495bSYour Name 
996*5113495bSYour Name 	epcs_ctx = &ml_dev->epcs_ctx;
997*5113495bSYour Name 	qdf_mem_zero(epcs_ctx, sizeof(struct wlan_epcs_context));
998*5113495bSYour Name 	epcs_dev_lock_create(epcs_ctx);
999*5113495bSYour Name }
1000*5113495bSYour Name 
1001*5113495bSYour Name #ifdef QCA_SUPPORT_PRIMARY_LINK_MIGRATE
1002*5113495bSYour Name /**
1003*5113495bSYour Name  * mlo_ptqm_migration_init() - API to initialize ptqm migration timer
1004*5113495bSYour Name  * @ml_dev: Pointer to ML Dev context
1005*5113495bSYour Name  *
1006*5113495bSYour Name  * Return: None
1007*5113495bSYour Name  */
mlo_ptqm_migration_init(struct wlan_mlo_dev_context * ml_dev)1008*5113495bSYour Name static inline void mlo_ptqm_migration_init(struct wlan_mlo_dev_context *ml_dev)
1009*5113495bSYour Name {
1010*5113495bSYour Name 	qdf_timer_init(NULL, &ml_dev->ptqm_migrate_timer,
1011*5113495bSYour Name 		       mlo_mlme_ptqm_migrate_timer_cb, (void *)(ml_dev),
1012*5113495bSYour Name 		       QDF_TIMER_TYPE_WAKE_APPS);
1013*5113495bSYour Name }
1014*5113495bSYour Name #else
mlo_ptqm_migration_init(struct wlan_mlo_dev_context * ml_dev)1015*5113495bSYour Name static inline void mlo_ptqm_migration_init(struct wlan_mlo_dev_context *ml_dev)
1016*5113495bSYour Name { }
1017*5113495bSYour Name #endif
1018*5113495bSYour Name 
1019*5113495bSYour Name #if defined(WLAN_FEATURE_11BE_MLO) && defined(WLAN_MLO_MULTI_CHIP)
1020*5113495bSYour Name static QDF_STATUS
mlo_add_to_bridge_vdev_list(struct wlan_objmgr_vdev * vdev)1021*5113495bSYour Name mlo_add_to_bridge_vdev_list(struct wlan_objmgr_vdev *vdev)
1022*5113495bSYour Name {
1023*5113495bSYour Name 	struct wlan_mlo_dev_context *ml_dev;
1024*5113495bSYour Name 	struct qdf_mac_addr *mld_addr;
1025*5113495bSYour Name 	uint8_t id = 0;
1026*5113495bSYour Name 
1027*5113495bSYour Name 	if (!vdev)
1028*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
1029*5113495bSYour Name 
1030*5113495bSYour Name 	mld_addr = (struct qdf_mac_addr *)wlan_vdev_mlme_get_mldaddr(vdev);
1031*5113495bSYour Name 	ml_dev = wlan_mlo_get_mld_ctx_by_mldaddr(mld_addr);
1032*5113495bSYour Name 
1033*5113495bSYour Name 	if (ml_dev) {
1034*5113495bSYour Name 		mlo_dev_lock_acquire(ml_dev);
1035*5113495bSYour Name 		while (id < WLAN_UMAC_MLO_MAX_BRIDGE_VDEVS) {
1036*5113495bSYour Name 			if (ml_dev->wlan_bridge_vdev_list[id]) {
1037*5113495bSYour Name 				id++;
1038*5113495bSYour Name 				continue;
1039*5113495bSYour Name 			}
1040*5113495bSYour Name 
1041*5113495bSYour Name 			ml_dev->wlan_bridge_vdev_list[id] = vdev;
1042*5113495bSYour Name 			ml_dev->wlan_bridge_vdev_count++;
1043*5113495bSYour Name 			vdev->mlo_dev_ctx = ml_dev;
1044*5113495bSYour Name 			break;
1045*5113495bSYour Name 		}
1046*5113495bSYour Name 		mlo_dev_lock_release(ml_dev);
1047*5113495bSYour Name 
1048*5113495bSYour Name 		if (id == WLAN_UMAC_MLO_MAX_BRIDGE_VDEVS)
1049*5113495bSYour Name 			return QDF_STATUS_E_FAILURE;
1050*5113495bSYour Name 
1051*5113495bSYour Name 		return QDF_STATUS_SUCCESS;
1052*5113495bSYour Name 	}
1053*5113495bSYour Name 
1054*5113495bSYour Name 	return QDF_STATUS_E_FAILURE;
1055*5113495bSYour Name }
1056*5113495bSYour Name 
1057*5113495bSYour Name static QDF_STATUS
mld_delete_from_bridge_vdev_list(struct wlan_objmgr_vdev * vdev)1058*5113495bSYour Name mld_delete_from_bridge_vdev_list(struct wlan_objmgr_vdev *vdev)
1059*5113495bSYour Name {
1060*5113495bSYour Name 	struct wlan_mlo_dev_context *ml_dev;
1061*5113495bSYour Name 	struct qdf_mac_addr *mld_addr;
1062*5113495bSYour Name 	uint8_t id = 0;
1063*5113495bSYour Name 
1064*5113495bSYour Name 	if (!vdev)
1065*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
1066*5113495bSYour Name 
1067*5113495bSYour Name 	mld_addr = (struct qdf_mac_addr *)wlan_vdev_mlme_get_mldaddr(vdev);
1068*5113495bSYour Name 	ml_dev = wlan_mlo_get_mld_ctx_by_mldaddr(mld_addr);
1069*5113495bSYour Name 
1070*5113495bSYour Name 	if (ml_dev) {
1071*5113495bSYour Name 		mlo_dev_lock_acquire(ml_dev);
1072*5113495bSYour Name 		while (id < WLAN_UMAC_MLO_MAX_BRIDGE_VDEVS) {
1073*5113495bSYour Name 			if (ml_dev->wlan_bridge_vdev_list[id] == vdev) {
1074*5113495bSYour Name 				vdev->mlo_dev_ctx = NULL;
1075*5113495bSYour Name 				ml_dev->wlan_bridge_vdev_list[id] = NULL;
1076*5113495bSYour Name 				ml_dev->wlan_bridge_vdev_count--;
1077*5113495bSYour Name 				break;
1078*5113495bSYour Name 			}
1079*5113495bSYour Name 			id++;
1080*5113495bSYour Name 		}
1081*5113495bSYour Name 		mlo_dev_lock_release(ml_dev);
1082*5113495bSYour Name 		return QDF_STATUS_SUCCESS;
1083*5113495bSYour Name 	}
1084*5113495bSYour Name 
1085*5113495bSYour Name 	return QDF_STATUS_E_FAILURE;
1086*5113495bSYour Name }
1087*5113495bSYour Name #else
1088*5113495bSYour Name static QDF_STATUS
mlo_add_to_bridge_vdev_list(struct wlan_objmgr_vdev * vdev)1089*5113495bSYour Name mlo_add_to_bridge_vdev_list(struct wlan_objmgr_vdev *vdev)
1090*5113495bSYour Name {
1091*5113495bSYour Name 	return QDF_STATUS_SUCCESS;
1092*5113495bSYour Name }
1093*5113495bSYour Name 
1094*5113495bSYour Name static QDF_STATUS
mld_delete_from_bridge_vdev_list(struct wlan_objmgr_vdev * vdev)1095*5113495bSYour Name mld_delete_from_bridge_vdev_list(struct wlan_objmgr_vdev *vdev)
1096*5113495bSYour Name {
1097*5113495bSYour Name 	return QDF_STATUS_SUCCESS;
1098*5113495bSYour Name }
1099*5113495bSYour Name #endif
1100*5113495bSYour Name 
mlo_dev_ctx_init(struct wlan_objmgr_vdev * vdev)1101*5113495bSYour Name static QDF_STATUS mlo_dev_ctx_init(struct wlan_objmgr_vdev *vdev)
1102*5113495bSYour Name {
1103*5113495bSYour Name 	struct wlan_mlo_dev_context *ml_dev;
1104*5113495bSYour Name 	QDF_STATUS status = QDF_STATUS_SUCCESS;
1105*5113495bSYour Name 	struct qdf_mac_addr *mld_addr;
1106*5113495bSYour Name 	struct mlo_mgr_context *g_mlo_ctx = wlan_objmgr_get_mlo_ctx();
1107*5113495bSYour Name 	uint8_t id = 0;
1108*5113495bSYour Name 	struct wlan_objmgr_psoc *psoc = NULL;
1109*5113495bSYour Name 
1110*5113495bSYour Name 	if (wlan_vdev_mlme_is_mlo_bridge_vdev(vdev)) {
1111*5113495bSYour Name 		status = mlo_add_to_bridge_vdev_list(vdev);
1112*5113495bSYour Name 		if (!QDF_IS_STATUS_SUCCESS(status))
1113*5113495bSYour Name 			mlo_err("Failed to init bridge vap ctx");
1114*5113495bSYour Name 		return status;
1115*5113495bSYour Name 	}
1116*5113495bSYour Name 
1117*5113495bSYour Name 	mld_addr = (struct qdf_mac_addr *)wlan_vdev_mlme_get_mldaddr(vdev);
1118*5113495bSYour Name 	ml_dev = wlan_mlo_get_mld_ctx_by_mldaddr(mld_addr);
1119*5113495bSYour Name 	psoc = wlan_vdev_get_psoc(vdev);
1120*5113495bSYour Name 
1121*5113495bSYour Name 	if (!psoc) {
1122*5113495bSYour Name 		mlo_err("Failed to get psoc");
1123*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
1124*5113495bSYour Name 	}
1125*5113495bSYour Name 
1126*5113495bSYour Name 	if (ml_dev) {
1127*5113495bSYour Name 		if (mlo_dev_config_check(ml_dev, vdev) != QDF_STATUS_SUCCESS)
1128*5113495bSYour Name 			return QDF_STATUS_E_FAILURE;
1129*5113495bSYour Name 
1130*5113495bSYour Name 		mlo_dev_lock_acquire(ml_dev);
1131*5113495bSYour Name 		while (id < WLAN_UMAC_MLO_MAX_VDEVS) {
1132*5113495bSYour Name 			if (ml_dev->wlan_vdev_list[id]) {
1133*5113495bSYour Name 				id++;
1134*5113495bSYour Name 				continue;
1135*5113495bSYour Name 			}
1136*5113495bSYour Name 
1137*5113495bSYour Name 			ml_dev->wlan_vdev_list[id] = vdev;
1138*5113495bSYour Name 			ml_dev->wlan_vdev_count++;
1139*5113495bSYour Name 			vdev->mlo_dev_ctx = ml_dev;
1140*5113495bSYour Name 
1141*5113495bSYour Name 			if (wlan_vdev_mlme_get_opmode(vdev) == QDF_SAP_MODE)
1142*5113495bSYour Name 				wlan_mlo_vdev_alloc_aid_mgr(ml_dev, vdev);
1143*5113495bSYour Name 
1144*5113495bSYour Name 			break;
1145*5113495bSYour Name 		}
1146*5113495bSYour Name 		mlo_dev_lock_release(ml_dev);
1147*5113495bSYour Name 		return QDF_STATUS_SUCCESS;
1148*5113495bSYour Name 	}
1149*5113495bSYour Name 
1150*5113495bSYour Name 	if (qdf_list_size(&g_mlo_ctx->ml_dev_list) >= WLAN_UMAC_MLO_MAX_DEV) {
1151*5113495bSYour Name 		mlo_err("No more MLD allowed");
1152*5113495bSYour Name 		return QDF_STATUS_E_RESOURCES;
1153*5113495bSYour Name 	}
1154*5113495bSYour Name 
1155*5113495bSYour Name 	/* Create a new ML dev context */
1156*5113495bSYour Name 	ml_dev = qdf_mem_malloc(sizeof(*ml_dev));
1157*5113495bSYour Name 	if (!ml_dev) {
1158*5113495bSYour Name 		mlo_err("Failed to allocate memory for ML dev");
1159*5113495bSYour Name 		return QDF_STATUS_E_NOMEM;
1160*5113495bSYour Name 	}
1161*5113495bSYour Name 
1162*5113495bSYour Name 	qdf_copy_macaddr(&ml_dev->mld_addr, mld_addr);
1163*5113495bSYour Name 	ml_dev->wlan_vdev_list[0] = vdev;
1164*5113495bSYour Name 	ml_dev->wlan_vdev_count++;
1165*5113495bSYour Name 	vdev->mlo_dev_ctx = ml_dev;
1166*5113495bSYour Name 
1167*5113495bSYour Name 	mlo_dev_lock_create(ml_dev);
1168*5113495bSYour Name 	tsf_recalculation_lock_create(ml_dev);
1169*5113495bSYour Name 	if (wlan_vdev_mlme_get_opmode(vdev) == QDF_STA_MODE) {
1170*5113495bSYour Name 		ml_dev->sta_ctx = qdf_mem_malloc(sizeof(struct wlan_mlo_sta));
1171*5113495bSYour Name 		if (!ml_dev->sta_ctx) {
1172*5113495bSYour Name 			tsf_recalculation_lock_destroy(ml_dev);
1173*5113495bSYour Name 			mlo_dev_lock_destroy(ml_dev);
1174*5113495bSYour Name 			qdf_mem_free(ml_dev);
1175*5113495bSYour Name 			return QDF_STATUS_E_NOMEM;
1176*5113495bSYour Name 		}
1177*5113495bSYour Name 		copied_conn_req_lock_create(ml_dev->sta_ctx);
1178*5113495bSYour Name #if defined(WLAN_FEATURE_11BE_MLO) && defined(WLAN_MLO_MULTI_CHIP)
1179*5113495bSYour Name 		ml_dev->bridge_sta_ctx = qdf_mem_malloc(sizeof(struct wlan_mlo_bridge_sta));
1180*5113495bSYour Name 		if (!ml_dev->bridge_sta_ctx) {
1181*5113495bSYour Name 			tsf_recalculation_lock_destroy(ml_dev);
1182*5113495bSYour Name 			mlo_dev_lock_destroy(ml_dev);
1183*5113495bSYour Name 			qdf_mem_free(ml_dev->sta_ctx);
1184*5113495bSYour Name 			qdf_mem_free(ml_dev);
1185*5113495bSYour Name 			return QDF_STATUS_E_NOMEM;
1186*5113495bSYour Name 		}
1187*5113495bSYour Name #endif
1188*5113495bSYour Name 	} else if (wlan_vdev_mlme_get_opmode(vdev) == QDF_SAP_MODE) {
1189*5113495bSYour Name 		if (mlo_ap_ctx_init(ml_dev) != QDF_STATUS_SUCCESS) {
1190*5113495bSYour Name 			tsf_recalculation_lock_destroy(ml_dev);
1191*5113495bSYour Name 			mlo_dev_lock_destroy(ml_dev);
1192*5113495bSYour Name 			qdf_mem_free(ml_dev);
1193*5113495bSYour Name 			mlo_err("Failed to allocate memory for ap ctx");
1194*5113495bSYour Name 			return QDF_STATUS_E_NOMEM;
1195*5113495bSYour Name 		}
1196*5113495bSYour Name 	}
1197*5113495bSYour Name 
1198*5113495bSYour Name 	/* Create DP MLO Device Context */
1199*5113495bSYour Name 	if (cdp_mlo_dev_ctxt_create(wlan_psoc_get_dp_handle(psoc),
1200*5113495bSYour Name 				    (uint8_t *)mld_addr) !=
1201*5113495bSYour Name 				    QDF_STATUS_SUCCESS) {
1202*5113495bSYour Name 		tsf_recalculation_lock_destroy(ml_dev);
1203*5113495bSYour Name 		if (wlan_vdev_mlme_get_opmode(vdev) == QDF_STA_MODE) {
1204*5113495bSYour Name 			qdf_mem_free(ml_dev->sta_ctx);
1205*5113495bSYour Name #if defined(WLAN_FEATURE_11BE_MLO) && defined(WLAN_MLO_MULTI_CHIP)
1206*5113495bSYour Name 			qdf_mem_free(ml_dev->bridge_sta_ctx);
1207*5113495bSYour Name #endif
1208*5113495bSYour Name 		} else if (wlan_vdev_mlme_get_opmode(vdev) == QDF_SAP_MODE) {
1209*5113495bSYour Name 			mlo_ap_ctx_deinit(ml_dev);
1210*5113495bSYour Name 		}
1211*5113495bSYour Name 		mlo_dev_lock_destroy(ml_dev);
1212*5113495bSYour Name 		qdf_mem_free(ml_dev);
1213*5113495bSYour Name 		mlo_err("Failed to create DP MLO Dev ctxt");
1214*5113495bSYour Name 		return QDF_STATUS_E_NOMEM;
1215*5113495bSYour Name 	}
1216*5113495bSYour Name 
1217*5113495bSYour Name 	ml_dev->mlo_max_recom_simult_links =
1218*5113495bSYour Name 		WLAN_UMAC_MLO_RECOM_MAX_SIMULT_LINKS_DEFAULT;
1219*5113495bSYour Name 
1220*5113495bSYour Name 	mlo_dev_mlpeer_list_init(ml_dev);
1221*5113495bSYour Name 
1222*5113495bSYour Name 	ml_link_lock_acquire(g_mlo_ctx);
1223*5113495bSYour Name 	if (qdf_list_size(&g_mlo_ctx->ml_dev_list) < WLAN_UMAC_MLO_MAX_DEV)
1224*5113495bSYour Name 		qdf_list_insert_back(&g_mlo_ctx->ml_dev_list, &ml_dev->node);
1225*5113495bSYour Name 	ml_link_lock_release(g_mlo_ctx);
1226*5113495bSYour Name 
1227*5113495bSYour Name 	mlo_t2lm_ctx_init(ml_dev, vdev);
1228*5113495bSYour Name 	mlo_epcs_ctx_init(ml_dev);
1229*5113495bSYour Name 	mlo_ptqm_migration_init(ml_dev);
1230*5113495bSYour Name 	mlo_mgr_link_switch_init(psoc, ml_dev);
1231*5113495bSYour Name 
1232*5113495bSYour Name 	return status;
1233*5113495bSYour Name }
1234*5113495bSYour Name 
1235*5113495bSYour Name #ifdef QCA_SUPPORT_PRIMARY_LINK_MIGRATE
1236*5113495bSYour Name /**
1237*5113495bSYour Name  * mlo_ptqm_migration_deinit() - API to deinitialize ptqm migration timer
1238*5113495bSYour Name  * @ml_dev: Pointer to ML Dev context
1239*5113495bSYour Name  *
1240*5113495bSYour Name  * Return: None
1241*5113495bSYour Name  */
mlo_ptqm_migration_deinit(struct wlan_mlo_dev_context * ml_dev)1242*5113495bSYour Name static inline void mlo_ptqm_migration_deinit(
1243*5113495bSYour Name 			struct wlan_mlo_dev_context *ml_dev)
1244*5113495bSYour Name {
1245*5113495bSYour Name 	qdf_timer_free(&ml_dev->ptqm_migrate_timer);
1246*5113495bSYour Name }
1247*5113495bSYour Name #else
mlo_ptqm_migration_deinit(struct wlan_mlo_dev_context * ml_dev)1248*5113495bSYour Name static inline void mlo_ptqm_migration_deinit(
1249*5113495bSYour Name 			struct wlan_mlo_dev_context *ml_dev)
1250*5113495bSYour Name { }
1251*5113495bSYour Name #endif
1252*5113495bSYour Name 
1253*5113495bSYour Name /**
1254*5113495bSYour Name  * mlo_t2lm_ctx_deinit() - API to deinitialize the t2lm context with the default
1255*5113495bSYour Name  * values.
1256*5113495bSYour Name  * @vdev: Pointer to vdev structure
1257*5113495bSYour Name  * @ml_dev: Pointer to mlo dev context
1258*5113495bSYour Name  *
1259*5113495bSYour Name  * Return: None
1260*5113495bSYour Name  */
mlo_t2lm_ctx_deinit(struct wlan_objmgr_vdev * vdev,struct wlan_mlo_dev_context * ml_dev)1261*5113495bSYour Name static inline void mlo_t2lm_ctx_deinit(struct wlan_objmgr_vdev *vdev,
1262*5113495bSYour Name 				       struct wlan_mlo_dev_context *ml_dev)
1263*5113495bSYour Name {
1264*5113495bSYour Name 	wlan_mlo_t2lm_timer_deinit(vdev);
1265*5113495bSYour Name 	wlan_unregister_t2lm_link_update_notify_handler(
1266*5113495bSYour Name 			ml_dev, ml_dev->t2lm_ctx.link_update_callback_index);
1267*5113495bSYour Name }
1268*5113495bSYour Name 
1269*5113495bSYour Name /**
1270*5113495bSYour Name  * mlo_epcs_ctx_deinit() - API to deinitialize the epcs context with the default
1271*5113495bSYour Name  * values.
1272*5113495bSYour Name  * @mlo_dev_ctx: MLO dev context pointer
1273*5113495bSYour Name  *
1274*5113495bSYour Name  * Return: None
1275*5113495bSYour Name  */
mlo_epcs_ctx_deinit(struct wlan_mlo_dev_context * mlo_dev_ctx)1276*5113495bSYour Name static inline void mlo_epcs_ctx_deinit(struct wlan_mlo_dev_context *mlo_dev_ctx)
1277*5113495bSYour Name {
1278*5113495bSYour Name 	epcs_dev_lock_destroy(&mlo_dev_ctx->epcs_ctx);
1279*5113495bSYour Name }
1280*5113495bSYour Name 
1281*5113495bSYour Name #ifdef WLAN_FEATURE_ROAM_OFFLOAD
ml_free_copied_reassoc_rsp(struct wlan_mlo_sta * sta_ctx)1282*5113495bSYour Name static void ml_free_copied_reassoc_rsp(struct wlan_mlo_sta *sta_ctx)
1283*5113495bSYour Name {
1284*5113495bSYour Name 	wlan_cm_free_connect_resp(sta_ctx->copied_reassoc_rsp);
1285*5113495bSYour Name }
1286*5113495bSYour Name #else
ml_free_copied_reassoc_rsp(struct wlan_mlo_sta * sta_ctx)1287*5113495bSYour Name static void ml_free_copied_reassoc_rsp(struct wlan_mlo_sta *sta_ctx)
1288*5113495bSYour Name {
1289*5113495bSYour Name 	return;
1290*5113495bSYour Name }
1291*5113495bSYour Name #endif
1292*5113495bSYour Name 
mlo_dev_ctx_deinit(struct wlan_objmgr_vdev * vdev)1293*5113495bSYour Name static QDF_STATUS mlo_dev_ctx_deinit(struct wlan_objmgr_vdev *vdev)
1294*5113495bSYour Name {
1295*5113495bSYour Name 	struct wlan_mlo_dev_context *ml_dev;
1296*5113495bSYour Name 	QDF_STATUS status = QDF_STATUS_SUCCESS;
1297*5113495bSYour Name 	struct qdf_mac_addr *mld_addr;
1298*5113495bSYour Name 	struct mlo_mgr_context *g_mlo_ctx = wlan_objmgr_get_mlo_ctx();
1299*5113495bSYour Name 	uint8_t id = 0;
1300*5113495bSYour Name 	struct wlan_cm_connect_req *connect_req;
1301*5113495bSYour Name 	struct wlan_objmgr_psoc *psoc = NULL;
1302*5113495bSYour Name 
1303*5113495bSYour Name 	mld_addr = (struct qdf_mac_addr *)wlan_vdev_mlme_get_mldaddr(vdev);
1304*5113495bSYour Name 	ml_dev = wlan_mlo_get_mld_ctx_by_mldaddr(mld_addr);
1305*5113495bSYour Name 	psoc = wlan_vdev_get_psoc(vdev);
1306*5113495bSYour Name 
1307*5113495bSYour Name 	if (!psoc) {
1308*5113495bSYour Name 		mlo_err("Failed to get psoc");
1309*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
1310*5113495bSYour Name 	}
1311*5113495bSYour Name 
1312*5113495bSYour Name 	if (!ml_dev) {
1313*5113495bSYour Name 		mlo_err("Failed to get MLD dev context by mld addr "QDF_MAC_ADDR_FMT,
1314*5113495bSYour Name 			QDF_MAC_ADDR_REF(mld_addr->bytes));
1315*5113495bSYour Name 		if (!vdev->mlo_dev_ctx) {
1316*5113495bSYour Name 			mlo_err("Failed to get MLD dev context from vdev");
1317*5113495bSYour Name 			return QDF_STATUS_SUCCESS;
1318*5113495bSYour Name 		}
1319*5113495bSYour Name 		ml_dev = vdev->mlo_dev_ctx;
1320*5113495bSYour Name 	}
1321*5113495bSYour Name 
1322*5113495bSYour Name 	mlo_debug("deleting vdev from MLD device ctx "QDF_MAC_ADDR_FMT,
1323*5113495bSYour Name 		  QDF_MAC_ADDR_REF(mld_addr->bytes));
1324*5113495bSYour Name 
1325*5113495bSYour Name 	mlo_dev_lock_acquire(ml_dev);
1326*5113495bSYour Name 	while (id < WLAN_UMAC_MLO_MAX_VDEVS) {
1327*5113495bSYour Name 		if (ml_dev->wlan_vdev_list[id] == vdev) {
1328*5113495bSYour Name 			if (wlan_vdev_mlme_get_opmode(vdev) ==
1329*5113495bSYour Name 							QDF_SAP_MODE)
1330*5113495bSYour Name 				wlan_mlo_vdev_free_aid_mgr(ml_dev,
1331*5113495bSYour Name 							   vdev);
1332*5113495bSYour Name 			ml_dev->wlan_vdev_list[id] = NULL;
1333*5113495bSYour Name 			ml_dev->wlan_vdev_count--;
1334*5113495bSYour Name 			vdev->mlo_dev_ctx = NULL;
1335*5113495bSYour Name 			break;
1336*5113495bSYour Name 		}
1337*5113495bSYour Name 		id++;
1338*5113495bSYour Name 	}
1339*5113495bSYour Name 	mlo_dev_lock_release(ml_dev);
1340*5113495bSYour Name 
1341*5113495bSYour Name 	if (wlan_vdev_mlme_is_mlo_bridge_vdev(vdev)) {
1342*5113495bSYour Name 		status = mld_delete_from_bridge_vdev_list(vdev);
1343*5113495bSYour Name 		if (!QDF_IS_STATUS_SUCCESS(status))
1344*5113495bSYour Name 			mlo_err("Failed to deinit bridge vap ctx");
1345*5113495bSYour Name 	}
1346*5113495bSYour Name 
1347*5113495bSYour Name 	ml_link_lock_acquire(g_mlo_ctx);
1348*5113495bSYour Name 	if (!ml_dev->wlan_vdev_count && !ml_dev->wlan_bridge_vdev_count) {
1349*5113495bSYour Name 		if (ml_dev->ap_ctx)
1350*5113495bSYour Name 			mlo_ap_ctx_deinit(ml_dev);
1351*5113495bSYour Name 
1352*5113495bSYour Name 		mlo_dev_mlpeer_list_deinit(ml_dev);
1353*5113495bSYour Name 		qdf_list_remove_node(&g_mlo_ctx->ml_dev_list,
1354*5113495bSYour Name 				     &ml_dev->node);
1355*5113495bSYour Name 		if (wlan_vdev_mlme_get_opmode(vdev) == QDF_STA_MODE) {
1356*5113495bSYour Name 			connect_req = ml_dev->sta_ctx->connect_req;
1357*5113495bSYour Name 			wlan_cm_free_connect_req(connect_req);
1358*5113495bSYour Name 
1359*5113495bSYour Name 			if (ml_dev->sta_ctx->disconn_req)
1360*5113495bSYour Name 				qdf_mem_free(ml_dev->sta_ctx->disconn_req);
1361*5113495bSYour Name 
1362*5113495bSYour Name 			if (ml_dev->sta_ctx->assoc_rsp.ptr)
1363*5113495bSYour Name 				qdf_mem_free(ml_dev->sta_ctx->assoc_rsp.ptr);
1364*5113495bSYour Name 
1365*5113495bSYour Name 			ml_free_copied_reassoc_rsp(ml_dev->sta_ctx);
1366*5113495bSYour Name 
1367*5113495bSYour Name 			copied_conn_req_lock_destroy(ml_dev->sta_ctx);
1368*5113495bSYour Name 
1369*5113495bSYour Name 			qdf_mem_free(ml_dev->sta_ctx);
1370*5113495bSYour Name #if defined(WLAN_FEATURE_11BE_MLO) && defined(WLAN_MLO_MULTI_CHIP)
1371*5113495bSYour Name 			qdf_mem_free(ml_dev->bridge_sta_ctx);
1372*5113495bSYour Name #endif
1373*5113495bSYour Name 		}
1374*5113495bSYour Name 		else if (wlan_vdev_mlme_get_opmode(vdev) == QDF_SAP_MODE)
1375*5113495bSYour Name 			qdf_mem_free(ml_dev->ap_ctx);
1376*5113495bSYour Name 
1377*5113495bSYour Name 		mlo_ptqm_migration_deinit(ml_dev);
1378*5113495bSYour Name 		mlo_mgr_link_switch_deinit(ml_dev);
1379*5113495bSYour Name 		mlo_t2lm_ctx_deinit(vdev, ml_dev);
1380*5113495bSYour Name 		mlo_epcs_ctx_deinit(ml_dev);
1381*5113495bSYour Name 
1382*5113495bSYour Name 		/* Destroy DP MLO Device Context */
1383*5113495bSYour Name 		if (cdp_mlo_dev_ctxt_destroy(wlan_psoc_get_dp_handle(psoc),
1384*5113495bSYour Name 					     (uint8_t *)mld_addr) !=
1385*5113495bSYour Name 					     QDF_STATUS_SUCCESS) {
1386*5113495bSYour Name 			mlo_err("Failed to destroy DP MLO Dev ctxt");
1387*5113495bSYour Name 			QDF_BUG(0);
1388*5113495bSYour Name 		}
1389*5113495bSYour Name 
1390*5113495bSYour Name 		tsf_recalculation_lock_destroy(ml_dev);
1391*5113495bSYour Name 		mlo_dev_lock_destroy(ml_dev);
1392*5113495bSYour Name 		qdf_mem_free(ml_dev);
1393*5113495bSYour Name 	}
1394*5113495bSYour Name 	ml_link_lock_release(g_mlo_ctx);
1395*5113495bSYour Name 	return status;
1396*5113495bSYour Name }
1397*5113495bSYour Name 
wlan_mlo_mgr_vdev_created_notification(struct wlan_objmgr_vdev * vdev,void * arg_list)1398*5113495bSYour Name QDF_STATUS wlan_mlo_mgr_vdev_created_notification(struct wlan_objmgr_vdev *vdev,
1399*5113495bSYour Name 						  void *arg_list)
1400*5113495bSYour Name {
1401*5113495bSYour Name 	QDF_STATUS status = QDF_STATUS_SUCCESS;
1402*5113495bSYour Name 	struct qdf_mac_addr *mld_addr;
1403*5113495bSYour Name 
1404*5113495bSYour Name 	mld_addr = (struct qdf_mac_addr *)wlan_vdev_mlme_get_mldaddr(vdev);
1405*5113495bSYour Name 	if (qdf_is_macaddr_zero(mld_addr)) {
1406*5113495bSYour Name 		/* It's not a ML interface*/
1407*5113495bSYour Name 		return QDF_STATUS_SUCCESS;
1408*5113495bSYour Name 	}
1409*5113495bSYour Name 	mlo_debug("MLD addr" QDF_MAC_ADDR_FMT,
1410*5113495bSYour Name 		  QDF_MAC_ADDR_REF(mld_addr->bytes));
1411*5113495bSYour Name 	status = mlo_dev_ctx_init(vdev);
1412*5113495bSYour Name 
1413*5113495bSYour Name 	wlan_vdev_set_link_id(vdev, WLAN_LINK_ID_INVALID);
1414*5113495bSYour Name 
1415*5113495bSYour Name 	return status;
1416*5113495bSYour Name }
1417*5113495bSYour Name 
wlan_mlo_mgr_vdev_destroyed_notification(struct wlan_objmgr_vdev * vdev,void * arg_list)1418*5113495bSYour Name QDF_STATUS wlan_mlo_mgr_vdev_destroyed_notification(struct wlan_objmgr_vdev *vdev,
1419*5113495bSYour Name 						    void *arg_list)
1420*5113495bSYour Name {
1421*5113495bSYour Name 	QDF_STATUS status = QDF_STATUS_SUCCESS;
1422*5113495bSYour Name 	struct qdf_mac_addr *mld_addr;
1423*5113495bSYour Name 
1424*5113495bSYour Name 	mld_addr = (struct qdf_mac_addr *)wlan_vdev_mlme_get_mldaddr(vdev);
1425*5113495bSYour Name 	if (qdf_is_macaddr_zero(mld_addr)) {
1426*5113495bSYour Name 		/* It's not a ML interface*/
1427*5113495bSYour Name 		return QDF_STATUS_SUCCESS;
1428*5113495bSYour Name 	}
1429*5113495bSYour Name 	mlo_debug("MLD addr" QDF_MAC_ADDR_FMT,
1430*5113495bSYour Name 		  QDF_MAC_ADDR_REF(mld_addr->bytes));
1431*5113495bSYour Name 
1432*5113495bSYour Name 	status = mlo_dev_ctx_deinit(vdev);
1433*5113495bSYour Name 
1434*5113495bSYour Name 	return status;
1435*5113495bSYour Name }
1436*5113495bSYour Name 
wlan_mlo_mgr_update_mld_addr(struct qdf_mac_addr * old_mac,struct qdf_mac_addr * new_mac)1437*5113495bSYour Name QDF_STATUS wlan_mlo_mgr_update_mld_addr(struct qdf_mac_addr *old_mac,
1438*5113495bSYour Name 					struct qdf_mac_addr *new_mac)
1439*5113495bSYour Name {
1440*5113495bSYour Name 	struct wlan_mlo_dev_context *ml_dev;
1441*5113495bSYour Name 
1442*5113495bSYour Name 	ml_dev = wlan_mlo_get_mld_ctx_by_mldaddr(old_mac);
1443*5113495bSYour Name 	if (!ml_dev) {
1444*5113495bSYour Name 		mlo_err("ML dev context not found for MLD:" QDF_MAC_ADDR_FMT,
1445*5113495bSYour Name 			QDF_MAC_ADDR_REF(old_mac->bytes));
1446*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
1447*5113495bSYour Name 	}
1448*5113495bSYour Name 	mlo_dev_lock_acquire(ml_dev);
1449*5113495bSYour Name 	qdf_copy_macaddr(&ml_dev->mld_addr, new_mac);
1450*5113495bSYour Name 	mlo_dev_lock_release(ml_dev);
1451*5113495bSYour Name 
1452*5113495bSYour Name 	return QDF_STATUS_SUCCESS;
1453*5113495bSYour Name }
1454*5113495bSYour Name 
wlan_mlo_mgr_mld_vdev_attach(struct wlan_objmgr_vdev * vdev,struct qdf_mac_addr * mld_addr)1455*5113495bSYour Name QDF_STATUS wlan_mlo_mgr_mld_vdev_attach(struct wlan_objmgr_vdev *vdev,
1456*5113495bSYour Name 					struct qdf_mac_addr *mld_addr)
1457*5113495bSYour Name {
1458*5113495bSYour Name 	QDF_STATUS status = QDF_STATUS_SUCCESS;
1459*5113495bSYour Name 	struct wlan_objmgr_psoc *psoc = NULL;
1460*5113495bSYour Name 
1461*5113495bSYour Name 	psoc = wlan_vdev_get_psoc(vdev);
1462*5113495bSYour Name 	if (!psoc) {
1463*5113495bSYour Name 		mlo_err("Failed to get psoc");
1464*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
1465*5113495bSYour Name 	}
1466*5113495bSYour Name 
1467*5113495bSYour Name 	wlan_vdev_obj_lock(vdev);
1468*5113495bSYour Name 	wlan_vdev_mlme_set_mldaddr(vdev, (uint8_t *)&mld_addr->bytes[0]);
1469*5113495bSYour Name 	wlan_vdev_obj_unlock(vdev);
1470*5113495bSYour Name 
1471*5113495bSYour Name 	status = mlo_dev_ctx_init(vdev);
1472*5113495bSYour Name 
1473*5113495bSYour Name 	if (cdp_mlo_dev_ctxt_attach(wlan_psoc_get_dp_handle(psoc),
1474*5113495bSYour Name 				    wlan_vdev_get_id(vdev),
1475*5113495bSYour Name 				    (uint8_t *)mld_addr)
1476*5113495bSYour Name 				    != QDF_STATUS_SUCCESS) {
1477*5113495bSYour Name 		mlo_err("Failed to attach DP vdev  (" QDF_MAC_ADDR_FMT ") to"
1478*5113495bSYour Name 			" MLO Dev ctxt (" QDF_MAC_ADDR_FMT ")",
1479*5113495bSYour Name 			QDF_MAC_ADDR_REF(wlan_vdev_mlme_get_macaddr(vdev)),
1480*5113495bSYour Name 			QDF_MAC_ADDR_REF(mld_addr->bytes));
1481*5113495bSYour Name 	}
1482*5113495bSYour Name 	return status;
1483*5113495bSYour Name }
1484*5113495bSYour Name 
wlan_mlo_mgr_mld_vdev_detach(struct wlan_objmgr_vdev * vdev)1485*5113495bSYour Name QDF_STATUS wlan_mlo_mgr_mld_vdev_detach(struct wlan_objmgr_vdev *vdev)
1486*5113495bSYour Name {
1487*5113495bSYour Name 	QDF_STATUS status = QDF_STATUS_SUCCESS;
1488*5113495bSYour Name 	struct qdf_mac_addr *mld_addr;
1489*5113495bSYour Name 	struct wlan_objmgr_psoc *psoc = NULL;
1490*5113495bSYour Name 
1491*5113495bSYour Name 	psoc = wlan_vdev_get_psoc(vdev);
1492*5113495bSYour Name 	if (!psoc) {
1493*5113495bSYour Name 		mlo_err("Failed to get psoc");
1494*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
1495*5113495bSYour Name 	}
1496*5113495bSYour Name 
1497*5113495bSYour Name 	status = mlo_dev_ctx_deinit(vdev);
1498*5113495bSYour Name 
1499*5113495bSYour Name 	/* Detach DP vdev from DP MLO Device Context */
1500*5113495bSYour Name 	mld_addr = (struct qdf_mac_addr *)wlan_vdev_mlme_get_mldaddr(vdev);
1501*5113495bSYour Name 
1502*5113495bSYour Name 	if (cdp_mlo_dev_ctxt_detach(wlan_psoc_get_dp_handle(psoc),
1503*5113495bSYour Name 				    wlan_vdev_get_id(vdev),
1504*5113495bSYour Name 				    (uint8_t *)mld_addr)
1505*5113495bSYour Name 				    != QDF_STATUS_SUCCESS) {
1506*5113495bSYour Name 		mlo_err("Failed to detach DP vdev (" QDF_MAC_ADDR_FMT ") from"
1507*5113495bSYour Name 			" MLO Dev ctxt (" QDF_MAC_ADDR_FMT ")",
1508*5113495bSYour Name 			QDF_MAC_ADDR_REF(wlan_vdev_mlme_get_macaddr(vdev)),
1509*5113495bSYour Name 			QDF_MAC_ADDR_REF(mld_addr->bytes));
1510*5113495bSYour Name 	}
1511*5113495bSYour Name 
1512*5113495bSYour Name 	wlan_vdev_obj_lock(vdev);
1513*5113495bSYour Name 	wlan_vdev_mlme_reset_mldaddr(vdev);
1514*5113495bSYour Name 	wlan_vdev_mlme_op_flags_clear(vdev, WLAN_VDEV_OP_MLO_REMOVE_LINK_VDEV);
1515*5113495bSYour Name 	wlan_vdev_obj_unlock(vdev);
1516*5113495bSYour Name 
1517*5113495bSYour Name 	return status;
1518*5113495bSYour Name }
1519