]>
Commit | Line | Data |
---|---|---|
d8187177 RC |
1 | /* |
2 | * Copyright (C) 2016 Red Hat | |
3 | * | |
4 | * Permission is hereby granted, free of charge, to any person obtaining a | |
5 | * copy of this software and associated documentation files (the "Software"), | |
6 | * to deal in the Software without restriction, including without limitation | |
7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, | |
8 | * and/or sell copies of the Software, and to permit persons to whom the | |
9 | * Software is furnished to do so, subject to the following conditions: | |
10 | * | |
11 | * The above copyright notice and this permission notice shall be included in | |
12 | * all copies or substantial portions of the Software. | |
13 | * | |
14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | |
17 | * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR | |
18 | * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, | |
19 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR | |
20 | * OTHER DEALINGS IN THE SOFTWARE. | |
21 | * | |
22 | * Authors: | |
23 | * Rob Clark <robdclark@gmail.com> | |
24 | */ | |
25 | ||
26 | #ifndef DRM_PRINT_H_ | |
27 | #define DRM_PRINT_H_ | |
28 | ||
3c6d6e0f JP |
29 | #include <linux/compiler.h> |
30 | #include <linux/printk.h> | |
d8187177 RC |
31 | #include <linux/seq_file.h> |
32 | #include <linux/device.h> | |
5f513cc8 | 33 | #include <linux/debugfs.h> |
d8187177 | 34 | |
656600ef SR |
35 | #include <drm/drm.h> |
36 | ||
959b077f JN |
37 | extern unsigned int drm_debug; |
38 | ||
d8187177 RC |
39 | /** |
40 | * DOC: print | |
41 | * | |
42 | * A simple wrapper for dev_printk(), seq_printf(), etc. Allows same | |
43 | * debug code to be used for both debugfs and printk logging. | |
44 | * | |
45 | * For example:: | |
46 | * | |
47 | * void log_some_info(struct drm_printer *p) | |
48 | * { | |
49 | * drm_printf(p, "foo=%d\n", foo); | |
50 | * drm_printf(p, "bar=%d\n", bar); | |
51 | * } | |
52 | * | |
53 | * #ifdef CONFIG_DEBUG_FS | |
54 | * void debugfs_show(struct seq_file *f) | |
55 | * { | |
56 | * struct drm_printer p = drm_seq_file_printer(f); | |
57 | * log_some_info(&p); | |
58 | * } | |
59 | * #endif | |
60 | * | |
61 | * void some_other_function(...) | |
62 | * { | |
63 | * struct drm_printer p = drm_info_printer(drm->dev); | |
64 | * log_some_info(&p); | |
65 | * } | |
66 | */ | |
67 | ||
68 | /** | |
69 | * struct drm_printer - drm output "stream" | |
d8187177 RC |
70 | * |
71 | * Do not use struct members directly. Use drm_printer_seq_file(), | |
72 | * drm_printer_info(), etc to initialize. And drm_printf() for output. | |
73 | */ | |
74 | struct drm_printer { | |
3d387d92 | 75 | /* private: */ |
d8187177 | 76 | void (*printfn)(struct drm_printer *p, struct va_format *vaf); |
63f4cc01 | 77 | void (*puts)(struct drm_printer *p, const char *str); |
d8187177 | 78 | void *arg; |
3d387d92 | 79 | const char *prefix; |
d8187177 RC |
80 | }; |
81 | ||
cfc57a18 | 82 | void __drm_printfn_coredump(struct drm_printer *p, struct va_format *vaf); |
5dc634bd | 83 | void __drm_puts_coredump(struct drm_printer *p, const char *str); |
d8187177 | 84 | void __drm_printfn_seq_file(struct drm_printer *p, struct va_format *vaf); |
4538d732 | 85 | void __drm_puts_seq_file(struct drm_printer *p, const char *str); |
d8187177 | 86 | void __drm_printfn_info(struct drm_printer *p, struct va_format *vaf); |
3d387d92 | 87 | void __drm_printfn_debug(struct drm_printer *p, struct va_format *vaf); |
0de54fb2 | 88 | void __drm_printfn_err(struct drm_printer *p, struct va_format *vaf); |
d8187177 | 89 | |
3c6d6e0f | 90 | __printf(2, 3) |
d8187177 | 91 | void drm_printf(struct drm_printer *p, const char *f, ...); |
63f4cc01 | 92 | void drm_puts(struct drm_printer *p, const char *str); |
5f513cc8 | 93 | void drm_print_regset32(struct drm_printer *p, struct debugfs_regset32 *regset); |
141f6357 GH |
94 | void drm_print_bits(struct drm_printer *p, unsigned long value, |
95 | const char * const bits[], unsigned int nbits); | |
d8187177 | 96 | |
42f1b310 | 97 | __printf(2, 0) |
e2b155e9 CW |
98 | /** |
99 | * drm_vprintf - print to a &drm_printer stream | |
100 | * @p: the &drm_printer | |
101 | * @fmt: format string | |
102 | * @va: the va_list | |
103 | */ | |
e2b155e9 CW |
104 | static inline void |
105 | drm_vprintf(struct drm_printer *p, const char *fmt, va_list *va) | |
106 | { | |
107 | struct va_format vaf = { .fmt = fmt, .va = va }; | |
108 | ||
109 | p->printfn(p, &vaf); | |
110 | } | |
111 | ||
bf6234a2 NT |
112 | /** |
113 | * drm_printf_indent - Print to a &drm_printer stream with indentation | |
114 | * @printer: DRM printer | |
115 | * @indent: Tab indentation level (max 5) | |
116 | * @fmt: Format string | |
117 | */ | |
118 | #define drm_printf_indent(printer, indent, fmt, ...) \ | |
119 | drm_printf((printer), "%.*s" fmt, (indent), "\t\t\t\t\tX", ##__VA_ARGS__) | |
d8187177 | 120 | |
cfc57a18 JC |
121 | /** |
122 | * struct drm_print_iterator - local struct used with drm_printer_coredump | |
123 | * @data: Pointer to the devcoredump output buffer | |
124 | * @start: The offset within the buffer to start writing | |
125 | * @remain: The number of bytes to write for this iteration | |
126 | */ | |
127 | struct drm_print_iterator { | |
128 | void *data; | |
129 | ssize_t start; | |
130 | ssize_t remain; | |
131 | /* private: */ | |
132 | ssize_t offset; | |
133 | }; | |
134 | ||
135 | /** | |
136 | * drm_coredump_printer - construct a &drm_printer that can output to a buffer | |
137 | * from the read function for devcoredump | |
138 | * @iter: A pointer to a struct drm_print_iterator for the read instance | |
139 | * | |
140 | * This wrapper extends drm_printf() to work with a dev_coredumpm() callback | |
141 | * function. The passed in drm_print_iterator struct contains the buffer | |
142 | * pointer, size and offset as passed in from devcoredump. | |
143 | * | |
144 | * For example:: | |
145 | * | |
146 | * void coredump_read(char *buffer, loff_t offset, size_t count, | |
147 | * void *data, size_t datalen) | |
148 | * { | |
149 | * struct drm_print_iterator iter; | |
150 | * struct drm_printer p; | |
151 | * | |
152 | * iter.data = buffer; | |
153 | * iter.start = offset; | |
154 | * iter.remain = count; | |
155 | * | |
156 | * p = drm_coredump_printer(&iter); | |
157 | * | |
158 | * drm_printf(p, "foo=%d\n", foo); | |
159 | * } | |
160 | * | |
161 | * void makecoredump(...) | |
162 | * { | |
163 | * ... | |
164 | * dev_coredumpm(dev, THIS_MODULE, data, 0, GFP_KERNEL, | |
165 | * coredump_read, ...) | |
166 | * } | |
167 | * | |
168 | * RETURNS: | |
169 | * The &drm_printer object | |
170 | */ | |
171 | static inline struct drm_printer | |
172 | drm_coredump_printer(struct drm_print_iterator *iter) | |
173 | { | |
174 | struct drm_printer p = { | |
175 | .printfn = __drm_printfn_coredump, | |
5dc634bd | 176 | .puts = __drm_puts_coredump, |
cfc57a18 JC |
177 | .arg = iter, |
178 | }; | |
179 | ||
180 | /* Set the internal offset of the iterator to zero */ | |
181 | iter->offset = 0; | |
182 | ||
183 | return p; | |
184 | } | |
185 | ||
d8187177 RC |
186 | /** |
187 | * drm_seq_file_printer - construct a &drm_printer that outputs to &seq_file | |
ea0dd85a | 188 | * @f: the &struct seq_file to output to |
d8187177 RC |
189 | * |
190 | * RETURNS: | |
191 | * The &drm_printer object | |
192 | */ | |
193 | static inline struct drm_printer drm_seq_file_printer(struct seq_file *f) | |
194 | { | |
195 | struct drm_printer p = { | |
196 | .printfn = __drm_printfn_seq_file, | |
4538d732 | 197 | .puts = __drm_puts_seq_file, |
d8187177 RC |
198 | .arg = f, |
199 | }; | |
200 | return p; | |
201 | } | |
202 | ||
203 | /** | |
204 | * drm_info_printer - construct a &drm_printer that outputs to dev_printk() | |
ea0dd85a | 205 | * @dev: the &struct device pointer |
d8187177 RC |
206 | * |
207 | * RETURNS: | |
208 | * The &drm_printer object | |
209 | */ | |
210 | static inline struct drm_printer drm_info_printer(struct device *dev) | |
211 | { | |
212 | struct drm_printer p = { | |
213 | .printfn = __drm_printfn_info, | |
214 | .arg = dev, | |
215 | }; | |
216 | return p; | |
217 | } | |
218 | ||
3d387d92 DV |
219 | /** |
220 | * drm_debug_printer - construct a &drm_printer that outputs to pr_debug() | |
221 | * @prefix: debug output prefix | |
222 | * | |
223 | * RETURNS: | |
224 | * The &drm_printer object | |
225 | */ | |
226 | static inline struct drm_printer drm_debug_printer(const char *prefix) | |
227 | { | |
228 | struct drm_printer p = { | |
229 | .printfn = __drm_printfn_debug, | |
230 | .prefix = prefix | |
231 | }; | |
232 | return p; | |
233 | } | |
02c9656b | 234 | |
0de54fb2 LP |
235 | /** |
236 | * drm_err_printer - construct a &drm_printer that outputs to pr_err() | |
237 | * @prefix: debug output prefix | |
238 | * | |
239 | * RETURNS: | |
240 | * The &drm_printer object | |
241 | */ | |
242 | static inline struct drm_printer drm_err_printer(const char *prefix) | |
243 | { | |
244 | struct drm_printer p = { | |
245 | .printfn = __drm_printfn_err, | |
246 | .prefix = prefix | |
247 | }; | |
248 | return p; | |
249 | } | |
250 | ||
02c9656b HM |
251 | /* |
252 | * The following categories are defined: | |
253 | * | |
254 | * CORE: Used in the generic drm code: drm_ioctl.c, drm_mm.c, drm_memory.c, ... | |
255 | * This is the category used by the DRM_DEBUG() macro. | |
256 | * | |
257 | * DRIVER: Used in the vendor specific part of the driver: i915, radeon, ... | |
258 | * This is the category used by the DRM_DEBUG_DRIVER() macro. | |
259 | * | |
260 | * KMS: used in the modesetting code. | |
261 | * This is the category used by the DRM_DEBUG_KMS() macro. | |
262 | * | |
263 | * PRIME: used in the prime code. | |
264 | * This is the category used by the DRM_DEBUG_PRIME() macro. | |
265 | * | |
266 | * ATOMIC: used in the atomic code. | |
267 | * This is the category used by the DRM_DEBUG_ATOMIC() macro. | |
268 | * | |
269 | * VBL: used for verbose debug message in the vblank code | |
270 | * This is the category used by the DRM_DEBUG_VBL() macro. | |
271 | * | |
272 | * Enabling verbose debug messages is done through the drm.debug parameter, | |
273 | * each category being enabled by a bit. | |
274 | * | |
275 | * drm.debug=0x1 will enable CORE messages | |
276 | * drm.debug=0x2 will enable DRIVER messages | |
277 | * drm.debug=0x3 will enable CORE and DRIVER messages | |
278 | * ... | |
279 | * drm.debug=0x3f will enable all messages | |
280 | * | |
281 | * An interesting feature is that it's possible to enable verbose logging at | |
282 | * run-time by echoing the debug value in its sysfs node: | |
283 | * # echo 0xf > /sys/module/drm/parameters/debug | |
284 | */ | |
285 | #define DRM_UT_NONE 0x00 | |
286 | #define DRM_UT_CORE 0x01 | |
287 | #define DRM_UT_DRIVER 0x02 | |
288 | #define DRM_UT_KMS 0x04 | |
289 | #define DRM_UT_PRIME 0x08 | |
290 | #define DRM_UT_ATOMIC 0x10 | |
291 | #define DRM_UT_VBL 0x20 | |
292 | #define DRM_UT_STATE 0x40 | |
70c5f936 | 293 | #define DRM_UT_LEASE 0x80 |
a18b2192 | 294 | #define DRM_UT_DP 0x100 |
02c9656b | 295 | |
f0a8f533 JN |
296 | static inline bool drm_debug_enabled(unsigned int category) |
297 | { | |
298 | return unlikely(drm_debug & category); | |
299 | } | |
300 | ||
db870864 | 301 | __printf(3, 4) |
02c9656b | 302 | void drm_dev_printk(const struct device *dev, const char *level, |
db870864 JP |
303 | const char *format, ...); |
304 | __printf(3, 4) | |
305 | void drm_dev_dbg(const struct device *dev, unsigned int category, | |
306 | const char *format, ...); | |
307 | ||
99a95487 JP |
308 | __printf(2, 3) |
309 | void drm_dbg(unsigned int category, const char *format, ...); | |
310 | __printf(1, 2) | |
311 | void drm_err(const char *format, ...); | |
091756bb HM |
312 | |
313 | /* Macros to make printk easier */ | |
02c9656b HM |
314 | |
315 | #define _DRM_PRINTK(once, level, fmt, ...) \ | |
db870864 | 316 | printk##once(KERN_##level "[" DRM_NAME "] " fmt, ##__VA_ARGS__) |
02c9656b HM |
317 | |
318 | #define DRM_INFO(fmt, ...) \ | |
319 | _DRM_PRINTK(, INFO, fmt, ##__VA_ARGS__) | |
320 | #define DRM_NOTE(fmt, ...) \ | |
321 | _DRM_PRINTK(, NOTICE, fmt, ##__VA_ARGS__) | |
322 | #define DRM_WARN(fmt, ...) \ | |
323 | _DRM_PRINTK(, WARNING, fmt, ##__VA_ARGS__) | |
324 | ||
325 | #define DRM_INFO_ONCE(fmt, ...) \ | |
326 | _DRM_PRINTK(_once, INFO, fmt, ##__VA_ARGS__) | |
327 | #define DRM_NOTE_ONCE(fmt, ...) \ | |
328 | _DRM_PRINTK(_once, NOTICE, fmt, ##__VA_ARGS__) | |
329 | #define DRM_WARN_ONCE(fmt, ...) \ | |
330 | _DRM_PRINTK(_once, WARNING, fmt, ##__VA_ARGS__) | |
331 | ||
332 | /** | |
333 | * Error output. | |
334 | * | |
091756bb HM |
335 | * @dev: device pointer |
336 | * @fmt: printf() like format string. | |
02c9656b HM |
337 | */ |
338 | #define DRM_DEV_ERROR(dev, fmt, ...) \ | |
db870864 | 339 | drm_dev_printk(dev, KERN_ERR, "*ERROR* " fmt, ##__VA_ARGS__) |
02c9656b | 340 | #define DRM_ERROR(fmt, ...) \ |
99a95487 | 341 | drm_err(fmt, ##__VA_ARGS__) |
02c9656b HM |
342 | |
343 | /** | |
344 | * Rate limited error output. Like DRM_ERROR() but won't flood the log. | |
345 | * | |
091756bb HM |
346 | * @dev: device pointer |
347 | * @fmt: printf() like format string. | |
02c9656b HM |
348 | */ |
349 | #define DRM_DEV_ERROR_RATELIMITED(dev, fmt, ...) \ | |
350 | ({ \ | |
351 | static DEFINE_RATELIMIT_STATE(_rs, \ | |
352 | DEFAULT_RATELIMIT_INTERVAL, \ | |
353 | DEFAULT_RATELIMIT_BURST); \ | |
354 | \ | |
355 | if (__ratelimit(&_rs)) \ | |
356 | DRM_DEV_ERROR(dev, fmt, ##__VA_ARGS__); \ | |
357 | }) | |
358 | #define DRM_ERROR_RATELIMITED(fmt, ...) \ | |
359 | DRM_DEV_ERROR_RATELIMITED(NULL, fmt, ##__VA_ARGS__) | |
360 | ||
361 | #define DRM_DEV_INFO(dev, fmt, ...) \ | |
db870864 | 362 | drm_dev_printk(dev, KERN_INFO, fmt, ##__VA_ARGS__) |
02c9656b HM |
363 | |
364 | #define DRM_DEV_INFO_ONCE(dev, fmt, ...) \ | |
365 | ({ \ | |
366 | static bool __print_once __read_mostly; \ | |
367 | if (!__print_once) { \ | |
368 | __print_once = true; \ | |
369 | DRM_DEV_INFO(dev, fmt, ##__VA_ARGS__); \ | |
370 | } \ | |
371 | }) | |
372 | ||
373 | /** | |
374 | * Debug output. | |
375 | * | |
091756bb HM |
376 | * @dev: device pointer |
377 | * @fmt: printf() like format string. | |
02c9656b | 378 | */ |
db870864 JP |
379 | #define DRM_DEV_DEBUG(dev, fmt, ...) \ |
380 | drm_dev_dbg(dev, DRM_UT_CORE, fmt, ##__VA_ARGS__) | |
02c9656b | 381 | #define DRM_DEBUG(fmt, ...) \ |
99a95487 | 382 | drm_dbg(DRM_UT_CORE, fmt, ##__VA_ARGS__) |
02c9656b | 383 | |
db870864 JP |
384 | #define DRM_DEV_DEBUG_DRIVER(dev, fmt, ...) \ |
385 | drm_dev_dbg(dev, DRM_UT_DRIVER, fmt, ##__VA_ARGS__) | |
02c9656b | 386 | #define DRM_DEBUG_DRIVER(fmt, ...) \ |
99a95487 | 387 | drm_dbg(DRM_UT_DRIVER, fmt, ##__VA_ARGS__) |
02c9656b | 388 | |
db870864 JP |
389 | #define DRM_DEV_DEBUG_KMS(dev, fmt, ...) \ |
390 | drm_dev_dbg(dev, DRM_UT_KMS, fmt, ##__VA_ARGS__) | |
99a95487 JP |
391 | #define DRM_DEBUG_KMS(fmt, ...) \ |
392 | drm_dbg(DRM_UT_KMS, fmt, ##__VA_ARGS__) | |
02c9656b | 393 | |
db870864 JP |
394 | #define DRM_DEV_DEBUG_PRIME(dev, fmt, ...) \ |
395 | drm_dev_dbg(dev, DRM_UT_PRIME, fmt, ##__VA_ARGS__) | |
02c9656b | 396 | #define DRM_DEBUG_PRIME(fmt, ...) \ |
99a95487 | 397 | drm_dbg(DRM_UT_PRIME, fmt, ##__VA_ARGS__) |
02c9656b | 398 | |
db870864 JP |
399 | #define DRM_DEV_DEBUG_ATOMIC(dev, fmt, ...) \ |
400 | drm_dev_dbg(dev, DRM_UT_ATOMIC, fmt, ##__VA_ARGS__) | |
02c9656b | 401 | #define DRM_DEBUG_ATOMIC(fmt, ...) \ |
99a95487 | 402 | drm_dbg(DRM_UT_ATOMIC, fmt, ##__VA_ARGS__) |
02c9656b | 403 | |
db870864 JP |
404 | #define DRM_DEV_DEBUG_VBL(dev, fmt, ...) \ |
405 | drm_dev_dbg(dev, DRM_UT_VBL, fmt, ##__VA_ARGS__) | |
99a95487 JP |
406 | #define DRM_DEBUG_VBL(fmt, ...) \ |
407 | drm_dbg(DRM_UT_VBL, fmt, ##__VA_ARGS__) | |
02c9656b | 408 | |
70c5f936 | 409 | #define DRM_DEBUG_LEASE(fmt, ...) \ |
99a95487 | 410 | drm_dbg(DRM_UT_LEASE, fmt, ##__VA_ARGS__) |
70c5f936 | 411 | |
a18b2192 LP |
412 | #define DRM_DEV_DEBUG_DP(dev, fmt, ...) \ |
413 | drm_dev_dbg(dev, DRM_UT_DP, fmt, ## __VA_ARGS__) | |
106b6c39 | 414 | #define DRM_DEBUG_DP(fmt, ...) \ |
a18b2192 LP |
415 | drm_dbg(DRM_UT_DP, fmt, ## __VA_ARGS__) |
416 | ||
db870864 | 417 | #define _DRM_DEV_DEFINE_DEBUG_RATELIMITED(dev, category, fmt, ...) \ |
02c9656b HM |
418 | ({ \ |
419 | static DEFINE_RATELIMIT_STATE(_rs, \ | |
420 | DEFAULT_RATELIMIT_INTERVAL, \ | |
421 | DEFAULT_RATELIMIT_BURST); \ | |
422 | if (__ratelimit(&_rs)) \ | |
db870864 | 423 | drm_dev_dbg(dev, category, fmt, ##__VA_ARGS__); \ |
02c9656b HM |
424 | }) |
425 | ||
426 | /** | |
427 | * Rate limited debug output. Like DRM_DEBUG() but won't flood the log. | |
428 | * | |
091756bb HM |
429 | * @dev: device pointer |
430 | * @fmt: printf() like format string. | |
02c9656b | 431 | */ |
db870864 JP |
432 | #define DRM_DEV_DEBUG_RATELIMITED(dev, fmt, ...) \ |
433 | _DEV_DRM_DEFINE_DEBUG_RATELIMITED(dev, DRM_UT_CORE, \ | |
434 | fmt, ##__VA_ARGS__) | |
435 | #define DRM_DEBUG_RATELIMITED(fmt, ...) \ | |
436 | DRM_DEV_DEBUG_RATELIMITED(NULL, fmt, ##__VA_ARGS__) | |
437 | ||
438 | #define DRM_DEV_DEBUG_DRIVER_RATELIMITED(dev, fmt, ...) \ | |
439 | _DRM_DEV_DEFINE_DEBUG_RATELIMITED(dev, DRM_UT_DRIVER, \ | |
440 | fmt, ##__VA_ARGS__) | |
441 | #define DRM_DEBUG_DRIVER_RATELIMITED(fmt, ...) \ | |
442 | DRM_DEV_DEBUG_DRIVER_RATELIMITED(NULL, fmt, ##__VA_ARGS__) | |
443 | ||
444 | #define DRM_DEV_DEBUG_KMS_RATELIMITED(dev, fmt, ...) \ | |
445 | _DRM_DEV_DEFINE_DEBUG_RATELIMITED(dev, DRM_UT_KMS, \ | |
446 | fmt, ##__VA_ARGS__) | |
447 | #define DRM_DEBUG_KMS_RATELIMITED(fmt, ...) \ | |
448 | DRM_DEV_DEBUG_KMS_RATELIMITED(NULL, fmt, ##__VA_ARGS__) | |
449 | ||
450 | #define DRM_DEV_DEBUG_PRIME_RATELIMITED(dev, fmt, ...) \ | |
451 | _DRM_DEV_DEFINE_DEBUG_RATELIMITED(dev, DRM_UT_PRIME, \ | |
452 | fmt, ##__VA_ARGS__) | |
453 | #define DRM_DEBUG_PRIME_RATELIMITED(fmt, ...) \ | |
454 | DRM_DEV_DEBUG_PRIME_RATELIMITED(NULL, fmt, ##__VA_ARGS__) | |
02c9656b | 455 | |
d8187177 | 456 | #endif /* DRM_PRINT_H_ */ |