1 /* 2 * Copyright (c) 2018-2021 The Linux Foundation. All rights reserved. 3 * 4 * Permission to use, copy, modify, and/or distribute this software for 5 * any purpose with or without fee is hereby granted, provided that the 6 * above copyright notice and this permission notice appear in all 7 * copies. 8 * 9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL 10 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED 11 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE 12 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL 13 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR 14 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 15 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 16 * PERFORMANCE OF THIS SOFTWARE. 17 */ 18 19 #include "qdf_module.h" 20 #include "qdf_trace.h" 21 #include "qdf_platform.h" 22 23 /** 24 * The following callbacks should be defined static to make sure they are 25 * initialized to NULL 26 */ 27 static qdf_self_recovery_callback self_recovery_cb; 28 static qdf_is_fw_down_callback is_fw_down_cb; 29 static qdf_is_driver_unloading_callback is_driver_unloading_cb; 30 static qdf_is_driver_state_module_stop_callback is_driver_state_module_stop_cb; 31 static qdf_is_recovering_callback is_recovering_cb; 32 static qdf_is_drv_connected_callback is_drv_connected_cb; 33 static qdf_wmi_send_over_qmi_callback _wmi_send_recv_qmi_cb; 34 static qdf_is_drv_supported_callback is_drv_supported_cb; 35 static qdf_recovery_reason_update_callback update_recovery_reason_cb; 36 static qdf_bus_reg_dump get_bus_reg_dump; 37 38 39 40 void qdf_register_fw_down_callback(qdf_is_fw_down_callback is_fw_down) 41 { 42 is_fw_down_cb = is_fw_down; 43 } 44 45 qdf_export_symbol(qdf_register_fw_down_callback); 46 47 bool qdf_is_fw_down(void) 48 { 49 if (!is_fw_down_cb) { 50 QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR, 51 "fw down callback is not registered"); 52 return false; 53 } 54 55 return is_fw_down_cb(); 56 } 57 qdf_export_symbol(qdf_is_fw_down); 58 59 void qdf_register_wmi_send_recv_qmi_callback(qdf_wmi_send_over_qmi_callback 60 wmi_send_recv_qmi_cb) 61 { 62 _wmi_send_recv_qmi_cb = wmi_send_recv_qmi_cb; 63 } 64 65 qdf_export_symbol(qdf_register_wmi_send_recv_qmi_callback); 66 67 QDF_STATUS qdf_wmi_send_recv_qmi(void *buf, uint32_t len, void *cb_ctx, 68 qdf_wmi_recv_qmi_cb wmi_recv_qmi_cb) 69 { 70 if (!_wmi_send_recv_qmi_cb) { 71 QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR, 72 "Platform callback for WMI over QMI not registered"); 73 return QDF_STATUS_E_INVAL; 74 } 75 76 return _wmi_send_recv_qmi_cb(buf, len, cb_ctx, wmi_recv_qmi_cb); 77 } 78 79 qdf_export_symbol(qdf_wmi_send_recv_qmi); 80 81 void qdf_register_is_driver_unloading_callback( 82 qdf_is_driver_unloading_callback callback) 83 { 84 is_driver_unloading_cb = callback; 85 } 86 87 qdf_export_symbol(qdf_register_is_driver_unloading_callback); 88 89 void qdf_register_is_driver_state_module_stop_callback( 90 qdf_is_driver_state_module_stop_callback callback) 91 { 92 is_driver_state_module_stop_cb = callback; 93 } 94 95 qdf_export_symbol(qdf_register_is_driver_state_module_stop_callback); 96 97 void qdf_register_self_recovery_callback(qdf_self_recovery_callback callback) 98 { 99 self_recovery_cb = callback; 100 } 101 102 qdf_export_symbol(qdf_register_self_recovery_callback); 103 104 void __qdf_trigger_self_recovery(void *psoc, enum qdf_hang_reason reason, 105 const char *func, const uint32_t line) 106 { 107 if (self_recovery_cb) 108 self_recovery_cb(psoc, reason, func, line); 109 else 110 QDF_DEBUG_PANIC_FL(func, line, ""); 111 } 112 113 qdf_export_symbol(__qdf_trigger_self_recovery); 114 115 void qdf_register_recovering_state_query_callback( 116 qdf_is_recovering_callback is_recovering) 117 { 118 is_recovering_cb = is_recovering; 119 } 120 121 bool qdf_is_driver_unloading(void) 122 { 123 if (is_driver_unloading_cb) 124 return is_driver_unloading_cb(); 125 return false; 126 } 127 128 qdf_export_symbol(qdf_is_driver_unloading); 129 130 bool qdf_is_driver_state_module_stop(void) 131 { 132 if (is_driver_state_module_stop_cb) 133 return is_driver_state_module_stop_cb(); 134 return false; 135 } 136 137 qdf_export_symbol(qdf_is_driver_state_module_stop); 138 139 bool qdf_is_recovering(void) 140 { 141 if (is_recovering_cb) 142 return is_recovering_cb(); 143 return false; 144 } 145 146 qdf_export_symbol(qdf_is_recovering); 147 148 static qdf_op_protect_cb __on_op_protect; 149 static qdf_op_unprotect_cb __on_op_unprotect; 150 151 void qdf_op_callbacks_register(qdf_op_protect_cb on_protect, 152 qdf_op_unprotect_cb on_unprotect) 153 { 154 __on_op_protect = on_protect; 155 __on_op_unprotect = on_unprotect; 156 } 157 qdf_export_symbol(qdf_op_callbacks_register); 158 159 int __qdf_op_protect(struct qdf_op_sync **out_sync, const char *func) 160 { 161 if (!__on_op_protect) 162 return 0; 163 164 return __on_op_protect((void **)out_sync, func); 165 } 166 qdf_export_symbol(__qdf_op_protect); 167 168 void __qdf_op_unprotect(struct qdf_op_sync *sync, const char *func) 169 { 170 if (__on_op_unprotect) 171 __on_op_unprotect(sync, func); 172 } 173 qdf_export_symbol(__qdf_op_unprotect); 174 175 void qdf_register_drv_connected_callback(qdf_is_drv_connected_callback 176 is_drv_connected) 177 { 178 is_drv_connected_cb = is_drv_connected; 179 } 180 qdf_export_symbol(qdf_register_drv_connected_callback); 181 182 bool qdf_is_drv_connected(void) 183 { 184 if (!is_drv_connected_cb) { 185 qdf_err("drv connected callback is not registered"); 186 return false; 187 } 188 189 return is_drv_connected_cb(); 190 } 191 qdf_export_symbol(qdf_is_drv_connected); 192 193 void qdf_check_state_before_panic(const char *func, const uint32_t line) 194 { 195 if (!qdf_is_recovering() && !qdf_is_fw_down()) 196 QDF_DEBUG_PANIC_FL(func, line, ""); 197 } 198 199 qdf_export_symbol(qdf_check_state_before_panic); 200 201 void qdf_register_drv_supported_callback(qdf_is_drv_supported_callback 202 is_drv_supported) 203 { 204 is_drv_supported_cb = is_drv_supported; 205 } 206 207 qdf_export_symbol(qdf_register_drv_supported_callback); 208 209 bool qdf_is_drv_supported(void) 210 { 211 if (!is_drv_supported_cb) { 212 qdf_err("drv supported callback is not registered"); 213 return false; 214 } 215 216 return is_drv_supported_cb(); 217 } 218 219 qdf_export_symbol(qdf_is_drv_supported); 220 221 void qdf_register_recovery_reason_update(qdf_recovery_reason_update_callback 222 callback) 223 { 224 update_recovery_reason_cb = callback; 225 } 226 227 qdf_export_symbol(qdf_register_recovery_reason_update); 228 229 void qdf_recovery_reason_update(enum qdf_hang_reason reason) 230 { 231 if (!update_recovery_reason_cb) 232 return; 233 234 update_recovery_reason_cb(reason); 235 } 236 237 qdf_export_symbol(qdf_recovery_reason_update); 238 239 void qdf_register_get_bus_reg_dump(qdf_bus_reg_dump callback) 240 { 241 get_bus_reg_dump = callback; 242 } 243 244 qdf_export_symbol(qdf_register_get_bus_reg_dump); 245 246 void qdf_get_bus_reg_dump(struct device *dev, uint8_t *buf, uint32_t len) 247 { 248 if (!get_bus_reg_dump) 249 return; 250 251 get_bus_reg_dump(dev, buf, len); 252 } 253 254 qdf_export_symbol(qdf_get_bus_reg_dump); 255