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