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