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