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