1 /*
2  * Copyright (c) 2018-2021 The Linux Foundation. All rights reserved.
3  * Copyright (c) 2023-2024 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 #include "qdf_module.h"
21 #include "qdf_trace.h"
22 #include "qdf_platform.h"
23 
24 /*
25  * The following callbacks should be defined static to make sure they are
26  * initialized to NULL
27  */
28 static qdf_self_recovery_callback	self_recovery_cb;
29 static qdf_is_fw_down_callback		is_fw_down_cb;
30 static qdf_is_driver_unloading_callback is_driver_unloading_cb;
31 static qdf_is_driver_state_module_stop_callback is_driver_state_module_stop_cb;
32 static qdf_is_recovering_callback	is_recovering_cb;
33 static qdf_is_drv_connected_callback    is_drv_connected_cb;
34 static qdf_wmi_send_over_qmi_callback _wmi_send_recv_qmi_cb;
35 static qdf_send_ind_over_qmi_callback _qmi_indication_cb;
36 static qdf_is_drv_supported_callback    is_drv_supported_cb;
37 static qdf_recovery_reason_update_callback   update_recovery_reason_cb;
38 static qdf_bus_reg_dump   get_bus_reg_dump;
39 
40 
41 
qdf_register_fw_down_callback(qdf_is_fw_down_callback is_fw_down)42 void qdf_register_fw_down_callback(qdf_is_fw_down_callback is_fw_down)
43 {
44 	is_fw_down_cb = is_fw_down;
45 }
46 
47 qdf_export_symbol(qdf_register_fw_down_callback);
48 
qdf_is_fw_down(void)49 bool qdf_is_fw_down(void)
50 {
51 	if (!is_fw_down_cb) {
52 		QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR,
53 			"fw down callback is not registered");
54 			return false;
55 	}
56 
57 	return is_fw_down_cb();
58 }
59 qdf_export_symbol(qdf_is_fw_down);
60 
qdf_register_wmi_send_recv_qmi_callback(qdf_wmi_send_over_qmi_callback wmi_send_recv_qmi_cb)61 void qdf_register_wmi_send_recv_qmi_callback(qdf_wmi_send_over_qmi_callback
62 					     wmi_send_recv_qmi_cb)
63 {
64 	_wmi_send_recv_qmi_cb = wmi_send_recv_qmi_cb;
65 }
66 
67 qdf_export_symbol(qdf_register_wmi_send_recv_qmi_callback);
68 
qdf_register_qmi_indication_callback(qdf_send_ind_over_qmi_callback cds_qmi_indication)69 void qdf_register_qmi_indication_callback(qdf_send_ind_over_qmi_callback
70 					  cds_qmi_indication)
71 {
72 	_qmi_indication_cb = cds_qmi_indication;
73 }
74 
75 qdf_export_symbol(qdf_register_qmi_indication_callback);
76 
qdf_wmi_send_recv_qmi(void * buf,uint32_t len,void * cb_ctx,qdf_wmi_recv_qmi_cb wmi_recv_qmi_cb)77 QDF_STATUS qdf_wmi_send_recv_qmi(void *buf, uint32_t len, void *cb_ctx,
78 				 qdf_wmi_recv_qmi_cb wmi_recv_qmi_cb)
79 {
80 	if (!_wmi_send_recv_qmi_cb) {
81 		QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR,
82 			  "Platform callback for WMI over QMI not registered");
83 			return QDF_STATUS_E_INVAL;
84 	}
85 
86 	return _wmi_send_recv_qmi_cb(buf, len, cb_ctx, wmi_recv_qmi_cb);
87 }
88 
89 qdf_export_symbol(qdf_wmi_send_recv_qmi);
90 
qdf_reg_qmi_indication(void * cb_ctx,qdf_qmi_ind_cb qmi_ind_cb)91 QDF_STATUS qdf_reg_qmi_indication(void *cb_ctx, qdf_qmi_ind_cb qmi_ind_cb)
92 {
93 	if (!_qmi_indication_cb) {
94 		QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR,
95 			  "Platform callback for QMI indication not registered");
96 			return QDF_STATUS_E_INVAL;
97 	}
98 
99 	return _qmi_indication_cb(cb_ctx, qmi_ind_cb);
100 }
101 
102 qdf_export_symbol(qdf_reg_qmi_indication);
103 
qdf_register_is_driver_unloading_callback(qdf_is_driver_unloading_callback callback)104 void qdf_register_is_driver_unloading_callback(
105 				qdf_is_driver_unloading_callback callback)
106 {
107 	is_driver_unloading_cb = callback;
108 }
109 
110 qdf_export_symbol(qdf_register_is_driver_unloading_callback);
111 
qdf_register_is_driver_state_module_stop_callback(qdf_is_driver_state_module_stop_callback callback)112 void qdf_register_is_driver_state_module_stop_callback(
113 			qdf_is_driver_state_module_stop_callback callback)
114 {
115 	is_driver_state_module_stop_cb = callback;
116 }
117 
118 qdf_export_symbol(qdf_register_is_driver_state_module_stop_callback);
119 
qdf_register_self_recovery_callback(qdf_self_recovery_callback callback)120 void qdf_register_self_recovery_callback(qdf_self_recovery_callback callback)
121 {
122 	self_recovery_cb = callback;
123 }
124 
125 qdf_export_symbol(qdf_register_self_recovery_callback);
126 
__qdf_trigger_self_recovery(void * psoc,enum qdf_hang_reason reason,const char * func,const uint32_t line)127 void __qdf_trigger_self_recovery(void *psoc, enum qdf_hang_reason reason,
128 				 const char *func, const uint32_t line)
129 {
130 	if (self_recovery_cb)
131 		self_recovery_cb(psoc, reason, func, line);
132 	else
133 		QDF_DEBUG_PANIC_FL(func, line, "");
134 }
135 
136 qdf_export_symbol(__qdf_trigger_self_recovery);
137 
qdf_register_recovering_state_query_callback(qdf_is_recovering_callback is_recovering)138 void qdf_register_recovering_state_query_callback(
139 			qdf_is_recovering_callback is_recovering)
140 {
141 	is_recovering_cb = is_recovering;
142 }
143 
qdf_is_driver_unloading(void)144 bool qdf_is_driver_unloading(void)
145 {
146 	if (is_driver_unloading_cb)
147 		return is_driver_unloading_cb();
148 	return false;
149 }
150 
151 qdf_export_symbol(qdf_is_driver_unloading);
152 
qdf_is_driver_state_module_stop(void)153 bool qdf_is_driver_state_module_stop(void)
154 {
155 	if (is_driver_state_module_stop_cb)
156 		return is_driver_state_module_stop_cb();
157 	return false;
158 }
159 
160 qdf_export_symbol(qdf_is_driver_state_module_stop);
161 
qdf_is_recovering(void)162 bool qdf_is_recovering(void)
163 {
164 	if (is_recovering_cb)
165 		return is_recovering_cb();
166 	return false;
167 }
168 
169 qdf_export_symbol(qdf_is_recovering);
170 
171 static qdf_op_protect_cb __on_op_protect;
172 static qdf_op_unprotect_cb __on_op_unprotect;
173 
qdf_op_callbacks_register(qdf_op_protect_cb on_protect,qdf_op_unprotect_cb on_unprotect)174 void qdf_op_callbacks_register(qdf_op_protect_cb on_protect,
175 			       qdf_op_unprotect_cb on_unprotect)
176 {
177 	__on_op_protect = on_protect;
178 	__on_op_unprotect = on_unprotect;
179 }
180 qdf_export_symbol(qdf_op_callbacks_register);
181 
__qdf_op_protect(struct qdf_op_sync ** out_sync,const char * func)182 int __qdf_op_protect(struct qdf_op_sync **out_sync, const char *func)
183 {
184 	if (!__on_op_protect)
185 		return 0;
186 
187 	return __on_op_protect((void **)out_sync, func);
188 }
189 qdf_export_symbol(__qdf_op_protect);
190 
__qdf_op_unprotect(struct qdf_op_sync * sync,const char * func)191 void __qdf_op_unprotect(struct qdf_op_sync *sync, const char *func)
192 {
193 	if (__on_op_unprotect)
194 		__on_op_unprotect(sync, func);
195 }
196 qdf_export_symbol(__qdf_op_unprotect);
197 
qdf_register_drv_connected_callback(qdf_is_drv_connected_callback is_drv_connected)198 void qdf_register_drv_connected_callback(qdf_is_drv_connected_callback
199 					 is_drv_connected)
200 {
201 	is_drv_connected_cb = is_drv_connected;
202 }
203 qdf_export_symbol(qdf_register_drv_connected_callback);
204 
qdf_is_drv_connected(void)205 bool qdf_is_drv_connected(void)
206 {
207 	if (!is_drv_connected_cb) {
208 		qdf_err("drv connected callback is not registered");
209 		return false;
210 	}
211 
212 	return is_drv_connected_cb();
213 }
214 qdf_export_symbol(qdf_is_drv_connected);
215 
qdf_check_state_before_panic(const char * func,const uint32_t line)216 void qdf_check_state_before_panic(const char *func, const uint32_t line)
217 {
218 	if (!qdf_is_recovering() && !qdf_is_fw_down())
219 		QDF_DEBUG_PANIC_FL(func, line, "");
220 }
221 
222 qdf_export_symbol(qdf_check_state_before_panic);
223 
qdf_register_drv_supported_callback(qdf_is_drv_supported_callback is_drv_supported)224 void qdf_register_drv_supported_callback(qdf_is_drv_supported_callback
225 					 is_drv_supported)
226 {
227 	is_drv_supported_cb = is_drv_supported;
228 }
229 
230 qdf_export_symbol(qdf_register_drv_supported_callback);
231 
qdf_is_drv_supported(void)232 bool qdf_is_drv_supported(void)
233 {
234 	if (!is_drv_supported_cb) {
235 		qdf_err("drv supported callback is not registered");
236 		return false;
237 	}
238 
239 	return is_drv_supported_cb();
240 }
241 
242 qdf_export_symbol(qdf_is_drv_supported);
243 
qdf_register_recovery_reason_update(qdf_recovery_reason_update_callback callback)244 void qdf_register_recovery_reason_update(qdf_recovery_reason_update_callback
245 					 callback)
246 {
247 	update_recovery_reason_cb = callback;
248 }
249 
250 qdf_export_symbol(qdf_register_recovery_reason_update);
251 
qdf_recovery_reason_update(enum qdf_hang_reason reason)252 void qdf_recovery_reason_update(enum qdf_hang_reason reason)
253 {
254 	if (!update_recovery_reason_cb)
255 		return;
256 
257 	update_recovery_reason_cb(reason);
258 }
259 
260 qdf_export_symbol(qdf_recovery_reason_update);
261 
qdf_register_get_bus_reg_dump(qdf_bus_reg_dump callback)262 void qdf_register_get_bus_reg_dump(qdf_bus_reg_dump callback)
263 {
264 	get_bus_reg_dump = callback;
265 }
266 
267 qdf_export_symbol(qdf_register_get_bus_reg_dump);
268 
qdf_get_bus_reg_dump(struct device * dev,uint8_t * buf,uint32_t len)269 void qdf_get_bus_reg_dump(struct device *dev, uint8_t *buf, uint32_t len)
270 {
271 	if (!get_bus_reg_dump)
272 		return;
273 
274 	get_bus_reg_dump(dev, buf, len);
275 }
276 
277 qdf_export_symbol(qdf_get_bus_reg_dump);
278 
279 #ifdef WLAN_SUPPORT_DPDK
qdf_uio_register_device(struct device * parent,qdf_uio_info_t * info)280 int qdf_uio_register_device(struct device *parent, qdf_uio_info_t *info)
281 {
282 	return uio_register_device(parent, (struct uio_info *)info);
283 }
284 
285 qdf_export_symbol(qdf_uio_register_device);
286 
qdf_uio_unregister_device(qdf_uio_info_t * info)287 void qdf_uio_unregister_device(qdf_uio_info_t *info)
288 {
289 	uio_unregister_device(info);
290 }
291 
292 qdf_export_symbol(qdf_uio_unregister_device);
293 #endif
294