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, ¶ms,
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