1 /* 2 * Copyright (c) 2018-2020 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_recovering_callback is_recovering_cb; 31 static qdf_is_drv_connected_callback is_drv_connected_cb; 32 static qdf_wmi_send_over_qmi_callback _wmi_send_recv_qmi_cb; 33 static qdf_is_drv_supported_callback is_drv_supported_cb; 34 static qdf_recovery_reason_update_callback update_recovery_reason_cb; 35 static qdf_bus_reg_dump get_bus_reg_dump; 36 37 38 39 void qdf_register_fw_down_callback(qdf_is_fw_down_callback is_fw_down) 40 { 41 is_fw_down_cb = is_fw_down; 42 } 43 44 qdf_export_symbol(qdf_register_fw_down_callback); 45 46 bool qdf_is_fw_down(void) 47 { 48 if (!is_fw_down_cb) { 49 QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR, 50 "fw down callback is not registered"); 51 return false; 52 } 53 54 return is_fw_down_cb(); 55 } 56 qdf_export_symbol(qdf_is_fw_down); 57 58 void qdf_register_wmi_send_recv_qmi_callback(qdf_wmi_send_over_qmi_callback 59 wmi_send_recv_qmi_cb) 60 { 61 _wmi_send_recv_qmi_cb = wmi_send_recv_qmi_cb; 62 } 63 64 qdf_export_symbol(qdf_register_wmi_send_recv_qmi_callback); 65 66 QDF_STATUS qdf_wmi_send_recv_qmi(void *buf, uint32_t len, void *cb_ctx, 67 qdf_wmi_recv_qmi_cb wmi_recv_qmi_cb) 68 { 69 if (!_wmi_send_recv_qmi_cb) { 70 QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR, 71 "Platform callback for WMI over QMI not registered"); 72 return QDF_STATUS_E_INVAL; 73 } 74 75 return _wmi_send_recv_qmi_cb(buf, len, cb_ctx, wmi_recv_qmi_cb); 76 } 77 78 qdf_export_symbol(qdf_wmi_send_recv_qmi); 79 80 void qdf_register_is_driver_unloading_callback( 81 qdf_is_driver_unloading_callback callback) 82 { 83 is_driver_unloading_cb = callback; 84 } 85 86 qdf_export_symbol(qdf_register_is_driver_unloading_callback); 87 88 void qdf_register_self_recovery_callback(qdf_self_recovery_callback callback) 89 { 90 self_recovery_cb = callback; 91 } 92 93 qdf_export_symbol(qdf_register_self_recovery_callback); 94 95 void __qdf_trigger_self_recovery(void *psoc, enum qdf_hang_reason reason, 96 const char *func, const uint32_t line) 97 { 98 if (self_recovery_cb) 99 self_recovery_cb(psoc, reason, func, line); 100 else 101 QDF_DEBUG_PANIC_FL(func, line, ""); 102 } 103 104 qdf_export_symbol(__qdf_trigger_self_recovery); 105 106 void qdf_register_recovering_state_query_callback( 107 qdf_is_recovering_callback is_recovering) 108 { 109 is_recovering_cb = is_recovering; 110 } 111 112 bool qdf_is_driver_unloading(void) 113 { 114 if (is_driver_unloading_cb) 115 return is_driver_unloading_cb(); 116 return false; 117 } 118 119 qdf_export_symbol(qdf_is_driver_unloading); 120 121 bool qdf_is_recovering(void) 122 { 123 if (is_recovering_cb) 124 return is_recovering_cb(); 125 return false; 126 } 127 128 qdf_export_symbol(qdf_is_recovering); 129 130 static qdf_op_protect_cb __on_op_protect; 131 static qdf_op_unprotect_cb __on_op_unprotect; 132 133 void qdf_op_callbacks_register(qdf_op_protect_cb on_protect, 134 qdf_op_unprotect_cb on_unprotect) 135 { 136 __on_op_protect = on_protect; 137 __on_op_unprotect = on_unprotect; 138 } 139 qdf_export_symbol(qdf_op_callbacks_register); 140 141 int __qdf_op_protect(struct qdf_op_sync **out_sync, const char *func) 142 { 143 if (!__on_op_protect) 144 return 0; 145 146 return __on_op_protect((void **)out_sync, func); 147 } 148 qdf_export_symbol(__qdf_op_protect); 149 150 void __qdf_op_unprotect(struct qdf_op_sync *sync, const char *func) 151 { 152 if (__on_op_unprotect) 153 __on_op_unprotect(sync, func); 154 } 155 qdf_export_symbol(__qdf_op_unprotect); 156 157 void qdf_register_drv_connected_callback(qdf_is_drv_connected_callback 158 is_drv_connected) 159 { 160 is_drv_connected_cb = is_drv_connected; 161 } 162 qdf_export_symbol(qdf_register_drv_connected_callback); 163 164 bool qdf_is_drv_connected(void) 165 { 166 if (!is_drv_connected_cb) { 167 qdf_err("drv connected callback is not registered"); 168 return false; 169 } 170 171 return is_drv_connected_cb(); 172 } 173 qdf_export_symbol(qdf_is_drv_connected); 174 175 void qdf_check_state_before_panic(void) 176 { 177 if (!qdf_is_recovering() && !qdf_is_fw_down()) 178 QDF_BUG(0); 179 } 180 181 qdf_export_symbol(qdf_check_state_before_panic); 182 183 void qdf_register_drv_supported_callback(qdf_is_drv_supported_callback 184 is_drv_supported) 185 { 186 is_drv_supported_cb = is_drv_supported; 187 } 188 189 qdf_export_symbol(qdf_register_drv_supported_callback); 190 191 bool qdf_is_drv_supported(void) 192 { 193 if (!is_drv_supported_cb) { 194 qdf_err("drv supported callback is not registered"); 195 return false; 196 } 197 198 return is_drv_supported_cb(); 199 } 200 201 qdf_export_symbol(qdf_is_drv_supported); 202 203 void qdf_register_recovery_reason_update(qdf_recovery_reason_update_callback 204 callback) 205 { 206 update_recovery_reason_cb = callback; 207 } 208 209 qdf_export_symbol(qdf_register_recovery_reason_update); 210 211 void qdf_recovery_reason_update(enum qdf_hang_reason reason) 212 { 213 if (!update_recovery_reason_cb) 214 return; 215 216 update_recovery_reason_cb(reason); 217 } 218 219 qdf_export_symbol(qdf_recovery_reason_update); 220 221 void qdf_register_get_bus_reg_dump(qdf_bus_reg_dump callback) 222 { 223 get_bus_reg_dump = callback; 224 } 225 226 qdf_export_symbol(qdf_register_get_bus_reg_dump); 227 228 void qdf_get_bus_reg_dump(struct device *dev, uint8_t *buf, uint32_t len) 229 { 230 if (!get_bus_reg_dump) 231 return; 232 233 get_bus_reg_dump(dev, buf, len); 234 } 235 236 qdf_export_symbol(qdf_get_bus_reg_dump); 237