Merge tag 'soc-5.15' of git://git.kernel.org/pub/scm/linux/kernel/git/soc/soc
[linux-2.6-microblaze.git] / drivers / firmware / tegra / bpmp-debugfs.c
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
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
28 static size_t seqbuf_avail(struct seqbuf *seqbuf)
29 {
30         return seqbuf->pos < seqbuf->size ? seqbuf->size - seqbuf->pos : 0;
31 }
32
33 static size_t seqbuf_status(struct seqbuf *seqbuf)
34 {
35         return seqbuf->pos <= seqbuf->size ? 0 : -EOVERFLOW;
36 }
37
38 static int seqbuf_eof(struct seqbuf *seqbuf)
39 {
40         return seqbuf->pos >= seqbuf->size;
41 }
42
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
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
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
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 */
74 static const char *get_filename(struct tegra_bpmp *bpmp,
75                                 const struct file *file, char *buf, int size)
76 {
77         char root_path_buf[512];
78         const char *root_path;
79         const char *filename;
80         size_t root_len;
81
82         root_path = dentry_path(bpmp->debugfs_mirror, root_path_buf,
83                                 sizeof(root_path_buf));
84         if (IS_ERR(root_path))
85                 return NULL;
86
87         root_len = strlen(root_path);
88
89         filename = dentry_path(file->f_path.dentry, buf, size);
90         if (IS_ERR(filename))
91                 return NULL;
92
93         if (strlen(filename) < root_len ||
94                         strncmp(filename, root_path, root_len))
95                 return NULL;
96
97         filename += root_len;
98
99         return filename;
100 }
101
102 static int mrq_debug_open(struct tegra_bpmp *bpmp, const char *name,
103                           uint32_t *fd, uint32_t *len, bool write)
104 {
105         struct mrq_debug_request req = {
106                 .cmd = cpu_to_le32(write ? CMD_DEBUG_OPEN_WO : CMD_DEBUG_OPEN_RO),
107         };
108         struct mrq_debug_response resp;
109         struct tegra_bpmp_message msg = {
110                 .mrq = MRQ_DEBUG,
111                 .tx = {
112                         .data = &req,
113                         .size = sizeof(req),
114                 },
115                 .rx = {
116                         .data = &resp,
117                         .size = sizeof(resp),
118                 },
119         };
120         ssize_t sz_name;
121         int err = 0;
122
123         sz_name = strscpy(req.fop.name, name, sizeof(req.fop.name));
124         if (sz_name < 0) {
125                 pr_err("File name too large: %s\n", name);
126                 return -EINVAL;
127         }
128
129         err = tegra_bpmp_transfer(bpmp, &msg);
130         if (err < 0)
131                 return err;
132         else if (msg.rx.ret < 0)
133                 return -EINVAL;
134
135         *len = resp.fop.datalen;
136         *fd = resp.fop.fd;
137
138         return 0;
139 }
140
141 static int mrq_debug_close(struct tegra_bpmp *bpmp, uint32_t fd)
142 {
143         struct mrq_debug_request req = {
144                 .cmd = cpu_to_le32(CMD_DEBUG_CLOSE),
145                 .frd = {
146                         .fd = fd,
147                 },
148         };
149         struct mrq_debug_response resp;
150         struct tegra_bpmp_message msg = {
151                 .mrq = MRQ_DEBUG,
152                 .tx = {
153                         .data = &req,
154                         .size = sizeof(req),
155                 },
156                 .rx = {
157                         .data = &resp,
158                         .size = sizeof(resp),
159                 },
160         };
161         int err = 0;
162
163         err = tegra_bpmp_transfer(bpmp, &msg);
164         if (err < 0)
165                 return err;
166         else if (msg.rx.ret < 0)
167                 return -EINVAL;
168
169         return 0;
170 }
171
172 static int mrq_debug_read(struct tegra_bpmp *bpmp, const char *name,
173                           char *data, size_t sz_data, uint32_t *nbytes)
174 {
175         struct mrq_debug_request req = {
176                 .cmd = cpu_to_le32(CMD_DEBUG_READ),
177         };
178         struct mrq_debug_response resp;
179         struct tegra_bpmp_message msg = {
180                 .mrq = MRQ_DEBUG,
181                 .tx = {
182                         .data = &req,
183                         .size = sizeof(req),
184                 },
185                 .rx = {
186                         .data = &resp,
187                         .size = sizeof(resp),
188                 },
189         };
190         uint32_t fd = 0, len = 0;
191         int remaining, err;
192
193         mutex_lock(&bpmp_debug_lock);
194         err = mrq_debug_open(bpmp, name, &fd, &len, 0);
195         if (err)
196                 goto out;
197
198         if (len > sz_data) {
199                 err = -EFBIG;
200                 goto close;
201         }
202
203         req.frd.fd = fd;
204         remaining = len;
205
206         while (remaining > 0) {
207                 err = tegra_bpmp_transfer(bpmp, &msg);
208                 if (err < 0) {
209                         goto close;
210                 } else if (msg.rx.ret < 0) {
211                         err = -EINVAL;
212                         goto close;
213                 }
214
215                 if (resp.frd.readlen > remaining) {
216                         pr_err("%s: read data length invalid\n", __func__);
217                         err = -EINVAL;
218                         goto close;
219                 }
220
221                 memcpy(data, resp.frd.data, resp.frd.readlen);
222                 data += resp.frd.readlen;
223                 remaining -= resp.frd.readlen;
224         }
225
226         *nbytes = len;
227
228 close:
229         err = mrq_debug_close(bpmp, fd);
230 out:
231         mutex_unlock(&bpmp_debug_lock);
232         return err;
233 }
234
235 static int mrq_debug_write(struct tegra_bpmp *bpmp, const char *name,
236                            uint8_t *data, size_t sz_data)
237 {
238         struct mrq_debug_request req = {
239                 .cmd = cpu_to_le32(CMD_DEBUG_WRITE)
240         };
241         struct mrq_debug_response resp;
242         struct tegra_bpmp_message msg = {
243                 .mrq = MRQ_DEBUG,
244                 .tx = {
245                         .data = &req,
246                         .size = sizeof(req),
247                 },
248                 .rx = {
249                         .data = &resp,
250                         .size = sizeof(resp),
251                 },
252         };
253         uint32_t fd = 0, len = 0;
254         size_t remaining;
255         int err;
256
257         mutex_lock(&bpmp_debug_lock);
258         err = mrq_debug_open(bpmp, name, &fd, &len, 1);
259         if (err)
260                 goto out;
261
262         if (sz_data > len) {
263                 err = -EINVAL;
264                 goto close;
265         }
266
267         req.fwr.fd = fd;
268         remaining = sz_data;
269
270         while (remaining > 0) {
271                 len = min(remaining, sizeof(req.fwr.data));
272                 memcpy(req.fwr.data, data, len);
273                 req.fwr.datalen = len;
274
275                 err = tegra_bpmp_transfer(bpmp, &msg);
276                 if (err < 0) {
277                         goto close;
278                 } else if (msg.rx.ret < 0) {
279                         err = -EINVAL;
280                         goto close;
281                 }
282
283                 data += req.fwr.datalen;
284                 remaining -= req.fwr.datalen;
285         }
286
287 close:
288         err = mrq_debug_close(bpmp, fd);
289 out:
290         mutex_unlock(&bpmp_debug_lock);
291         return err;
292 }
293
294 static int bpmp_debug_show(struct seq_file *m, void *p)
295 {
296         struct file *file = m->private;
297         struct inode *inode = file_inode(file);
298         struct tegra_bpmp *bpmp = inode->i_private;
299         char *databuf = NULL;
300         char fnamebuf[256];
301         const char *filename;
302         uint32_t nbytes = 0;
303         size_t len;
304         int err;
305
306         len = seq_get_buf(m, &databuf);
307         if (!databuf)
308                 return -ENOMEM;
309
310         filename = get_filename(bpmp, file, fnamebuf, sizeof(fnamebuf));
311         if (!filename)
312                 return -ENOENT;
313
314         err = mrq_debug_read(bpmp, filename, databuf, len, &nbytes);
315         if (!err)
316                 seq_commit(m, nbytes);
317
318         return err;
319 }
320
321 static ssize_t bpmp_debug_store(struct file *file, const char __user *buf,
322                 size_t count, loff_t *f_pos)
323 {
324         struct inode *inode = file_inode(file);
325         struct tegra_bpmp *bpmp = inode->i_private;
326         char *databuf = NULL;
327         char fnamebuf[256];
328         const char *filename;
329         ssize_t err;
330
331         filename = get_filename(bpmp, file, fnamebuf, sizeof(fnamebuf));
332         if (!filename)
333                 return -ENOENT;
334
335         databuf = kmalloc(count, GFP_KERNEL);
336         if (!databuf)
337                 return -ENOMEM;
338
339         if (copy_from_user(databuf, buf, count)) {
340                 err = -EFAULT;
341                 goto free_ret;
342         }
343
344         err = mrq_debug_write(bpmp, filename, databuf, count);
345
346 free_ret:
347         kfree(databuf);
348
349         return err ?: count;
350 }
351
352 static int bpmp_debug_open(struct inode *inode, struct file *file)
353 {
354         return single_open_size(file, bpmp_debug_show, file, SZ_256K);
355 }
356
357 static const struct file_operations bpmp_debug_fops = {
358         .open           = bpmp_debug_open,
359         .read           = seq_read,
360         .llseek         = seq_lseek,
361         .write          = bpmp_debug_store,
362         .release        = single_release,
363 };
364
365 static int bpmp_populate_debugfs_inband(struct tegra_bpmp *bpmp,
366                                         struct dentry *parent,
367                                         char *ppath)
368 {
369         const size_t pathlen = SZ_256;
370         const size_t bufsize = SZ_16K;
371         uint32_t dsize, attrs = 0;
372         struct dentry *dentry;
373         struct seqbuf seqbuf;
374         char *buf, *pathbuf;
375         const char *name;
376         int err = 0;
377
378         if (!bpmp || !parent || !ppath)
379                 return -EINVAL;
380
381         buf = kmalloc(bufsize, GFP_KERNEL);
382         if (!buf)
383                 return -ENOMEM;
384
385         pathbuf = kzalloc(pathlen, GFP_KERNEL);
386         if (!pathbuf) {
387                 kfree(buf);
388                 return -ENOMEM;
389         }
390
391         err = mrq_debug_read(bpmp, ppath, buf, bufsize, &dsize);
392         if (err)
393                 goto out;
394
395         seqbuf_init(&seqbuf, buf, dsize);
396
397         while (!seqbuf_eof(&seqbuf)) {
398                 err = seqbuf_read_u32(&seqbuf, &attrs);
399                 if (err)
400                         goto out;
401
402                 err = seqbuf_read_str(&seqbuf, &name);
403                 if (err < 0)
404                         goto out;
405
406                 if (attrs & DEBUGFS_S_ISDIR) {
407                         size_t len;
408
409                         dentry = debugfs_create_dir(name, parent);
410                         if (IS_ERR(dentry)) {
411                                 err = PTR_ERR(dentry);
412                                 goto out;
413                         }
414
415                         len = snprintf(pathbuf, pathlen, "%s%s/", ppath, name);
416                         if (len >= pathlen) {
417                                 err = -EINVAL;
418                                 goto out;
419                         }
420
421                         err = bpmp_populate_debugfs_inband(bpmp, dentry,
422                                                            pathbuf);
423                         if (err < 0)
424                                 goto out;
425                 } else {
426                         umode_t mode;
427
428                         mode = attrs & DEBUGFS_S_IRUSR ? 0400 : 0;
429                         mode |= attrs & DEBUGFS_S_IWUSR ? 0200 : 0;
430                         dentry = debugfs_create_file(name, mode, parent, bpmp,
431                                                      &bpmp_debug_fops);
432                         if (!dentry) {
433                                 err = -ENOMEM;
434                                 goto out;
435                         }
436                 }
437         }
438
439 out:
440         kfree(pathbuf);
441         kfree(buf);
442
443         return err;
444 }
445
446 static int mrq_debugfs_read(struct tegra_bpmp *bpmp,
447                             dma_addr_t name, size_t sz_name,
448                             dma_addr_t data, size_t sz_data,
449                             size_t *nbytes)
450 {
451         struct mrq_debugfs_request req = {
452                 .cmd = cpu_to_le32(CMD_DEBUGFS_READ),
453                 .fop = {
454                         .fnameaddr = cpu_to_le32((uint32_t)name),
455                         .fnamelen = cpu_to_le32((uint32_t)sz_name),
456                         .dataaddr = cpu_to_le32((uint32_t)data),
457                         .datalen = cpu_to_le32((uint32_t)sz_data),
458                 },
459         };
460         struct mrq_debugfs_response resp;
461         struct tegra_bpmp_message msg = {
462                 .mrq = MRQ_DEBUGFS,
463                 .tx = {
464                         .data = &req,
465                         .size = sizeof(req),
466                 },
467                 .rx = {
468                         .data = &resp,
469                         .size = sizeof(resp),
470                 },
471         };
472         int err;
473
474         err = tegra_bpmp_transfer(bpmp, &msg);
475         if (err < 0)
476                 return err;
477         else if (msg.rx.ret < 0)
478                 return -EINVAL;
479
480         *nbytes = (size_t)resp.fop.nbytes;
481
482         return 0;
483 }
484
485 static int mrq_debugfs_write(struct tegra_bpmp *bpmp,
486                              dma_addr_t name, size_t sz_name,
487                              dma_addr_t data, size_t sz_data)
488 {
489         const struct mrq_debugfs_request req = {
490                 .cmd = cpu_to_le32(CMD_DEBUGFS_WRITE),
491                 .fop = {
492                         .fnameaddr = cpu_to_le32((uint32_t)name),
493                         .fnamelen = cpu_to_le32((uint32_t)sz_name),
494                         .dataaddr = cpu_to_le32((uint32_t)data),
495                         .datalen = cpu_to_le32((uint32_t)sz_data),
496                 },
497         };
498         struct tegra_bpmp_message msg = {
499                 .mrq = MRQ_DEBUGFS,
500                 .tx = {
501                         .data = &req,
502                         .size = sizeof(req),
503                 },
504         };
505
506         return tegra_bpmp_transfer(bpmp, &msg);
507 }
508
509 static int mrq_debugfs_dumpdir(struct tegra_bpmp *bpmp, dma_addr_t addr,
510                                size_t size, size_t *nbytes)
511 {
512         const struct mrq_debugfs_request req = {
513                 .cmd = cpu_to_le32(CMD_DEBUGFS_DUMPDIR),
514                 .dumpdir = {
515                         .dataaddr = cpu_to_le32((uint32_t)addr),
516                         .datalen = cpu_to_le32((uint32_t)size),
517                 },
518         };
519         struct mrq_debugfs_response resp;
520         struct tegra_bpmp_message msg = {
521                 .mrq = MRQ_DEBUGFS,
522                 .tx = {
523                         .data = &req,
524                         .size = sizeof(req),
525                 },
526                 .rx = {
527                         .data = &resp,
528                         .size = sizeof(resp),
529                 },
530         };
531         int err;
532
533         err = tegra_bpmp_transfer(bpmp, &msg);
534         if (err < 0)
535                 return err;
536         else if (msg.rx.ret < 0)
537                 return -EINVAL;
538
539         *nbytes = (size_t)resp.dumpdir.nbytes;
540
541         return 0;
542 }
543
544 static int debugfs_show(struct seq_file *m, void *p)
545 {
546         struct file *file = m->private;
547         struct inode *inode = file_inode(file);
548         struct tegra_bpmp *bpmp = inode->i_private;
549         const size_t datasize = m->size;
550         const size_t namesize = SZ_256;
551         void *datavirt, *namevirt;
552         dma_addr_t dataphys, namephys;
553         char buf[256];
554         const char *filename;
555         size_t len, nbytes;
556         int err;
557
558         filename = get_filename(bpmp, file, buf, sizeof(buf));
559         if (!filename)
560                 return -ENOENT;
561
562         namevirt = dma_alloc_coherent(bpmp->dev, namesize, &namephys,
563                                       GFP_KERNEL | GFP_DMA32);
564         if (!namevirt)
565                 return -ENOMEM;
566
567         datavirt = dma_alloc_coherent(bpmp->dev, datasize, &dataphys,
568                                       GFP_KERNEL | GFP_DMA32);
569         if (!datavirt) {
570                 err = -ENOMEM;
571                 goto free_namebuf;
572         }
573
574         len = strlen(filename);
575         strncpy(namevirt, filename, namesize);
576
577         err = mrq_debugfs_read(bpmp, namephys, len, dataphys, datasize,
578                                &nbytes);
579
580         if (!err)
581                 seq_write(m, datavirt, nbytes);
582
583         dma_free_coherent(bpmp->dev, datasize, datavirt, dataphys);
584 free_namebuf:
585         dma_free_coherent(bpmp->dev, namesize, namevirt, namephys);
586
587         return err;
588 }
589
590 static int debugfs_open(struct inode *inode, struct file *file)
591 {
592         return single_open_size(file, debugfs_show, file, SZ_128K);
593 }
594
595 static ssize_t debugfs_store(struct file *file, const char __user *buf,
596                 size_t count, loff_t *f_pos)
597 {
598         struct inode *inode = file_inode(file);
599         struct tegra_bpmp *bpmp = inode->i_private;
600         const size_t datasize = count;
601         const size_t namesize = SZ_256;
602         void *datavirt, *namevirt;
603         dma_addr_t dataphys, namephys;
604         char fnamebuf[256];
605         const char *filename;
606         size_t len;
607         int err;
608
609         filename = get_filename(bpmp, file, fnamebuf, sizeof(fnamebuf));
610         if (!filename)
611                 return -ENOENT;
612
613         namevirt = dma_alloc_coherent(bpmp->dev, namesize, &namephys,
614                                       GFP_KERNEL | GFP_DMA32);
615         if (!namevirt)
616                 return -ENOMEM;
617
618         datavirt = dma_alloc_coherent(bpmp->dev, datasize, &dataphys,
619                                       GFP_KERNEL | GFP_DMA32);
620         if (!datavirt) {
621                 err = -ENOMEM;
622                 goto free_namebuf;
623         }
624
625         len = strlen(filename);
626         strncpy(namevirt, filename, namesize);
627
628         if (copy_from_user(datavirt, buf, count)) {
629                 err = -EFAULT;
630                 goto free_databuf;
631         }
632
633         err = mrq_debugfs_write(bpmp, namephys, len, dataphys,
634                                 count);
635
636 free_databuf:
637         dma_free_coherent(bpmp->dev, datasize, datavirt, dataphys);
638 free_namebuf:
639         dma_free_coherent(bpmp->dev, namesize, namevirt, namephys);
640
641         return err ?: count;
642 }
643
644 static const struct file_operations debugfs_fops = {
645         .open           = debugfs_open,
646         .read           = seq_read,
647         .llseek         = seq_lseek,
648         .write          = debugfs_store,
649         .release        = single_release,
650 };
651
652 static int bpmp_populate_dir(struct tegra_bpmp *bpmp, struct seqbuf *seqbuf,
653                              struct dentry *parent, uint32_t depth)
654 {
655         int err;
656         uint32_t d, t;
657         const char *name;
658         struct dentry *dentry;
659
660         while (!seqbuf_eof(seqbuf)) {
661                 err = seqbuf_read_u32(seqbuf, &d);
662                 if (err < 0)
663                         return err;
664
665                 if (d < depth) {
666                         seqbuf_seek(seqbuf, -4);
667                         /* go up a level */
668                         return 0;
669                 } else if (d != depth) {
670                         /* malformed data received from BPMP */
671                         return -EIO;
672                 }
673
674                 err = seqbuf_read_u32(seqbuf, &t);
675                 if (err < 0)
676                         return err;
677                 err = seqbuf_read_str(seqbuf, &name);
678                 if (err < 0)
679                         return err;
680
681                 if (t & DEBUGFS_S_ISDIR) {
682                         dentry = debugfs_create_dir(name, parent);
683                         if (!dentry)
684                                 return -ENOMEM;
685                         err = bpmp_populate_dir(bpmp, seqbuf, dentry, depth+1);
686                         if (err < 0)
687                                 return err;
688                 } else {
689                         umode_t mode;
690
691                         mode = t & DEBUGFS_S_IRUSR ? S_IRUSR : 0;
692                         mode |= t & DEBUGFS_S_IWUSR ? S_IWUSR : 0;
693                         dentry = debugfs_create_file(name, mode,
694                                                      parent, bpmp,
695                                                      &debugfs_fops);
696                         if (!dentry)
697                                 return -ENOMEM;
698                 }
699         }
700
701         return 0;
702 }
703
704 static int bpmp_populate_debugfs_shmem(struct tegra_bpmp *bpmp)
705 {
706         struct seqbuf seqbuf;
707         const size_t sz = SZ_512K;
708         dma_addr_t phys;
709         size_t nbytes;
710         void *virt;
711         int err;
712
713         virt = dma_alloc_coherent(bpmp->dev, sz, &phys,
714                                   GFP_KERNEL | GFP_DMA32);
715         if (!virt)
716                 return -ENOMEM;
717
718         err = mrq_debugfs_dumpdir(bpmp, phys, sz, &nbytes);
719         if (err < 0) {
720                 goto free;
721         } else if (nbytes > sz) {
722                 err = -EINVAL;
723                 goto free;
724         }
725
726         seqbuf_init(&seqbuf, virt, nbytes);
727         err = bpmp_populate_dir(bpmp, &seqbuf, bpmp->debugfs_mirror, 0);
728 free:
729         dma_free_coherent(bpmp->dev, sz, virt, phys);
730
731         return err;
732 }
733
734 int tegra_bpmp_init_debugfs(struct tegra_bpmp *bpmp)
735 {
736         struct dentry *root;
737         bool inband;
738         int err;
739
740         inband = tegra_bpmp_mrq_is_supported(bpmp, MRQ_DEBUG);
741
742         if (!inband && !tegra_bpmp_mrq_is_supported(bpmp, MRQ_DEBUGFS))
743                 return 0;
744
745         root = debugfs_create_dir("bpmp", NULL);
746         if (!root)
747                 return -ENOMEM;
748
749         bpmp->debugfs_mirror = debugfs_create_dir("debug", root);
750         if (!bpmp->debugfs_mirror) {
751                 err = -ENOMEM;
752                 goto out;
753         }
754
755         if (inband)
756                 err = bpmp_populate_debugfs_inband(bpmp, bpmp->debugfs_mirror,
757                                                    "/");
758         else
759                 err = bpmp_populate_debugfs_shmem(bpmp);
760
761 out:
762         if (err < 0)
763                 debugfs_remove_recursive(root);
764
765         return err;
766 }