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
__iwl_err(struct device * dev,enum iwl_err_mode mode,const char * fmt,...)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
iwl_have_debug_level(enum iwl_dl level)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
iwl_print_hex_dump(void * drv __unused,enum iwl_dl level,const char * prefix,uint8_t * data,size_t len)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
__iwl_dbg(struct device * dev,u32 level,bool limit,const char * function,const char * fmt,...)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