1 // SPDX-License-Identifier: GPL-2.0-only
3 * Copyright (c) 2017, NVIDIA CORPORATION. All rights reserved.
5 #include <linux/debugfs.h>
6 #include <linux/dma-mapping.h>
7 #include <linux/slab.h>
8 #include <linux/uaccess.h>
10 #include <soc/tegra/bpmp.h>
11 #include <soc/tegra/bpmp-abi.h>
13 static DEFINE_MUTEX(bpmp_debug_lock
);
21 static void seqbuf_init(struct seqbuf
*seqbuf
, void *buf
, size_t size
)
28 static size_t seqbuf_avail(struct seqbuf
*seqbuf
)
30 return seqbuf
->pos
< seqbuf
->size
? seqbuf
->size
- seqbuf
->pos
: 0;
33 static size_t seqbuf_status(struct seqbuf
*seqbuf
)
35 return seqbuf
->pos
<= seqbuf
->size
? 0 : -EOVERFLOW
;
38 static int seqbuf_eof(struct seqbuf
*seqbuf
)
40 return seqbuf
->pos
>= seqbuf
->size
;
43 static int seqbuf_read(struct seqbuf
*seqbuf
, void *buf
, size_t nbyte
)
45 nbyte
= min(nbyte
, seqbuf_avail(seqbuf
));
46 memcpy(buf
, seqbuf
->buf
+ seqbuf
->pos
, nbyte
);
48 return seqbuf_status(seqbuf
);
51 static int seqbuf_read_u32(struct seqbuf
*seqbuf
, u32
*v
)
53 return seqbuf_read(seqbuf
, v
, 4);
56 static int seqbuf_read_str(struct seqbuf
*seqbuf
, const char **str
)
58 *str
= seqbuf
->buf
+ seqbuf
->pos
;
59 seqbuf
->pos
+= strnlen(*str
, seqbuf_avail(seqbuf
));
61 return seqbuf_status(seqbuf
);
64 static void seqbuf_seek(struct seqbuf
*seqbuf
, ssize_t offset
)
66 seqbuf
->pos
+= offset
;
69 /* map filename in Linux debugfs to corresponding entry in BPMP */
70 static const char *get_filename(struct tegra_bpmp
*bpmp
,
71 const struct file
*file
, char *buf
, int size
)
73 const char *root_path
, *filename
= NULL
;
76 size_t root_path_buf_len
= 512;
78 root_path_buf
= kzalloc(root_path_buf_len
, GFP_KERNEL
);
82 root_path
= dentry_path(bpmp
->debugfs_mirror
, root_path_buf
,
84 if (IS_ERR(root_path
))
87 root_len
= strlen(root_path
);
89 filename
= dentry_path(file
->f_path
.dentry
, buf
, size
);
90 if (IS_ERR(filename
)) {
95 if (strlen(filename
) < root_len
|| strncmp(filename
, root_path
, root_len
)) {
100 filename
+= root_len
;
103 kfree(root_path_buf
);
107 static int mrq_debug_open(struct tegra_bpmp
*bpmp
, const char *name
,
108 u32
*fd
, u32
*len
, bool write
)
110 struct mrq_debug_request req
= {
111 .cmd
= write
? CMD_DEBUG_OPEN_WO
: CMD_DEBUG_OPEN_RO
,
113 struct mrq_debug_response resp
;
114 struct tegra_bpmp_message msg
= {
122 .size
= sizeof(resp
),
128 sz_name
= strscpy(req
.fop
.name
, name
, sizeof(req
.fop
.name
));
130 pr_err("File name too large: %s\n", name
);
134 err
= tegra_bpmp_transfer(bpmp
, &msg
);
137 else if (msg
.rx
.ret
< 0)
140 *len
= resp
.fop
.datalen
;
146 static int mrq_debug_close(struct tegra_bpmp
*bpmp
, u32 fd
)
148 struct mrq_debug_request req
= {
149 .cmd
= CMD_DEBUG_CLOSE
,
154 struct mrq_debug_response resp
;
155 struct tegra_bpmp_message msg
= {
163 .size
= sizeof(resp
),
168 err
= tegra_bpmp_transfer(bpmp
, &msg
);
171 else if (msg
.rx
.ret
< 0)
177 static int mrq_debug_read(struct tegra_bpmp
*bpmp
, const char *name
,
178 char *data
, size_t sz_data
, u32
*nbytes
)
180 struct mrq_debug_request req
= {
181 .cmd
= CMD_DEBUG_READ
,
183 struct mrq_debug_response resp
;
184 struct tegra_bpmp_message msg
= {
192 .size
= sizeof(resp
),
196 int remaining
, err
, close_err
;
198 mutex_lock(&bpmp_debug_lock
);
199 err
= mrq_debug_open(bpmp
, name
, &fd
, &len
, 0);
211 while (remaining
> 0) {
212 err
= tegra_bpmp_transfer(bpmp
, &msg
);
215 } else if (msg
.rx
.ret
< 0) {
220 if (resp
.frd
.readlen
> remaining
) {
221 pr_err("%s: read data length invalid\n", __func__
);
226 memcpy(data
, resp
.frd
.data
, resp
.frd
.readlen
);
227 data
+= resp
.frd
.readlen
;
228 remaining
-= resp
.frd
.readlen
;
234 close_err
= mrq_debug_close(bpmp
, fd
);
238 mutex_unlock(&bpmp_debug_lock
);
242 static int mrq_debug_write(struct tegra_bpmp
*bpmp
, const char *name
,
243 uint8_t *data
, size_t sz_data
)
245 struct mrq_debug_request req
= {
246 .cmd
= CMD_DEBUG_WRITE
248 struct mrq_debug_response resp
;
249 struct tegra_bpmp_message msg
= {
257 .size
= sizeof(resp
),
264 mutex_lock(&bpmp_debug_lock
);
265 err
= mrq_debug_open(bpmp
, name
, &fd
, &len
, 1);
277 while (remaining
> 0) {
278 len
= min(remaining
, sizeof(req
.fwr
.data
));
279 memcpy(req
.fwr
.data
, data
, len
);
280 req
.fwr
.datalen
= len
;
282 err
= tegra_bpmp_transfer(bpmp
, &msg
);
285 } else if (msg
.rx
.ret
< 0) {
290 data
+= req
.fwr
.datalen
;
291 remaining
-= req
.fwr
.datalen
;
295 err
= mrq_debug_close(bpmp
, fd
);
297 mutex_unlock(&bpmp_debug_lock
);
301 static int bpmp_debug_show(struct seq_file
*m
, void *p
)
303 struct file
*file
= m
->private;
304 struct inode
*inode
= file_inode(file
);
305 struct tegra_bpmp
*bpmp
= inode
->i_private
;
307 const char *filename
;
308 struct mrq_debug_request req
= {
309 .cmd
= CMD_DEBUG_READ
,
311 struct mrq_debug_response resp
;
312 struct tegra_bpmp_message msg
= {
320 .size
= sizeof(resp
),
324 int remaining
, err
, close_err
;
326 filename
= get_filename(bpmp
, file
, fnamebuf
, sizeof(fnamebuf
));
330 mutex_lock(&bpmp_debug_lock
);
331 err
= mrq_debug_open(bpmp
, filename
, &fd
, &len
, 0);
338 while (remaining
> 0) {
339 err
= tegra_bpmp_transfer(bpmp
, &msg
);
342 } else if (msg
.rx
.ret
< 0) {
347 if (resp
.frd
.readlen
> remaining
) {
348 pr_err("%s: read data length invalid\n", __func__
);
353 seq_write(m
, resp
.frd
.data
, resp
.frd
.readlen
);
354 remaining
-= resp
.frd
.readlen
;
358 close_err
= mrq_debug_close(bpmp
, fd
);
362 mutex_unlock(&bpmp_debug_lock
);
366 static ssize_t
bpmp_debug_store(struct file
*file
, const char __user
*buf
,
367 size_t count
, loff_t
*f_pos
)
369 struct inode
*inode
= file_inode(file
);
370 struct tegra_bpmp
*bpmp
= inode
->i_private
;
371 char *databuf
= NULL
;
373 const char *filename
;
376 filename
= get_filename(bpmp
, file
, fnamebuf
, sizeof(fnamebuf
));
380 databuf
= memdup_user(buf
, count
);
382 return PTR_ERR(databuf
);
384 err
= mrq_debug_write(bpmp
, filename
, databuf
, count
);
390 static int bpmp_debug_open(struct inode
*inode
, struct file
*file
)
392 return single_open_size(file
, bpmp_debug_show
, file
, SZ_256K
);
395 static const struct file_operations bpmp_debug_fops
= {
396 .open
= bpmp_debug_open
,
399 .write
= bpmp_debug_store
,
400 .release
= single_release
,
403 static int bpmp_populate_debugfs_inband(struct tegra_bpmp
*bpmp
,
404 struct dentry
*parent
,
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
;
416 if (!bpmp
|| !parent
|| !ppath
)
419 buf
= kmalloc(bufsize
, GFP_KERNEL
);
423 pathbuf
= kzalloc(pathlen
, GFP_KERNEL
);
429 err
= mrq_debug_read(bpmp
, ppath
, buf
, bufsize
, &dsize
);
433 seqbuf_init(&seqbuf
, buf
, dsize
);
435 while (!seqbuf_eof(&seqbuf
)) {
436 err
= seqbuf_read_u32(&seqbuf
, &attrs
);
440 err
= seqbuf_read_str(&seqbuf
, &name
);
444 if (attrs
& DEBUGFS_S_ISDIR
) {
447 dentry
= debugfs_create_dir(name
, parent
);
448 if (IS_ERR(dentry
)) {
449 err
= PTR_ERR(dentry
);
453 len
= snprintf(pathbuf
, pathlen
, "%s%s/", ppath
, name
);
454 if (len
>= pathlen
) {
459 err
= bpmp_populate_debugfs_inband(bpmp
, dentry
,
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
,
470 if (IS_ERR(dentry
)) {
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
,
489 struct mrq_debugfs_request req
= {
490 .cmd
= CMD_DEBUGFS_READ
,
492 .fnameaddr
= (u32
)name
,
493 .fnamelen
= (u32
)sz_name
,
494 .dataaddr
= (u32
)data
,
495 .datalen
= (u32
)sz_data
,
498 struct mrq_debugfs_response resp
;
499 struct tegra_bpmp_message msg
= {
507 .size
= sizeof(resp
),
512 err
= tegra_bpmp_transfer(bpmp
, &msg
);
515 else if (msg
.rx
.ret
< 0)
518 *nbytes
= (size_t)resp
.fop
.nbytes
;
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
)
527 const struct mrq_debugfs_request req
= {
528 .cmd
= CMD_DEBUGFS_WRITE
,
530 .fnameaddr
= (u32
)name
,
531 .fnamelen
= (u32
)sz_name
,
532 .dataaddr
= (u32
)data
,
533 .datalen
= (u32
)sz_data
,
536 struct tegra_bpmp_message msg
= {
544 return tegra_bpmp_transfer(bpmp
, &msg
);
547 static int mrq_debugfs_dumpdir(struct tegra_bpmp
*bpmp
, dma_addr_t addr
,
548 size_t size
, size_t *nbytes
)
550 const struct mrq_debugfs_request req
= {
551 .cmd
= CMD_DEBUGFS_DUMPDIR
,
553 .dataaddr
= (u32
)addr
,
554 .datalen
= (u32
)size
,
557 struct mrq_debugfs_response resp
;
558 struct tegra_bpmp_message msg
= {
566 .size
= sizeof(resp
),
571 err
= tegra_bpmp_transfer(bpmp
, &msg
);
574 else if (msg
.rx
.ret
< 0)
577 *nbytes
= (size_t)resp
.dumpdir
.nbytes
;
582 static int debugfs_show(struct seq_file
*m
, void *p
)
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
;
592 const char *filename
;
596 filename
= get_filename(bpmp
, file
, buf
, sizeof(buf
));
600 namevirt
= dma_alloc_coherent(bpmp
->dev
, namesize
, &namephys
,
601 GFP_KERNEL
| GFP_DMA32
);
605 datavirt
= dma_alloc_coherent(bpmp
->dev
, datasize
, &dataphys
,
606 GFP_KERNEL
| GFP_DMA32
);
612 len
= strlen(filename
);
613 strscpy_pad(namevirt
, filename
, namesize
);
615 err
= mrq_debugfs_read(bpmp
, namephys
, len
, dataphys
, datasize
,
619 seq_write(m
, datavirt
, nbytes
);
621 dma_free_coherent(bpmp
->dev
, datasize
, datavirt
, dataphys
);
623 dma_free_coherent(bpmp
->dev
, namesize
, namevirt
, namephys
);
628 static int debugfs_open(struct inode
*inode
, struct file
*file
)
630 return single_open_size(file
, debugfs_show
, file
, SZ_128K
);
633 static ssize_t
debugfs_store(struct file
*file
, const char __user
*buf
,
634 size_t count
, loff_t
*f_pos
)
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
;
643 const char *filename
;
647 filename
= get_filename(bpmp
, file
, fnamebuf
, sizeof(fnamebuf
));
651 namevirt
= dma_alloc_coherent(bpmp
->dev
, namesize
, &namephys
,
652 GFP_KERNEL
| GFP_DMA32
);
656 datavirt
= dma_alloc_coherent(bpmp
->dev
, datasize
, &dataphys
,
657 GFP_KERNEL
| GFP_DMA32
);
663 len
= strlen(filename
);
664 strscpy_pad(namevirt
, filename
, namesize
);
666 if (copy_from_user(datavirt
, buf
, count
)) {
671 err
= mrq_debugfs_write(bpmp
, namephys
, len
, dataphys
,
675 dma_free_coherent(bpmp
->dev
, datasize
, datavirt
, dataphys
);
677 dma_free_coherent(bpmp
->dev
, namesize
, namevirt
, namephys
);
682 static const struct file_operations debugfs_fops
= {
683 .open
= debugfs_open
,
686 .write
= debugfs_store
,
687 .release
= single_release
,
690 static int bpmp_populate_dir(struct tegra_bpmp
*bpmp
, struct seqbuf
*seqbuf
,
691 struct dentry
*parent
, u32 depth
)
696 struct dentry
*dentry
;
698 while (!seqbuf_eof(seqbuf
)) {
699 err
= seqbuf_read_u32(seqbuf
, &d
);
704 seqbuf_seek(seqbuf
, -4);
707 } else if (d
!= depth
) {
708 /* malformed data received from BPMP */
712 err
= seqbuf_read_u32(seqbuf
, &t
);
715 err
= seqbuf_read_str(seqbuf
, &name
);
719 if (t
& DEBUGFS_S_ISDIR
) {
720 dentry
= debugfs_create_dir(name
, parent
);
723 err
= bpmp_populate_dir(bpmp
, seqbuf
, dentry
, depth
+1);
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
,
742 static int bpmp_populate_debugfs_shmem(struct tegra_bpmp
*bpmp
)
744 struct seqbuf seqbuf
;
745 const size_t sz
= SZ_512K
;
751 virt
= dma_alloc_coherent(bpmp
->dev
, sz
, &phys
,
752 GFP_KERNEL
| GFP_DMA32
);
756 err
= mrq_debugfs_dumpdir(bpmp
, phys
, sz
, &nbytes
);
759 } else if (nbytes
> sz
) {
764 seqbuf_init(&seqbuf
, virt
, nbytes
);
765 err
= bpmp_populate_dir(bpmp
, &seqbuf
, bpmp
->debugfs_mirror
, 0);
767 dma_free_coherent(bpmp
->dev
, sz
, virt
, phys
);
772 int tegra_bpmp_init_debugfs(struct tegra_bpmp
*bpmp
)
778 inband
= tegra_bpmp_mrq_is_supported(bpmp
, MRQ_DEBUG
);
780 if (!inband
&& !tegra_bpmp_mrq_is_supported(bpmp
, MRQ_DEBUGFS
))
783 root
= debugfs_create_dir("bpmp", NULL
);
787 bpmp
->debugfs_mirror
= debugfs_create_dir("debug", root
);
788 if (IS_ERR(bpmp
->debugfs_mirror
)) {
794 err
= bpmp_populate_debugfs_inband(bpmp
, bpmp
->debugfs_mirror
,
797 err
= bpmp_populate_debugfs_shmem(bpmp
);
801 debugfs_remove_recursive(root
);