2 * Copyright (c) 2017, NVIDIA CORPORATION. All rights reserved.
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms and conditions of the GNU General Public License,
6 * version 2, as published by the Free Software Foundation.
8 * This program is distributed in the hope it will be useful, but WITHOUT
9 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
14 #include <linux/debugfs.h>
15 #include <linux/dma-mapping.h>
16 #include <linux/uaccess.h>
18 #include <soc/tegra/bpmp.h>
19 #include <soc/tegra/bpmp-abi.h>
27 static void seqbuf_init(struct seqbuf
*seqbuf
, void *buf
, size_t size
)
34 static size_t seqbuf_avail(struct seqbuf
*seqbuf
)
36 return seqbuf
->pos
< seqbuf
->size
? seqbuf
->size
- seqbuf
->pos
: 0;
39 static size_t seqbuf_status(struct seqbuf
*seqbuf
)
41 return seqbuf
->pos
<= seqbuf
->size
? 0 : -EOVERFLOW
;
44 static int seqbuf_eof(struct seqbuf
*seqbuf
)
46 return seqbuf
->pos
>= seqbuf
->size
;
49 static int seqbuf_read(struct seqbuf
*seqbuf
, void *buf
, size_t nbyte
)
51 nbyte
= min(nbyte
, seqbuf_avail(seqbuf
));
52 memcpy(buf
, seqbuf
->buf
+ seqbuf
->pos
, nbyte
);
54 return seqbuf_status(seqbuf
);
57 static int seqbuf_read_u32(struct seqbuf
*seqbuf
, uint32_t *v
)
61 err
= seqbuf_read(seqbuf
, v
, 4);
66 static int seqbuf_read_str(struct seqbuf
*seqbuf
, const char **str
)
68 *str
= seqbuf
->buf
+ seqbuf
->pos
;
69 seqbuf
->pos
+= strnlen(*str
, seqbuf_avail(seqbuf
));
71 return seqbuf_status(seqbuf
);
74 static void seqbuf_seek(struct seqbuf
*seqbuf
, ssize_t offset
)
76 seqbuf
->pos
+= offset
;
79 /* map filename in Linux debugfs to corresponding entry in BPMP */
80 static const char *get_filename(struct tegra_bpmp
*bpmp
,
81 const struct file
*file
, char *buf
, int size
)
83 char root_path_buf
[512];
84 const char *root_path
;
88 root_path
= dentry_path(bpmp
->debugfs_mirror
, root_path_buf
,
89 sizeof(root_path_buf
));
90 if (IS_ERR(root_path
))
93 root_len
= strlen(root_path
);
95 filename
= dentry_path(file
->f_path
.dentry
, buf
, size
);
99 if (strlen(filename
) < root_len
||
100 strncmp(filename
, root_path
, root_len
))
103 filename
+= root_len
;
108 static int mrq_debugfs_read(struct tegra_bpmp
*bpmp
,
109 dma_addr_t name
, size_t sz_name
,
110 dma_addr_t data
, size_t sz_data
,
113 struct mrq_debugfs_request req
= {
114 .cmd
= cpu_to_le32(CMD_DEBUGFS_READ
),
116 .fnameaddr
= cpu_to_le32((uint32_t)name
),
117 .fnamelen
= cpu_to_le32((uint32_t)sz_name
),
118 .dataaddr
= cpu_to_le32((uint32_t)data
),
119 .datalen
= cpu_to_le32((uint32_t)sz_data
),
122 struct mrq_debugfs_response resp
;
123 struct tegra_bpmp_message msg
= {
131 .size
= sizeof(resp
),
136 err
= tegra_bpmp_transfer(bpmp
, &msg
);
140 *nbytes
= (size_t)resp
.fop
.nbytes
;
145 static int mrq_debugfs_write(struct tegra_bpmp
*bpmp
,
146 dma_addr_t name
, size_t sz_name
,
147 dma_addr_t data
, size_t sz_data
)
149 const struct mrq_debugfs_request req
= {
150 .cmd
= cpu_to_le32(CMD_DEBUGFS_WRITE
),
152 .fnameaddr
= cpu_to_le32((uint32_t)name
),
153 .fnamelen
= cpu_to_le32((uint32_t)sz_name
),
154 .dataaddr
= cpu_to_le32((uint32_t)data
),
155 .datalen
= cpu_to_le32((uint32_t)sz_data
),
158 struct tegra_bpmp_message msg
= {
166 return tegra_bpmp_transfer(bpmp
, &msg
);
169 static int mrq_debugfs_dumpdir(struct tegra_bpmp
*bpmp
, dma_addr_t addr
,
170 size_t size
, size_t *nbytes
)
172 const struct mrq_debugfs_request req
= {
173 .cmd
= cpu_to_le32(CMD_DEBUGFS_DUMPDIR
),
175 .dataaddr
= cpu_to_le32((uint32_t)addr
),
176 .datalen
= cpu_to_le32((uint32_t)size
),
179 struct mrq_debugfs_response resp
;
180 struct tegra_bpmp_message msg
= {
188 .size
= sizeof(resp
),
193 err
= tegra_bpmp_transfer(bpmp
, &msg
);
197 *nbytes
= (size_t)resp
.dumpdir
.nbytes
;
202 static int debugfs_show(struct seq_file
*m
, void *p
)
204 struct file
*file
= m
->private;
205 struct inode
*inode
= file_inode(file
);
206 struct tegra_bpmp
*bpmp
= inode
->i_private
;
207 const size_t datasize
= m
->size
;
208 const size_t namesize
= SZ_256
;
209 void *datavirt
, *namevirt
;
210 dma_addr_t dataphys
, namephys
;
212 const char *filename
;
216 filename
= get_filename(bpmp
, file
, buf
, sizeof(buf
));
220 namevirt
= dma_alloc_coherent(bpmp
->dev
, namesize
, &namephys
,
221 GFP_KERNEL
| GFP_DMA32
);
225 datavirt
= dma_alloc_coherent(bpmp
->dev
, datasize
, &dataphys
,
226 GFP_KERNEL
| GFP_DMA32
);
232 len
= strlen(filename
);
233 strncpy(namevirt
, filename
, namesize
);
235 ret
= mrq_debugfs_read(bpmp
, namephys
, len
, dataphys
, datasize
,
239 seq_write(m
, datavirt
, nbytes
);
241 dma_free_coherent(bpmp
->dev
, datasize
, datavirt
, dataphys
);
243 dma_free_coherent(bpmp
->dev
, namesize
, namevirt
, namephys
);
248 static int debugfs_open(struct inode
*inode
, struct file
*file
)
250 return single_open_size(file
, debugfs_show
, file
, SZ_128K
);
253 static ssize_t
debugfs_store(struct file
*file
, const char __user
*buf
,
254 size_t count
, loff_t
*f_pos
)
256 struct inode
*inode
= file_inode(file
);
257 struct tegra_bpmp
*bpmp
= inode
->i_private
;
258 const size_t datasize
= count
;
259 const size_t namesize
= SZ_256
;
260 void *datavirt
, *namevirt
;
261 dma_addr_t dataphys
, namephys
;
263 const char *filename
;
267 filename
= get_filename(bpmp
, file
, fnamebuf
, sizeof(fnamebuf
));
271 namevirt
= dma_alloc_coherent(bpmp
->dev
, namesize
, &namephys
,
272 GFP_KERNEL
| GFP_DMA32
);
276 datavirt
= dma_alloc_coherent(bpmp
->dev
, datasize
, &dataphys
,
277 GFP_KERNEL
| GFP_DMA32
);
283 len
= strlen(filename
);
284 strncpy(namevirt
, filename
, namesize
);
286 if (copy_from_user(datavirt
, buf
, count
)) {
291 ret
= mrq_debugfs_write(bpmp
, namephys
, len
, dataphys
,
295 dma_free_coherent(bpmp
->dev
, datasize
, datavirt
, dataphys
);
297 dma_free_coherent(bpmp
->dev
, namesize
, namevirt
, namephys
);
302 static const struct file_operations debugfs_fops
= {
303 .open
= debugfs_open
,
306 .write
= debugfs_store
,
307 .release
= single_release
,
310 static int bpmp_populate_dir(struct tegra_bpmp
*bpmp
, struct seqbuf
*seqbuf
,
311 struct dentry
*parent
, uint32_t depth
)
316 struct dentry
*dentry
;
318 while (!seqbuf_eof(seqbuf
)) {
319 err
= seqbuf_read_u32(seqbuf
, &d
);
324 seqbuf_seek(seqbuf
, -4);
327 } else if (d
!= depth
) {
328 /* malformed data received from BPMP */
332 err
= seqbuf_read_u32(seqbuf
, &t
);
335 err
= seqbuf_read_str(seqbuf
, &name
);
339 if (t
& DEBUGFS_S_ISDIR
) {
340 dentry
= debugfs_create_dir(name
, parent
);
343 err
= bpmp_populate_dir(bpmp
, seqbuf
, dentry
, depth
+1);
349 mode
= t
& DEBUGFS_S_IRUSR
? S_IRUSR
: 0;
350 mode
|= t
& DEBUGFS_S_IWUSR
? S_IWUSR
: 0;
351 dentry
= debugfs_create_file(name
, mode
,
362 static int create_debugfs_mirror(struct tegra_bpmp
*bpmp
, void *buf
,
363 size_t bufsize
, struct dentry
*root
)
365 struct seqbuf seqbuf
;
368 bpmp
->debugfs_mirror
= debugfs_create_dir("debug", root
);
369 if (!bpmp
->debugfs_mirror
)
372 seqbuf_init(&seqbuf
, buf
, bufsize
);
373 err
= bpmp_populate_dir(bpmp
, &seqbuf
, bpmp
->debugfs_mirror
, 0);
375 debugfs_remove_recursive(bpmp
->debugfs_mirror
);
376 bpmp
->debugfs_mirror
= NULL
;
382 static int mrq_is_supported(struct tegra_bpmp
*bpmp
, unsigned int mrq
)
384 struct mrq_query_abi_request req
= { .mrq
= cpu_to_le32(mrq
) };
385 struct mrq_query_abi_response resp
;
386 struct tegra_bpmp_message msg
= {
387 .mrq
= MRQ_QUERY_ABI
,
394 .size
= sizeof(resp
),
399 ret
= tegra_bpmp_transfer(bpmp
, &msg
);
401 /* something went wrong; assume not supported */
402 dev_warn(bpmp
->dev
, "tegra_bpmp_transfer failed (%d)\n", ret
);
406 return resp
.status
? 0 : 1;
409 int tegra_bpmp_init_debugfs(struct tegra_bpmp
*bpmp
)
413 const size_t sz
= SZ_256K
;
418 if (!mrq_is_supported(bpmp
, MRQ_DEBUGFS
))
421 root
= debugfs_create_dir("bpmp", NULL
);
425 virt
= dma_alloc_coherent(bpmp
->dev
, sz
, &phys
,
426 GFP_KERNEL
| GFP_DMA32
);
432 ret
= mrq_debugfs_dumpdir(bpmp
, phys
, sz
, &nbytes
);
436 ret
= create_debugfs_mirror(bpmp
, virt
, nbytes
, root
);
438 dma_free_coherent(bpmp
->dev
, sz
, virt
, phys
);
441 debugfs_remove(root
);