xref: /wlan-dirver/qca-wifi-host-cmn/umac/mlo_mgr/src/wlan_mlo_mgr_setup.c (revision 8c3c4172fbd442a68f7b879958acb6794236aee0)
1 /* Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. All rights reserved.
2  *
3  * Permission to use, copy, modify, and/or distribute this software for any
4  * purpose with or without fee is hereby granted, provided that the above
5  * copyright notice and this permission notice appear in all copies.
6  *
7  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
8  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
9  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
10  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
11  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
12  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
13  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
14  */
15 
16 /*
17  * DOC: contains MLO manager ap related functionality
18  */
19 #include "wlan_mlo_mgr_cmn.h"
20 #include "wlan_mlo_mgr_main.h"
21 #ifdef WLAN_MLO_MULTI_CHIP
22 #include "wlan_lmac_if_def.h"
23 #include <cdp_txrx_mlo.h>
24 #endif
25 
26 #ifdef WLAN_MLO_MULTI_CHIP
27 void mlo_setup_update_total_socs(uint8_t tot_socs)
28 {
29 	struct mlo_mgr_context *mlo_ctx = wlan_objmgr_get_mlo_ctx();
30 
31 	if (!mlo_ctx)
32 		return;
33 
34 	mlo_ctx->setup_info.tot_socs = tot_socs;
35 }
36 
37 qdf_export_symbol(mlo_setup_update_total_socs);
38 
39 void mlo_setup_update_num_links(struct wlan_objmgr_psoc *psoc,
40 				uint8_t num_links)
41 {
42 	struct mlo_mgr_context *mlo_ctx = wlan_objmgr_get_mlo_ctx();
43 
44 	if (!mlo_ctx)
45 		return;
46 
47 	mlo_ctx->setup_info.tot_links += num_links;
48 }
49 
50 qdf_export_symbol(mlo_setup_update_num_links);
51 
52 void mlo_setup_update_soc_ready(struct wlan_objmgr_psoc *psoc)
53 {
54 	struct mlo_mgr_context *mlo_ctx = wlan_objmgr_get_mlo_ctx();
55 	uint8_t chip_idx;
56 
57 	if (!mlo_ctx || !mlo_ctx->setup_info.tot_socs)
58 		return;
59 
60 	chip_idx = mlo_ctx->setup_info.num_soc;
61 	qdf_assert_always(chip_idx < MAX_MLO_CHIPS);
62 	mlo_ctx->setup_info.soc_list[chip_idx] = psoc;
63 	mlo_ctx->setup_info.num_soc++;
64 
65 	if (mlo_ctx->setup_info.num_soc != mlo_ctx->setup_info.tot_socs)
66 		return;
67 
68 	for (chip_idx = 0; chip_idx < mlo_ctx->setup_info.num_soc;
69 			chip_idx++) {
70 		struct wlan_objmgr_psoc *tmp_soc =
71 			mlo_ctx->setup_info.soc_list[chip_idx];
72 
73 		cdp_soc_mlo_soc_setup(wlan_psoc_get_dp_handle(tmp_soc),
74 				      mlo_ctx->dp_handle);
75 	}
76 
77 	cdp_mlo_setup_complete(wlan_psoc_get_dp_handle(psoc),
78 			       mlo_ctx->dp_handle);
79 }
80 
81 qdf_export_symbol(mlo_setup_update_soc_ready);
82 
83 void mlo_setup_link_ready(struct wlan_objmgr_pdev *pdev)
84 {
85 	struct mlo_mgr_context *mlo_ctx = wlan_objmgr_get_mlo_ctx();
86 	uint8_t link_idx;
87 
88 	if (!mlo_ctx || !mlo_ctx->setup_info.tot_links)
89 		return;
90 
91 	link_idx = mlo_ctx->setup_info.num_links;
92 	/* TODO: Get reference to PDEV */
93 	qdf_assert_always(link_idx < MAX_MLO_LINKS);
94 	mlo_ctx->setup_info.pdev_list[link_idx] = pdev;
95 	mlo_ctx->setup_info.state[link_idx] = MLO_LINK_SETUP_INIT;
96 	mlo_ctx->setup_info.num_links++;
97 
98 	if (mlo_ctx->setup_info.num_links == mlo_ctx->setup_info.tot_links &&
99 	    mlo_ctx->setup_info.num_soc == mlo_ctx->setup_info.tot_socs) {
100 		struct wlan_objmgr_psoc *psoc;
101 		struct wlan_lmac_if_tx_ops *tx_ops;
102 
103 		psoc = wlan_pdev_get_psoc(pdev);
104 		tx_ops = wlan_psoc_get_lmac_if_txops(psoc);
105 		/* Trigger MLO setup */
106 		if (tx_ops && tx_ops->mops.target_if_mlo_setup_req) {
107 			tx_ops->mops.target_if_mlo_setup_req(
108 					mlo_ctx->setup_info.pdev_list,
109 					mlo_ctx->setup_info.num_links,
110 					mlo_ctx->setup_info.ml_grp_id);
111 		}
112 	}
113 }
114 
115 qdf_export_symbol(mlo_setup_link_ready);
116 
117 void mlo_link_setup_complete(struct wlan_objmgr_pdev *pdev)
118 {
119 	struct mlo_mgr_context *mlo_ctx = wlan_objmgr_get_mlo_ctx();
120 	uint8_t link_idx;
121 
122 	if (!mlo_ctx)
123 		return;
124 
125 	for (link_idx = 0; link_idx < mlo_ctx->setup_info.tot_links; link_idx++)
126 		if (mlo_ctx->setup_info.pdev_list[link_idx] == pdev) {
127 			mlo_ctx->setup_info.state[link_idx] =
128 							MLO_LINK_SETUP_DONE;
129 			break;
130 		}
131 
132 	for (link_idx = 0; link_idx < mlo_ctx->setup_info.tot_links; link_idx++)
133 		if (mlo_ctx->setup_info.state[link_idx] == MLO_LINK_SETUP_DONE)
134 			continue;
135 		else
136 			break;
137 
138 	if (link_idx == mlo_ctx->setup_info.tot_links) {
139 		struct wlan_objmgr_psoc *psoc;
140 		struct wlan_lmac_if_tx_ops *tx_ops;
141 
142 		psoc = wlan_pdev_get_psoc(pdev);
143 		tx_ops = wlan_psoc_get_lmac_if_txops(psoc);
144 		/* Trigger MLO ready */
145 		if (tx_ops && tx_ops->mops.target_if_mlo_ready) {
146 			tx_ops->mops.target_if_mlo_ready(
147 					mlo_ctx->setup_info.pdev_list,
148 					mlo_ctx->setup_info.num_links);
149 		}
150 	}
151 }
152 
153 qdf_export_symbol(mlo_link_setup_complete);
154 
155 static QDF_STATUS mlo_find_pdev_idx(struct wlan_objmgr_pdev *pdev,
156 				    uint8_t *link_idx)
157 {
158 	struct mlo_mgr_context *mlo_ctx = wlan_objmgr_get_mlo_ctx();
159 	uint8_t idx;
160 
161 	if (!mlo_ctx)
162 		return QDF_STATUS_E_FAILURE;
163 
164 	if (!link_idx)
165 		return QDF_STATUS_E_FAILURE;
166 
167 	for (idx = 0; idx < mlo_ctx->setup_info.tot_links; idx++) {
168 		if (mlo_ctx->setup_info.pdev_list[idx] == pdev) {
169 			*link_idx = idx;
170 			return QDF_STATUS_SUCCESS;
171 		}
172 	}
173 
174 	return QDF_STATUS_E_FAILURE;
175 }
176 
177 void mlo_link_teardown_complete(struct wlan_objmgr_pdev *pdev)
178 {
179 	struct mlo_mgr_context *mlo_ctx = wlan_objmgr_get_mlo_ctx();
180 	uint8_t link_idx;
181 
182 	if (!mlo_ctx)
183 		return;
184 
185 	if (!mlo_ctx->setup_info.num_links) {
186 		qdf_err("Delayed response ignore");
187 		return;
188 	}
189 
190 	if (mlo_find_pdev_idx(pdev, &link_idx) != QDF_STATUS_SUCCESS) {
191 		qdf_info("Failed to find pdev");
192 		return;
193 	}
194 
195 	qdf_debug("link idx = %d", link_idx);
196 	mlo_ctx->setup_info.pdev_list[link_idx] = NULL;
197 	mlo_ctx->setup_info.state[link_idx] = MLO_LINK_TEARDOWN;
198 	mlo_ctx->setup_info.num_links--;
199 
200 	if (!mlo_ctx->setup_info.num_links) {
201 		qdf_info("Teardown complete");
202 		qdf_event_set(&mlo_ctx->setup_info.event);
203 	}
204 }
205 
206 qdf_export_symbol(mlo_link_teardown_complete);
207 
208 #define MLO_MGR_TEARDOWN_TIMEOUT 3000
209 QDF_STATUS mlo_link_teardown_link(struct wlan_objmgr_psoc *psoc,
210 				  uint32_t reason)
211 {
212 	struct wlan_lmac_if_tx_ops *tx_ops;
213 	QDF_STATUS status;
214 	struct mlo_mgr_context *mlo_ctx = wlan_objmgr_get_mlo_ctx();
215 
216 	qdf_debug(" %d %d ",
217 		  mlo_ctx->setup_info.num_soc,
218 		  mlo_ctx->setup_info.num_links);
219 
220 	if (!mlo_ctx)
221 		return QDF_STATUS_E_FAILURE;
222 
223 	if (!mlo_ctx->setup_info.num_soc)
224 		return QDF_STATUS_SUCCESS;
225 
226 	if (!mlo_ctx->setup_info.num_links) {
227 		mlo_ctx->setup_info.num_soc--;
228 		return QDF_STATUS_SUCCESS;
229 	}
230 
231 	if (qdf_event_create(&mlo_ctx->setup_info.event) != QDF_STATUS_SUCCESS)
232 		return QDF_STATUS_E_FAULT;
233 
234 	tx_ops = wlan_psoc_get_lmac_if_txops(psoc);
235 	/* Trigger MLO teardown */
236 	if (tx_ops && tx_ops->mops.target_if_mlo_teardown_req) {
237 		tx_ops->mops.target_if_mlo_teardown_req(
238 				mlo_ctx->setup_info.pdev_list,
239 				mlo_ctx->setup_info.num_links,
240 				reason);
241 	}
242 
243 	status = qdf_wait_for_event_completion(&mlo_ctx->setup_info.event,
244 					       MLO_MGR_TEARDOWN_TIMEOUT);
245 	if (status != QDF_STATUS_SUCCESS) {
246 		qdf_info("Teardown timeout");
247 		mlo_ctx->setup_info.num_links = 0;
248 	}
249 
250 	qdf_event_destroy(&mlo_ctx->setup_info.event);
251 
252 	mlo_ctx->setup_info.num_soc--;
253 
254 	return status;
255 }
256 
257 qdf_export_symbol(mlo_link_teardown_link);
258 #endif /*WLAN_MLO_MULTI_CHIP*/
259