xref: /linux/drivers/firmware/tegra/bpmp-debugfs.c (revision 79790b6818e96c58fe2bffee1b418c16e64e7b80)
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * Copyright (c) 2017, NVIDIA CORPORATION.  All rights reserved.
4  */
5 #include <linux/debugfs.h>
6 #include <linux/dma-mapping.h>
7 #include <linux/slab.h>
8 #include <linux/uaccess.h>
9 
10 #include <soc/tegra/bpmp.h>
11 #include <soc/tegra/bpmp-abi.h>
12 
13 static DEFINE_MUTEX(bpmp_debug_lock);
14 
15 struct seqbuf {
16 	char *buf;
17 	size_t pos;
18 	size_t size;
19 };
20 
seqbuf_init(struct seqbuf * seqbuf,void * buf,size_t size)21 static void seqbuf_init(struct seqbuf *seqbuf, void *buf, size_t size)
22 {
23 	seqbuf->buf = buf;
24 	seqbuf->size = size;
25 	seqbuf->pos = 0;
26 }
27 
seqbuf_avail(struct seqbuf * seqbuf)28 static size_t seqbuf_avail(struct seqbuf *seqbuf)
29 {
30 	return seqbuf->pos < seqbuf->size ? seqbuf->size - seqbuf->pos : 0;
31 }
32 
seqbuf_status(struct seqbuf * seqbuf)33 static size_t seqbuf_status(struct seqbuf *seqbuf)
34 {
35 	return seqbuf->pos <= seqbuf->size ? 0 : -EOVERFLOW;
36 }
37 
seqbuf_eof(struct seqbuf * seqbuf)38 static int seqbuf_eof(struct seqbuf *seqbuf)
39 {
40 	return seqbuf->pos >= seqbuf->size;
41 }
42 
seqbuf_read(struct seqbuf * seqbuf,void * buf,size_t nbyte)43 static int seqbuf_read(struct seqbuf *seqbuf, void *buf, size_t nbyte)
44 {
45 	nbyte = min(nbyte, seqbuf_avail(seqbuf));
46 	memcpy(buf, seqbuf->buf + seqbuf->pos, nbyte);
47 	seqbuf->pos += nbyte;
48 	return seqbuf_status(seqbuf);
49 }
50 
seqbuf_read_u32(struct seqbuf * seqbuf,u32 * v)51 static int seqbuf_read_u32(struct seqbuf *seqbuf, u32 *v)
52 {
53 	return seqbuf_read(seqbuf, v, 4);
54 }
55 
seqbuf_read_str(struct seqbuf * seqbuf,const char ** str)56 static int seqbuf_read_str(struct seqbuf *seqbuf, const char **str)
57 {
58 	*str = seqbuf->buf + seqbuf->pos;
59 	seqbuf->pos += strnlen(*str, seqbuf_avail(seqbuf));
60 	seqbuf->pos++;
61 	return seqbuf_status(seqbuf);
62 }
63 
seqbuf_seek(struct seqbuf * seqbuf,ssize_t offset)64 static void seqbuf_seek(struct seqbuf *seqbuf, ssize_t offset)
65 {
66 	seqbuf->pos += offset;
67 }
68 
69 /* map filename in Linux debugfs to corresponding entry in BPMP */
get_filename(struct tegra_bpmp * bpmp,const struct file * file,char * buf,int size)70 static const char *get_filename(struct tegra_bpmp *bpmp,
71 				const struct file *file, char *buf, int size)
72 {
73 	const char *root_path, *filename = NULL;
74 	char *root_path_buf;
75 	size_t root_len;
76 	size_t root_path_buf_len = 512;
77 
78 	root_path_buf = kzalloc(root_path_buf_len, GFP_KERNEL);
79 	if (!root_path_buf)
80 		return NULL;
81 
82 	root_path = dentry_path(bpmp->debugfs_mirror, root_path_buf,
83 				root_path_buf_len);
84 	if (IS_ERR(root_path))
85 		goto out;
86 
87 	root_len = strlen(root_path);
88 
89 	filename = dentry_path(file->f_path.dentry, buf, size);
90 	if (IS_ERR(filename)) {
91 		filename = NULL;
92 		goto out;
93 	}
94 
95 	if (strlen(filename) < root_len || strncmp(filename, root_path, root_len)) {
96 		filename = NULL;
97 		goto out;
98 	}
99 
100 	filename += root_len;
101 
102 out:
103 	kfree(root_path_buf);
104 	return filename;
105 }
106 
mrq_debug_open(struct tegra_bpmp * bpmp,const char * name,u32 * fd,u32 * len,bool write)107 static int mrq_debug_open(struct tegra_bpmp *bpmp, const char *name,
108 			  u32 *fd, u32 *len, bool write)
109 {
110 	struct mrq_debug_request req = {
111 		.cmd = write ? CMD_DEBUG_OPEN_WO : CMD_DEBUG_OPEN_RO,
112 	};
113 	struct mrq_debug_response resp;
114 	struct tegra_bpmp_message msg = {
115 		.mrq = MRQ_DEBUG,
116 		.tx = {
117 			.data = &req,
118 			.size = sizeof(req),
119 		},
120 		.rx = {
121 			.data = &resp,
122 			.size = sizeof(resp),
123 		},
124 	};
125 	ssize_t sz_name;
126 	int err = 0;
127 
128 	sz_name = strscpy(req.fop.name, name, sizeof(req.fop.name));
129 	if (sz_name < 0) {
130 		pr_err("File name too large: %s\n", name);
131 		return -EINVAL;
132 	}
133 
134 	err = tegra_bpmp_transfer(bpmp, &msg);
135 	if (err < 0)
136 		return err;
137 	else if (msg.rx.ret < 0)
138 		return -EINVAL;
139 
140 	*len = resp.fop.datalen;
141 	*fd = resp.fop.fd;
142 
143 	return 0;
144 }
145 
mrq_debug_close(struct tegra_bpmp * bpmp,u32 fd)146 static int mrq_debug_close(struct tegra_bpmp *bpmp, u32 fd)
147 {
148 	struct mrq_debug_request req = {
149 		.cmd = CMD_DEBUG_CLOSE,
150 		.frd = {
151 			.fd = fd,
152 		},
153 	};
154 	struct mrq_debug_response resp;
155 	struct tegra_bpmp_message msg = {
156 		.mrq = MRQ_DEBUG,
157 		.tx = {
158 			.data = &req,
159 			.size = sizeof(req),
160 		},
161 		.rx = {
162 			.data = &resp,
163 			.size = sizeof(resp),
164 		},
165 	};
166 	int err = 0;
167 
168 	err = tegra_bpmp_transfer(bpmp, &msg);
169 	if (err < 0)
170 		return err;
171 	else if (msg.rx.ret < 0)
172 		return -EINVAL;
173 
174 	return 0;
175 }
176 
mrq_debug_read(struct tegra_bpmp * bpmp,const char * name,char * data,size_t sz_data,u32 * nbytes)177 static int mrq_debug_read(struct tegra_bpmp *bpmp, const char *name,
178 			  char *data, size_t sz_data, u32 *nbytes)
179 {
180 	struct mrq_debug_request req = {
181 		.cmd = CMD_DEBUG_READ,
182 	};
183 	struct mrq_debug_response resp;
184 	struct tegra_bpmp_message msg = {
185 		.mrq = MRQ_DEBUG,
186 		.tx = {
187 			.data = &req,
188 			.size = sizeof(req),
189 		},
190 		.rx = {
191 			.data = &resp,
192 			.size = sizeof(resp),
193 		},
194 	};
195 	u32 fd = 0, len = 0;
196 	int remaining, err, close_err;
197 
198 	mutex_lock(&bpmp_debug_lock);
199 	err = mrq_debug_open(bpmp, name, &fd, &len, 0);
200 	if (err)
201 		goto out;
202 
203 	if (len > sz_data) {
204 		err = -EFBIG;
205 		goto close;
206 	}
207 
208 	req.frd.fd = fd;
209 	remaining = len;
210 
211 	while (remaining > 0) {
212 		err = tegra_bpmp_transfer(bpmp, &msg);
213 		if (err < 0) {
214 			goto close;
215 		} else if (msg.rx.ret < 0) {
216 			err = -EINVAL;
217 			goto close;
218 		}
219 
220 		if (resp.frd.readlen > remaining) {
221 			pr_err("%s: read data length invalid\n", __func__);
222 			err = -EINVAL;
223 			goto close;
224 		}
225 
226 		memcpy(data, resp.frd.data, resp.frd.readlen);
227 		data += resp.frd.readlen;
228 		remaining -= resp.frd.readlen;
229 	}
230 
231 	*nbytes = len;
232 
233 close:
234 	close_err = mrq_debug_close(bpmp, fd);
235 	if (!err)
236 		err = close_err;
237 out:
238 	mutex_unlock(&bpmp_debug_lock);
239 	return err;
240 }
241 
mrq_debug_write(struct tegra_bpmp * bpmp,const char * name,uint8_t * data,size_t sz_data)242 static int mrq_debug_write(struct tegra_bpmp *bpmp, const char *name,
243 			   uint8_t *data, size_t sz_data)
244 {
245 	struct mrq_debug_request req = {
246 		.cmd = CMD_DEBUG_WRITE
247 	};
248 	struct mrq_debug_response resp;
249 	struct tegra_bpmp_message msg = {
250 		.mrq = MRQ_DEBUG,
251 		.tx = {
252 			.data = &req,
253 			.size = sizeof(req),
254 		},
255 		.rx = {
256 			.data = &resp,
257 			.size = sizeof(resp),
258 		},
259 	};
260 	u32 fd = 0, len = 0;
261 	size_t remaining;
262 	int err;
263 
264 	mutex_lock(&bpmp_debug_lock);
265 	err = mrq_debug_open(bpmp, name, &fd, &len, 1);
266 	if (err)
267 		goto out;
268 
269 	if (sz_data > len) {
270 		err = -EINVAL;
271 		goto close;
272 	}
273 
274 	req.fwr.fd = fd;
275 	remaining = sz_data;
276 
277 	while (remaining > 0) {
278 		len = min(remaining, sizeof(req.fwr.data));
279 		memcpy(req.fwr.data, data, len);
280 		req.fwr.datalen = len;
281 
282 		err = tegra_bpmp_transfer(bpmp, &msg);
283 		if (err < 0) {
284 			goto close;
285 		} else if (msg.rx.ret < 0) {
286 			err = -EINVAL;
287 			goto close;
288 		}
289 
290 		data += req.fwr.datalen;
291 		remaining -= req.fwr.datalen;
292 	}
293 
294 close:
295 	err = mrq_debug_close(bpmp, fd);
296 out:
297 	mutex_unlock(&bpmp_debug_lock);
298 	return err;
299 }
300 
bpmp_debug_show(struct seq_file * m,void * p)301 static int bpmp_debug_show(struct seq_file *m, void *p)
302 {
303 	struct file *file = m->private;
304 	struct inode *inode = file_inode(file);
305 	struct tegra_bpmp *bpmp = inode->i_private;
306 	char fnamebuf[256];
307 	const char *filename;
308 	struct mrq_debug_request req = {
309 		.cmd = CMD_DEBUG_READ,
310 	};
311 	struct mrq_debug_response resp;
312 	struct tegra_bpmp_message msg = {
313 		.mrq = MRQ_DEBUG,
314 		.tx = {
315 			.data = &req,
316 			.size = sizeof(req),
317 		},
318 		.rx = {
319 			.data = &resp,
320 			.size = sizeof(resp),
321 		},
322 	};
323 	u32 fd = 0, len = 0;
324 	int remaining, err, close_err;
325 
326 	filename = get_filename(bpmp, file, fnamebuf, sizeof(fnamebuf));
327 	if (!filename)
328 		return -ENOENT;
329 
330 	mutex_lock(&bpmp_debug_lock);
331 	err = mrq_debug_open(bpmp, filename, &fd, &len, 0);
332 	if (err)
333 		goto out;
334 
335 	req.frd.fd = fd;
336 	remaining = len;
337 
338 	while (remaining > 0) {
339 		err = tegra_bpmp_transfer(bpmp, &msg);
340 		if (err < 0) {
341 			goto close;
342 		} else if (msg.rx.ret < 0) {
343 			err = -EINVAL;
344 			goto close;
345 		}
346 
347 		if (resp.frd.readlen > remaining) {
348 			pr_err("%s: read data length invalid\n", __func__);
349 			err = -EINVAL;
350 			goto close;
351 		}
352 
353 		seq_write(m, resp.frd.data, resp.frd.readlen);
354 		remaining -= resp.frd.readlen;
355 	}
356 
357 close:
358 	close_err = mrq_debug_close(bpmp, fd);
359 	if (!err)
360 		err = close_err;
361 out:
362 	mutex_unlock(&bpmp_debug_lock);
363 	return err;
364 }
365 
bpmp_debug_store(struct file * file,const char __user * buf,size_t count,loff_t * f_pos)366 static ssize_t bpmp_debug_store(struct file *file, const char __user *buf,
367 		size_t count, loff_t *f_pos)
368 {
369 	struct inode *inode = file_inode(file);
370 	struct tegra_bpmp *bpmp = inode->i_private;
371 	char *databuf = NULL;
372 	char fnamebuf[256];
373 	const char *filename;
374 	ssize_t err;
375 
376 	filename = get_filename(bpmp, file, fnamebuf, sizeof(fnamebuf));
377 	if (!filename)
378 		return -ENOENT;
379 
380 	databuf = memdup_user(buf, count);
381 	if (IS_ERR(databuf))
382 		return PTR_ERR(databuf);
383 
384 	err = mrq_debug_write(bpmp, filename, databuf, count);
385 	kfree(databuf);
386 
387 	return err ?: count;
388 }
389 
bpmp_debug_open(struct inode * inode,struct file * file)390 static int bpmp_debug_open(struct inode *inode, struct file *file)
391 {
392 	return single_open_size(file, bpmp_debug_show, file, SZ_256K);
393 }
394 
395 static const struct file_operations bpmp_debug_fops = {
396 	.open		= bpmp_debug_open,
397 	.read		= seq_read,
398 	.llseek		= seq_lseek,
399 	.write		= bpmp_debug_store,
400 	.release	= single_release,
401 };
402 
bpmp_populate_debugfs_inband(struct tegra_bpmp * bpmp,struct dentry * parent,char * ppath)403 static int bpmp_populate_debugfs_inband(struct tegra_bpmp *bpmp,
404 					struct dentry *parent,
405 					char *ppath)
406 {
407 	const size_t pathlen = SZ_256;
408 	const size_t bufsize = SZ_16K;
409 	struct dentry *dentry;
410 	u32 dsize, attrs = 0;
411 	struct seqbuf seqbuf;
412 	char *buf, *pathbuf;
413 	const char *name;
414 	int err = 0;
415 
416 	if (!bpmp || !parent || !ppath)
417 		return -EINVAL;
418 
419 	buf = kmalloc(bufsize, GFP_KERNEL);
420 	if (!buf)
421 		return -ENOMEM;
422 
423 	pathbuf = kzalloc(pathlen, GFP_KERNEL);
424 	if (!pathbuf) {
425 		kfree(buf);
426 		return -ENOMEM;
427 	}
428 
429 	err = mrq_debug_read(bpmp, ppath, buf, bufsize, &dsize);
430 	if (err)
431 		goto out;
432 
433 	seqbuf_init(&seqbuf, buf, dsize);
434 
435 	while (!seqbuf_eof(&seqbuf)) {
436 		err = seqbuf_read_u32(&seqbuf, &attrs);
437 		if (err)
438 			goto out;
439 
440 		err = seqbuf_read_str(&seqbuf, &name);
441 		if (err < 0)
442 			goto out;
443 
444 		if (attrs & DEBUGFS_S_ISDIR) {
445 			size_t len;
446 
447 			dentry = debugfs_create_dir(name, parent);
448 			if (IS_ERR(dentry)) {
449 				err = PTR_ERR(dentry);
450 				goto out;
451 			}
452 
453 			len = snprintf(pathbuf, pathlen, "%s%s/", ppath, name);
454 			if (len >= pathlen) {
455 				err = -EINVAL;
456 				goto out;
457 			}
458 
459 			err = bpmp_populate_debugfs_inband(bpmp, dentry,
460 							   pathbuf);
461 			if (err < 0)
462 				goto out;
463 		} else {
464 			umode_t mode;
465 
466 			mode = attrs & DEBUGFS_S_IRUSR ? 0400 : 0;
467 			mode |= attrs & DEBUGFS_S_IWUSR ? 0200 : 0;
468 			dentry = debugfs_create_file(name, mode, parent, bpmp,
469 						     &bpmp_debug_fops);
470 			if (IS_ERR(dentry)) {
471 				err = -ENOMEM;
472 				goto out;
473 			}
474 		}
475 	}
476 
477 out:
478 	kfree(pathbuf);
479 	kfree(buf);
480 
481 	return err;
482 }
483 
mrq_debugfs_read(struct tegra_bpmp * bpmp,dma_addr_t name,size_t sz_name,dma_addr_t data,size_t sz_data,size_t * nbytes)484 static int mrq_debugfs_read(struct tegra_bpmp *bpmp,
485 			    dma_addr_t name, size_t sz_name,
486 			    dma_addr_t data, size_t sz_data,
487 			    size_t *nbytes)
488 {
489 	struct mrq_debugfs_request req = {
490 		.cmd = CMD_DEBUGFS_READ,
491 		.fop = {
492 			.fnameaddr = (u32)name,
493 			.fnamelen = (u32)sz_name,
494 			.dataaddr = (u32)data,
495 			.datalen = (u32)sz_data,
496 		},
497 	};
498 	struct mrq_debugfs_response resp;
499 	struct tegra_bpmp_message msg = {
500 		.mrq = MRQ_DEBUGFS,
501 		.tx = {
502 			.data = &req,
503 			.size = sizeof(req),
504 		},
505 		.rx = {
506 			.data = &resp,
507 			.size = sizeof(resp),
508 		},
509 	};
510 	int err;
511 
512 	err = tegra_bpmp_transfer(bpmp, &msg);
513 	if (err < 0)
514 		return err;
515 	else if (msg.rx.ret < 0)
516 		return -EINVAL;
517 
518 	*nbytes = (size_t)resp.fop.nbytes;
519 
520 	return 0;
521 }
522 
mrq_debugfs_write(struct tegra_bpmp * bpmp,dma_addr_t name,size_t sz_name,dma_addr_t data,size_t sz_data)523 static int mrq_debugfs_write(struct tegra_bpmp *bpmp,
524 			     dma_addr_t name, size_t sz_name,
525 			     dma_addr_t data, size_t sz_data)
526 {
527 	const struct mrq_debugfs_request req = {
528 		.cmd = CMD_DEBUGFS_WRITE,
529 		.fop = {
530 			.fnameaddr = (u32)name,
531 			.fnamelen = (u32)sz_name,
532 			.dataaddr = (u32)data,
533 			.datalen = (u32)sz_data,
534 		},
535 	};
536 	struct tegra_bpmp_message msg = {
537 		.mrq = MRQ_DEBUGFS,
538 		.tx = {
539 			.data = &req,
540 			.size = sizeof(req),
541 		},
542 	};
543 
544 	return tegra_bpmp_transfer(bpmp, &msg);
545 }
546 
mrq_debugfs_dumpdir(struct tegra_bpmp * bpmp,dma_addr_t addr,size_t size,size_t * nbytes)547 static int mrq_debugfs_dumpdir(struct tegra_bpmp *bpmp, dma_addr_t addr,
548 			       size_t size, size_t *nbytes)
549 {
550 	const struct mrq_debugfs_request req = {
551 		.cmd = CMD_DEBUGFS_DUMPDIR,
552 		.dumpdir = {
553 			.dataaddr = (u32)addr,
554 			.datalen = (u32)size,
555 		},
556 	};
557 	struct mrq_debugfs_response resp;
558 	struct tegra_bpmp_message msg = {
559 		.mrq = MRQ_DEBUGFS,
560 		.tx = {
561 			.data = &req,
562 			.size = sizeof(req),
563 		},
564 		.rx = {
565 			.data = &resp,
566 			.size = sizeof(resp),
567 		},
568 	};
569 	int err;
570 
571 	err = tegra_bpmp_transfer(bpmp, &msg);
572 	if (err < 0)
573 		return err;
574 	else if (msg.rx.ret < 0)
575 		return -EINVAL;
576 
577 	*nbytes = (size_t)resp.dumpdir.nbytes;
578 
579 	return 0;
580 }
581 
debugfs_show(struct seq_file * m,void * p)582 static int debugfs_show(struct seq_file *m, void *p)
583 {
584 	struct file *file = m->private;
585 	struct inode *inode = file_inode(file);
586 	struct tegra_bpmp *bpmp = inode->i_private;
587 	const size_t datasize = m->size;
588 	const size_t namesize = SZ_256;
589 	void *datavirt, *namevirt;
590 	dma_addr_t dataphys, namephys;
591 	char buf[256];
592 	const char *filename;
593 	size_t len, nbytes;
594 	int err;
595 
596 	filename = get_filename(bpmp, file, buf, sizeof(buf));
597 	if (!filename)
598 		return -ENOENT;
599 
600 	namevirt = dma_alloc_coherent(bpmp->dev, namesize, &namephys,
601 				      GFP_KERNEL | GFP_DMA32);
602 	if (!namevirt)
603 		return -ENOMEM;
604 
605 	datavirt = dma_alloc_coherent(bpmp->dev, datasize, &dataphys,
606 				      GFP_KERNEL | GFP_DMA32);
607 	if (!datavirt) {
608 		err = -ENOMEM;
609 		goto free_namebuf;
610 	}
611 
612 	len = strlen(filename);
613 	strscpy_pad(namevirt, filename, namesize);
614 
615 	err = mrq_debugfs_read(bpmp, namephys, len, dataphys, datasize,
616 			       &nbytes);
617 
618 	if (!err)
619 		seq_write(m, datavirt, nbytes);
620 
621 	dma_free_coherent(bpmp->dev, datasize, datavirt, dataphys);
622 free_namebuf:
623 	dma_free_coherent(bpmp->dev, namesize, namevirt, namephys);
624 
625 	return err;
626 }
627 
debugfs_open(struct inode * inode,struct file * file)628 static int debugfs_open(struct inode *inode, struct file *file)
629 {
630 	return single_open_size(file, debugfs_show, file, SZ_128K);
631 }
632 
debugfs_store(struct file * file,const char __user * buf,size_t count,loff_t * f_pos)633 static ssize_t debugfs_store(struct file *file, const char __user *buf,
634 		size_t count, loff_t *f_pos)
635 {
636 	struct inode *inode = file_inode(file);
637 	struct tegra_bpmp *bpmp = inode->i_private;
638 	const size_t datasize = count;
639 	const size_t namesize = SZ_256;
640 	void *datavirt, *namevirt;
641 	dma_addr_t dataphys, namephys;
642 	char fnamebuf[256];
643 	const char *filename;
644 	size_t len;
645 	int err;
646 
647 	filename = get_filename(bpmp, file, fnamebuf, sizeof(fnamebuf));
648 	if (!filename)
649 		return -ENOENT;
650 
651 	namevirt = dma_alloc_coherent(bpmp->dev, namesize, &namephys,
652 				      GFP_KERNEL | GFP_DMA32);
653 	if (!namevirt)
654 		return -ENOMEM;
655 
656 	datavirt = dma_alloc_coherent(bpmp->dev, datasize, &dataphys,
657 				      GFP_KERNEL | GFP_DMA32);
658 	if (!datavirt) {
659 		err = -ENOMEM;
660 		goto free_namebuf;
661 	}
662 
663 	len = strlen(filename);
664 	strscpy_pad(namevirt, filename, namesize);
665 
666 	if (copy_from_user(datavirt, buf, count)) {
667 		err = -EFAULT;
668 		goto free_databuf;
669 	}
670 
671 	err = mrq_debugfs_write(bpmp, namephys, len, dataphys,
672 				count);
673 
674 free_databuf:
675 	dma_free_coherent(bpmp->dev, datasize, datavirt, dataphys);
676 free_namebuf:
677 	dma_free_coherent(bpmp->dev, namesize, namevirt, namephys);
678 
679 	return err ?: count;
680 }
681 
682 static const struct file_operations debugfs_fops = {
683 	.open		= debugfs_open,
684 	.read		= seq_read,
685 	.llseek		= seq_lseek,
686 	.write		= debugfs_store,
687 	.release	= single_release,
688 };
689 
bpmp_populate_dir(struct tegra_bpmp * bpmp,struct seqbuf * seqbuf,struct dentry * parent,u32 depth)690 static int bpmp_populate_dir(struct tegra_bpmp *bpmp, struct seqbuf *seqbuf,
691 			     struct dentry *parent, u32 depth)
692 {
693 	int err;
694 	u32 d, t;
695 	const char *name;
696 	struct dentry *dentry;
697 
698 	while (!seqbuf_eof(seqbuf)) {
699 		err = seqbuf_read_u32(seqbuf, &d);
700 		if (err < 0)
701 			return err;
702 
703 		if (d < depth) {
704 			seqbuf_seek(seqbuf, -4);
705 			/* go up a level */
706 			return 0;
707 		} else if (d != depth) {
708 			/* malformed data received from BPMP */
709 			return -EIO;
710 		}
711 
712 		err = seqbuf_read_u32(seqbuf, &t);
713 		if (err < 0)
714 			return err;
715 		err = seqbuf_read_str(seqbuf, &name);
716 		if (err < 0)
717 			return err;
718 
719 		if (t & DEBUGFS_S_ISDIR) {
720 			dentry = debugfs_create_dir(name, parent);
721 			if (IS_ERR(dentry))
722 				return -ENOMEM;
723 			err = bpmp_populate_dir(bpmp, seqbuf, dentry, depth+1);
724 			if (err < 0)
725 				return err;
726 		} else {
727 			umode_t mode;
728 
729 			mode = t & DEBUGFS_S_IRUSR ? S_IRUSR : 0;
730 			mode |= t & DEBUGFS_S_IWUSR ? S_IWUSR : 0;
731 			dentry = debugfs_create_file(name, mode,
732 						     parent, bpmp,
733 						     &debugfs_fops);
734 			if (IS_ERR(dentry))
735 				return -ENOMEM;
736 		}
737 	}
738 
739 	return 0;
740 }
741 
bpmp_populate_debugfs_shmem(struct tegra_bpmp * bpmp)742 static int bpmp_populate_debugfs_shmem(struct tegra_bpmp *bpmp)
743 {
744 	struct seqbuf seqbuf;
745 	const size_t sz = SZ_512K;
746 	dma_addr_t phys;
747 	size_t nbytes;
748 	void *virt;
749 	int err;
750 
751 	virt = dma_alloc_coherent(bpmp->dev, sz, &phys,
752 				  GFP_KERNEL | GFP_DMA32);
753 	if (!virt)
754 		return -ENOMEM;
755 
756 	err = mrq_debugfs_dumpdir(bpmp, phys, sz, &nbytes);
757 	if (err < 0) {
758 		goto free;
759 	} else if (nbytes > sz) {
760 		err = -EINVAL;
761 		goto free;
762 	}
763 
764 	seqbuf_init(&seqbuf, virt, nbytes);
765 	err = bpmp_populate_dir(bpmp, &seqbuf, bpmp->debugfs_mirror, 0);
766 free:
767 	dma_free_coherent(bpmp->dev, sz, virt, phys);
768 
769 	return err;
770 }
771 
tegra_bpmp_init_debugfs(struct tegra_bpmp * bpmp)772 int tegra_bpmp_init_debugfs(struct tegra_bpmp *bpmp)
773 {
774 	struct dentry *root;
775 	bool inband;
776 	int err;
777 
778 	inband = tegra_bpmp_mrq_is_supported(bpmp, MRQ_DEBUG);
779 
780 	if (!inband && !tegra_bpmp_mrq_is_supported(bpmp, MRQ_DEBUGFS))
781 		return 0;
782 
783 	root = debugfs_create_dir("bpmp", NULL);
784 	if (IS_ERR(root))
785 		return -ENOMEM;
786 
787 	bpmp->debugfs_mirror = debugfs_create_dir("debug", root);
788 	if (IS_ERR(bpmp->debugfs_mirror)) {
789 		err = -ENOMEM;
790 		goto out;
791 	}
792 
793 	if (inband)
794 		err = bpmp_populate_debugfs_inband(bpmp, bpmp->debugfs_mirror,
795 						   "/");
796 	else
797 		err = bpmp_populate_debugfs_shmem(bpmp);
798 
799 out:
800 	if (err < 0)
801 		debugfs_remove_recursive(root);
802 
803 	return err;
804 }
805