xref: /openbsd-src/sys/dev/pci/drm/drm_print.c (revision 99fd087599a8791921855f21bd7e36130f39aadc)
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 #ifdef __linux__
27 #define DEBUG /* for pr_debug() */
28 #endif
29 
30 #include <sys/stdarg.h>
31 #include <linux/seq_file.h>
32 #include <drm/drmP.h>
33 #include <drm/drm_print.h>
34 
35 void __drm_puts_coredump(struct drm_printer *p, const char *str)
36 {
37 	struct drm_print_iterator *iterator = p->arg;
38 	ssize_t len;
39 
40 	if (!iterator->remain)
41 		return;
42 
43 	if (iterator->offset < iterator->start) {
44 		ssize_t copy;
45 
46 		len = strlen(str);
47 
48 		if (iterator->offset + len <= iterator->start) {
49 			iterator->offset += len;
50 			return;
51 		}
52 
53 		copy = len - (iterator->start - iterator->offset);
54 
55 		if (copy > iterator->remain)
56 			copy = iterator->remain;
57 
58 		/* Copy out the bit of the string that we need */
59 		memcpy(iterator->data,
60 			str + (iterator->start - iterator->offset), copy);
61 
62 		iterator->offset = iterator->start + copy;
63 		iterator->remain -= copy;
64 	} else {
65 		ssize_t pos = iterator->offset - iterator->start;
66 
67 		len = min_t(ssize_t, strlen(str), iterator->remain);
68 
69 		memcpy(iterator->data + pos, str, len);
70 
71 		iterator->offset += len;
72 		iterator->remain -= len;
73 	}
74 }
75 EXPORT_SYMBOL(__drm_puts_coredump);
76 
77 void __drm_printfn_coredump(struct drm_printer *p, struct va_format *vaf)
78 {
79 	struct drm_print_iterator *iterator = p->arg;
80 	size_t len;
81 	char *buf;
82 
83 	if (!iterator->remain)
84 		return;
85 
86 	/* Figure out how big the string will be */
87 	len = snprintf(NULL, 0, "%pV", vaf);
88 
89 	/* This is the easiest path, we've already advanced beyond the offset */
90 	if (iterator->offset + len <= iterator->start) {
91 		iterator->offset += len;
92 		return;
93 	}
94 
95 	/* Then check if we can directly copy into the target buffer */
96 	if ((iterator->offset >= iterator->start) && (len < iterator->remain)) {
97 		ssize_t pos = iterator->offset - iterator->start;
98 
99 		snprintf(((char *) iterator->data) + pos,
100 			iterator->remain, "%pV", vaf);
101 
102 		iterator->offset += len;
103 		iterator->remain -= len;
104 
105 		return;
106 	}
107 
108 	/*
109 	 * Finally, hit the slow path and make a temporary string to copy over
110 	 * using _drm_puts_coredump
111 	 */
112 	buf = kmalloc(len + 1, GFP_KERNEL | __GFP_NOWARN | __GFP_NORETRY);
113 	if (!buf)
114 		return;
115 
116 	snprintf(buf, len + 1, "%pV", vaf);
117 	__drm_puts_coredump(p, (const char *) buf);
118 
119 	kfree(buf);
120 }
121 EXPORT_SYMBOL(__drm_printfn_coredump);
122 
123 void __drm_puts_seq_file(struct drm_printer *p, const char *str)
124 {
125 	seq_puts(p->arg, str);
126 }
127 EXPORT_SYMBOL(__drm_puts_seq_file);
128 
129 void __drm_printfn_seq_file(struct drm_printer *p, struct va_format *vaf)
130 {
131 	seq_printf(p->arg, "%pV", vaf);
132 }
133 EXPORT_SYMBOL(__drm_printfn_seq_file);
134 
135 #ifdef __linux__
136 void __drm_printfn_info(struct drm_printer *p, struct va_format *vaf)
137 {
138 	dev_info(p->arg, "[" DRM_NAME "] %pV", vaf);
139 }
140 EXPORT_SYMBOL(__drm_printfn_info);
141 
142 void __drm_printfn_debug(struct drm_printer *p, struct va_format *vaf)
143 {
144 	pr_debug("%s %pV", p->prefix, vaf);
145 }
146 EXPORT_SYMBOL(__drm_printfn_debug);
147 #else
148 void __drm_printfn_info(struct drm_printer *p, struct va_format *vaf)
149 {
150 #ifdef DRMDEBUG
151 	printf("[" DRM_NAME "] ");
152 	vprintf(vaf->fmt, *vaf->va);
153 #endif
154 }
155 
156 void __drm_printfn_debug(struct drm_printer *p, struct va_format *vaf)
157 {
158 #ifdef DRMDEBUG
159 	printf("%s ", p->prefix);
160 	vprintf(vaf->fmt, *vaf->va);
161 #endif
162 }
163 #endif
164 
165 /**
166  * drm_puts - print a const string to a &drm_printer stream
167  * @p: the &drm printer
168  * @str: const string
169  *
170  * Allow &drm_printer types that have a constant string
171  * option to use it.
172  */
173 void drm_puts(struct drm_printer *p, const char *str)
174 {
175 	if (p->puts)
176 		p->puts(p, str);
177 	else
178 		drm_printf(p, "%s", str);
179 }
180 EXPORT_SYMBOL(drm_puts);
181 
182 /**
183  * drm_printf - print to a &drm_printer stream
184  * @p: the &drm_printer
185  * @f: format string
186  */
187 void drm_printf(struct drm_printer *p, const char *f, ...)
188 {
189 	va_list args;
190 
191 	va_start(args, f);
192 	drm_vprintf(p, f, &args);
193 	va_end(args);
194 }
195 EXPORT_SYMBOL(drm_printf);
196 
197 #ifdef __linux__
198 void drm_dev_printk(const struct device *dev, const char *level,
199 		    const char *format, ...)
200 {
201 	struct va_format vaf;
202 	va_list args;
203 
204 	va_start(args, format);
205 	vaf.fmt = format;
206 	vaf.va = &args;
207 
208 	if (dev)
209 		dev_printk(level, dev, "[" DRM_NAME ":%ps] %pV",
210 			   __builtin_return_address(0), &vaf);
211 	else
212 		printk("%s" "[" DRM_NAME ":%ps] %pV",
213 		       level, __builtin_return_address(0), &vaf);
214 
215 	va_end(args);
216 }
217 EXPORT_SYMBOL(drm_dev_printk);
218 
219 void drm_dev_dbg(const struct device *dev, unsigned int category,
220 		 const char *format, ...)
221 {
222 	struct va_format vaf;
223 	va_list args;
224 
225 	if (!(drm_debug & category))
226 		return;
227 
228 	va_start(args, format);
229 	vaf.fmt = format;
230 	vaf.va = &args;
231 
232 	if (dev)
233 		dev_printk(KERN_DEBUG, dev, "[" DRM_NAME ":%ps] %pV",
234 			   __builtin_return_address(0), &vaf);
235 	else
236 		printk(KERN_DEBUG "[" DRM_NAME ":%ps] %pV",
237 		       __builtin_return_address(0), &vaf);
238 
239 	va_end(args);
240 }
241 EXPORT_SYMBOL(drm_dev_dbg);
242 
243 void drm_dbg(unsigned int category, const char *format, ...)
244 {
245 	struct va_format vaf;
246 	va_list args;
247 
248 	if (!(drm_debug & category))
249 		return;
250 
251 	va_start(args, format);
252 	vaf.fmt = format;
253 	vaf.va = &args;
254 
255 	printk(KERN_DEBUG "[" DRM_NAME ":%ps] %pV",
256 	       __builtin_return_address(0), &vaf);
257 
258 	va_end(args);
259 }
260 EXPORT_SYMBOL(drm_dbg);
261 
262 void drm_err(const char *format, ...)
263 {
264 	struct va_format vaf;
265 	va_list args;
266 
267 	va_start(args, format);
268 	vaf.fmt = format;
269 	vaf.va = &args;
270 
271 	printk(KERN_ERR "[" DRM_NAME ":%ps] *ERROR* %pV",
272 	       __builtin_return_address(0), &vaf);
273 
274 	va_end(args);
275 }
276 EXPORT_SYMBOL(drm_err);
277 
278 #else
279 
280 void drm_dev_printk(const struct device *dev, const char *level,
281 		    const char *format, ...)
282 {
283 	va_list args;
284 
285 	va_start(args, format);
286 	printk("%s" "[" DRM_NAME "] ", level);
287 	vprintf(format, args);
288 	va_end(args);
289 }
290 
291 void drm_dev_dbg(const struct device *dev, unsigned int category,
292 		 const char *format, ...)
293 {
294 	va_list args;
295 
296 	if (!(drm_debug & category))
297 		return;
298 
299 	va_start(args, format);
300 	printf(KERN_DEBUG "[" DRM_NAME "] ");
301 	vprintf(format, args);
302 	va_end(args);
303 }
304 
305 void drm_dbg(unsigned int category, const char *format, ...)
306 {
307 	va_list args;
308 
309 	if (!(drm_debug & category))
310 		return;
311 
312 	va_start(args, format);
313 	printf(KERN_DEBUG "[" DRM_NAME "] ");
314 	vprintf(format, args);
315 	va_end(args);
316 }
317 
318 void drm_err(const char *format, ...)
319 {
320 	va_list args;
321 
322 	va_start(args, format);
323 	printf(KERN_ERR "[" DRM_NAME "] *ERROR* ");
324 	vprintf(format, args);
325 	va_end(args);
326 }
327 #endif
328