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 #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, 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, 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 trace_iwlwifi_err(&vaf); 101 va_end(args); 102 } 103 IWL_EXPORT_SYMBOL(__iwl_err); 104 105 #if defined(CONFIG_IWLWIFI_DEBUG) || defined(CONFIG_IWLWIFI_DEVICE_TRACING) 106 107 #ifdef CONFIG_IWLWIFI_DEBUG 108 bool 109 iwl_have_debug_level(enum iwl_dl level) 110 { 111 112 return (iwlwifi_mod_params.debug_level & level || level == IWL_DL_ANY); 113 } 114 115 /* Passing the iwl_drv * in seems pointless. */ 116 void 117 iwl_print_hex_dump(void *drv __unused, enum iwl_dl level, 118 const char *prefix, uint8_t *data, size_t len) 119 { 120 121 /* Given we have a level, check for it. */ 122 if (!iwl_have_debug_level(level)) 123 return; 124 125 #if defined(__linux_) 126 /* XXX I am cluseless in my editor. pcie/trans.c to the rescue. */ 127 print_hex_dump(KERN_ERR, prefix, DUMP_PREFIX_OFFSET, 128 32, 4, data, len, 0); 129 #elif defined(__FreeBSD__) 130 hexdump(data, len, prefix, 0); 131 #endif 132 } 133 #endif 134 135 void __iwl_dbg(struct device *dev, 136 u32 level, bool limit, const char *function, 137 const char *fmt, ...) 138 { 139 struct va_format vaf = { 140 .fmt = fmt, 141 }; 142 va_list args; 143 144 va_start(args, fmt); 145 vaf.va = &args; 146 #ifdef CONFIG_IWLWIFI_DEBUG 147 if (iwl_have_debug_level(level) && 148 (!limit || net_ratelimit())) { 149 #if defined(__linux_) 150 dev_printk(KERN_DEBUG, dev, "%s %pV", function, &vaf); 151 #elif defined(__FreeBSD__) 152 char *str; 153 vasprintf(&str, M_KMALLOC, fmt, args); 154 dev_printk(KERN_DEBUG, dev, "%d %u %s %s", 155 curthread->td_tid, (unsigned int)ticks, function, str); 156 free(str, M_KMALLOC); 157 #endif 158 } 159 160 #endif 161 trace_iwlwifi_dbg(level, function, &vaf); 162 va_end(args); 163 } 164 IWL_EXPORT_SYMBOL(__iwl_dbg); 165 #endif 166