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) \ 27void __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) \ 42void __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) 61IWL_EXPORT_SYMBOL(__iwl_warn); 62__iwl_fn(info) 63IWL_EXPORT_SYMBOL(__iwl_info); 64__iwl_fn(crit) 65IWL_EXPORT_SYMBOL(__iwl_crit); 66 67void __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} 104IWL_EXPORT_SYMBOL(__iwl_err); 105 106#if defined(CONFIG_IWLWIFI_DEBUG) || defined(CONFIG_IWLWIFI_DEVICE_TRACING) 107 108#ifdef CONFIG_IWLWIFI_DEBUG 109bool 110iwl_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. */ 117void 118iwl_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 140void __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 char *str; 158 vasprintf(&str, M_KMALLOC, vaf.fmt, args); 159 dev_printk(KERN_DEBUG, dev, "%d %u %s %s", 160 curthread->td_tid, (unsigned int)ticks, function, str); 161 free(str, M_KMALLOC); 162#endif 163 } 164 165#endif 166 trace_iwlwifi_dbg(level, function, &vaf); 167 va_end(args); 168} 169IWL_EXPORT_SYMBOL(__iwl_dbg); 170#endif 171