drm_print.c revision 1.5 1 /* $NetBSD: drm_print.c,v 1.5 2021/12/19 01:54:20 riastradh Exp $ */
2
3 /*
4 * Copyright (C) 2016 Red Hat
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the "Software"),
8 * to deal in the Software without restriction, including without limitation
9 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 * and/or sell copies of the Software, and to permit persons to whom the
11 * Software is furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
20 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22 * OTHER DEALINGS IN THE SOFTWARE.
23 *
24 * Authors:
25 * Rob Clark <robdclark (at) gmail.com>
26 */
27
28 #include <sys/cdefs.h>
29 __KERNEL_RCSID(0, "$NetBSD: drm_print.c,v 1.5 2021/12/19 01:54:20 riastradh Exp $");
30
31 #ifndef __NetBSD__ /* XXX ??? */
32 #define DEBUG /* for pr_debug() */
33 #endif
34
35 #ifdef __NetBSD__
36 #include <sys/stdarg.h>
37 #else
38 #include <stdarg.h>
39
40 #include <linux/io.h>
41 #include <linux/moduleparam.h>
42 #endif
43 #include <linux/seq_file.h>
44 #include <linux/slab.h>
45
46 #include <drm/drm.h>
47 #include <drm/drm_drv.h>
48 #include <drm/drm_print.h>
49
50 /*
51 * __drm_debug: Enable debug output.
52 * Bitmask of DRM_UT_x. See include/drm/drm_print.h for details.
53 */
54 unsigned int __drm_debug;
55 EXPORT_SYMBOL(__drm_debug);
56
57 MODULE_PARM_DESC(debug, "Enable debug output, where each bit enables a debug category.\n"
58 "\t\tBit 0 (0x01) will enable CORE messages (drm core code)\n"
59 "\t\tBit 1 (0x02) will enable DRIVER messages (drm controller code)\n"
60 "\t\tBit 2 (0x04) will enable KMS messages (modesetting code)\n"
61 "\t\tBit 3 (0x08) will enable PRIME messages (prime code)\n"
62 "\t\tBit 4 (0x10) will enable ATOMIC messages (atomic code)\n"
63 "\t\tBit 5 (0x20) will enable VBL messages (vblank code)\n"
64 "\t\tBit 7 (0x80) will enable LEASE messages (leasing code)\n"
65 "\t\tBit 8 (0x100) will enable DP messages (displayport code)");
66 module_param_named(debug, __drm_debug, int, 0600);
67
68 void __drm_puts_coredump(struct drm_printer *p, const char *str)
69 {
70 struct drm_print_iterator *iterator = p->arg;
71 ssize_t len;
72
73 if (!iterator->remain)
74 return;
75
76 if (iterator->offset < iterator->start) {
77 ssize_t copy;
78
79 len = strlen(str);
80
81 if (iterator->offset + len <= iterator->start) {
82 iterator->offset += len;
83 return;
84 }
85
86 copy = len - (iterator->start - iterator->offset);
87
88 if (copy > iterator->remain)
89 copy = iterator->remain;
90
91 /* Copy out the bit of the string that we need */
92 memcpy(iterator->data,
93 str + (iterator->start - iterator->offset), copy);
94
95 iterator->offset = iterator->start + copy;
96 iterator->remain -= copy;
97 } else {
98 ssize_t pos = iterator->offset - iterator->start;
99
100 len = min_t(ssize_t, strlen(str), iterator->remain);
101
102 memcpy((char *)iterator->data + pos, str, len);
103
104 iterator->offset += len;
105 iterator->remain -= len;
106 }
107 }
108 EXPORT_SYMBOL(__drm_puts_coredump);
109
110 void __drm_printfn_coredump(struct drm_printer *p, struct va_format *vaf)
111 {
112 struct drm_print_iterator *iterator = p->arg;
113 size_t len;
114 char *buf;
115
116 if (!iterator->remain)
117 return;
118
119 /* Figure out how big the string will be */
120 len = snprintf(NULL, 0, "%pV", vaf);
121
122 /* This is the easiest path, we've already advanced beyond the offset */
123 if (iterator->offset + len <= iterator->start) {
124 iterator->offset += len;
125 return;
126 }
127
128 /* Then check if we can directly copy into the target buffer */
129 if ((iterator->offset >= iterator->start) && (len < iterator->remain)) {
130 ssize_t pos = iterator->offset - iterator->start;
131
132 snprintf(((char *) iterator->data) + pos,
133 iterator->remain, "%pV", vaf);
134
135 iterator->offset += len;
136 iterator->remain -= len;
137
138 return;
139 }
140
141 /*
142 * Finally, hit the slow path and make a temporary string to copy over
143 * using _drm_puts_coredump
144 */
145 buf = kmalloc(len + 1, GFP_KERNEL | __GFP_NOWARN | __GFP_NORETRY);
146 if (!buf)
147 return;
148
149 snprintf(buf, len + 1, "%pV", vaf);
150 __drm_puts_coredump(p, (const char *) buf);
151
152 kfree(buf);
153 }
154 EXPORT_SYMBOL(__drm_printfn_coredump);
155
156 #ifndef __NetBSD__ /* XXX seq file */
157 void __drm_puts_seq_file(struct drm_printer *p, const char *str)
158 {
159 seq_puts(p->arg, str);
160 }
161 EXPORT_SYMBOL(__drm_puts_seq_file);
162 #endif
163
164 #ifndef __NetBSD__ /* XXX seq file */
165 void __drm_printfn_seq_file(struct drm_printer *p, struct va_format *vaf)
166 {
167 seq_printf(p->arg, "%pV", vaf);
168 }
169 EXPORT_SYMBOL(__drm_printfn_seq_file);
170 #endif
171
172 void __drm_printfn_info(struct drm_printer *p, struct va_format *vaf)
173 {
174 dev_info(p->arg, "[" DRM_NAME "] %pV", vaf);
175 }
176 EXPORT_SYMBOL(__drm_printfn_info);
177
178 void __drm_printfn_debug(struct drm_printer *p, struct va_format *vaf)
179 {
180 pr_debug("%s %pV", p->prefix, vaf);
181 }
182 EXPORT_SYMBOL(__drm_printfn_debug);
183
184 void __drm_printfn_err(struct drm_printer *p, struct va_format *vaf)
185 {
186 pr_err("*ERROR* %s %pV", p->prefix, vaf);
187 }
188 EXPORT_SYMBOL(__drm_printfn_err);
189
190 /**
191 * drm_puts - print a const string to a &drm_printer stream
192 * @p: the &drm printer
193 * @str: const string
194 *
195 * Allow &drm_printer types that have a constant string
196 * option to use it.
197 */
198 void drm_puts(struct drm_printer *p, const char *str)
199 {
200 if (p->puts)
201 p->puts(p, str);
202 else
203 drm_printf(p, "%s", str);
204 }
205 EXPORT_SYMBOL(drm_puts);
206
207 /**
208 * drm_printf - print to a &drm_printer stream
209 * @p: the &drm_printer
210 * @f: format string
211 */
212 void drm_printf(struct drm_printer *p, const char *f, ...)
213 {
214 va_list args;
215
216 va_start(args, f);
217 drm_vprintf(p, f, &args);
218 va_end(args);
219 }
220 EXPORT_SYMBOL(drm_printf);
221
222 /**
223 * drm_print_bits - print bits to a &drm_printer stream
224 *
225 * Print bits (in flag fields for example) in human readable form.
226 *
227 * @p: the &drm_printer
228 * @value: field value.
229 * @bits: Array with bit names.
230 * @nbits: Size of bit names array.
231 */
232 void drm_print_bits(struct drm_printer *p, unsigned long value,
233 const char * const bits[], unsigned int nbits)
234 {
235 bool first = true;
236 unsigned int i;
237
238 if (WARN_ON_ONCE(nbits > BITS_PER_TYPE(value)))
239 nbits = BITS_PER_TYPE(value);
240
241 for_each_set_bit(i, &value, nbits) {
242 if (WARN_ON_ONCE(!bits[i]))
243 continue;
244 drm_printf(p, "%s%s", first ? "" : ",",
245 bits[i]);
246 first = false;
247 }
248 if (first)
249 drm_printf(p, "(none)");
250 }
251 EXPORT_SYMBOL(drm_print_bits);
252
253 void drm_dev_printk(const struct device *dev, const char *level,
254 const char *format, ...)
255 {
256 #ifdef __NetBSD__
257 va_list va;
258
259 va_start(va, format);
260 if (dev)
261 printf("%s: ", device_xname(__UNCONST(dev)));
262 vprintf(format, va);
263 va_end(va);
264 #else
265 struct va_format vaf;
266 va_list args;
267
268 va_start(args, format);
269 vaf.fmt = format;
270 vaf.va = &args;
271
272 if (dev)
273 dev_printk(level, dev, "[" DRM_NAME ":%ps] %pV",
274 __builtin_return_address(0), &vaf);
275 else
276 printk("%s" "[" DRM_NAME ":%ps] %pV",
277 level, __builtin_return_address(0), &vaf);
278
279 va_end(args);
280 #endif
281 }
282 EXPORT_SYMBOL(drm_dev_printk);
283
284 void drm_dev_dbg(const struct device *dev, enum drm_debug_category category,
285 const char *format, ...)
286 {
287 #ifdef __NetBSD__
288 va_list va;
289
290 if (!(drm_debug & category))
291 return;
292
293 va_start(va, format);
294 if (dev)
295 printf("%s: ", device_xname(__UNCONST(dev)));
296 vprintf(format, va);
297 va_end(va);
298 #else
299 struct va_format vaf;
300 va_list args;
301
302 if (!drm_debug_enabled(category))
303 return;
304
305 va_start(args, format);
306 vaf.fmt = format;
307 vaf.va = &args;
308
309 if (dev)
310 dev_printk(KERN_DEBUG, dev, "[" DRM_NAME ":%ps] %pV",
311 __builtin_return_address(0), &vaf);
312 else
313 printk(KERN_DEBUG "[" DRM_NAME ":%ps] %pV",
314 __builtin_return_address(0), &vaf);
315
316 va_end(args);
317 #endif
318 }
319 EXPORT_SYMBOL(drm_dev_dbg);
320
321 void __drm_dbg(enum drm_debug_category category, const char *format, ...)
322 {
323 #ifdef __NetBSD__
324 va_list va;
325
326 if (!(drm_debug & category))
327 return;
328
329 va_start(va, format);
330 vprintf(format, va);
331 va_end(va);
332 #else
333 struct va_format vaf;
334 va_list args;
335
336 if (!drm_debug_enabled(category))
337 return;
338
339 va_start(args, format);
340 vaf.fmt = format;
341 vaf.va = &args;
342
343 printk(KERN_DEBUG "[" DRM_NAME ":%ps] %pV",
344 __builtin_return_address(0), &vaf);
345
346 va_end(args);
347 #endif
348 }
349 EXPORT_SYMBOL(__drm_dbg);
350
351 void __drm_err(const char *format, ...)
352 {
353 struct va_format vaf;
354 va_list args;
355
356 va_start(args, format);
357 vaf.fmt = format;
358 vaf.va = &args;
359
360 printk(KERN_ERR "[" DRM_NAME ":%ps] *ERROR* %pV",
361 __builtin_return_address(0), &vaf);
362
363 va_end(args);
364 }
365 EXPORT_SYMBOL(__drm_err);
366
367 #ifndef __NetBSD__
368 /**
369 * drm_print_regset32 - print the contents of registers to a
370 * &drm_printer stream.
371 *
372 * @p: the &drm printer
373 * @regset: the list of registers to print.
374 *
375 * Often in driver debug, it's useful to be able to either capture the
376 * contents of registers in the steady state using debugfs or at
377 * specific points during operation. This lets the driver have a
378 * single list of registers for both.
379 */
380 void drm_print_regset32(struct drm_printer *p, struct debugfs_regset32 *regset)
381 {
382 int namelen = 0;
383 int i;
384
385 for (i = 0; i < regset->nregs; i++)
386 namelen = max(namelen, (int)strlen(regset->regs[i].name));
387
388 for (i = 0; i < regset->nregs; i++) {
389 drm_printf(p, "%*s = 0x%08x\n",
390 namelen, regset->regs[i].name,
391 readl(regset->base + regset->regs[i].offset));
392 }
393 }
394 EXPORT_SYMBOL(drm_print_regset32);
395 #endif
396