1 /* 2 * Copyright (c) 2014-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 /** 20 * DOC: i_qdf_trace.h 21 * 22 * Linux-specific definitions for QDF trace 23 * 24 */ 25 26 #if !defined(__I_QDF_TRACE_H) 27 #define __I_QDF_TRACE_H 28 29 /* older kernels have a bug in kallsyms, so ensure module.h is included */ 30 #include <linux/module.h> 31 #include <linux/kallsyms.h> 32 #ifdef CONFIG_QCA_MINIDUMP 33 #include <linux/minidump_tlv.h> 34 #endif 35 36 #if !defined(__printf) 37 #define __printf(a, b) 38 #endif 39 40 /* QDF_TRACE is the macro invoked to add trace messages to code. See the 41 * documenation for qdf_trace_msg() for the parameters etc. for this function. 42 * 43 * NOTE: Code QDF_TRACE() macros into the source code. Do not code directly 44 * to the qdf_trace_msg() function. 45 * 46 * NOTE 2: qdf tracing is totally turned off if WLAN_DEBUG is *not* defined. 47 * This allows us to build 'performance' builds where we can measure performance 48 * without being bogged down by all the tracing in the code 49 */ 50 #if defined(QDF_TRACE_PRINT_ENABLE) 51 #define qdf_trace(log_level, args...) \ 52 do { \ 53 extern int qdf_dbg_mask; \ 54 if (qdf_dbg_mask >= log_level) { \ 55 printk(args); \ 56 printk("\n"); \ 57 } \ 58 } while (0) 59 #endif 60 61 #if defined(WLAN_DEBUG) || defined(DEBUG) || defined(QDF_TRACE_PRINT_ENABLE) 62 #define QDF_TRACE qdf_trace_msg 63 #define QDF_VTRACE qdf_vtrace_msg 64 #define QDF_TRACE_HEX_DUMP qdf_trace_hex_dump 65 #else 66 #define QDF_TRACE(arg ...) __qdf_trace_dummy(arg) 67 #define QDF_VTRACE(arg ...) __qdf_vtrace_dummy(arg) 68 #define QDF_TRACE_HEX_DUMP(arg ...) __qdf_trace_hexdump_dummy(arg) 69 #endif 70 71 #if defined(WLAN_DEBUG) || defined(DEBUG) || defined(QDF_TRACE_PRINT_ENABLE) 72 #define QDF_MAX_LOGS_PER_SEC 2 73 /** 74 * __QDF_TRACE_RATE_LIMITED() - rate limited version of QDF_TRACE 75 * @params: parameters to pass through to QDF_TRACE 76 * 77 * This API prevents logging a message more than QDF_MAX_LOGS_PER_SEC times per 78 * second. This means any subsequent calls to this API from the same location 79 * within 1/QDF_MAX_LOGS_PER_SEC seconds will be dropped. 80 * 81 * Return: None 82 */ 83 #define __QDF_TRACE_RATE_LIMITED(params...)\ 84 do {\ 85 static ulong __last_ticks;\ 86 ulong __ticks = jiffies;\ 87 if (time_after(__ticks,\ 88 __last_ticks + HZ / QDF_MAX_LOGS_PER_SEC)) {\ 89 QDF_TRACE(params);\ 90 __last_ticks = __ticks;\ 91 } \ 92 } while (0) 93 94 #define __QDF_TRACE_HEX_DUMP_RATE_LIMITED(params...)\ 95 do {\ 96 static ulong __last_ticks;\ 97 ulong __ticks = jiffies;\ 98 if (time_after(__ticks,\ 99 __last_ticks + HZ / QDF_MAX_LOGS_PER_SEC)) {\ 100 QDF_TRACE_HEX_DUMP(params);\ 101 __last_ticks = __ticks;\ 102 } \ 103 } while (0) 104 #else 105 #define __QDF_TRACE_RATE_LIMITED(arg ...) 106 #define __QDF_TRACE_HEX_DUMP_RATE_LIMITED(arg ...) 107 #endif 108 109 #define __QDF_TRACE_NO_FL(log_level, module_id, format, args...) \ 110 QDF_TRACE(module_id, log_level, format, ## args) 111 112 #define __QDF_TRACE_FL(log_level, module_id, format, args...) \ 113 QDF_TRACE(module_id, log_level, FL(format), ## args) 114 115 #define __QDF_TRACE_RL(log_level, module_id, format, args...) \ 116 __QDF_TRACE_RATE_LIMITED(module_id, log_level, FL(format), ## args) 117 118 #define __QDF_TRACE_RL_NO_FL(log_level, module_id, format, args...) \ 119 __QDF_TRACE_RATE_LIMITED(module_id, log_level, format, ## args) 120 121 #define __QDF_TRACE_HEX_DUMP_RL(log_level, module_id, args...) \ 122 __QDF_TRACE_HEX_DUMP_RATE_LIMITED(module_id, log_level, ## args) 123 124 static inline void __qdf_trace_noop(QDF_MODULE_ID module, 125 const char *format, ...) { } 126 static inline void __qdf_trace_dummy(QDF_MODULE_ID module, 127 QDF_TRACE_LEVEL level, 128 const char *format, ...) { } 129 static inline void __qdf_vtrace_dummy(QDF_MODULE_ID module, 130 QDF_TRACE_LEVEL level, 131 const char *str_format, va_list val) { } 132 static inline void __qdf_trace_hexdump_dummy(QDF_MODULE_ID module, 133 QDF_TRACE_LEVEL level, 134 void *data, int buf_len) { } 135 136 137 #ifdef WLAN_LOG_FATAL 138 #define QDF_TRACE_FATAL(params...) \ 139 __QDF_TRACE_FL(QDF_TRACE_LEVEL_FATAL, ## params) 140 #define QDF_TRACE_FATAL_NO_FL(params...) \ 141 __QDF_TRACE_NO_FL(QDF_TRACE_LEVEL_FATAL, ## params) 142 #define QDF_TRACE_FATAL_RL(params...) \ 143 __QDF_TRACE_RL(QDF_TRACE_LEVEL_FATAL, ## params) 144 #define QDF_TRACE_FATAL_RL_NO_FL(params...) \ 145 __QDF_TRACE_RL_NO_FL(QDF_TRACE_LEVEL_FATAL, ## params) 146 #define QDF_VTRACE_FATAL(module_id, fmt, args) \ 147 QDF_VTRACE(module_id, QDF_TRACE_LEVEL_FATAL, fmt, args) 148 #define QDF_TRACE_HEX_DUMP_FATAL_RL(params...) \ 149 __QDF_TRACE_HEX_DUMP_RL(QDF_TRACE_LEVEL_FATAL, ## params) 150 #else 151 #define QDF_TRACE_FATAL(params...) __qdf_trace_noop(params) 152 #define QDF_TRACE_FATAL_NO_FL(params...) __qdf_trace_noop(params) 153 #define QDF_TRACE_FATAL_RL(params...) __qdf_trace_noop(params) 154 #define QDF_TRACE_FATAL_RL_NO_FL(params...) __qdf_trace_noop(params) 155 #define QDF_VTRACE_FATAL(params...) __qdf_trace_noop(params) 156 #define QDF_TRACE_HEX_DUMP_FATAL_RL(params...) __qdf_trace_noop(params) 157 #endif 158 159 #ifdef WLAN_LOG_ERROR 160 #define QDF_TRACE_ERROR(params...) \ 161 __QDF_TRACE_FL(QDF_TRACE_LEVEL_ERROR, ## params) 162 #define QDF_TRACE_ERROR_NO_FL(params...) \ 163 __QDF_TRACE_NO_FL(QDF_TRACE_LEVEL_ERROR, ## params) 164 #define QDF_TRACE_ERROR_RL(params...) \ 165 __QDF_TRACE_RL(QDF_TRACE_LEVEL_ERROR, ## params) 166 #define QDF_TRACE_ERROR_RL_NO_FL(params...) \ 167 __QDF_TRACE_RL_NO_FL(QDF_TRACE_LEVEL_ERROR, ## params) 168 #define QDF_VTRACE_ERROR(module_id, fmt, args) \ 169 QDF_VTRACE(module_id, QDF_TRACE_LEVEL_ERROR, fmt, args) 170 #define QDF_TRACE_HEX_DUMP_ERROR_RL(params...) \ 171 __QDF_TRACE_HEX_DUMP_RL(QDF_TRACE_LEVEL_ERROR, ## params) 172 #else 173 #define QDF_TRACE_ERROR(params...) __qdf_trace_noop(params) 174 #define QDF_TRACE_ERROR_NO_FL(params...) __qdf_trace_noop(params) 175 #define QDF_TRACE_ERROR_RL(params...) __qdf_trace_noop(params) 176 #define QDF_TRACE_ERROR_RL_NO_FL(params...) __qdf_trace_noop(params) 177 #define QDF_VTRACE_ERROR(params...) __qdf_trace_noop(params) 178 #define QDF_TRACE_HEX_DUMP_ERROR_RL(params...) __qdf_trace_noop(params) 179 #endif 180 181 #ifdef WLAN_LOG_WARN 182 #define QDF_TRACE_WARN(params...) \ 183 __QDF_TRACE_FL(QDF_TRACE_LEVEL_WARN, ## params) 184 #define QDF_TRACE_WARN_NO_FL(params...) \ 185 __QDF_TRACE_NO_FL(QDF_TRACE_LEVEL_WARN, ## params) 186 #define QDF_TRACE_WARN_RL(params...) \ 187 __QDF_TRACE_RL(QDF_TRACE_LEVEL_WARN, ## params) 188 #define QDF_TRACE_WARN_RL_NO_FL(params...) \ 189 __QDF_TRACE_RL_NO_FL(QDF_TRACE_LEVEL_WARN, ## params) 190 #define QDF_VTRACE_WARN(module_id, fmt, args) \ 191 QDF_VTRACE(module_id, QDF_TRACE_LEVEL_WARN, fmt, args) 192 #define QDF_TRACE_HEX_DUMP_WARN_RL(params...) \ 193 __QDF_TRACE_HEX_DUMP_RL(QDF_TRACE_LEVEL_WARN, ## params) 194 #else 195 #define QDF_TRACE_WARN(params...) __qdf_trace_noop(params) 196 #define QDF_TRACE_WARN_NO_FL(params...) __qdf_trace_noop(params) 197 #define QDF_TRACE_WARN_RL(params...) __qdf_trace_noop(params) 198 #define QDF_TRACE_WARN_RL_NO_FL(params...) __qdf_trace_noop(params) 199 #define QDF_VTRACE_WARN(params...) __qdf_trace_noop(params) 200 #define QDF_TRACE_HEX_DUMP_WARN_RL(params...) __qdf_trace_noop(params) 201 #endif 202 203 #ifdef WLAN_LOG_INFO 204 #define QDF_TRACE_INFO(params...) \ 205 __QDF_TRACE_FL(QDF_TRACE_LEVEL_INFO, ## params) 206 #define QDF_TRACE_INFO_NO_FL(params...) \ 207 __QDF_TRACE_NO_FL(QDF_TRACE_LEVEL_INFO, ## params) 208 #define QDF_TRACE_INFO_RL(params...) \ 209 __QDF_TRACE_RL(QDF_TRACE_LEVEL_INFO, ## params) 210 #define QDF_TRACE_INFO_RL_NO_FL(params...) \ 211 __QDF_TRACE_RL_NO_FL(QDF_TRACE_LEVEL_INFO, ## params) 212 #define QDF_VTRACE_INFO(module_id, fmt, args) \ 213 QDF_VTRACE(module_id, QDF_TRACE_LEVEL_INFO, fmt, args) 214 #define QDF_TRACE_HEX_DUMP_INFO_RL(params...) \ 215 __QDF_TRACE_HEX_DUMP_RL(QDF_TRACE_LEVEL_INFO, ## params) 216 #else 217 #define QDF_TRACE_INFO(params...) __qdf_trace_noop(params) 218 #define QDF_TRACE_INFO_NO_FL(params...) __qdf_trace_noop(params) 219 #define QDF_TRACE_INFO_RL(params...) __qdf_trace_noop(params) 220 #define QDF_TRACE_INFO_RL_NO_FL(params...) __qdf_trace_noop(params) 221 #define QDF_VTRACE_INFO(params...) __qdf_trace_noop(params) 222 #define QDF_TRACE_HEX_DUMP_INFO_RL(params...) __qdf_trace_noop(params) 223 #endif 224 225 #ifdef WLAN_LOG_DEBUG 226 #define QDF_TRACE_DEBUG(params...) \ 227 __QDF_TRACE_FL(QDF_TRACE_LEVEL_DEBUG, ## params) 228 #define QDF_TRACE_DEBUG_NO_FL(params...) \ 229 __QDF_TRACE_NO_FL(QDF_TRACE_LEVEL_DEBUG, ## params) 230 #define QDF_TRACE_DEBUG_RL(params...) \ 231 __QDF_TRACE_RL(QDF_TRACE_LEVEL_DEBUG, ## params) 232 #define QDF_TRACE_DEBUG_RL_NO_FL(params...) \ 233 __QDF_TRACE_RL_NO_FL(QDF_TRACE_LEVEL_DEBUG, ## params) 234 #define QDF_VTRACE_DEBUG(module_id, fmt, args) \ 235 QDF_VTRACE(module_id, QDF_TRACE_LEVEL_DEBUG, fmt, args) 236 #define QDF_TRACE_HEX_DUMP_DEBUG_RL(params...) \ 237 __QDF_TRACE_HEX_DUMP_RL(QDF_TRACE_LEVEL_DEBUG, ## params) 238 #else 239 #define QDF_TRACE_DEBUG(params...) __qdf_trace_noop(params) 240 #define QDF_TRACE_DEBUG_NO_FL(params...) __qdf_trace_noop(params) 241 #define QDF_TRACE_DEBUG_RL(params...) __qdf_trace_noop(params) 242 #define QDF_TRACE_DEBUG_RL_NO_FL(params...) __qdf_trace_noop(params) 243 #define QDF_VTRACE_DEBUG(params...) __qdf_trace_noop(params) 244 #define QDF_TRACE_HEX_DUMP_DEBUG_RL(params...) __qdf_trace_noop(params) 245 #endif 246 247 #ifdef WLAN_LOG_ENTER 248 #define QDF_TRACE_ENTER(params...) \ 249 __QDF_TRACE_FL(QDF_TRACE_LEVEL_DEBUG, ## params) 250 #else 251 #define QDF_TRACE_ENTER(params...) __qdf_trace_noop(params) 252 #endif 253 254 #ifdef WLAN_LOG_EXIT 255 #define QDF_TRACE_EXIT(params...) \ 256 __QDF_TRACE_FL(QDF_TRACE_LEVEL_DEBUG, ## params) 257 #else 258 #define QDF_TRACE_EXIT(params...) __qdf_trace_noop(params) 259 #endif 260 261 #define QDF_ENABLE_TRACING 262 #define qdf_scnprintf scnprintf 263 264 #ifdef QDF_ENABLE_TRACING 265 266 #ifdef WLAN_WARN_ON_ASSERT 267 #define QDF_ASSERT(_condition) \ 268 do { \ 269 if (!(_condition)) { \ 270 pr_err("QDF ASSERT in %s Line %d\n", \ 271 __func__, __LINE__); \ 272 WARN_ON(1); \ 273 } \ 274 } while (0) 275 #else 276 #define QDF_ASSERT(_condition) \ 277 do { \ 278 if (!(_condition)) { \ 279 /* no-op */ \ 280 } \ 281 } while (0) 282 #endif /* WLAN_WARN_ON_ASSERT */ 283 /** 284 * qdf_trace_msg()- logging API 285 * @module: Module identifier. A member of the QDF_MODULE_ID enumeration that 286 * identifies the module issuing the trace message. 287 * @level: Trace level. A member of the QDF_TRACE_LEVEL enumeration indicating 288 * the severity of the condition causing the trace message to be issued. 289 * More severe conditions are more likely to be logged. 290 * @str_format: Format string. The message to be logged. This format string 291 * contains printf-like replacement parameters, which follow this 292 * parameter in the variable argument list. 293 * 294 * Users wishing to add tracing information to their code should use 295 * QDF_TRACE. QDF_TRACE() will compile into a call to qdf_trace_msg() when 296 * tracing is enabled. 297 * 298 * Return: nothing 299 * 300 * implemented in qdf_trace.c 301 */ 302 void __printf(3, 4) qdf_trace_msg(QDF_MODULE_ID module, QDF_TRACE_LEVEL level, 303 const char *str_format, ...); 304 305 /** 306 * qdf_vtrace_msg() - the va_list version of qdf_trace_msg 307 * @module: the calling module's Id 308 * @level: the logging level to log using 309 * @str_format: the log format string 310 * @val: the va_list containing the values to format according to str_format 311 * 312 * Return: None 313 */ 314 void qdf_vtrace_msg(QDF_MODULE_ID module, QDF_TRACE_LEVEL level, 315 const char *str_format, va_list val); 316 317 #else 318 319 /* This code will be used for compilation if tracing is to be compiled out */ 320 /* of the code so these functions/macros are 'do nothing' */ 321 static inline void qdf_trace_msg(QDF_MODULE_ID module, QDF_TRACE_LEVEL level, 322 const char *str_format, ...) 323 { 324 } 325 326 #define QDF_ASSERT(_condition) 327 328 #endif 329 330 #ifdef QDF_TRACE_PRINT_ENABLE 331 static inline void qdf_vprint(const char *fmt, va_list args) 332 { 333 QDF_VTRACE_INFO(QDF_MODULE_ID_ANY, fmt, args); 334 } 335 #else /* QDF_TRACE_PRINT_ENABLE */ 336 static inline void qdf_vprint(const char *fmt, va_list args) 337 { 338 QDF_VTRACE_ERROR(QDF_MODULE_ID_QDF, fmt, args); 339 } 340 #endif 341 342 #ifdef PANIC_ON_BUG 343 #ifdef CONFIG_SLUB_DEBUG 344 /** 345 * __qdf_bug() - Calls BUG() when the PANIC_ON_BUG compilation option is enabled 346 * 347 * Note: Calling BUG() can cause a compiler to assume any following code is 348 * unreachable. Because these BUG's may or may not be enabled by the build 349 * configuration, this can cause developers some pain. Consider: 350 * 351 * bool bit; 352 * 353 * if (ptr) 354 * bit = ptr->returns_bool(); 355 * else 356 * __qdf_bug(); 357 * 358 * // do stuff with @bit 359 * 360 * return bit; 361 * 362 * In this case, @bit is potentially uninitialized when we return! However, the 363 * compiler can correctly assume this case is impossible when PANIC_ON_BUG is 364 * enabled. Because developers typically enable this feature, the "maybe 365 * uninitialized" warning will not be emitted, and the bug remains uncaught 366 * until someone tries to make a build without PANIC_ON_BUG. 367 * 368 * A simple workaround for this, is to put the definition of __qdf_bug in 369 * another compilation unit, which prevents the compiler from assuming 370 * subsequent code is unreachable. For CONFIG_SLUB_DEBUG, do this to catch more 371 * bugs. Otherwise, use the typical inlined approach. 372 * 373 * Return: None 374 */ 375 void __qdf_bug(void); 376 #else /* CONFIG_SLUB_DEBUG */ 377 static inline void __qdf_bug(void) 378 { 379 BUG(); 380 } 381 #endif /* CONFIG_SLUB_DEBUG */ 382 383 /** 384 * QDF_DEBUG_PANIC() - In debug builds, panic, otherwise do nothing 385 * @reason_fmt: a format string containing the reason for the panic 386 * @args: zero or more printf compatible logging arguments 387 * 388 * Return: None 389 */ 390 #define QDF_DEBUG_PANIC(reason_fmt, args...) \ 391 QDF_DEBUG_PANIC_FL(__func__, __LINE__, reason_fmt, ## args) 392 393 /** 394 * QDF_DEBUG_PANIC_FL() - In debug builds, panic, otherwise do nothing 395 * @func: origin function name to be logged 396 * @line: origin line number to be logged 397 * @fmt: printf compatible format string to be logged 398 * @args: zero or more printf compatible logging arguments 399 * 400 * Return: None 401 */ 402 #define QDF_DEBUG_PANIC_FL(func, line, fmt, args...) \ 403 do { \ 404 pr_err("WLAN Panic @ %s:%d: " fmt "\n", func, line, ##args); \ 405 __qdf_bug(); \ 406 } while (false) 407 408 #define QDF_BUG(_condition) \ 409 do { \ 410 if (!(_condition)) { \ 411 pr_err("QDF BUG in %s Line %d: Failed assertion '" \ 412 #_condition "'\n", __func__, __LINE__); \ 413 __qdf_bug(); \ 414 } \ 415 } while (0) 416 417 #else /* PANIC_ON_BUG */ 418 419 #define QDF_DEBUG_PANIC(reason...) \ 420 do { \ 421 /* no-op */ \ 422 } while (false) 423 424 #define QDF_DEBUG_PANIC_FL(func, line, fmt, args...) \ 425 do { \ 426 /* no-op */ \ 427 } while (false) 428 429 #define QDF_BUG(_condition) \ 430 do { \ 431 if (!(_condition)) { \ 432 /* no-op */ \ 433 } \ 434 } while (0) 435 436 #endif /* PANIC_ON_BUG */ 437 438 #ifdef KSYM_SYMBOL_LEN 439 #define __QDF_SYMBOL_LEN KSYM_SYMBOL_LEN 440 #else 441 #define __QDF_SYMBOL_LEN 1 442 #endif 443 444 #ifdef CONFIG_QCA_MINIDUMP 445 static inline void 446 __qdf_minidump_log(void *start_addr, size_t size, const char *name) 447 { 448 if (minidump_fill_segments((const uintptr_t)start_addr, size, 449 QCA_WDT_LOG_DUMP_TYPE_WLAN_MOD, 450 name) < 0) 451 QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_INFO, 452 "%s: failed to log %pK (%s)\n", 453 __func__, start_addr, name); 454 } 455 456 static inline void 457 __qdf_minidump_remove(void *addr) 458 { 459 minidump_remove_segments((const uintptr_t)addr); 460 } 461 #else 462 static inline void 463 __qdf_minidump_log(void *start_addr, size_t size, const char *name) {} 464 static inline void 465 __qdf_minidump_remove(void *addr) {} 466 #endif 467 #endif /* __I_QDF_TRACE_H */ 468