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