1 // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause 2 /* 3 * Copyright (C) 2005-2011, 2021 Intel Corporation 4 */ 5 #include <linux/device.h> 6 #include <linux/interrupt.h> 7 #include <linux/export.h> 8 #if defined(CONFIG_IWLWIFI_DEBUG) 9 #include <linux/net.h> 10 #endif 11 #include "iwl-drv.h" 12 #include "iwl-debug.h" 13 #include "iwl-modparams.h" 14 #include "iwl-devtrace.h" 15 16 #if defined(__FreeBSD__) 17 #if defined(CONFIG_IWLWIFI_DEBUG) 18 #include <sys/systm.h> /* hexdump(9) */ 19 #include <linux/preempt.h> 20 #endif 21 #endif 22 23 #if defined(__linux__) 24 #define __iwl_fn(fn) \ 25 void __iwl_ ##fn(struct device *dev, const char *fmt, ...) \ 26 { \ 27 struct va_format vaf = { \ 28 .fmt = fmt, \ 29 }; \ 30 va_list args; \ 31 \ 32 va_start(args, fmt); \ 33 vaf.va = &args; \ 34 dev_ ##fn(dev, "%pV", &vaf); \ 35 trace_iwlwifi_ ##fn(&vaf); \ 36 va_end(args); \ 37 } 38 #elif defined(__FreeBSD__) 39 #define __iwl_fn(fn) \ 40 void __iwl_ ##fn(struct device *dev, const char *fmt, ...) \ 41 { \ 42 struct va_format vaf = { \ 43 .fmt = fmt, \ 44 }; \ 45 va_list args; \ 46 char *str; \ 47 \ 48 va_start(args, fmt); \ 49 vaf.va = &args; \ 50 vasprintf(&str, M_KMALLOC, fmt, args); \ 51 dev_ ##fn(dev, "%s", str); \ 52 trace_iwlwifi_ ##fn(&vaf); \ 53 free(str, M_KMALLOC); \ 54 va_end(args); \ 55 } 56 #endif 57 58 __iwl_fn(warn) 59 IWL_EXPORT_SYMBOL(__iwl_warn); 60 __iwl_fn(info) 61 IWL_EXPORT_SYMBOL(__iwl_info); 62 __iwl_fn(crit) 63 IWL_EXPORT_SYMBOL(__iwl_crit); 64 65 void __iwl_err(struct device *dev, enum iwl_err_mode mode, const char *fmt, ...) 66 { 67 struct va_format vaf = { 68 .fmt = fmt, 69 }; 70 va_list args, args2; 71 72 va_start(args, fmt); 73 switch (mode) { 74 case IWL_ERR_MODE_RATELIMIT: 75 if (net_ratelimit()) 76 break; 77 fallthrough; 78 case IWL_ERR_MODE_REGULAR: 79 case IWL_ERR_MODE_RFKILL: 80 va_copy(args2, args); 81 vaf.va = &args2; 82 #if defined(__linux_) 83 if (mode == IWL_ERR_MODE_RFKILL) 84 dev_err(dev, "(RFKILL) %pV", &vaf); 85 else 86 dev_err(dev, "%pV", &vaf); 87 #elif defined(__FreeBSD__) 88 char *str; 89 vasprintf(&str, M_KMALLOC, fmt, args2); 90 dev_err(dev, "%s%s", (mode == IWL_ERR_MODE_RFKILL) ? "(RFKILL)" : "", str); 91 free(str, M_KMALLOC); 92 #endif 93 va_end(args2); 94 break; 95 default: 96 break; 97 } 98 trace_iwlwifi_err(&vaf); 99 va_end(args); 100 } 101 IWL_EXPORT_SYMBOL(__iwl_err); 102 103 #if defined(CONFIG_IWLWIFI_DEBUG) || defined(CONFIG_IWLWIFI_DEVICE_TRACING) 104 105 #ifdef CONFIG_IWLWIFI_DEBUG 106 bool 107 iwl_have_debug_level(enum iwl_dl level) 108 { 109 110 return (iwlwifi_mod_params.debug_level & level || level == IWL_DL_ANY); 111 } 112 113 /* Passing the iwl_drv * in seems pointless. */ 114 void 115 iwl_print_hex_dump(void *drv __unused, enum iwl_dl level, 116 const char *prefix, uint8_t *data, size_t len) 117 { 118 119 /* Given we have a level, check for it. */ 120 if (!iwl_have_debug_level(level)) 121 return; 122 123 #if defined(__linux_) 124 /* XXX I am cluseless in my editor. pcie/trans.c to the rescue. */ 125 print_hex_dump(KERN_ERR, prefix, DUMP_PREFIX_OFFSET, 126 32, 4, data, len, 0); 127 #elif defined(__FreeBSD__) 128 hexdump(data, len, prefix, 0); 129 #endif 130 } 131 #endif 132 133 void __iwl_dbg(struct device *dev, 134 u32 level, bool limit, const char *function, 135 const char *fmt, ...) 136 { 137 struct va_format vaf = { 138 .fmt = fmt, 139 }; 140 va_list args; 141 142 va_start(args, fmt); 143 vaf.va = &args; 144 #if defined(CONFIG_IWLWIFI_DEBUG) 145 if (iwl_have_debug_level(level) && 146 (!limit || net_ratelimit())) { 147 #if defined(__linux_) 148 dev_printk(KERN_DEBUG, dev, "%s %pV", function, &vaf); 149 #elif defined(__FreeBSD__) 150 char *str; 151 vasprintf(&str, M_KMALLOC, fmt, args); 152 dev_printk(KERN_DEBUG, dev, "%d %u %s %s", 153 curthread->td_tid, (unsigned int)ticks, function, str); 154 free(str, M_KMALLOC); 155 #endif 156 } 157 158 #endif 159 trace_iwlwifi_dbg(level, function, &vaf); 160 va_end(args); 161 } 162 IWL_EXPORT_SYMBOL(__iwl_dbg); 163 #endif 164