]> Git Repo - linux.git/blob - drivers/firmware/tegra/bpmp-debugfs.c
drm/nouveau/kms: Don't change EDID when it hasn't actually changed
[linux.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 = strlen(ppath) + strlen(name) + 1;
416                         if (len >= pathlen) {
417                                 err = -EINVAL;
418                                 goto out;
419                         }
420
421                         strncpy(pathbuf, ppath, pathlen);
422                         strncat(pathbuf, name, strlen(name));
423                         strcat(pathbuf, "/");
424
425                         err = bpmp_populate_debugfs_inband(bpmp, dentry,
426                                                            pathbuf);
427                         if (err < 0)
428                                 goto out;
429                 } else {
430                         umode_t mode;
431
432                         mode = attrs & DEBUGFS_S_IRUSR ? 0400 : 0;
433                         mode |= attrs & DEBUGFS_S_IWUSR ? 0200 : 0;
434                         dentry = debugfs_create_file(name, mode, parent, bpmp,
435                                                      &bpmp_debug_fops);
436                         if (!dentry) {
437                                 err = -ENOMEM;
438                                 goto out;
439                         }
440                 }
441         }
442
443 out:
444         kfree(pathbuf);
445         kfree(buf);
446
447         return err;
448 }
449
450 static int mrq_debugfs_read(struct tegra_bpmp *bpmp,
451                             dma_addr_t name, size_t sz_name,
452                             dma_addr_t data, size_t sz_data,
453                             size_t *nbytes)
454 {
455         struct mrq_debugfs_request req = {
456                 .cmd = cpu_to_le32(CMD_DEBUGFS_READ),
457                 .fop = {
458                         .fnameaddr = cpu_to_le32((uint32_t)name),
459                         .fnamelen = cpu_to_le32((uint32_t)sz_name),
460                         .dataaddr = cpu_to_le32((uint32_t)data),
461                         .datalen = cpu_to_le32((uint32_t)sz_data),
462                 },
463         };
464         struct mrq_debugfs_response resp;
465         struct tegra_bpmp_message msg = {
466                 .mrq = MRQ_DEBUGFS,
467                 .tx = {
468                         .data = &req,
469                         .size = sizeof(req),
470                 },
471                 .rx = {
472                         .data = &resp,
473                         .size = sizeof(resp),
474                 },
475         };
476         int err;
477
478         err = tegra_bpmp_transfer(bpmp, &msg);
479         if (err < 0)
480                 return err;
481         else if (msg.rx.ret < 0)
482                 return -EINVAL;
483
484         *nbytes = (size_t)resp.fop.nbytes;
485
486         return 0;
487 }
488
489 static int mrq_debugfs_write(struct tegra_bpmp *bpmp,
490                              dma_addr_t name, size_t sz_name,
491                              dma_addr_t data, size_t sz_data)
492 {
493         const struct mrq_debugfs_request req = {
494                 .cmd = cpu_to_le32(CMD_DEBUGFS_WRITE),
495                 .fop = {
496                         .fnameaddr = cpu_to_le32((uint32_t)name),
497                         .fnamelen = cpu_to_le32((uint32_t)sz_name),
498                         .dataaddr = cpu_to_le32((uint32_t)data),
499                         .datalen = cpu_to_le32((uint32_t)sz_data),
500                 },
501         };
502         struct tegra_bpmp_message msg = {
503                 .mrq = MRQ_DEBUGFS,
504                 .tx = {
505                         .data = &req,
506                         .size = sizeof(req),
507                 },
508         };
509
510         return tegra_bpmp_transfer(bpmp, &msg);
511 }
512
513 static int mrq_debugfs_dumpdir(struct tegra_bpmp *bpmp, dma_addr_t addr,
514                                size_t size, size_t *nbytes)
515 {
516         const struct mrq_debugfs_request req = {
517                 .cmd = cpu_to_le32(CMD_DEBUGFS_DUMPDIR),
518                 .dumpdir = {
519                         .dataaddr = cpu_to_le32((uint32_t)addr),
520                         .datalen = cpu_to_le32((uint32_t)size),
521                 },
522         };
523         struct mrq_debugfs_response resp;
524         struct tegra_bpmp_message msg = {
525                 .mrq = MRQ_DEBUGFS,
526                 .tx = {
527                         .data = &req,
528                         .size = sizeof(req),
529                 },
530                 .rx = {
531                         .data = &resp,
532                         .size = sizeof(resp),
533                 },
534         };
535         int err;
536
537         err = tegra_bpmp_transfer(bpmp, &msg);
538         if (err < 0)
539                 return err;
540         else if (msg.rx.ret < 0)
541                 return -EINVAL;
542
543         *nbytes = (size_t)resp.dumpdir.nbytes;
544
545         return 0;
546 }
547
548 static int debugfs_show(struct seq_file *m, void *p)
549 {
550         struct file *file = m->private;
551         struct inode *inode = file_inode(file);
552         struct tegra_bpmp *bpmp = inode->i_private;
553         const size_t datasize = m->size;
554         const size_t namesize = SZ_256;
555         void *datavirt, *namevirt;
556         dma_addr_t dataphys, namephys;
557         char buf[256];
558         const char *filename;
559         size_t len, nbytes;
560         int err;
561
562         filename = get_filename(bpmp, file, buf, sizeof(buf));
563         if (!filename)
564                 return -ENOENT;
565
566         namevirt = dma_alloc_coherent(bpmp->dev, namesize, &namephys,
567                                       GFP_KERNEL | GFP_DMA32);
568         if (!namevirt)
569                 return -ENOMEM;
570
571         datavirt = dma_alloc_coherent(bpmp->dev, datasize, &dataphys,
572                                       GFP_KERNEL | GFP_DMA32);
573         if (!datavirt) {
574                 err = -ENOMEM;
575                 goto free_namebuf;
576         }
577
578         len = strlen(filename);
579         strncpy(namevirt, filename, namesize);
580
581         err = mrq_debugfs_read(bpmp, namephys, len, dataphys, datasize,
582                                &nbytes);
583
584         if (!err)
585                 seq_write(m, datavirt, nbytes);
586
587         dma_free_coherent(bpmp->dev, datasize, datavirt, dataphys);
588 free_namebuf:
589         dma_free_coherent(bpmp->dev, namesize, namevirt, namephys);
590
591         return err;
592 }
593
594 static int debugfs_open(struct inode *inode, struct file *file)
595 {
596         return single_open_size(file, debugfs_show, file, SZ_128K);
597 }
598
599 static ssize_t debugfs_store(struct file *file, const char __user *buf,
600                 size_t count, loff_t *f_pos)
601 {
602         struct inode *inode = file_inode(file);
603         struct tegra_bpmp *bpmp = inode->i_private;
604         const size_t datasize = count;
605         const size_t namesize = SZ_256;
606         void *datavirt, *namevirt;
607         dma_addr_t dataphys, namephys;
608         char fnamebuf[256];
609         const char *filename;
610         size_t len;
611         int err;
612
613         filename = get_filename(bpmp, file, fnamebuf, sizeof(fnamebuf));
614         if (!filename)
615                 return -ENOENT;
616
617         namevirt = dma_alloc_coherent(bpmp->dev, namesize, &namephys,
618                                       GFP_KERNEL | GFP_DMA32);
619         if (!namevirt)
620                 return -ENOMEM;
621
622         datavirt = dma_alloc_coherent(bpmp->dev, datasize, &dataphys,
623                                       GFP_KERNEL | GFP_DMA32);
624         if (!datavirt) {
625                 err = -ENOMEM;
626                 goto free_namebuf;
627         }
628
629         len = strlen(filename);
630         strncpy(namevirt, filename, namesize);
631
632         if (copy_from_user(datavirt, buf, count)) {
633                 err = -EFAULT;
634                 goto free_databuf;
635         }
636
637         err = mrq_debugfs_write(bpmp, namephys, len, dataphys,
638                                 count);
639
640 free_databuf:
641         dma_free_coherent(bpmp->dev, datasize, datavirt, dataphys);
642 free_namebuf:
643         dma_free_coherent(bpmp->dev, namesize, namevirt, namephys);
644
645         return err ?: count;
646 }
647
648 static const struct file_operations debugfs_fops = {
649         .open           = debugfs_open,
650         .read           = seq_read,
651         .llseek         = seq_lseek,
652         .write          = debugfs_store,
653         .release        = single_release,
654 };
655
656 static int bpmp_populate_dir(struct tegra_bpmp *bpmp, struct seqbuf *seqbuf,
657                              struct dentry *parent, uint32_t depth)
658 {
659         int err;
660         uint32_t d, t;
661         const char *name;
662         struct dentry *dentry;
663
664         while (!seqbuf_eof(seqbuf)) {
665                 err = seqbuf_read_u32(seqbuf, &d);
666                 if (err < 0)
667                         return err;
668
669                 if (d < depth) {
670                         seqbuf_seek(seqbuf, -4);
671                         /* go up a level */
672                         return 0;
673                 } else if (d != depth) {
674                         /* malformed data received from BPMP */
675                         return -EIO;
676                 }
677
678                 err = seqbuf_read_u32(seqbuf, &t);
679                 if (err < 0)
680                         return err;
681                 err = seqbuf_read_str(seqbuf, &name);
682                 if (err < 0)
683                         return err;
684
685                 if (t & DEBUGFS_S_ISDIR) {
686                         dentry = debugfs_create_dir(name, parent);
687                         if (!dentry)
688                                 return -ENOMEM;
689                         err = bpmp_populate_dir(bpmp, seqbuf, dentry, depth+1);
690                         if (err < 0)
691                                 return err;
692                 } else {
693                         umode_t mode;
694
695                         mode = t & DEBUGFS_S_IRUSR ? S_IRUSR : 0;
696                         mode |= t & DEBUGFS_S_IWUSR ? S_IWUSR : 0;
697                         dentry = debugfs_create_file(name, mode,
698                                                      parent, bpmp,
699                                                      &debugfs_fops);
700                         if (!dentry)
701                                 return -ENOMEM;
702                 }
703         }
704
705         return 0;
706 }
707
708 static int bpmp_populate_debugfs_shmem(struct tegra_bpmp *bpmp)
709 {
710         struct seqbuf seqbuf;
711         const size_t sz = SZ_512K;
712         dma_addr_t phys;
713         size_t nbytes;
714         void *virt;
715         int err;
716
717         virt = dma_alloc_coherent(bpmp->dev, sz, &phys,
718                                   GFP_KERNEL | GFP_DMA32);
719         if (!virt)
720                 return -ENOMEM;
721
722         err = mrq_debugfs_dumpdir(bpmp, phys, sz, &nbytes);
723         if (err < 0) {
724                 goto free;
725         } else if (nbytes > sz) {
726                 err = -EINVAL;
727                 goto free;
728         }
729
730         seqbuf_init(&seqbuf, virt, nbytes);
731         err = bpmp_populate_dir(bpmp, &seqbuf, bpmp->debugfs_mirror, 0);
732 free:
733         dma_free_coherent(bpmp->dev, sz, virt, phys);
734
735         return err;
736 }
737
738 int tegra_bpmp_init_debugfs(struct tegra_bpmp *bpmp)
739 {
740         struct dentry *root;
741         bool inband;
742         int err;
743
744         inband = tegra_bpmp_mrq_is_supported(bpmp, MRQ_DEBUG);
745
746         if (!inband && !tegra_bpmp_mrq_is_supported(bpmp, MRQ_DEBUGFS))
747                 return 0;
748
749         root = debugfs_create_dir("bpmp", NULL);
750         if (!root)
751                 return -ENOMEM;
752
753         bpmp->debugfs_mirror = debugfs_create_dir("debug", root);
754         if (!bpmp->debugfs_mirror) {
755                 err = -ENOMEM;
756                 goto out;
757         }
758
759         if (inband)
760                 err = bpmp_populate_debugfs_inband(bpmp, bpmp->debugfs_mirror,
761                                                    "/");
762         else
763                 err = bpmp_populate_debugfs_shmem(bpmp);
764
765 out:
766         if (err < 0)
767                 debugfs_remove_recursive(root);
768
769         return err;
770 }
This page took 0.075142 seconds and 4 git commands to generate.