xref: /wlan-driver/qca-wifi-host-cmn/umac/mlo_mgr/src/wlan_mlo_mgr_setup.c (revision 5113495b16420b49004c444715d2daae2066e7dc)
1*5113495bSYour Name /* Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved.
2*5113495bSYour Name  *
3*5113495bSYour Name  * Permission to use, copy, modify, and/or distribute this software for any
4*5113495bSYour Name  * purpose with or without fee is hereby granted, provided that the above
5*5113495bSYour Name  * copyright notice and this permission notice appear in all copies.
6*5113495bSYour Name  *
7*5113495bSYour Name  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
8*5113495bSYour Name  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
9*5113495bSYour Name  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
10*5113495bSYour Name  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
11*5113495bSYour Name  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
12*5113495bSYour Name  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
13*5113495bSYour Name  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
14*5113495bSYour Name  */
15*5113495bSYour Name 
16*5113495bSYour Name /*
17*5113495bSYour Name  * DOC: contains MLO manager ap related functionality
18*5113495bSYour Name  */
19*5113495bSYour Name #include "wlan_mlo_mgr_cmn.h"
20*5113495bSYour Name #include "wlan_mlo_mgr_main.h"
21*5113495bSYour Name #ifdef WLAN_MLO_MULTI_CHIP
22*5113495bSYour Name #include "wlan_lmac_if_def.h"
23*5113495bSYour Name #include <cdp_txrx_mlo.h>
24*5113495bSYour Name #endif
25*5113495bSYour Name #include <wlan_mgmt_txrx_rx_reo_utils_api.h>
26*5113495bSYour Name 
27*5113495bSYour Name #ifdef WLAN_MLO_MULTI_CHIP
28*5113495bSYour Name static inline
mlo_psoc_get_index_id(struct wlan_objmgr_psoc * psoc,uint8_t grp_id,uint8_t * index,bool teardown)29*5113495bSYour Name bool mlo_psoc_get_index_id(struct wlan_objmgr_psoc *psoc,
30*5113495bSYour Name 			   uint8_t grp_id,
31*5113495bSYour Name 			   uint8_t *index,
32*5113495bSYour Name 			   bool teardown)
33*5113495bSYour Name {
34*5113495bSYour Name 	struct mlo_mgr_context *mlo_ctx = wlan_objmgr_get_mlo_ctx();
35*5113495bSYour Name 	uint8_t id;
36*5113495bSYour Name 
37*5113495bSYour Name 	if (!mlo_ctx)
38*5113495bSYour Name 		return false;
39*5113495bSYour Name 
40*5113495bSYour Name 	if (!psoc)
41*5113495bSYour Name 		return false;
42*5113495bSYour Name 
43*5113495bSYour Name 	if (!index)
44*5113495bSYour Name 		return false;
45*5113495bSYour Name 
46*5113495bSYour Name 	if (grp_id >= mlo_ctx->total_grp) {
47*5113495bSYour Name 		mlo_err("Invalid grp id %d, total no of groups %d",
48*5113495bSYour Name 			grp_id, mlo_ctx->total_grp);
49*5113495bSYour Name 		return false;
50*5113495bSYour Name 	}
51*5113495bSYour Name 
52*5113495bSYour Name 	for (id = 0; id < mlo_ctx->setup_info[grp_id].tot_socs; id++)
53*5113495bSYour Name 		if (mlo_ctx->setup_info[grp_id].curr_soc_list[id] == psoc) {
54*5113495bSYour Name 			*index = id;
55*5113495bSYour Name 			return true;
56*5113495bSYour Name 		}
57*5113495bSYour Name 
58*5113495bSYour Name 	if (teardown)
59*5113495bSYour Name 		return false;
60*5113495bSYour Name 
61*5113495bSYour Name 	for (id = 0; id < mlo_ctx->setup_info[grp_id].tot_socs; id++)
62*5113495bSYour Name 		if (!mlo_ctx->setup_info[grp_id].curr_soc_list[id]) {
63*5113495bSYour Name 			*index = id;
64*5113495bSYour Name 			return true;
65*5113495bSYour Name 		}
66*5113495bSYour Name 
67*5113495bSYour Name 	return false;
68*5113495bSYour Name }
69*5113495bSYour Name 
mlo_psoc_get_grp_id(struct wlan_objmgr_psoc * psoc,uint8_t * ret_id)70*5113495bSYour Name bool mlo_psoc_get_grp_id(struct wlan_objmgr_psoc *psoc, uint8_t *ret_id)
71*5113495bSYour Name {
72*5113495bSYour Name 	struct mlo_mgr_context *mlo_ctx = wlan_objmgr_get_mlo_ctx();
73*5113495bSYour Name 	uint8_t grp_id;
74*5113495bSYour Name 	uint8_t tot_socs;
75*5113495bSYour Name 	uint8_t id;
76*5113495bSYour Name 
77*5113495bSYour Name 	if (!mlo_ctx)
78*5113495bSYour Name 		return false;
79*5113495bSYour Name 
80*5113495bSYour Name 	if (!psoc)
81*5113495bSYour Name 		return false;
82*5113495bSYour Name 
83*5113495bSYour Name 	if (!ret_id)
84*5113495bSYour Name 		return false;
85*5113495bSYour Name 
86*5113495bSYour Name 	for (grp_id = 0; grp_id < mlo_ctx->total_grp; grp_id++) {
87*5113495bSYour Name 		tot_socs = mlo_ctx->setup_info[grp_id].tot_socs;
88*5113495bSYour Name 		for (id = 0; id < tot_socs; id++)
89*5113495bSYour Name 			if (mlo_ctx->setup_info[grp_id].soc_list[id] == psoc) {
90*5113495bSYour Name 				*ret_id = grp_id;
91*5113495bSYour Name 				return true;
92*5113495bSYour Name 			}
93*5113495bSYour Name 	}
94*5113495bSYour Name 
95*5113495bSYour Name 	return false;
96*5113495bSYour Name }
97*5113495bSYour Name 
98*5113495bSYour Name qdf_export_symbol(mlo_psoc_get_grp_id);
99*5113495bSYour Name 
mlo_is_ml_soc(struct wlan_objmgr_psoc * psoc,uint8_t grp_id)100*5113495bSYour Name bool mlo_is_ml_soc(struct wlan_objmgr_psoc *psoc, uint8_t grp_id)
101*5113495bSYour Name {
102*5113495bSYour Name 	struct mlo_mgr_context *mlo_ctx = wlan_objmgr_get_mlo_ctx();
103*5113495bSYour Name 	uint8_t id;
104*5113495bSYour Name 
105*5113495bSYour Name 	if (!mlo_ctx)
106*5113495bSYour Name 		return false;
107*5113495bSYour Name 
108*5113495bSYour Name 	if (!psoc)
109*5113495bSYour Name 		return false;
110*5113495bSYour Name 
111*5113495bSYour Name 	if (grp_id >= mlo_ctx->total_grp) {
112*5113495bSYour Name 		mlo_err("Invalid grp id %d, total no of groups %d",
113*5113495bSYour Name 			grp_id, mlo_ctx->total_grp);
114*5113495bSYour Name 		return false;
115*5113495bSYour Name 	}
116*5113495bSYour Name 
117*5113495bSYour Name 	for (id = 0; id < mlo_ctx->setup_info[grp_id].tot_socs; id++)
118*5113495bSYour Name 		if (mlo_ctx->setup_info[grp_id].curr_soc_list[id] == psoc)
119*5113495bSYour Name 			return true;
120*5113495bSYour Name 
121*5113495bSYour Name 	return false;
122*5113495bSYour Name }
123*5113495bSYour Name 
124*5113495bSYour Name qdf_export_symbol(mlo_is_ml_soc);
125*5113495bSYour Name 
mlo_set_soc_list(uint8_t grp_id,struct wlan_objmgr_psoc * psoc)126*5113495bSYour Name static void mlo_set_soc_list(uint8_t grp_id, struct wlan_objmgr_psoc *psoc)
127*5113495bSYour Name {
128*5113495bSYour Name 	struct mlo_mgr_context *mlo_ctx = wlan_objmgr_get_mlo_ctx();
129*5113495bSYour Name 	uint8_t idx;
130*5113495bSYour Name 
131*5113495bSYour Name 	if (!mlo_ctx)
132*5113495bSYour Name 		return;
133*5113495bSYour Name 
134*5113495bSYour Name 	if (!psoc)
135*5113495bSYour Name 		return;
136*5113495bSYour Name 
137*5113495bSYour Name 	if (grp_id >= mlo_ctx->total_grp) {
138*5113495bSYour Name 		mlo_err("Invalid grp id %d, total no of groups %d",
139*5113495bSYour Name 			grp_id, mlo_ctx->total_grp);
140*5113495bSYour Name 		return;
141*5113495bSYour Name 	}
142*5113495bSYour Name 
143*5113495bSYour Name 	for (idx = 0; idx < mlo_ctx->setup_info[grp_id].tot_socs; idx++) {
144*5113495bSYour Name 		if (mlo_ctx->setup_info[grp_id].soc_id_list[idx] ==
145*5113495bSYour Name 				psoc->soc_objmgr.psoc_id) {
146*5113495bSYour Name 			mlo_ctx->setup_info[grp_id].soc_list[idx] = psoc;
147*5113495bSYour Name 			mlo_wsi_link_info_update_soc(psoc, grp_id);
148*5113495bSYour Name 		}
149*5113495bSYour Name 	}
150*5113495bSYour Name }
151*5113495bSYour Name 
mlo_get_soc_list(struct wlan_objmgr_psoc ** soc_list,uint8_t grp_id,uint8_t total_socs,enum MLO_SOC_LIST curr)152*5113495bSYour Name void mlo_get_soc_list(struct wlan_objmgr_psoc **soc_list,
153*5113495bSYour Name 		      uint8_t grp_id,
154*5113495bSYour Name 		      uint8_t total_socs,
155*5113495bSYour Name 		      enum MLO_SOC_LIST curr)
156*5113495bSYour Name {
157*5113495bSYour Name 	struct mlo_mgr_context *mlo_ctx = wlan_objmgr_get_mlo_ctx();
158*5113495bSYour Name 	uint8_t chip_idx;
159*5113495bSYour Name 
160*5113495bSYour Name 	if (!mlo_ctx)
161*5113495bSYour Name 		goto err_case;
162*5113495bSYour Name 
163*5113495bSYour Name 	if (grp_id >= mlo_ctx->total_grp) {
164*5113495bSYour Name 		mlo_err("Invalid grp id %d, total no of groups %d",
165*5113495bSYour Name 			grp_id, mlo_ctx->total_grp);
166*5113495bSYour Name 		goto err_case;
167*5113495bSYour Name 	}
168*5113495bSYour Name 
169*5113495bSYour Name 	if (total_socs != mlo_ctx->setup_info[grp_id].tot_socs) {
170*5113495bSYour Name 		mlo_err("Mismatch in number of socs in the grp id %d, expected %d observed %d",
171*5113495bSYour Name 			grp_id, total_socs,
172*5113495bSYour Name 			mlo_ctx->setup_info[grp_id].tot_socs);
173*5113495bSYour Name 		goto err_case;
174*5113495bSYour Name 	}
175*5113495bSYour Name 
176*5113495bSYour Name 	if (curr == WLAN_MLO_GROUP_CURRENT_SOC_LIST) {
177*5113495bSYour Name 		for (chip_idx = 0; chip_idx < total_socs; chip_idx++)
178*5113495bSYour Name 			soc_list[chip_idx] =
179*5113495bSYour Name 			mlo_ctx->setup_info[grp_id].curr_soc_list[chip_idx];
180*5113495bSYour Name 	} else {
181*5113495bSYour Name 		for (chip_idx = 0; chip_idx < total_socs; chip_idx++)
182*5113495bSYour Name 			soc_list[chip_idx] =
183*5113495bSYour Name 				mlo_ctx->setup_info[grp_id].soc_list[chip_idx];
184*5113495bSYour Name 	}
185*5113495bSYour Name 
186*5113495bSYour Name 	return;
187*5113495bSYour Name 
188*5113495bSYour Name err_case:
189*5113495bSYour Name 		for (chip_idx = 0; chip_idx < total_socs; chip_idx++)
190*5113495bSYour Name 			soc_list[chip_idx] = NULL;
191*5113495bSYour Name 
192*5113495bSYour Name 		return;
193*5113495bSYour Name }
194*5113495bSYour Name 
195*5113495bSYour Name qdf_export_symbol(mlo_get_soc_list);
196*5113495bSYour Name 
mlo_cleanup_asserted_soc_setup_info(struct wlan_objmgr_psoc * psoc,uint8_t grp_id)197*5113495bSYour Name void mlo_cleanup_asserted_soc_setup_info(struct wlan_objmgr_psoc *psoc,
198*5113495bSYour Name 					 uint8_t grp_id)
199*5113495bSYour Name {
200*5113495bSYour Name 	struct mlo_mgr_context *mlo_ctx = wlan_objmgr_get_mlo_ctx();
201*5113495bSYour Name 	uint8_t link_idx;
202*5113495bSYour Name 	struct wlan_objmgr_pdev *pdev;
203*5113495bSYour Name 	struct mlo_setup_info *setup_info;
204*5113495bSYour Name 
205*5113495bSYour Name 	if (!mlo_ctx)
206*5113495bSYour Name 		return;
207*5113495bSYour Name 
208*5113495bSYour Name 	if (!psoc)
209*5113495bSYour Name 		return;
210*5113495bSYour Name 
211*5113495bSYour Name 	if (grp_id >= mlo_ctx->total_grp) {
212*5113495bSYour Name 		mlo_err("Invalid grp id %d, total no of groups %d",
213*5113495bSYour Name 			grp_id, mlo_ctx->total_grp);
214*5113495bSYour Name 		return;
215*5113495bSYour Name 	}
216*5113495bSYour Name 
217*5113495bSYour Name 	setup_info = &mlo_ctx->setup_info[grp_id];
218*5113495bSYour Name 
219*5113495bSYour Name 	if (!setup_info->num_links)
220*5113495bSYour Name 		return;
221*5113495bSYour Name 
222*5113495bSYour Name 	if (!psoc) {
223*5113495bSYour Name 		mlo_info("NULL psoc");
224*5113495bSYour Name 		return;
225*5113495bSYour Name 	}
226*5113495bSYour Name 
227*5113495bSYour Name 	for (link_idx = 0; link_idx < MAX_MLO_LINKS; link_idx++) {
228*5113495bSYour Name 		pdev = setup_info->pdev_list[link_idx];
229*5113495bSYour Name 		if (pdev) {
230*5113495bSYour Name 			if (wlan_pdev_get_psoc(pdev) == psoc) {
231*5113495bSYour Name 				setup_info->pdev_list[link_idx] = NULL;
232*5113495bSYour Name 				setup_info->state[link_idx] = MLO_LINK_TEARDOWN;
233*5113495bSYour Name 				setup_info->num_links--;
234*5113495bSYour Name 			}
235*5113495bSYour Name 		}
236*5113495bSYour Name 	}
237*5113495bSYour Name }
238*5113495bSYour Name 
239*5113495bSYour Name qdf_export_symbol(mlo_cleanup_asserted_soc_setup_info);
240*5113495bSYour Name 
mlo_setup_update_soc_id_list(uint8_t grp_id,uint8_t * soc_id_list)241*5113495bSYour Name void mlo_setup_update_soc_id_list(uint8_t grp_id, uint8_t *soc_id_list)
242*5113495bSYour Name {
243*5113495bSYour Name 	struct mlo_mgr_context *mlo_ctx = wlan_objmgr_get_mlo_ctx();
244*5113495bSYour Name 	uint32_t tot_socs;
245*5113495bSYour Name 	uint32_t num_soc;
246*5113495bSYour Name 	uint8_t *soc_list;
247*5113495bSYour Name 
248*5113495bSYour Name 	if (!mlo_ctx)
249*5113495bSYour Name 		return;
250*5113495bSYour Name 
251*5113495bSYour Name 	if (grp_id >= mlo_ctx->total_grp) {
252*5113495bSYour Name 		mlo_err("Invalid grp id %d, total no of groups %d",
253*5113495bSYour Name 			grp_id, mlo_ctx->total_grp);
254*5113495bSYour Name 		return;
255*5113495bSYour Name 	}
256*5113495bSYour Name 
257*5113495bSYour Name 	tot_socs = mlo_ctx->setup_info[grp_id].tot_socs;
258*5113495bSYour Name 	soc_list = mlo_ctx->setup_info[grp_id].soc_id_list;
259*5113495bSYour Name 
260*5113495bSYour Name 	for (num_soc = 0; num_soc < tot_socs; num_soc++)
261*5113495bSYour Name 		soc_list[num_soc] = soc_id_list[num_soc];
262*5113495bSYour Name }
263*5113495bSYour Name 
264*5113495bSYour Name qdf_export_symbol(mlo_setup_update_soc_id_list);
265*5113495bSYour Name 
mlo_setup_get_total_socs(uint8_t grp_id)266*5113495bSYour Name uint8_t mlo_setup_get_total_socs(uint8_t grp_id)
267*5113495bSYour Name {
268*5113495bSYour Name 	struct mlo_mgr_context *mlo_ctx = wlan_objmgr_get_mlo_ctx();
269*5113495bSYour Name 
270*5113495bSYour Name 	if (!mlo_ctx)
271*5113495bSYour Name 		return 0;
272*5113495bSYour Name 
273*5113495bSYour Name 	if (grp_id >= mlo_ctx->total_grp) {
274*5113495bSYour Name 		mlo_err("Invalid grp id %d, total no of groups %d",
275*5113495bSYour Name 			grp_id, mlo_ctx->total_grp);
276*5113495bSYour Name 		return 0;
277*5113495bSYour Name 	}
278*5113495bSYour Name 
279*5113495bSYour Name 	return mlo_ctx->setup_info[grp_id].tot_socs;
280*5113495bSYour Name }
281*5113495bSYour Name 
282*5113495bSYour Name qdf_export_symbol(mlo_setup_get_total_socs);
283*5113495bSYour Name 
mlo_setup_update_total_socs(uint8_t grp_id,uint8_t tot_socs)284*5113495bSYour Name void mlo_setup_update_total_socs(uint8_t grp_id, uint8_t tot_socs)
285*5113495bSYour Name {
286*5113495bSYour Name 	struct mlo_mgr_context *mlo_ctx = wlan_objmgr_get_mlo_ctx();
287*5113495bSYour Name 
288*5113495bSYour Name 	if (!mlo_ctx)
289*5113495bSYour Name 		return;
290*5113495bSYour Name 
291*5113495bSYour Name 	if (grp_id >= mlo_ctx->total_grp) {
292*5113495bSYour Name 		mlo_err("Invalid grp id %d, total no of groups %d",
293*5113495bSYour Name 			grp_id, mlo_ctx->total_grp);
294*5113495bSYour Name 		return;
295*5113495bSYour Name 	}
296*5113495bSYour Name 
297*5113495bSYour Name 	mlo_ctx->setup_info[grp_id].tot_socs = tot_socs;
298*5113495bSYour Name 	mlo_ctx->setup_info[grp_id].ml_grp_id = grp_id;
299*5113495bSYour Name 	mlo_ctx->setup_info[grp_id].tot_links = 0;
300*5113495bSYour Name 	qdf_info("Grp_id %d Total MLO socs = %d links = %d",
301*5113495bSYour Name 		 grp_id, mlo_ctx->setup_info[grp_id].tot_socs,
302*5113495bSYour Name 		 mlo_ctx->setup_info[grp_id].tot_links);
303*5113495bSYour Name }
304*5113495bSYour Name 
305*5113495bSYour Name qdf_export_symbol(mlo_setup_update_total_socs);
306*5113495bSYour Name 
mlo_find_pdev_idx(struct wlan_objmgr_pdev * pdev,uint8_t * link_idx,uint8_t grp_id)307*5113495bSYour Name static QDF_STATUS mlo_find_pdev_idx(struct wlan_objmgr_pdev *pdev,
308*5113495bSYour Name 				    uint8_t *link_idx, uint8_t grp_id)
309*5113495bSYour Name {
310*5113495bSYour Name 	struct mlo_mgr_context *mlo_ctx = wlan_objmgr_get_mlo_ctx();
311*5113495bSYour Name 	uint8_t idx;
312*5113495bSYour Name 
313*5113495bSYour Name 	if (!mlo_ctx)
314*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
315*5113495bSYour Name 
316*5113495bSYour Name 	if (!pdev)
317*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
318*5113495bSYour Name 
319*5113495bSYour Name 	if (!link_idx)
320*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
321*5113495bSYour Name 
322*5113495bSYour Name 	if (grp_id >= mlo_ctx->total_grp) {
323*5113495bSYour Name 		mlo_err("Invalid grp id %d, total no of groups %d",
324*5113495bSYour Name 			grp_id, mlo_ctx->total_grp);
325*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
326*5113495bSYour Name 	}
327*5113495bSYour Name 
328*5113495bSYour Name 	for (idx = 0; idx < mlo_ctx->setup_info[grp_id].tot_links; idx++) {
329*5113495bSYour Name 		if (mlo_ctx->setup_info[grp_id].pdev_list[idx] == pdev) {
330*5113495bSYour Name 			*link_idx = idx;
331*5113495bSYour Name 			return QDF_STATUS_SUCCESS;
332*5113495bSYour Name 		}
333*5113495bSYour Name 	}
334*5113495bSYour Name 
335*5113495bSYour Name 	return QDF_STATUS_E_FAILURE;
336*5113495bSYour Name }
337*5113495bSYour Name 
mlo_check_start_stop_inprogress(uint8_t grp_id)338*5113495bSYour Name bool mlo_check_start_stop_inprogress(uint8_t grp_id)
339*5113495bSYour Name {
340*5113495bSYour Name 	struct mlo_mgr_context *mlo_ctx = wlan_objmgr_get_mlo_ctx();
341*5113495bSYour Name 
342*5113495bSYour Name 	if (!mlo_ctx)
343*5113495bSYour Name 		return true;
344*5113495bSYour Name 
345*5113495bSYour Name 	if (grp_id >= mlo_ctx->total_grp) {
346*5113495bSYour Name 		mlo_err("Invalid grp id %d, total no of groups %d",
347*5113495bSYour Name 			grp_id, mlo_ctx->total_grp);
348*5113495bSYour Name 		return true;
349*5113495bSYour Name 	}
350*5113495bSYour Name 
351*5113495bSYour Name 	return qdf_atomic_test_and_set_bit(
352*5113495bSYour Name 			START_STOP_INPROGRESS_BIT,
353*5113495bSYour Name 			&mlo_ctx->setup_info[grp_id].start_stop_inprogress);
354*5113495bSYour Name }
355*5113495bSYour Name 
356*5113495bSYour Name qdf_export_symbol(mlo_check_start_stop_inprogress);
357*5113495bSYour Name 
mlo_clear_start_stop_inprogress(uint8_t grp_id)358*5113495bSYour Name void mlo_clear_start_stop_inprogress(uint8_t grp_id)
359*5113495bSYour Name {
360*5113495bSYour Name 	struct mlo_mgr_context *mlo_ctx = wlan_objmgr_get_mlo_ctx();
361*5113495bSYour Name 
362*5113495bSYour Name 	if (!mlo_ctx)
363*5113495bSYour Name 		return;
364*5113495bSYour Name 
365*5113495bSYour Name 	if (grp_id >= mlo_ctx->total_grp) {
366*5113495bSYour Name 		mlo_err("Invalid grp id %d, total no of groups %d",
367*5113495bSYour Name 			grp_id, mlo_ctx->total_grp);
368*5113495bSYour Name 		return;
369*5113495bSYour Name 	}
370*5113495bSYour Name 
371*5113495bSYour Name 	qdf_atomic_clear_bit(
372*5113495bSYour Name 			START_STOP_INPROGRESS_BIT,
373*5113495bSYour Name 			&mlo_ctx->setup_info[grp_id].start_stop_inprogress);
374*5113495bSYour Name }
375*5113495bSYour Name 
376*5113495bSYour Name qdf_export_symbol(mlo_clear_start_stop_inprogress);
377*5113495bSYour Name 
378*5113495bSYour Name #define WLAN_SOC_ID_NOT_INITIALIZED -1
mlo_vdevs_check_single_soc(struct wlan_objmgr_vdev ** wlan_vdev_list,uint8_t vdev_count)379*5113495bSYour Name bool mlo_vdevs_check_single_soc(struct wlan_objmgr_vdev **wlan_vdev_list,
380*5113495bSYour Name 				uint8_t vdev_count)
381*5113495bSYour Name {
382*5113495bSYour Name 	int i;
383*5113495bSYour Name 	uint8_t soc_id = WLAN_SOC_ID_NOT_INITIALIZED;
384*5113495bSYour Name 
385*5113495bSYour Name 	for (i = 0; i < vdev_count; i++) {
386*5113495bSYour Name 		uint8_t vdev_soc_id = wlan_vdev_get_psoc_id(wlan_vdev_list[i]);
387*5113495bSYour Name 
388*5113495bSYour Name 		if (i == 0)
389*5113495bSYour Name 			soc_id = vdev_soc_id;
390*5113495bSYour Name 		else if (soc_id != vdev_soc_id)
391*5113495bSYour Name 			return false;
392*5113495bSYour Name 	}
393*5113495bSYour Name 
394*5113495bSYour Name 	return true;
395*5113495bSYour Name }
396*5113495bSYour Name 
397*5113495bSYour Name qdf_export_symbol(mlo_vdevs_check_single_soc);
398*5113495bSYour Name 
mlo_check_state(struct wlan_objmgr_psoc * psoc,void * obj,void * args)399*5113495bSYour Name static void mlo_check_state(struct wlan_objmgr_psoc *psoc,
400*5113495bSYour Name 			    void *obj, void *args)
401*5113495bSYour Name {
402*5113495bSYour Name 	struct wlan_objmgr_pdev *pdev;
403*5113495bSYour Name 	uint8_t link_idx;
404*5113495bSYour Name 	struct mlo_mgr_context *mlo_ctx = wlan_objmgr_get_mlo_ctx();
405*5113495bSYour Name 	struct mlo_state_params *params = (struct mlo_state_params *)args;
406*5113495bSYour Name 
407*5113495bSYour Name 	uint8_t grp_id = params->grp_id;
408*5113495bSYour Name 	pdev = (struct wlan_objmgr_pdev *)obj;
409*5113495bSYour Name 
410*5113495bSYour Name 	if (!mlo_ctx)
411*5113495bSYour Name 		return;
412*5113495bSYour Name 
413*5113495bSYour Name 	if (!psoc)
414*5113495bSYour Name 		return;
415*5113495bSYour Name 
416*5113495bSYour Name 	if (grp_id >= mlo_ctx->total_grp) {
417*5113495bSYour Name 		mlo_err("Invalid grp id %d, total no of groups %d",
418*5113495bSYour Name 			grp_id, mlo_ctx->total_grp);
419*5113495bSYour Name 		return;
420*5113495bSYour Name 	}
421*5113495bSYour Name 
422*5113495bSYour Name 	if (mlo_find_pdev_idx(pdev, &link_idx, grp_id) != QDF_STATUS_SUCCESS) {
423*5113495bSYour Name 		mlo_info("Failed to find pdev");
424*5113495bSYour Name 		return;
425*5113495bSYour Name 	}
426*5113495bSYour Name 
427*5113495bSYour Name 	if (mlo_ctx->setup_info[grp_id].state[link_idx] != params->check_state)
428*5113495bSYour Name 		params->link_state_fail = 1;
429*5113495bSYour Name }
430*5113495bSYour Name 
mlo_check_all_pdev_state(struct wlan_objmgr_psoc * psoc,uint8_t grp_id,enum MLO_LINK_STATE state)431*5113495bSYour Name QDF_STATUS mlo_check_all_pdev_state(struct wlan_objmgr_psoc *psoc,
432*5113495bSYour Name 				    uint8_t grp_id,
433*5113495bSYour Name 				    enum MLO_LINK_STATE state)
434*5113495bSYour Name {
435*5113495bSYour Name 	QDF_STATUS status = QDF_STATUS_E_INVAL;
436*5113495bSYour Name 	struct mlo_state_params params = {0};
437*5113495bSYour Name 
438*5113495bSYour Name 	params.check_state = state;
439*5113495bSYour Name 	params.grp_id = grp_id;
440*5113495bSYour Name 
441*5113495bSYour Name 	wlan_objmgr_iterate_obj_list(psoc, WLAN_PDEV_OP,
442*5113495bSYour Name 				     mlo_check_state, &params,
443*5113495bSYour Name 				     0, WLAN_MLME_NB_ID);
444*5113495bSYour Name 
445*5113495bSYour Name 	if (params.link_state_fail)
446*5113495bSYour Name 		status = QDF_STATUS_E_INVAL;
447*5113495bSYour Name 	else
448*5113495bSYour Name 		status = QDF_STATUS_SUCCESS;
449*5113495bSYour Name 
450*5113495bSYour Name 	return status;
451*5113495bSYour Name }
452*5113495bSYour Name 
mlo_setup_init(uint8_t total_grp)453*5113495bSYour Name void mlo_setup_init(uint8_t total_grp)
454*5113495bSYour Name {
455*5113495bSYour Name 	struct mlo_mgr_context *mlo_ctx = wlan_objmgr_get_mlo_ctx();
456*5113495bSYour Name 	struct mlo_setup_info *setup_info;
457*5113495bSYour Name 	uint8_t id;
458*5113495bSYour Name 
459*5113495bSYour Name 	if (!mlo_ctx)
460*5113495bSYour Name 		return;
461*5113495bSYour Name 
462*5113495bSYour Name 	if (!total_grp && total_grp > WLAN_MAX_MLO_GROUPS) {
463*5113495bSYour Name 		mlo_err("Total number of groups (%d) is greater than MAX (%d), MLD Setup failed!!",
464*5113495bSYour Name 			total_grp, WLAN_MAX_MLO_GROUPS);
465*5113495bSYour Name 		return;
466*5113495bSYour Name 	}
467*5113495bSYour Name 
468*5113495bSYour Name 	mlo_ctx->total_grp = total_grp;
469*5113495bSYour Name 	setup_info = qdf_mem_malloc(sizeof(struct mlo_setup_info) *
470*5113495bSYour Name 					      total_grp);
471*5113495bSYour Name 
472*5113495bSYour Name 	if (!setup_info)
473*5113495bSYour Name 		return;
474*5113495bSYour Name 
475*5113495bSYour Name 	mlo_ctx->setup_info = setup_info;
476*5113495bSYour Name 	mlo_ctx->setup_info[0].ml_grp_id = 0;
477*5113495bSYour Name 	for (id = 0; id < total_grp; id++) {
478*5113495bSYour Name 		mlo_ctx->setup_info[id].tsf_sync_enabled = true;
479*5113495bSYour Name 		mlo_ctx->setup_info[id].wsi_stats_info_support = 0xff;
480*5113495bSYour Name 
481*5113495bSYour Name 		if (qdf_event_create(&mlo_ctx->setup_info[id].event) !=
482*5113495bSYour Name 							QDF_STATUS_SUCCESS)
483*5113495bSYour Name 			mlo_err("Unable to create teardown event");
484*5113495bSYour Name 	}
485*5113495bSYour Name }
486*5113495bSYour Name 
487*5113495bSYour Name qdf_export_symbol(mlo_setup_init);
488*5113495bSYour Name 
mlo_setup_deinit(void)489*5113495bSYour Name void mlo_setup_deinit(void)
490*5113495bSYour Name {
491*5113495bSYour Name 	struct mlo_mgr_context *mlo_ctx = wlan_objmgr_get_mlo_ctx();
492*5113495bSYour Name 	uint8_t id;
493*5113495bSYour Name 
494*5113495bSYour Name 	if (!mlo_ctx)
495*5113495bSYour Name 		return;
496*5113495bSYour Name 
497*5113495bSYour Name 	if (!mlo_ctx->setup_info)
498*5113495bSYour Name 		return;
499*5113495bSYour Name 
500*5113495bSYour Name 	for (id = 0; id < mlo_ctx->total_grp; id++)
501*5113495bSYour Name 		qdf_event_destroy(&mlo_ctx->setup_info[id].event);
502*5113495bSYour Name 
503*5113495bSYour Name 	qdf_mem_free(mlo_ctx->setup_info);
504*5113495bSYour Name 	mlo_ctx->setup_info = NULL;
505*5113495bSYour Name }
506*5113495bSYour Name 
507*5113495bSYour Name qdf_export_symbol(mlo_setup_deinit);
508*5113495bSYour Name 
mlo_setup_update_chip_info(struct wlan_objmgr_psoc * psoc,uint8_t chip_id,uint8_t * adj_chip_id)509*5113495bSYour Name void mlo_setup_update_chip_info(struct wlan_objmgr_psoc *psoc,
510*5113495bSYour Name 				uint8_t chip_id, uint8_t *adj_chip_id)
511*5113495bSYour Name {
512*5113495bSYour Name 	uint8_t psoc_id, i;
513*5113495bSYour Name 	struct mlo_mgr_context *mlo_ctx = wlan_objmgr_get_mlo_ctx();
514*5113495bSYour Name 	struct mlo_chip_info *chip_info;
515*5113495bSYour Name 
516*5113495bSYour Name 	if (!mlo_ctx)
517*5113495bSYour Name 		return;
518*5113495bSYour Name 
519*5113495bSYour Name 	chip_info = &mlo_ctx->setup_info->chip_info;
520*5113495bSYour Name 	/* get psoc_id of a soc */
521*5113495bSYour Name 	psoc_id = wlan_psoc_get_id(psoc);
522*5113495bSYour Name 
523*5113495bSYour Name 	if (psoc_id >= MAX_MLO_CHIPS)
524*5113495bSYour Name 		return;
525*5113495bSYour Name 	/* chip id & psoc id need not be same, assign here based on psoc index*/
526*5113495bSYour Name 	chip_info->chip_id[psoc_id] = chip_id;
527*5113495bSYour Name 
528*5113495bSYour Name 	/* For a particular psoc id populate the adjacent chip id's */
529*5113495bSYour Name 	for (i = 0; i < MAX_ADJ_CHIPS; i++)
530*5113495bSYour Name 		chip_info->adj_chip_ids[psoc_id][i] = adj_chip_id[i];
531*5113495bSYour Name 
532*5113495bSYour Name 	chip_info->info_valid = 1;
533*5113495bSYour Name }
534*5113495bSYour Name 
535*5113495bSYour Name qdf_export_symbol(mlo_setup_update_chip_info);
536*5113495bSYour Name 
mlo_chip_adjacent(uint8_t psoc_id_1,uint8_t psoc_id_2,uint8_t * is_adjacent)537*5113495bSYour Name QDF_STATUS mlo_chip_adjacent(uint8_t psoc_id_1, uint8_t psoc_id_2,
538*5113495bSYour Name 			     uint8_t *is_adjacent)
539*5113495bSYour Name {
540*5113495bSYour Name 	struct mlo_mgr_context *mlo_ctx = wlan_objmgr_get_mlo_ctx();
541*5113495bSYour Name 	uint8_t chip_id2, i;
542*5113495bSYour Name 	struct mlo_chip_info *chip_info;
543*5113495bSYour Name 
544*5113495bSYour Name 	if (!mlo_ctx)
545*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
546*5113495bSYour Name 
547*5113495bSYour Name 	if ((psoc_id_1 >= MAX_MLO_CHIPS) || (psoc_id_2 >= MAX_MLO_CHIPS)) {
548*5113495bSYour Name 		mlo_err("psoc id's greater then max limit of %d",
549*5113495bSYour Name 			MAX_MLO_CHIPS);
550*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
551*5113495bSYour Name 	}
552*5113495bSYour Name 
553*5113495bSYour Name 	chip_info = &mlo_ctx->setup_info->chip_info;
554*5113495bSYour Name 
555*5113495bSYour Name 	/* default case is adjacent */
556*5113495bSYour Name 	*is_adjacent = 1;
557*5113495bSYour Name 
558*5113495bSYour Name 	if (!chip_info->info_valid) {
559*5113495bSYour Name 		/* This is default (non-ini), they are adjacent */
560*5113495bSYour Name 		return QDF_STATUS_SUCCESS;
561*5113495bSYour Name 	}
562*5113495bSYour Name 
563*5113495bSYour Name 	if (psoc_id_1 == psoc_id_2) {
564*5113495bSYour Name 		/* this is probably a single soc case, they are adjacent */
565*5113495bSYour Name 		return QDF_STATUS_SUCCESS;
566*5113495bSYour Name 	}
567*5113495bSYour Name 	/* get chip id from psoc */
568*5113495bSYour Name 	chip_id2 = chip_info->chip_id[psoc_id_2];
569*5113495bSYour Name 	for (i = 0; i < MAX_ADJ_CHIPS; i++) {
570*5113495bSYour Name 		if (chip_info->adj_chip_ids[psoc_id_1][i] == chip_id2)
571*5113495bSYour Name 			return QDF_STATUS_SUCCESS;
572*5113495bSYour Name 	}
573*5113495bSYour Name 
574*5113495bSYour Name 	*is_adjacent = 0;
575*5113495bSYour Name 	return QDF_STATUS_SUCCESS;
576*5113495bSYour Name }
577*5113495bSYour Name 
578*5113495bSYour Name qdf_export_symbol(mlo_chip_adjacent);
579*5113495bSYour Name 
mlo_setup_update_num_links(struct wlan_objmgr_psoc * psoc,uint8_t grp_id,uint8_t num_links)580*5113495bSYour Name void mlo_setup_update_num_links(struct wlan_objmgr_psoc *psoc,
581*5113495bSYour Name 				uint8_t grp_id, uint8_t num_links)
582*5113495bSYour Name {
583*5113495bSYour Name 	struct mlo_mgr_context *mlo_ctx = wlan_objmgr_get_mlo_ctx();
584*5113495bSYour Name 
585*5113495bSYour Name 	if (!mlo_ctx)
586*5113495bSYour Name 		return;
587*5113495bSYour Name 
588*5113495bSYour Name 	if (!psoc)
589*5113495bSYour Name 		return;
590*5113495bSYour Name 
591*5113495bSYour Name 	if (grp_id >= mlo_ctx->total_grp) {
592*5113495bSYour Name 		mlo_err("Invalid grp id %d, total no of groups %d",
593*5113495bSYour Name 			grp_id, mlo_ctx->total_grp);
594*5113495bSYour Name 		return;
595*5113495bSYour Name 	}
596*5113495bSYour Name 
597*5113495bSYour Name 	mlo_ctx->setup_info[grp_id].tot_links += num_links;
598*5113495bSYour Name 	qdf_info("Grp_id %d Total MLO links = %d",
599*5113495bSYour Name 		 grp_id, mlo_ctx->setup_info[grp_id].tot_links);
600*5113495bSYour Name }
601*5113495bSYour Name 
602*5113495bSYour Name qdf_export_symbol(mlo_setup_update_num_links);
603*5113495bSYour Name 
mlo_setup_update_soc_ready(struct wlan_objmgr_psoc * psoc,uint8_t grp_id)604*5113495bSYour Name void mlo_setup_update_soc_ready(struct wlan_objmgr_psoc *psoc, uint8_t grp_id)
605*5113495bSYour Name {
606*5113495bSYour Name 	struct mlo_mgr_context *mlo_ctx = wlan_objmgr_get_mlo_ctx();
607*5113495bSYour Name 	struct mlo_setup_info *setup_info;
608*5113495bSYour Name 	uint8_t chip_idx, tot_socs;
609*5113495bSYour Name 	struct cdp_mlo_ctxt *dp_mlo_ctxt = NULL;
610*5113495bSYour Name 
611*5113495bSYour Name 	if (!mlo_ctx)
612*5113495bSYour Name 		return;
613*5113495bSYour Name 
614*5113495bSYour Name 	if (!psoc)
615*5113495bSYour Name 		return;
616*5113495bSYour Name 
617*5113495bSYour Name 	if (grp_id >= mlo_ctx->total_grp) {
618*5113495bSYour Name 		mlo_err("Invalid grp id %d, total no of groups %d",
619*5113495bSYour Name 			grp_id, mlo_ctx->total_grp);
620*5113495bSYour Name 		return;
621*5113495bSYour Name 	}
622*5113495bSYour Name 
623*5113495bSYour Name 	setup_info = &mlo_ctx->setup_info[grp_id];
624*5113495bSYour Name 
625*5113495bSYour Name 	if (!setup_info->tot_socs)
626*5113495bSYour Name 		return;
627*5113495bSYour Name 
628*5113495bSYour Name 	tot_socs = setup_info->tot_socs;
629*5113495bSYour Name 	if (!mlo_psoc_get_index_id(psoc, grp_id, &chip_idx, 0))  {
630*5113495bSYour Name 		mlo_err("Unable to fetch chip idx for psoc id %d grp id %d",
631*5113495bSYour Name 			psoc->soc_objmgr.psoc_id,
632*5113495bSYour Name 			grp_id);
633*5113495bSYour Name 		return;
634*5113495bSYour Name 	}
635*5113495bSYour Name 
636*5113495bSYour Name 	if (!(chip_idx < tot_socs)) {
637*5113495bSYour Name 		mlo_err("Invalid chip index, SoC setup failed");
638*5113495bSYour Name 		return;
639*5113495bSYour Name 	}
640*5113495bSYour Name 
641*5113495bSYour Name 	setup_info->curr_soc_list[chip_idx] = psoc;
642*5113495bSYour Name 	mlo_set_soc_list(grp_id, psoc);
643*5113495bSYour Name 	setup_info->num_soc++;
644*5113495bSYour Name 
645*5113495bSYour Name 	mlo_debug("SoC updated to mld grp %d , chip idx %d num soc %d",
646*5113495bSYour Name 		  grp_id, chip_idx, setup_info->num_soc);
647*5113495bSYour Name 
648*5113495bSYour Name 	if (setup_info->num_soc != tot_socs)
649*5113495bSYour Name 		return;
650*5113495bSYour Name 
651*5113495bSYour Name 	dp_mlo_ctxt = wlan_objmgr_get_dp_mlo_ctx(grp_id);
652*5113495bSYour Name 
653*5113495bSYour Name 	if (!dp_mlo_ctxt) {
654*5113495bSYour Name 		dp_mlo_ctxt = cdp_mlo_ctxt_attach(
655*5113495bSYour Name 				wlan_psoc_get_dp_handle(psoc),
656*5113495bSYour Name 				(struct cdp_ctrl_mlo_mgr *)mlo_ctx);
657*5113495bSYour Name 		wlan_objmgr_set_dp_mlo_ctx(dp_mlo_ctxt, grp_id);
658*5113495bSYour Name 	}
659*5113495bSYour Name 
660*5113495bSYour Name 	for (chip_idx = 0; chip_idx < tot_socs; chip_idx++) {
661*5113495bSYour Name 		struct wlan_objmgr_psoc *tmp_soc =
662*5113495bSYour Name 			setup_info->curr_soc_list[chip_idx];
663*5113495bSYour Name 		if (tmp_soc)
664*5113495bSYour Name 			cdp_soc_mlo_soc_setup(wlan_psoc_get_dp_handle(tmp_soc),
665*5113495bSYour Name 					      setup_info->dp_handle);
666*5113495bSYour Name 	}
667*5113495bSYour Name 
668*5113495bSYour Name 	cdp_mlo_setup_complete(wlan_psoc_get_dp_handle(psoc),
669*5113495bSYour Name 			       setup_info->dp_handle);
670*5113495bSYour Name }
671*5113495bSYour Name 
672*5113495bSYour Name qdf_export_symbol(mlo_setup_update_soc_ready);
673*5113495bSYour Name 
mlo_setup_link_ready(struct wlan_objmgr_pdev * pdev,uint8_t grp_id)674*5113495bSYour Name void mlo_setup_link_ready(struct wlan_objmgr_pdev *pdev, uint8_t grp_id)
675*5113495bSYour Name {
676*5113495bSYour Name 	struct mlo_mgr_context *mlo_ctx = wlan_objmgr_get_mlo_ctx();
677*5113495bSYour Name 	struct mlo_setup_info *setup_info;
678*5113495bSYour Name 	uint8_t link_idx;
679*5113495bSYour Name 	uint16_t link_id;
680*5113495bSYour Name 
681*5113495bSYour Name 	if (!mlo_ctx)
682*5113495bSYour Name 		return;
683*5113495bSYour Name 
684*5113495bSYour Name 	if (!pdev)
685*5113495bSYour Name 		return;
686*5113495bSYour Name 
687*5113495bSYour Name 	if (grp_id >= mlo_ctx->total_grp) {
688*5113495bSYour Name 		mlo_err("Invalid grp id %d, total no of groups %d",
689*5113495bSYour Name 			grp_id, mlo_ctx->total_grp);
690*5113495bSYour Name 		return;
691*5113495bSYour Name 	}
692*5113495bSYour Name 
693*5113495bSYour Name 	setup_info = &mlo_ctx->setup_info[grp_id];
694*5113495bSYour Name 
695*5113495bSYour Name 	if (!setup_info->tot_links) {
696*5113495bSYour Name 		mlo_err("Setup info total links %d for grp id %d",
697*5113495bSYour Name 			setup_info->tot_links, grp_id);
698*5113495bSYour Name 		return;
699*5113495bSYour Name 	}
700*5113495bSYour Name 
701*5113495bSYour Name 	if (mlo_find_pdev_idx(pdev, &link_idx, grp_id) == QDF_STATUS_SUCCESS) {
702*5113495bSYour Name 		mlo_debug("Pdev already part of list link idx %d", link_idx);
703*5113495bSYour Name 		return;
704*5113495bSYour Name 	}
705*5113495bSYour Name 
706*5113495bSYour Name 	for (link_idx = 0; link_idx < setup_info->tot_links; link_idx++)
707*5113495bSYour Name 		if (!setup_info->pdev_list[link_idx])
708*5113495bSYour Name 			break;
709*5113495bSYour Name 
710*5113495bSYour Name 	if (link_idx >= setup_info->tot_links) {
711*5113495bSYour Name 		mlo_err("Exceeding max total mld links");
712*5113495bSYour Name 		return;
713*5113495bSYour Name 	}
714*5113495bSYour Name 
715*5113495bSYour Name 	setup_info->pdev_list[link_idx] = pdev;
716*5113495bSYour Name 	setup_info->state[link_idx] = MLO_LINK_SETUP_INIT;
717*5113495bSYour Name 	setup_info->num_links++;
718*5113495bSYour Name 
719*5113495bSYour Name 	link_id = wlan_mlo_get_pdev_hw_link_id(pdev);
720*5113495bSYour Name 	if (link_id == INVALID_HW_LINK_ID) {
721*5113495bSYour Name 		mlo_err("Invalid HW link id for the pdev");
722*5113495bSYour Name 		return;
723*5113495bSYour Name 	}
724*5113495bSYour Name 	setup_info->valid_link_bitmap |= (1 << link_id);
725*5113495bSYour Name 
726*5113495bSYour Name 	qdf_info("Pdev updated to Grp id %d mld link %d num_links %d  hw link id %d Valid link bitmap %d",
727*5113495bSYour Name 		 grp_id, link_idx, setup_info->num_links,
728*5113495bSYour Name 		 link_id, setup_info->valid_link_bitmap);
729*5113495bSYour Name 
730*5113495bSYour Name 	qdf_assert_always(link_idx < MAX_MLO_LINKS);
731*5113495bSYour Name 
732*5113495bSYour Name 	if (setup_info->num_links == setup_info->tot_links &&
733*5113495bSYour Name 	    setup_info->num_soc == setup_info->tot_socs) {
734*5113495bSYour Name 		struct wlan_objmgr_psoc *psoc;
735*5113495bSYour Name 		struct wlan_lmac_if_tx_ops *tx_ops;
736*5113495bSYour Name 		QDF_STATUS status;
737*5113495bSYour Name 
738*5113495bSYour Name 		psoc = wlan_pdev_get_psoc(pdev);
739*5113495bSYour Name 		tx_ops = wlan_psoc_get_lmac_if_txops(psoc);
740*5113495bSYour Name 
741*5113495bSYour Name 		status = wlan_mgmt_rx_reo_validate_mlo_link_info(psoc);
742*5113495bSYour Name 		if (QDF_IS_STATUS_ERROR(status)) {
743*5113495bSYour Name 			mlo_err("Failed to validate MLO HW link info");
744*5113495bSYour Name 			qdf_assert_always(0);
745*5113495bSYour Name 		}
746*5113495bSYour Name 
747*5113495bSYour Name 		qdf_info("Trigger MLO Setup request");
748*5113495bSYour Name 		if (tx_ops && tx_ops->mops.target_if_mlo_setup_req) {
749*5113495bSYour Name 			tx_ops->mops.target_if_mlo_setup_req(
750*5113495bSYour Name 					setup_info->pdev_list,
751*5113495bSYour Name 					setup_info->num_links,
752*5113495bSYour Name 					grp_id);
753*5113495bSYour Name 		}
754*5113495bSYour Name 	}
755*5113495bSYour Name }
756*5113495bSYour Name 
757*5113495bSYour Name qdf_export_symbol(mlo_setup_link_ready);
758*5113495bSYour Name 
mlo_link_setup_complete(struct wlan_objmgr_pdev * pdev,uint8_t grp_id)759*5113495bSYour Name void mlo_link_setup_complete(struct wlan_objmgr_pdev *pdev, uint8_t grp_id)
760*5113495bSYour Name {
761*5113495bSYour Name 	struct mlo_mgr_context *mlo_ctx = wlan_objmgr_get_mlo_ctx();
762*5113495bSYour Name 	struct mlo_setup_info *setup_info;
763*5113495bSYour Name 	uint8_t link_idx;
764*5113495bSYour Name 
765*5113495bSYour Name 	if (!mlo_ctx)
766*5113495bSYour Name 		return;
767*5113495bSYour Name 
768*5113495bSYour Name 	if (!pdev)
769*5113495bSYour Name 		return;
770*5113495bSYour Name 
771*5113495bSYour Name 	if (grp_id >= mlo_ctx->total_grp) {
772*5113495bSYour Name 		mlo_err("Invalid grp id %d, total no of groups %d",
773*5113495bSYour Name 			grp_id, mlo_ctx->total_grp);
774*5113495bSYour Name 		return;
775*5113495bSYour Name 	}
776*5113495bSYour Name 
777*5113495bSYour Name 	setup_info = &mlo_ctx->setup_info[grp_id];
778*5113495bSYour Name 
779*5113495bSYour Name 	for (link_idx = 0; link_idx < setup_info->tot_links; link_idx++)
780*5113495bSYour Name 		if (setup_info->pdev_list[link_idx] == pdev) {
781*5113495bSYour Name 			setup_info->state[link_idx] =
782*5113495bSYour Name 							MLO_LINK_SETUP_DONE;
783*5113495bSYour Name 			break;
784*5113495bSYour Name 		}
785*5113495bSYour Name 
786*5113495bSYour Name 	mlo_debug("Setup complete for pdev id %d mlo group %d",
787*5113495bSYour Name 		  pdev->pdev_objmgr.wlan_pdev_id, grp_id);
788*5113495bSYour Name 
789*5113495bSYour Name 	for (link_idx = 0; link_idx < setup_info->tot_links; link_idx++)
790*5113495bSYour Name 		if (setup_info->state[link_idx] == MLO_LINK_SETUP_DONE)
791*5113495bSYour Name 			continue;
792*5113495bSYour Name 		else
793*5113495bSYour Name 			break;
794*5113495bSYour Name 
795*5113495bSYour Name 	if (link_idx == setup_info->tot_links) {
796*5113495bSYour Name 		struct wlan_objmgr_psoc *psoc;
797*5113495bSYour Name 		struct wlan_lmac_if_tx_ops *tx_ops;
798*5113495bSYour Name 
799*5113495bSYour Name 		psoc = wlan_pdev_get_psoc(pdev);
800*5113495bSYour Name 		tx_ops = wlan_psoc_get_lmac_if_txops(psoc);
801*5113495bSYour Name 		mlo_debug("Trigger MLO ready");
802*5113495bSYour Name 		if (tx_ops && tx_ops->mops.target_if_mlo_ready) {
803*5113495bSYour Name 			tx_ops->mops.target_if_mlo_ready(
804*5113495bSYour Name 					setup_info->pdev_list,
805*5113495bSYour Name 					setup_info->num_links);
806*5113495bSYour Name 		}
807*5113495bSYour Name 	}
808*5113495bSYour Name }
809*5113495bSYour Name 
810*5113495bSYour Name qdf_export_symbol(mlo_link_setup_complete);
811*5113495bSYour Name 
mlo_setup_link_down(struct wlan_objmgr_psoc * psoc,void * obj,void * args)812*5113495bSYour Name static void mlo_setup_link_down(struct wlan_objmgr_psoc *psoc,
813*5113495bSYour Name 				void *obj, void *args)
814*5113495bSYour Name {
815*5113495bSYour Name 	struct wlan_objmgr_pdev *pdev;
816*5113495bSYour Name 	uint8_t link_idx;
817*5113495bSYour Name 	struct mlo_mgr_context *mlo_ctx = wlan_objmgr_get_mlo_ctx();
818*5113495bSYour Name 	struct mlo_setup_info *setup_info;
819*5113495bSYour Name 	uint16_t link_id;
820*5113495bSYour Name 	uint8_t grp_id = *(uint8_t *)args;
821*5113495bSYour Name 
822*5113495bSYour Name 	if (!mlo_ctx)
823*5113495bSYour Name 		return;
824*5113495bSYour Name 
825*5113495bSYour Name 	if (!psoc)
826*5113495bSYour Name 		return;
827*5113495bSYour Name 
828*5113495bSYour Name 	if (grp_id >= mlo_ctx->total_grp) {
829*5113495bSYour Name 		mlo_err("Invalid grp id %d, total no of groups %d",
830*5113495bSYour Name 			grp_id, mlo_ctx->total_grp);
831*5113495bSYour Name 		return;
832*5113495bSYour Name 	}
833*5113495bSYour Name 
834*5113495bSYour Name 	setup_info = &mlo_ctx->setup_info[grp_id];
835*5113495bSYour Name 
836*5113495bSYour Name 	pdev = (struct wlan_objmgr_pdev *)obj;
837*5113495bSYour Name 
838*5113495bSYour Name 	if (mlo_find_pdev_idx(pdev, &link_idx, grp_id) != QDF_STATUS_SUCCESS) {
839*5113495bSYour Name 		mlo_info("Failed to find pdev");
840*5113495bSYour Name 		return;
841*5113495bSYour Name 	}
842*5113495bSYour Name 
843*5113495bSYour Name 	if (setup_info->pdev_list[link_idx]) {
844*5113495bSYour Name 		setup_info->pdev_list[link_idx] = NULL;
845*5113495bSYour Name 		setup_info->state[link_idx] = MLO_LINK_UNINITIALIZED;
846*5113495bSYour Name 		setup_info->num_links--;
847*5113495bSYour Name 
848*5113495bSYour Name 		link_id = wlan_mlo_get_pdev_hw_link_id(pdev);
849*5113495bSYour Name 		if (link_id == INVALID_HW_LINK_ID) {
850*5113495bSYour Name 			mlo_err("Invalid HW link id for the pdev");
851*5113495bSYour Name 			return;
852*5113495bSYour Name 		}
853*5113495bSYour Name 		setup_info->valid_link_bitmap &= ~(1 << link_id);
854*5113495bSYour Name 	}
855*5113495bSYour Name 
856*5113495bSYour Name 	mlo_debug("Pdev link down grp_id %d link_idx %d num_links %d",
857*5113495bSYour Name 		  grp_id, link_idx, setup_info->num_links);
858*5113495bSYour Name }
859*5113495bSYour Name 
mlo_dp_ctxt_detach(struct wlan_objmgr_psoc * psoc,uint8_t grp_id,struct cdp_mlo_ctxt * dp_mlo_ctxt)860*5113495bSYour Name static void mlo_dp_ctxt_detach(struct wlan_objmgr_psoc *psoc,
861*5113495bSYour Name 			       uint8_t grp_id,
862*5113495bSYour Name 			       struct cdp_mlo_ctxt *dp_mlo_ctxt)
863*5113495bSYour Name {
864*5113495bSYour Name 	if (!psoc)
865*5113495bSYour Name 		return;
866*5113495bSYour Name 
867*5113495bSYour Name 	wlan_objmgr_set_dp_mlo_ctx(NULL, grp_id);
868*5113495bSYour Name 	if (dp_mlo_ctxt)
869*5113495bSYour Name 		cdp_mlo_ctxt_detach(wlan_psoc_get_dp_handle(psoc), dp_mlo_ctxt);
870*5113495bSYour Name }
871*5113495bSYour Name 
mlo_setup_update_soc_down(struct wlan_objmgr_psoc * psoc,uint8_t grp_id)872*5113495bSYour Name void mlo_setup_update_soc_down(struct wlan_objmgr_psoc *psoc, uint8_t grp_id)
873*5113495bSYour Name {
874*5113495bSYour Name 	struct mlo_mgr_context *mlo_ctx = wlan_objmgr_get_mlo_ctx();
875*5113495bSYour Name 	struct mlo_setup_info *setup_info;
876*5113495bSYour Name 	uint8_t chip_idx;
877*5113495bSYour Name 	struct wlan_objmgr_psoc *soc;
878*5113495bSYour Name 
879*5113495bSYour Name 	if (!mlo_ctx)
880*5113495bSYour Name 		return;
881*5113495bSYour Name 
882*5113495bSYour Name 	if (!psoc)
883*5113495bSYour Name 		return;
884*5113495bSYour Name 
885*5113495bSYour Name 	if (grp_id >= mlo_ctx->total_grp) {
886*5113495bSYour Name 		mlo_err("Invalid grp id %d, total no of groups %d",
887*5113495bSYour Name 			grp_id, mlo_ctx->total_grp);
888*5113495bSYour Name 		return;
889*5113495bSYour Name 	}
890*5113495bSYour Name 
891*5113495bSYour Name 	setup_info = &mlo_ctx->setup_info[grp_id];
892*5113495bSYour Name 
893*5113495bSYour Name 	if (setup_info->num_links) {
894*5113495bSYour Name 		wlan_objmgr_iterate_obj_list(psoc, WLAN_PDEV_OP,
895*5113495bSYour Name 					     mlo_setup_link_down, &grp_id,
896*5113495bSYour Name 					     0, WLAN_MLME_NB_ID);
897*5113495bSYour Name 	}
898*5113495bSYour Name 
899*5113495bSYour Name 	if (!mlo_psoc_get_index_id(psoc, grp_id, &chip_idx, 1)) {
900*5113495bSYour Name 		mlo_err("Unable to fetch chip idx for psoc id %d grp id %d",
901*5113495bSYour Name 			psoc->soc_objmgr.psoc_id,
902*5113495bSYour Name 			grp_id);
903*5113495bSYour Name 		return;
904*5113495bSYour Name 	}
905*5113495bSYour Name 
906*5113495bSYour Name 	if (!(chip_idx < MAX_MLO_CHIPS)) {
907*5113495bSYour Name 		mlo_err("Invalid chip index, SoC setup down failed");
908*5113495bSYour Name 		return;
909*5113495bSYour Name 	}
910*5113495bSYour Name 
911*5113495bSYour Name 	if (setup_info->curr_soc_list[chip_idx]) {
912*5113495bSYour Name 		soc = setup_info->curr_soc_list[chip_idx];
913*5113495bSYour Name 		cdp_soc_mlo_soc_teardown(wlan_psoc_get_dp_handle(soc),
914*5113495bSYour Name 					 setup_info->dp_handle, false);
915*5113495bSYour Name 
916*5113495bSYour Name 		setup_info->curr_soc_list[chip_idx] = NULL;
917*5113495bSYour Name 		setup_info->num_soc--;
918*5113495bSYour Name 
919*5113495bSYour Name 		if (!setup_info->num_soc)
920*5113495bSYour Name 			mlo_dp_ctxt_detach(soc, grp_id, setup_info->dp_handle);
921*5113495bSYour Name 	}
922*5113495bSYour Name 
923*5113495bSYour Name 	mlo_debug("Soc down, mlo group %d num soc %d num links %d",
924*5113495bSYour Name 		  grp_id, setup_info->num_soc,
925*5113495bSYour Name 		  setup_info->num_links);
926*5113495bSYour Name }
927*5113495bSYour Name 
928*5113495bSYour Name qdf_export_symbol(mlo_setup_update_soc_down);
929*5113495bSYour Name 
mlo_link_teardown_complete(struct wlan_objmgr_pdev * pdev,uint8_t grp_id)930*5113495bSYour Name void mlo_link_teardown_complete(struct wlan_objmgr_pdev *pdev, uint8_t grp_id)
931*5113495bSYour Name {
932*5113495bSYour Name 	struct mlo_mgr_context *mlo_ctx = wlan_objmgr_get_mlo_ctx();
933*5113495bSYour Name 	struct mlo_setup_info *setup_info;
934*5113495bSYour Name 	uint8_t link_idx;
935*5113495bSYour Name 
936*5113495bSYour Name 	if (!mlo_ctx)
937*5113495bSYour Name 		return;
938*5113495bSYour Name 
939*5113495bSYour Name 	if (!pdev)
940*5113495bSYour Name 		return;
941*5113495bSYour Name 
942*5113495bSYour Name 	if (grp_id >= mlo_ctx->total_grp) {
943*5113495bSYour Name 		mlo_err("Invalid grp id %d, total no of groups %d",
944*5113495bSYour Name 			grp_id, mlo_ctx->total_grp);
945*5113495bSYour Name 		return;
946*5113495bSYour Name 	}
947*5113495bSYour Name 
948*5113495bSYour Name 	setup_info = &mlo_ctx->setup_info[grp_id];
949*5113495bSYour Name 
950*5113495bSYour Name 	if (!setup_info->num_links) {
951*5113495bSYour Name 		mlo_err("Delayed response ignore");
952*5113495bSYour Name 		return;
953*5113495bSYour Name 	}
954*5113495bSYour Name 
955*5113495bSYour Name 	if (mlo_find_pdev_idx(pdev, &link_idx, grp_id) != QDF_STATUS_SUCCESS) {
956*5113495bSYour Name 		mlo_info("Failed to find pdev");
957*5113495bSYour Name 		return;
958*5113495bSYour Name 	}
959*5113495bSYour Name 
960*5113495bSYour Name 	mlo_debug("Teardown link idx = %d", link_idx);
961*5113495bSYour Name 	setup_info->state[link_idx] = MLO_LINK_TEARDOWN;
962*5113495bSYour Name 
963*5113495bSYour Name 	/* Waiting for teardown on other links */
964*5113495bSYour Name 	for (link_idx = 0; link_idx < setup_info->tot_links; link_idx++)
965*5113495bSYour Name 		if (setup_info->state[link_idx] != MLO_LINK_TEARDOWN)
966*5113495bSYour Name 			return;
967*5113495bSYour Name 
968*5113495bSYour Name 	qdf_info("Teardown complete");
969*5113495bSYour Name 
970*5113495bSYour Name 	setup_info->trigger_umac_reset = false;
971*5113495bSYour Name 
972*5113495bSYour Name 	qdf_event_set(&setup_info->event);
973*5113495bSYour Name }
974*5113495bSYour Name 
975*5113495bSYour Name qdf_export_symbol(mlo_link_teardown_complete);
976*5113495bSYour Name 
mlo_force_teardown(uint8_t grp_id)977*5113495bSYour Name static void mlo_force_teardown(uint8_t grp_id)
978*5113495bSYour Name {
979*5113495bSYour Name 	struct mlo_mgr_context *mlo_ctx = wlan_objmgr_get_mlo_ctx();
980*5113495bSYour Name 	struct mlo_setup_info *setup_info;
981*5113495bSYour Name 	uint8_t link_idx;
982*5113495bSYour Name 
983*5113495bSYour Name 	if (!mlo_ctx)
984*5113495bSYour Name 		return;
985*5113495bSYour Name 
986*5113495bSYour Name 	if (grp_id >= mlo_ctx->total_grp) {
987*5113495bSYour Name 		mlo_err("Invalid grp id %d, total no of groups %d",
988*5113495bSYour Name 			grp_id, mlo_ctx->total_grp);
989*5113495bSYour Name 		return;
990*5113495bSYour Name 	}
991*5113495bSYour Name 
992*5113495bSYour Name 	setup_info = &mlo_ctx->setup_info[grp_id];
993*5113495bSYour Name 
994*5113495bSYour Name 	for (link_idx = 0; link_idx < setup_info->tot_links; link_idx++)
995*5113495bSYour Name 		setup_info->state[link_idx] = MLO_LINK_TEARDOWN;
996*5113495bSYour Name }
997*5113495bSYour Name 
mlo_send_teardown_req(struct wlan_objmgr_psoc * psoc,uint8_t grp_id,uint32_t reason)998*5113495bSYour Name static void mlo_send_teardown_req(struct wlan_objmgr_psoc *psoc,
999*5113495bSYour Name 				  uint8_t grp_id, uint32_t reason)
1000*5113495bSYour Name {
1001*5113495bSYour Name 	struct mlo_mgr_context *mlo_ctx = wlan_objmgr_get_mlo_ctx();
1002*5113495bSYour Name 	struct wlan_lmac_if_tx_ops *tx_ops;
1003*5113495bSYour Name 	struct wlan_objmgr_pdev *temp_pdev;
1004*5113495bSYour Name 	struct mlo_setup_info *setup_info;
1005*5113495bSYour Name 	uint8_t link_idx;
1006*5113495bSYour Name 	uint8_t tot_links;
1007*5113495bSYour Name 	bool umac_reset = 0;
1008*5113495bSYour Name 
1009*5113495bSYour Name 	if (!mlo_ctx)
1010*5113495bSYour Name 		return;
1011*5113495bSYour Name 
1012*5113495bSYour Name 	if (grp_id >= mlo_ctx->total_grp) {
1013*5113495bSYour Name 		mlo_err("Invalid grp id %d, total no of groups %d",
1014*5113495bSYour Name 			grp_id, mlo_ctx->total_grp);
1015*5113495bSYour Name 		return;
1016*5113495bSYour Name 	}
1017*5113495bSYour Name 
1018*5113495bSYour Name 	tx_ops = wlan_psoc_get_lmac_if_txops(psoc);
1019*5113495bSYour Name 	if (!tx_ops) {
1020*5113495bSYour Name 		mlo_err("Tx Ops is null for the psoc id %d",
1021*5113495bSYour Name 			wlan_psoc_get_id(psoc));
1022*5113495bSYour Name 		return;
1023*5113495bSYour Name 	}
1024*5113495bSYour Name 
1025*5113495bSYour Name 	setup_info = &mlo_ctx->setup_info[grp_id];
1026*5113495bSYour Name 	tot_links = setup_info->tot_links;
1027*5113495bSYour Name 
1028*5113495bSYour Name 	if (reason == WMI_HOST_MLO_TEARDOWN_REASON_MODE1_SSR ||
1029*5113495bSYour Name 	    reason == WMI_HOST_MLO_TEARDOWN_REASON_STANDBY) {
1030*5113495bSYour Name 		for (link_idx = 0; link_idx < tot_links; link_idx++) {
1031*5113495bSYour Name 			umac_reset = 0;
1032*5113495bSYour Name 			temp_pdev = setup_info->pdev_list[link_idx];
1033*5113495bSYour Name 			if (!temp_pdev)
1034*5113495bSYour Name 				continue;
1035*5113495bSYour Name 
1036*5113495bSYour Name 			if (!setup_info->trigger_umac_reset) {
1037*5113495bSYour Name 				if (psoc == wlan_pdev_get_psoc(temp_pdev)) {
1038*5113495bSYour Name 					umac_reset = 1;
1039*5113495bSYour Name 					setup_info->trigger_umac_reset = 1;
1040*5113495bSYour Name 				}
1041*5113495bSYour Name 			}
1042*5113495bSYour Name 
1043*5113495bSYour Name 			if (tx_ops && tx_ops->mops.target_if_mlo_teardown_req) {
1044*5113495bSYour Name 				mlo_info(
1045*5113495bSYour Name 				"Trigger Teardown with Pdev id: %d Psoc id: %d link idx: %d Umac reset: %d Standby Active: %d",
1046*5113495bSYour Name 				wlan_objmgr_pdev_get_pdev_id(temp_pdev),
1047*5113495bSYour Name 				wlan_psoc_get_id(wlan_pdev_get_psoc(temp_pdev)),
1048*5113495bSYour Name 				link_idx, umac_reset,
1049*5113495bSYour Name 				temp_pdev->standby_active);
1050*5113495bSYour Name 				tx_ops->mops.target_if_mlo_teardown_req(
1051*5113495bSYour Name 						setup_info->pdev_list[link_idx],
1052*5113495bSYour Name 						reason, umac_reset,
1053*5113495bSYour Name 						temp_pdev->standby_active);
1054*5113495bSYour Name 			}
1055*5113495bSYour Name 		}
1056*5113495bSYour Name 	} else {
1057*5113495bSYour Name 		for (link_idx = 0; link_idx < setup_info->tot_links; link_idx++)
1058*5113495bSYour Name 			if (tx_ops && tx_ops->mops.target_if_mlo_teardown_req) {
1059*5113495bSYour Name 				if (!setup_info->pdev_list[link_idx])
1060*5113495bSYour Name 					continue;
1061*5113495bSYour Name 				tx_ops->mops.target_if_mlo_teardown_req(
1062*5113495bSYour Name 						setup_info->pdev_list[link_idx],
1063*5113495bSYour Name 						reason, 0, 0);
1064*5113495bSYour Name 			}
1065*5113495bSYour Name 	}
1066*5113495bSYour Name }
1067*5113495bSYour Name 
mlo_grp_in_teardown(uint8_t grp_id)1068*5113495bSYour Name static bool mlo_grp_in_teardown(uint8_t grp_id)
1069*5113495bSYour Name {
1070*5113495bSYour Name 	struct mlo_mgr_context *mlo_ctx = wlan_objmgr_get_mlo_ctx();
1071*5113495bSYour Name 	struct mlo_setup_info *setup_info;
1072*5113495bSYour Name 	uint8_t link_idx;
1073*5113495bSYour Name 
1074*5113495bSYour Name 	if (!mlo_ctx) {
1075*5113495bSYour Name 		mlo_err("MLO ctx null, teardown failed");
1076*5113495bSYour Name 		return true;
1077*5113495bSYour Name 	}
1078*5113495bSYour Name 
1079*5113495bSYour Name 	if (grp_id >= mlo_ctx->total_grp) {
1080*5113495bSYour Name 		mlo_err("Invalid grp id %d, total no of groups %d",
1081*5113495bSYour Name 			grp_id, mlo_ctx->total_grp);
1082*5113495bSYour Name 		return true;
1083*5113495bSYour Name 	}
1084*5113495bSYour Name 
1085*5113495bSYour Name 	setup_info = &mlo_ctx->setup_info[grp_id];
1086*5113495bSYour Name 
1087*5113495bSYour Name 	for (link_idx = 0; link_idx < setup_info->tot_links; link_idx++)
1088*5113495bSYour Name 		if (setup_info->pdev_list[link_idx] &&
1089*5113495bSYour Name 		    (setup_info->state[link_idx] == MLO_LINK_TEARDOWN))
1090*5113495bSYour Name 			return true;
1091*5113495bSYour Name 
1092*5113495bSYour Name 	return false;
1093*5113495bSYour Name }
1094*5113495bSYour Name 
1095*5113495bSYour Name #define MLO_MGR_TEARDOWN_TIMEOUT 3000
mlo_link_teardown_link(struct wlan_objmgr_psoc * psoc,uint8_t grp_id,uint32_t reason)1096*5113495bSYour Name QDF_STATUS mlo_link_teardown_link(struct wlan_objmgr_psoc *psoc,
1097*5113495bSYour Name 				  uint8_t grp_id,
1098*5113495bSYour Name 				  uint32_t reason)
1099*5113495bSYour Name {
1100*5113495bSYour Name 	QDF_STATUS status;
1101*5113495bSYour Name 	struct mlo_setup_info *setup_info;
1102*5113495bSYour Name 	struct mlo_mgr_context *mlo_ctx = wlan_objmgr_get_mlo_ctx();
1103*5113495bSYour Name 
1104*5113495bSYour Name 	if (!mlo_ctx)
1105*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
1106*5113495bSYour Name 
1107*5113495bSYour Name 	if (!psoc)
1108*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
1109*5113495bSYour Name 
1110*5113495bSYour Name 	if (grp_id >= mlo_ctx->total_grp) {
1111*5113495bSYour Name 		mlo_err("Invalid grp id %d, total no of groups %d",
1112*5113495bSYour Name 			grp_id, mlo_ctx->total_grp);
1113*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
1114*5113495bSYour Name 	}
1115*5113495bSYour Name 
1116*5113495bSYour Name 	setup_info = &mlo_ctx->setup_info[grp_id];
1117*5113495bSYour Name 
1118*5113495bSYour Name 	mlo_debug("Teardown req with grp_id %d num_soc %d num_link %d",
1119*5113495bSYour Name 		  grp_id, setup_info->num_soc, setup_info->num_links);
1120*5113495bSYour Name 
1121*5113495bSYour Name 	if (!setup_info->num_soc)
1122*5113495bSYour Name 		return QDF_STATUS_SUCCESS;
1123*5113495bSYour Name 
1124*5113495bSYour Name 	if (mlo_grp_in_teardown(grp_id)) {
1125*5113495bSYour Name 		mlo_debug("Skip teardown: as teardown sent already, grp_id %d num_soc %d num_link %d",
1126*5113495bSYour Name 			  grp_id, setup_info->num_soc, setup_info->num_links);
1127*5113495bSYour Name 		return QDF_STATUS_SUCCESS;
1128*5113495bSYour Name 	}
1129*5113495bSYour Name 
1130*5113495bSYour Name 	/* Trigger MLO teardown */
1131*5113495bSYour Name 	mlo_send_teardown_req(psoc, grp_id, reason);
1132*5113495bSYour Name 
1133*5113495bSYour Name 	if (reason == WMI_HOST_MLO_TEARDOWN_REASON_SSR) {
1134*5113495bSYour Name 		/* do not wait for teardown event completion here for SSR */
1135*5113495bSYour Name 		return QDF_STATUS_SUCCESS;
1136*5113495bSYour Name 	}
1137*5113495bSYour Name 
1138*5113495bSYour Name 	status = qdf_wait_for_event_completion(
1139*5113495bSYour Name 			&setup_info->event,
1140*5113495bSYour Name 			MLO_MGR_TEARDOWN_TIMEOUT);
1141*5113495bSYour Name 
1142*5113495bSYour Name 	if (status != QDF_STATUS_SUCCESS) {
1143*5113495bSYour Name 		qdf_info("Teardown timeout");
1144*5113495bSYour Name 		mlo_force_teardown(grp_id);
1145*5113495bSYour Name 	}
1146*5113495bSYour Name 
1147*5113495bSYour Name 	return status;
1148*5113495bSYour Name }
1149*5113495bSYour Name 
1150*5113495bSYour Name qdf_export_symbol(mlo_link_teardown_link);
1151*5113495bSYour Name 
mlo_update_wsi_stats_info_support(struct wlan_objmgr_psoc * psoc,bool wsi_stats_info_support)1152*5113495bSYour Name void mlo_update_wsi_stats_info_support(struct wlan_objmgr_psoc *psoc,
1153*5113495bSYour Name 				       bool wsi_stats_info_support)
1154*5113495bSYour Name {
1155*5113495bSYour Name 	uint8_t ml_grp_id;
1156*5113495bSYour Name 	struct mlo_mgr_context *mlo_ctx = wlan_objmgr_get_mlo_ctx();
1157*5113495bSYour Name 	struct mlo_setup_info *mlo_setup;
1158*5113495bSYour Name 
1159*5113495bSYour Name 	ml_grp_id = wlan_mlo_get_psoc_group_id(psoc);
1160*5113495bSYour Name 	if ((ml_grp_id ==  WLAN_MLO_GROUP_INVALID) ||
1161*5113495bSYour Name 	    (ml_grp_id < 0)) {
1162*5113495bSYour Name 		mlo_err("Invalid ML Grp ID %d", ml_grp_id);
1163*5113495bSYour Name 		return;
1164*5113495bSYour Name 	}
1165*5113495bSYour Name 
1166*5113495bSYour Name 	mlo_setup = &mlo_ctx->setup_info[ml_grp_id];
1167*5113495bSYour Name 	if (mlo_setup->wsi_stats_info_support == 0xFF)
1168*5113495bSYour Name 		mlo_setup->wsi_stats_info_support = wsi_stats_info_support;
1169*5113495bSYour Name 	else
1170*5113495bSYour Name 		mlo_setup->wsi_stats_info_support &= wsi_stats_info_support;
1171*5113495bSYour Name }
1172*5113495bSYour Name 
1173*5113495bSYour Name qdf_export_symbol(mlo_update_wsi_stats_info_support);
1174*5113495bSYour Name 
mlo_get_wsi_stats_info_support(struct wlan_objmgr_psoc * psoc)1175*5113495bSYour Name uint8_t mlo_get_wsi_stats_info_support(struct wlan_objmgr_psoc *psoc)
1176*5113495bSYour Name {
1177*5113495bSYour Name 	uint8_t ml_grp_id;
1178*5113495bSYour Name 	struct mlo_mgr_context *mlo_ctx = wlan_objmgr_get_mlo_ctx();
1179*5113495bSYour Name 	struct mlo_setup_info *mlo_setup;
1180*5113495bSYour Name 
1181*5113495bSYour Name 	ml_grp_id = wlan_mlo_get_psoc_group_id(psoc);
1182*5113495bSYour Name 	if ((ml_grp_id ==  WLAN_MLO_GROUP_INVALID) ||
1183*5113495bSYour Name 	    (ml_grp_id < 0)) {
1184*5113495bSYour Name 		mlo_err("Invalid ML Grp ID %d", ml_grp_id);
1185*5113495bSYour Name 		return 0;
1186*5113495bSYour Name 	}
1187*5113495bSYour Name 
1188*5113495bSYour Name 	mlo_setup = &mlo_ctx->setup_info[ml_grp_id];
1189*5113495bSYour Name 	if (mlo_setup->wsi_stats_info_support == 0xFF)
1190*5113495bSYour Name 		return 0;
1191*5113495bSYour Name 
1192*5113495bSYour Name 	return mlo_setup->wsi_stats_info_support;
1193*5113495bSYour Name }
1194*5113495bSYour Name 
mlo_update_tsf_sync_support(struct wlan_objmgr_psoc * psoc,bool tsf_sync_enab)1195*5113495bSYour Name void mlo_update_tsf_sync_support(struct wlan_objmgr_psoc *psoc,
1196*5113495bSYour Name 				 bool tsf_sync_enab)
1197*5113495bSYour Name {
1198*5113495bSYour Name 	uint8_t ml_grp_id;
1199*5113495bSYour Name 	struct mlo_mgr_context *mlo_ctx = wlan_objmgr_get_mlo_ctx();
1200*5113495bSYour Name 	struct mlo_setup_info *mlo_setup;
1201*5113495bSYour Name 
1202*5113495bSYour Name 	ml_grp_id = wlan_mlo_get_psoc_group_id(psoc);
1203*5113495bSYour Name 	if (ml_grp_id < 0) {
1204*5113495bSYour Name 		mlo_err("Invalid ML Grp ID %d", ml_grp_id);
1205*5113495bSYour Name 		return;
1206*5113495bSYour Name 	}
1207*5113495bSYour Name 
1208*5113495bSYour Name 	mlo_setup = &mlo_ctx->setup_info[ml_grp_id];
1209*5113495bSYour Name 	mlo_setup->tsf_sync_enabled &= tsf_sync_enab;
1210*5113495bSYour Name }
1211*5113495bSYour Name 
1212*5113495bSYour Name qdf_export_symbol(mlo_update_tsf_sync_support);
1213*5113495bSYour Name 
mlo_pdev_derive_bridge_link_pdevs(struct wlan_objmgr_pdev * pdev,struct wlan_objmgr_pdev ** pdev_list)1214*5113495bSYour Name bool mlo_pdev_derive_bridge_link_pdevs(struct wlan_objmgr_pdev *pdev,
1215*5113495bSYour Name 				       struct wlan_objmgr_pdev **pdev_list)
1216*5113495bSYour Name {
1217*5113495bSYour Name 	struct wlan_objmgr_psoc *psoc;
1218*5113495bSYour Name 	struct wlan_objmgr_psoc *grp_soc_list[MAX_MLO_CHIPS];
1219*5113495bSYour Name 	struct wlan_objmgr_pdev *tmp_pdev;
1220*5113495bSYour Name 	uint8_t tot_grp_socs;
1221*5113495bSYour Name 	uint8_t grp_id;
1222*5113495bSYour Name 	uint8_t psoc_id, tmp_psoc_id;
1223*5113495bSYour Name 	uint8_t idx;
1224*5113495bSYour Name 	uint8_t is_adjacent;
1225*5113495bSYour Name 	QDF_STATUS status;
1226*5113495bSYour Name 
1227*5113495bSYour Name 	psoc = wlan_pdev_get_psoc(pdev);
1228*5113495bSYour Name 
1229*5113495bSYour Name 	/* Initialize pdev list to NULL by default */
1230*5113495bSYour Name 	for (idx = 0; idx < MLO_MAX_BRIDGE_LINKS_PER_MLD; idx++)
1231*5113495bSYour Name 		pdev_list[idx] = NULL;
1232*5113495bSYour Name 
1233*5113495bSYour Name 	if (!mlo_psoc_get_grp_id(psoc, &grp_id)) {
1234*5113495bSYour Name 		qdf_err("Unable to get group id");
1235*5113495bSYour Name 		return false;
1236*5113495bSYour Name 	}
1237*5113495bSYour Name 
1238*5113495bSYour Name 	/* Get the total SOCs in the MLO group */
1239*5113495bSYour Name 	tot_grp_socs = mlo_setup_get_total_socs(grp_id);
1240*5113495bSYour Name 	if (!tot_grp_socs || tot_grp_socs > MAX_MLO_CHIPS) {
1241*5113495bSYour Name 		qdf_err("Unable to get total SOCs");
1242*5113495bSYour Name 		return false;
1243*5113495bSYour Name 	}
1244*5113495bSYour Name 	qdf_info("Total SOCs in MLO group%d: %d", grp_id, tot_grp_socs);
1245*5113495bSYour Name 
1246*5113495bSYour Name 	/* Get the SOC list in the MLO group */
1247*5113495bSYour Name 	mlo_get_soc_list(grp_soc_list, grp_id, tot_grp_socs,
1248*5113495bSYour Name 			 WLAN_MLO_GROUP_DEFAULT_SOC_LIST);
1249*5113495bSYour Name 
1250*5113495bSYour Name 	psoc_id = wlan_psoc_get_id(psoc);
1251*5113495bSYour Name 
1252*5113495bSYour Name 	/*
1253*5113495bSYour Name 	 * Check the current pdev for num bridge links created and
1254*5113495bSYour Name 	 * add to the pdev list if possible otherwise find opposite pdev
1255*5113495bSYour Name 	 */
1256*5113495bSYour Name 	if (wlan_pdev_get_mlo_bridge_vdev_count(pdev)
1257*5113495bSYour Name 	    < MLO_MAX_BRIDGE_LINKS_PER_RADIO)
1258*5113495bSYour Name 		pdev_list[0] = pdev;
1259*5113495bSYour Name 
1260*5113495bSYour Name 	/*
1261*5113495bSYour Name 	 * Iterate over the MLO group SOC list
1262*5113495bSYour Name 	 * and get the pdevs for bridge links
1263*5113495bSYour Name 	 */
1264*5113495bSYour Name 	for (idx = 0; idx < tot_grp_socs; idx++) {
1265*5113495bSYour Name 		if (!grp_soc_list[idx])
1266*5113495bSYour Name 			continue;
1267*5113495bSYour Name 
1268*5113495bSYour Name 		if (grp_soc_list[idx] == psoc)
1269*5113495bSYour Name 			continue;
1270*5113495bSYour Name 
1271*5113495bSYour Name 		/* Skip the pdev if bridge link quota is over */
1272*5113495bSYour Name 		tmp_pdev = grp_soc_list[idx]->soc_objmgr.wlan_pdev_list[0];
1273*5113495bSYour Name 
1274*5113495bSYour Name 		if (wlan_pdev_get_mlo_bridge_vdev_count(tmp_pdev)
1275*5113495bSYour Name 		    >= MLO_MAX_BRIDGE_LINKS_PER_RADIO)
1276*5113495bSYour Name 			continue;
1277*5113495bSYour Name 
1278*5113495bSYour Name 		tmp_psoc_id = wlan_psoc_get_id(grp_soc_list[idx]);
1279*5113495bSYour Name 
1280*5113495bSYour Name 		qdf_info("Checking adjacency of soc %d and %d",
1281*5113495bSYour Name 			 psoc_id, tmp_psoc_id);
1282*5113495bSYour Name 		status = mlo_chip_adjacent(psoc_id, tmp_psoc_id, &is_adjacent);
1283*5113495bSYour Name 		if (status != QDF_STATUS_SUCCESS) {
1284*5113495bSYour Name 			qdf_info("Check adjacency failed");
1285*5113495bSYour Name 			return false;
1286*5113495bSYour Name 		}
1287*5113495bSYour Name 
1288*5113495bSYour Name 		if (is_adjacent) {
1289*5113495bSYour Name 			if (!pdev_list[1])
1290*5113495bSYour Name 				pdev_list[1] = tmp_pdev;
1291*5113495bSYour Name 		} else if (!pdev_list[0]) {
1292*5113495bSYour Name 			pdev_list[0] = tmp_pdev;
1293*5113495bSYour Name 		}
1294*5113495bSYour Name 
1295*5113495bSYour Name 		if (pdev_list[0] && pdev_list[1])
1296*5113495bSYour Name 			return true;
1297*5113495bSYour Name 	}
1298*5113495bSYour Name 
1299*5113495bSYour Name 	return false;
1300*5113495bSYour Name }
1301*5113495bSYour Name 
1302*5113495bSYour Name qdf_export_symbol(mlo_pdev_derive_bridge_link_pdevs);
1303*5113495bSYour Name #endif /*WLAN_MLO_MULTI_CHIP*/
1304