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