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