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