xref: /wlan-dirver/qca-wifi-host-cmn/ipa/dispatcher/src/wlan_ipa_obj_mgmt_api.c (revision 45c28558a520fd0e975b20c0ad534a0aa7f08021)
1 /*
2  * Copyright (c) 2018, 2020-2021 The Linux Foundation. All rights reserved.
3  * Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. All rights reserved.
4  *
5  * Permission to use, copy, modify, and/or distribute this software for
6  * any purpose with or without fee is hereby granted, provided that the
7  * above copyright notice and this permission notice appear in all
8  * copies.
9  *
10  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
11  * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
12  * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
13  * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
14  * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
15  * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
16  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17  * PERFORMANCE OF THIS SOFTWARE.
18  */
19 /**
20  * DOC: public API related to the wlan ipa called by north bound HDD/OSIF
21  */
22 
23 #include "wlan_ipa_obj_mgmt_api.h"
24 #include "wlan_ipa_main.h"
25 #include "wlan_objmgr_global_obj.h"
26 #include <wlan_objmgr_global_obj_i.h>
27 #include "target_if_ipa.h"
28 #include "wlan_ipa_ucfg_api.h"
29 #include "qdf_platform.h"
30 #include "qdf_module.h"
31 
32 /* This is as per IPA capbility */
33 #define MAX_INSTANCES_SUPPORTED 2
34 
35 uint8_t g_instances_added;
36 static bool g_ipa_is_ready;
37 qdf_mutex_t g_init_deinit_lock;
38 
39 bool ipa_cb_is_ready(void)
40 {
41 	return g_ipa_is_ready;
42 }
43 
44 void ipa_disable_register_cb(void)
45 {
46 	ipa_debug("Don't register ready cb with IPA driver");
47 	g_ipa_is_ready = false;
48 }
49 
50 qdf_export_symbol(ipa_disable_register_cb);
51 
52 void ipa_init_deinit_lock(void)
53 {
54 	qdf_mutex_acquire(&g_init_deinit_lock);
55 }
56 
57 void ipa_init_deinit_unlock(void)
58 {
59 	qdf_mutex_release(&g_init_deinit_lock);
60 }
61 
62 /**
63  * ipa_pdev_obj_destroy_notification() - IPA pdev object destroy notification
64  * @pdev: pdev handle
65  * @arg_list: arguments list
66  *
67  * Return: QDF_STATUS_SUCCESS on success
68  */
69 static QDF_STATUS
70 ipa_pdev_obj_destroy_notification(struct wlan_objmgr_pdev *pdev,
71 				  void *arg_list)
72 {
73 	QDF_STATUS status;
74 	struct wlan_ipa_priv *ipa_obj;
75 
76 	ipa_debug("ipa pdev destroyed");
77 	if (!ipa_config_is_enabled()) {
78 		ipa_debug("IPA is disabled");
79 		return QDF_STATUS_SUCCESS;
80 	}
81 
82 	ipa_obj = wlan_objmgr_pdev_get_comp_private_obj(pdev,
83 							WLAN_UMAC_COMP_IPA);
84 	if (!ipa_obj) {
85 		ipa_err("Failed to get ipa pdev object");
86 		return QDF_STATUS_E_FAILURE;
87 	}
88 
89 	status = wlan_objmgr_pdev_component_obj_detach(pdev,
90 						       WLAN_UMAC_COMP_IPA,
91 						       ipa_obj);
92 	if (QDF_IS_STATUS_ERROR(status))
93 		ipa_err("Failed to detach ipa pdev object");
94 
95 	qdf_mem_free(ipa_obj);
96 
97 	return status;
98 }
99 
100 /**
101  * ipa_pdev_obj_create_notification() - IPA pdev object creation notification
102  * @pdev: pdev handle
103  * @arg_list: arguments list
104  *
105  * Return: QDF_STATUS_SUCCESS on success
106  */
107 static QDF_STATUS
108 ipa_pdev_obj_create_notification(struct wlan_objmgr_pdev *pdev,
109 				 void *arg_list)
110 {
111 	QDF_STATUS status;
112 	struct wlan_ipa_priv *ipa_obj;
113 
114 	ipa_debug("ipa pdev created");
115 
116 	if (!ipa_config_is_enabled()) {
117 		ipa_info("IPA is disabled");
118 		return QDF_STATUS_SUCCESS;
119 	}
120 
121 	ipa_obj = qdf_mem_malloc(sizeof(*ipa_obj));
122 	if (!ipa_obj)
123 		return QDF_STATUS_E_NOMEM;
124 
125 	status = wlan_objmgr_pdev_component_obj_attach(pdev,
126 						       WLAN_UMAC_COMP_IPA,
127 						       (void *)ipa_obj,
128 						       QDF_STATUS_SUCCESS);
129 	if (QDF_IS_STATUS_ERROR(status)) {
130 		ipa_err("Failed to attach pdev ipa component");
131 		qdf_mem_free(ipa_obj);
132 		return status;
133 	}
134 
135 	ipa_obj->pdev = pdev;
136 
137 	ipa_debug("ipa pdev attached");
138 
139 	return status;
140 }
141 
142 static void ipa_register_ready_cb(void *user_data)
143 {
144 	QDF_STATUS status = QDF_STATUS_SUCCESS;
145 	struct wlan_ipa_priv *ipa_obj;
146 	struct wlan_objmgr_pdev *pdev;
147 	struct wlan_objmgr_psoc *psoc;
148 	qdf_device_t qdf_dev;
149 	qdf_ipa_wdi_capabilities_out_params_t out_param;
150 	uint8_t pdev_id;
151 
152 	if (!ipa_config_is_enabled()) {
153 		ipa_info("IPA config is disabled");
154 		return;
155 	}
156 
157 	if (!user_data) {
158 		ipa_err("User_data object is NULL");
159 		return;
160 	}
161 
162 	/* Validate driver state to determine ipa_obj is valid or not */
163 	if (qdf_is_driver_state_module_stop()) {
164 		ipa_err("Driver modules stop in-progress or done");
165 		return;
166 	}
167 
168 	ipa_init_deinit_lock();
169 
170 	/*
171 	 * Meanwhile acquiring lock, driver stop modules can happen in parallel,
172 	 * validate driver state once again to proceed with IPA init.
173 	 */
174 	if (qdf_is_driver_state_module_stop()) {
175 		ipa_err("Driver modules stop in-progress/done, releasing lock");
176 		goto out;
177 	}
178 
179 	g_ipa_is_ready = true;
180 	ipa_info("IPA ready callback invoked: ipa_register_ready_cb");
181 
182 	/* Make call to get num_instances supported by IPA */
183 	qdf_ipa_wdi_get_capabilities(&out_param);
184 
185 	ipa_obj = (struct wlan_ipa_priv *)user_data;
186 
187 	pdev = ipa_priv_obj_get_pdev(ipa_obj);
188 	if (!pdev) {
189 		qdf_err("Pdev is NULL for");
190 		goto out;
191 	}
192 
193 	pdev_id = pdev->pdev_objmgr.wlan_pdev_id;
194 	psoc = wlan_pdev_get_psoc(pdev);
195 	if (!psoc) {
196 		qdf_err("Psoc is NULL for pdev_id %d", pdev_id);
197 		goto out;
198 	}
199 
200 	if (ipa_obj->handle_initialized) {
201 		ipa_info("ipa_obj hdl is true for pdev_id %d", pdev_id);
202 		goto out;
203 	}
204 
205 	/* Update instance_id for current pdev */
206 	ipa_obj->instance_id = psoc->soc_objmgr.psoc_id;
207 
208 	qdf_dev = wlan_psoc_get_qdf_dev(psoc);
209 	if (!qdf_dev) {
210 		ipa_err("QDF device context is NULL");
211 		goto out;
212 	}
213 
214 	status = ipa_obj_setup(ipa_obj);
215 	if (QDF_IS_STATUS_ERROR(status)) {
216 		ipa_err("Failed to setup ipa component");
217 		wlan_objmgr_pdev_component_obj_detach(pdev, WLAN_UMAC_COMP_IPA,
218 						      ipa_obj);
219 		qdf_mem_free(ipa_obj);
220 		goto out;
221 	}
222 	if (ucfg_ipa_uc_ol_init(pdev, qdf_dev)) {
223 		ipa_err("IPA ucfg_ipa_uc_ol_init failed");
224 		goto out;
225 	}
226 
227 	ipa_obj->handle_initialized = true;
228 out:
229 	ipa_init_deinit_unlock();
230 }
231 
232 QDF_STATUS ipa_register_is_ipa_ready(struct wlan_objmgr_pdev *pdev)
233 {
234 	int ret;
235 	struct wlan_ipa_priv *ipa_obj;
236 
237 	if (!ipa_config_is_enabled()) {
238 		ipa_info("IPA config is disabled");
239 		return QDF_STATUS_SUCCESS;
240 	}
241 
242 	ipa_obj = ipa_pdev_get_priv_obj(pdev);
243 	if (!ipa_obj) {
244 		ipa_err("IPA object is NULL");
245 		return QDF_STATUS_E_FAILURE;
246 	}
247 
248 	/* Acquire lock */
249 	ipa_init_deinit_lock();
250 	g_instances_added++;
251 	ipa_info("No. of instances added for IPA is %d", g_instances_added);
252 	/* Unlock */
253 	ipa_init_deinit_unlock();
254 
255 	ret = qdf_ipa_register_ipa_ready_cb(ipa_register_ready_cb,
256 					    (void *)ipa_obj);
257 	if (ret == -EEXIST) {
258 		ipa_info("IPA is ready, invoke callback");
259 		ipa_register_ready_cb((void *)ipa_obj);
260 	} else if (ret) {
261 		ipa_err("Failed to check IPA readiness %d", ret);
262 		return QDF_STATUS_E_FAILURE;
263 	}
264 	return QDF_STATUS_SUCCESS;
265 }
266 
267 qdf_export_symbol(ipa_register_is_ipa_ready);
268 
269 QDF_STATUS ipa_init(void)
270 {
271 	QDF_STATUS status = QDF_STATUS_SUCCESS;
272 
273 	ipa_info("ipa module dispatcher init");
274 
275 	if (!ipa_check_hw_present()) {
276 		ipa_info("ipa hw not present");
277 		return status;
278 	}
279 
280 	status = wlan_objmgr_register_pdev_create_handler(WLAN_UMAC_COMP_IPA,
281 		ipa_pdev_obj_create_notification, NULL);
282 
283 	if (QDF_IS_STATUS_ERROR(status)) {
284 		ipa_err("Failed to register pdev create handler for ipa");
285 
286 		return status;
287 	}
288 
289 	status = wlan_objmgr_register_pdev_destroy_handler(WLAN_UMAC_COMP_IPA,
290 		ipa_pdev_obj_destroy_notification, NULL);
291 
292 	if (QDF_IS_STATUS_ERROR(status)) {
293 		ipa_err("Failed to register pdev destroy handler for ipa");
294 		goto fail_delete_pdev;
295 	}
296 
297 	qdf_mutex_create(&g_init_deinit_lock);
298 
299 	return status;
300 
301 fail_delete_pdev:
302 	wlan_objmgr_unregister_pdev_create_handler(WLAN_UMAC_COMP_IPA,
303 		ipa_pdev_obj_create_notification, NULL);
304 
305 	return status;
306 }
307 
308 QDF_STATUS ipa_deinit(void)
309 {
310 	QDF_STATUS status = QDF_STATUS_SUCCESS;
311 
312 	ipa_info("ipa module dispatcher deinit");
313 
314 	if (!ipa_is_hw_support()) {
315 		ipa_info("ipa hw is not present");
316 		return status;
317 	}
318 
319 	if (!ipa_config_is_enabled()) {
320 		ipa_info("ipa is disabled");
321 		return status;
322 	}
323 
324 	qdf_mutex_destroy(&g_init_deinit_lock);
325 
326 	status = wlan_objmgr_unregister_pdev_destroy_handler(WLAN_UMAC_COMP_IPA,
327 				ipa_pdev_obj_destroy_notification, NULL);
328 	if (QDF_IS_STATUS_ERROR(status))
329 		ipa_err("Failed to unregister pdev destroy handler");
330 
331 	status = wlan_objmgr_unregister_pdev_create_handler(WLAN_UMAC_COMP_IPA,
332 				ipa_pdev_obj_create_notification, NULL);
333 	if (QDF_IS_STATUS_ERROR(status))
334 		ipa_err("Failed to unregister pdev create handler");
335 
336 	return status;
337 }
338 
339 qdf_ipa_wdi_hdl_t wlan_ipa_get_hdl(void *soc, uint8_t pdev_id)
340 {
341 	struct wlan_objmgr_psoc *psoc = (struct wlan_objmgr_psoc *)soc;
342 	struct wlan_objmgr_pdev *pdev;
343 	struct wlan_ipa_priv *ipa_obj;
344 	qdf_ipa_wdi_hdl_t hdl;
345 
346 	pdev = wlan_objmgr_get_pdev_by_id(psoc, pdev_id, WLAN_IPA_ID);
347 
348 	if (!pdev) {
349 		ipa_err("Failed to get pdev handle");
350 		return IPA_INVALID_HDL;
351 	}
352 
353 	ipa_obj = ipa_pdev_get_priv_obj(pdev);
354 	if (!ipa_obj) {
355 		ipa_err("IPA object is NULL for pdev_id[%d]", pdev_id);
356 		wlan_objmgr_pdev_release_ref(pdev, WLAN_IPA_ID);
357 		return IPA_INVALID_HDL;
358 	}
359 	hdl = ipa_obj->hdl;
360 
361 	wlan_objmgr_pdev_release_ref(pdev, WLAN_IPA_ID);
362 	return hdl;
363 }
364 
365 qdf_export_symbol(wlan_ipa_get_hdl);
366 
367 bool wlan_ipa_is_vlan_enabled(void)
368 {
369 	return ipa_config_is_vlan_enabled();
370 }
371 
372 qdf_export_symbol(wlan_ipa_is_vlan_enabled);
373