xref: /freebsd/sys/contrib/dev/iwlwifi/iwl-debug.c (revision d4eeb02986980bf33dd56c41ceb9fc5f180c0d47)
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