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/uaccess.h>
9 #include <soc/tegra/bpmp.h>
10 #include <soc/tegra/bpmp-abi.h>
18 static void seqbuf_init(struct seqbuf
*seqbuf
, void *buf
, size_t size
)
25 static size_t seqbuf_avail(struct seqbuf
*seqbuf
)
27 return seqbuf
->pos
< seqbuf
->size
? seqbuf
->size
- seqbuf
->pos
: 0;
30 static size_t seqbuf_status(struct seqbuf
*seqbuf
)
32 return seqbuf
->pos
<= seqbuf
->size
? 0 : -EOVERFLOW
;
35 static int seqbuf_eof(struct seqbuf
*seqbuf
)
37 return seqbuf
->pos
>= seqbuf
->size
;
40 static int seqbuf_read(struct seqbuf
*seqbuf
, void *buf
, size_t nbyte
)
42 nbyte
= min(nbyte
, seqbuf_avail(seqbuf
));
43 memcpy(buf
, seqbuf
->buf
+ seqbuf
->pos
, nbyte
);
45 return seqbuf_status(seqbuf
);
48 static int seqbuf_read_u32(struct seqbuf
*seqbuf
, uint32_t *v
)
52 err
= seqbuf_read(seqbuf
, v
, 4);
57 static int seqbuf_read_str(struct seqbuf
*seqbuf
, const char **str
)
59 *str
= seqbuf
->buf
+ seqbuf
->pos
;
60 seqbuf
->pos
+= strnlen(*str
, seqbuf_avail(seqbuf
));
62 return seqbuf_status(seqbuf
);
65 static void seqbuf_seek(struct seqbuf
*seqbuf
, ssize_t offset
)
67 seqbuf
->pos
+= offset
;
70 /* map filename in Linux debugfs to corresponding entry in BPMP */
71 static const char *get_filename(struct tegra_bpmp
*bpmp
,
72 const struct file
*file
, char *buf
, int size
)
74 char root_path_buf
[512];
75 const char *root_path
;
79 root_path
= dentry_path(bpmp
->debugfs_mirror
, root_path_buf
,
80 sizeof(root_path_buf
));
81 if (IS_ERR(root_path
))
84 root_len
= strlen(root_path
);
86 filename
= dentry_path(file
->f_path
.dentry
, buf
, size
);
90 if (strlen(filename
) < root_len
||
91 strncmp(filename
, root_path
, root_len
))
99 static int mrq_debugfs_read(struct tegra_bpmp
*bpmp
,
100 dma_addr_t name
, size_t sz_name
,
101 dma_addr_t data
, size_t sz_data
,
104 struct mrq_debugfs_request req
= {
105 .cmd
= cpu_to_le32(CMD_DEBUGFS_READ
),
107 .fnameaddr
= cpu_to_le32((uint32_t)name
),
108 .fnamelen
= cpu_to_le32((uint32_t)sz_name
),
109 .dataaddr
= cpu_to_le32((uint32_t)data
),
110 .datalen
= cpu_to_le32((uint32_t)sz_data
),
113 struct mrq_debugfs_response resp
;
114 struct tegra_bpmp_message msg
= {
122 .size
= sizeof(resp
),
127 err
= tegra_bpmp_transfer(bpmp
, &msg
);
131 *nbytes
= (size_t)resp
.fop
.nbytes
;
136 static int mrq_debugfs_write(struct tegra_bpmp
*bpmp
,
137 dma_addr_t name
, size_t sz_name
,
138 dma_addr_t data
, size_t sz_data
)
140 const struct mrq_debugfs_request req
= {
141 .cmd
= cpu_to_le32(CMD_DEBUGFS_WRITE
),
143 .fnameaddr
= cpu_to_le32((uint32_t)name
),
144 .fnamelen
= cpu_to_le32((uint32_t)sz_name
),
145 .dataaddr
= cpu_to_le32((uint32_t)data
),
146 .datalen
= cpu_to_le32((uint32_t)sz_data
),
149 struct tegra_bpmp_message msg
= {
157 return tegra_bpmp_transfer(bpmp
, &msg
);
160 static int mrq_debugfs_dumpdir(struct tegra_bpmp
*bpmp
, dma_addr_t addr
,
161 size_t size
, size_t *nbytes
)
163 const struct mrq_debugfs_request req
= {
164 .cmd
= cpu_to_le32(CMD_DEBUGFS_DUMPDIR
),
166 .dataaddr
= cpu_to_le32((uint32_t)addr
),
167 .datalen
= cpu_to_le32((uint32_t)size
),
170 struct mrq_debugfs_response resp
;
171 struct tegra_bpmp_message msg
= {
179 .size
= sizeof(resp
),
184 err
= tegra_bpmp_transfer(bpmp
, &msg
);
188 *nbytes
= (size_t)resp
.dumpdir
.nbytes
;
193 static int debugfs_show(struct seq_file
*m
, void *p
)
195 struct file
*file
= m
->private;
196 struct inode
*inode
= file_inode(file
);
197 struct tegra_bpmp
*bpmp
= inode
->i_private
;
198 const size_t datasize
= m
->size
;
199 const size_t namesize
= SZ_256
;
200 void *datavirt
, *namevirt
;
201 dma_addr_t dataphys
, namephys
;
203 const char *filename
;
207 filename
= get_filename(bpmp
, file
, buf
, sizeof(buf
));
211 namevirt
= dma_alloc_coherent(bpmp
->dev
, namesize
, &namephys
,
212 GFP_KERNEL
| GFP_DMA32
);
216 datavirt
= dma_alloc_coherent(bpmp
->dev
, datasize
, &dataphys
,
217 GFP_KERNEL
| GFP_DMA32
);
223 len
= strlen(filename
);
224 strncpy(namevirt
, filename
, namesize
);
226 ret
= mrq_debugfs_read(bpmp
, namephys
, len
, dataphys
, datasize
,
230 seq_write(m
, datavirt
, nbytes
);
232 dma_free_coherent(bpmp
->dev
, datasize
, datavirt
, dataphys
);
234 dma_free_coherent(bpmp
->dev
, namesize
, namevirt
, namephys
);
239 static int debugfs_open(struct inode
*inode
, struct file
*file
)
241 return single_open_size(file
, debugfs_show
, file
, SZ_128K
);
244 static ssize_t
debugfs_store(struct file
*file
, const char __user
*buf
,
245 size_t count
, loff_t
*f_pos
)
247 struct inode
*inode
= file_inode(file
);
248 struct tegra_bpmp
*bpmp
= inode
->i_private
;
249 const size_t datasize
= count
;
250 const size_t namesize
= SZ_256
;
251 void *datavirt
, *namevirt
;
252 dma_addr_t dataphys
, namephys
;
254 const char *filename
;
258 filename
= get_filename(bpmp
, file
, fnamebuf
, sizeof(fnamebuf
));
262 namevirt
= dma_alloc_coherent(bpmp
->dev
, namesize
, &namephys
,
263 GFP_KERNEL
| GFP_DMA32
);
267 datavirt
= dma_alloc_coherent(bpmp
->dev
, datasize
, &dataphys
,
268 GFP_KERNEL
| GFP_DMA32
);
274 len
= strlen(filename
);
275 strncpy(namevirt
, filename
, namesize
);
277 if (copy_from_user(datavirt
, buf
, count
)) {
282 ret
= mrq_debugfs_write(bpmp
, namephys
, len
, dataphys
,
286 dma_free_coherent(bpmp
->dev
, datasize
, datavirt
, dataphys
);
288 dma_free_coherent(bpmp
->dev
, namesize
, namevirt
, namephys
);
293 static const struct file_operations debugfs_fops
= {
294 .open
= debugfs_open
,
297 .write
= debugfs_store
,
298 .release
= single_release
,
301 static int bpmp_populate_dir(struct tegra_bpmp
*bpmp
, struct seqbuf
*seqbuf
,
302 struct dentry
*parent
, uint32_t depth
)
307 struct dentry
*dentry
;
309 while (!seqbuf_eof(seqbuf
)) {
310 err
= seqbuf_read_u32(seqbuf
, &d
);
315 seqbuf_seek(seqbuf
, -4);
318 } else if (d
!= depth
) {
319 /* malformed data received from BPMP */
323 err
= seqbuf_read_u32(seqbuf
, &t
);
326 err
= seqbuf_read_str(seqbuf
, &name
);
330 if (t
& DEBUGFS_S_ISDIR
) {
331 dentry
= debugfs_create_dir(name
, parent
);
334 err
= bpmp_populate_dir(bpmp
, seqbuf
, dentry
, depth
+1);
340 mode
= t
& DEBUGFS_S_IRUSR
? S_IRUSR
: 0;
341 mode
|= t
& DEBUGFS_S_IWUSR
? S_IWUSR
: 0;
342 dentry
= debugfs_create_file(name
, mode
,
353 static int create_debugfs_mirror(struct tegra_bpmp
*bpmp
, void *buf
,
354 size_t bufsize
, struct dentry
*root
)
356 struct seqbuf seqbuf
;
359 bpmp
->debugfs_mirror
= debugfs_create_dir("debug", root
);
360 if (!bpmp
->debugfs_mirror
)
363 seqbuf_init(&seqbuf
, buf
, bufsize
);
364 err
= bpmp_populate_dir(bpmp
, &seqbuf
, bpmp
->debugfs_mirror
, 0);
366 debugfs_remove_recursive(bpmp
->debugfs_mirror
);
367 bpmp
->debugfs_mirror
= NULL
;
373 int tegra_bpmp_init_debugfs(struct tegra_bpmp
*bpmp
)
377 const size_t sz
= SZ_256K
;
382 if (!tegra_bpmp_mrq_is_supported(bpmp
, MRQ_DEBUGFS
))
385 root
= debugfs_create_dir("bpmp", NULL
);
389 virt
= dma_alloc_coherent(bpmp
->dev
, sz
, &phys
,
390 GFP_KERNEL
| GFP_DMA32
);
396 ret
= mrq_debugfs_dumpdir(bpmp
, phys
, sz
, &nbytes
);
400 ret
= create_debugfs_mirror(bpmp
, virt
, nbytes
, root
);
402 dma_free_coherent(bpmp
->dev
, sz
, virt
, phys
);
405 debugfs_remove(root
);