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, 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 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 #if defined(__linux__) 119 const char *prefix, uint8_t *data, size_t len) 120 #elif defined(__FreeBSD__) 121 const char *prefix, const uint8_t *data, size_t len) 122 #endif 123 { 124 125 /* Given we have a level, check for it. */ 126 if (!iwl_have_debug_level(level)) 127 return; 128 129 #if defined(__linux_) 130 /* XXX I am cluseless in my editor. pcie/trans.c to the rescue. */ 131 print_hex_dump(KERN_ERR, prefix, DUMP_PREFIX_OFFSET, 132 32, 4, data, len, 0); 133 #elif defined(__FreeBSD__) 134 hexdump(data, len, prefix, 0); 135 #endif 136 } 137 #endif 138 139 void __iwl_dbg(struct device *dev, 140 u32 level, bool limit, const char *function, 141 const char *fmt, ...) 142 { 143 struct va_format vaf = { 144 .fmt = fmt, 145 }; 146 va_list args; 147 148 va_start(args, fmt); 149 vaf.va = &args; 150 #ifdef CONFIG_IWLWIFI_DEBUG 151 if (iwl_have_debug_level(level) && 152 (!limit || net_ratelimit())) { 153 #if defined(__linux_) 154 dev_printk(KERN_DEBUG, dev, "%s %pV", function, &vaf); 155 #elif defined(__FreeBSD__) 156 char *str; 157 vasprintf(&str, M_KMALLOC, vaf.fmt, args); 158 dev_printk(KERN_DEBUG, dev, "%d %u %s %s", 159 curthread->td_tid, (unsigned int)ticks, function, str); 160 free(str, M_KMALLOC); 161 #endif 162 } 163 164 #endif 165 trace_iwlwifi_dbg(level, function, &vaf); 166 va_end(args); 167 } 168 IWL_EXPORT_SYMBOL(__iwl_dbg); 169 #endif 170