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