linux/drivers/firmware/tegra/bpmp-debugfs.c
<<
>>
Prefs
   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
  13static DEFINE_MUTEX(bpmp_debug_lock);
  14
  15struct seqbuf {
  16        char *buf;
  17        size_t pos;
  18        size_t size;
  19};
  20
  21static 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
  28static size_t seqbuf_avail(struct seqbuf *seqbuf)
  29{
  30        return seqbuf->pos < seqbuf->size ? seqbuf->size - seqbuf->pos : 0;
  31}
  32
  33static size_t seqbuf_status(struct seqbuf *seqbuf)
  34{
  35        return seqbuf->pos <= seqbuf->size ? 0 : -EOVERFLOW;
  36}
  37
  38static int seqbuf_eof(struct seqbuf *seqbuf)
  39{
  40        return seqbuf->pos >= seqbuf->size;
  41}
  42
  43static 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
  51static 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
  60static 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
  68static 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 */
  74static 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
 102static 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
 141static 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
 172static 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
 228close:
 229        err = mrq_debug_close(bpmp, fd);
 230out:
 231        mutex_unlock(&bpmp_debug_lock);
 232        return err;
 233}
 234
 235static 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
 287close:
 288        err = mrq_debug_close(bpmp, fd);
 289out:
 290        mutex_unlock(&bpmp_debug_lock);
 291        return err;
 292}
 293
 294static 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 fnamebuf[256];
 300        const char *filename;
 301        struct mrq_debug_request req = {
 302                .cmd = cpu_to_le32(CMD_DEBUG_READ),
 303        };
 304        struct mrq_debug_response resp;
 305        struct tegra_bpmp_message msg = {
 306                .mrq = MRQ_DEBUG,
 307                .tx = {
 308                        .data = &req,
 309                        .size = sizeof(req),
 310                },
 311                .rx = {
 312                        .data = &resp,
 313                        .size = sizeof(resp),
 314                },
 315        };
 316        uint32_t fd = 0, len = 0;
 317        int remaining, err;
 318
 319        filename = get_filename(bpmp, file, fnamebuf, sizeof(fnamebuf));
 320        if (!filename)
 321                return -ENOENT;
 322
 323        mutex_lock(&bpmp_debug_lock);
 324        err = mrq_debug_open(bpmp, filename, &fd, &len, 0);
 325        if (err)
 326                goto out;
 327
 328        req.frd.fd = fd;
 329        remaining = len;
 330
 331        while (remaining > 0) {
 332                err = tegra_bpmp_transfer(bpmp, &msg);
 333                if (err < 0) {
 334                        goto close;
 335                } else if (msg.rx.ret < 0) {
 336                        err = -EINVAL;
 337                        goto close;
 338                }
 339
 340                if (resp.frd.readlen > remaining) {
 341                        pr_err("%s: read data length invalid\n", __func__);
 342                        err = -EINVAL;
 343                        goto close;
 344                }
 345
 346                seq_write(m, resp.frd.data, resp.frd.readlen);
 347                remaining -= resp.frd.readlen;
 348        }
 349
 350close:
 351        err = mrq_debug_close(bpmp, fd);
 352out:
 353        mutex_unlock(&bpmp_debug_lock);
 354        return err;
 355}
 356
 357static ssize_t bpmp_debug_store(struct file *file, const char __user *buf,
 358                size_t count, loff_t *f_pos)
 359{
 360        struct inode *inode = file_inode(file);
 361        struct tegra_bpmp *bpmp = inode->i_private;
 362        char *databuf = NULL;
 363        char fnamebuf[256];
 364        const char *filename;
 365        ssize_t err;
 366
 367        filename = get_filename(bpmp, file, fnamebuf, sizeof(fnamebuf));
 368        if (!filename)
 369                return -ENOENT;
 370
 371        databuf = kmalloc(count, GFP_KERNEL);
 372        if (!databuf)
 373                return -ENOMEM;
 374
 375        if (copy_from_user(databuf, buf, count)) {
 376                err = -EFAULT;
 377                goto free_ret;
 378        }
 379
 380        err = mrq_debug_write(bpmp, filename, databuf, count);
 381
 382free_ret:
 383        kfree(databuf);
 384
 385        return err ?: count;
 386}
 387
 388static int bpmp_debug_open(struct inode *inode, struct file *file)
 389{
 390        return single_open_size(file, bpmp_debug_show, file, SZ_256K);
 391}
 392
 393static const struct file_operations bpmp_debug_fops = {
 394        .open           = bpmp_debug_open,
 395        .read           = seq_read,
 396        .llseek         = seq_lseek,
 397        .write          = bpmp_debug_store,
 398        .release        = single_release,
 399};
 400
 401static int bpmp_populate_debugfs_inband(struct tegra_bpmp *bpmp,
 402                                        struct dentry *parent,
 403                                        char *ppath)
 404{
 405        const size_t pathlen = SZ_256;
 406        const size_t bufsize = SZ_16K;
 407        uint32_t dsize, attrs = 0;
 408        struct dentry *dentry;
 409        struct seqbuf seqbuf;
 410        char *buf, *pathbuf;
 411        const char *name;
 412        int err = 0;
 413
 414        if (!bpmp || !parent || !ppath)
 415                return -EINVAL;
 416
 417        buf = kmalloc(bufsize, GFP_KERNEL);
 418        if (!buf)
 419                return -ENOMEM;
 420
 421        pathbuf = kzalloc(pathlen, GFP_KERNEL);
 422        if (!pathbuf) {
 423                kfree(buf);
 424                return -ENOMEM;
 425        }
 426
 427        err = mrq_debug_read(bpmp, ppath, buf, bufsize, &dsize);
 428        if (err)
 429                goto out;
 430
 431        seqbuf_init(&seqbuf, buf, dsize);
 432
 433        while (!seqbuf_eof(&seqbuf)) {
 434                err = seqbuf_read_u32(&seqbuf, &attrs);
 435                if (err)
 436                        goto out;
 437
 438                err = seqbuf_read_str(&seqbuf, &name);
 439                if (err < 0)
 440                        goto out;
 441
 442                if (attrs & DEBUGFS_S_ISDIR) {
 443                        size_t len;
 444
 445                        dentry = debugfs_create_dir(name, parent);
 446                        if (IS_ERR(dentry)) {
 447                                err = PTR_ERR(dentry);
 448                                goto out;
 449                        }
 450
 451                        len = snprintf(pathbuf, pathlen, "%s%s/", ppath, name);
 452                        if (len >= pathlen) {
 453                                err = -EINVAL;
 454                                goto out;
 455                        }
 456
 457                        err = bpmp_populate_debugfs_inband(bpmp, dentry,
 458                                                           pathbuf);
 459                        if (err < 0)
 460                                goto out;
 461                } else {
 462                        umode_t mode;
 463
 464                        mode = attrs & DEBUGFS_S_IRUSR ? 0400 : 0;
 465                        mode |= attrs & DEBUGFS_S_IWUSR ? 0200 : 0;
 466                        dentry = debugfs_create_file(name, mode, parent, bpmp,
 467                                                     &bpmp_debug_fops);
 468                        if (!dentry) {
 469                                err = -ENOMEM;
 470                                goto out;
 471                        }
 472                }
 473        }
 474
 475out:
 476        kfree(pathbuf);
 477        kfree(buf);
 478
 479        return err;
 480}
 481
 482static int mrq_debugfs_read(struct tegra_bpmp *bpmp,
 483                            dma_addr_t name, size_t sz_name,
 484                            dma_addr_t data, size_t sz_data,
 485                            size_t *nbytes)
 486{
 487        struct mrq_debugfs_request req = {
 488                .cmd = cpu_to_le32(CMD_DEBUGFS_READ),
 489                .fop = {
 490                        .fnameaddr = cpu_to_le32((uint32_t)name),
 491                        .fnamelen = cpu_to_le32((uint32_t)sz_name),
 492                        .dataaddr = cpu_to_le32((uint32_t)data),
 493                        .datalen = cpu_to_le32((uint32_t)sz_data),
 494                },
 495        };
 496        struct mrq_debugfs_response resp;
 497        struct tegra_bpmp_message msg = {
 498                .mrq = MRQ_DEBUGFS,
 499                .tx = {
 500                        .data = &req,
 501                        .size = sizeof(req),
 502                },
 503                .rx = {
 504                        .data = &resp,
 505                        .size = sizeof(resp),
 506                },
 507        };
 508        int err;
 509
 510        err = tegra_bpmp_transfer(bpmp, &msg);
 511        if (err < 0)
 512                return err;
 513        else if (msg.rx.ret < 0)
 514                return -EINVAL;
 515
 516        *nbytes = (size_t)resp.fop.nbytes;
 517
 518        return 0;
 519}
 520
 521static int mrq_debugfs_write(struct tegra_bpmp *bpmp,
 522                             dma_addr_t name, size_t sz_name,
 523                             dma_addr_t data, size_t sz_data)
 524{
 525        const struct mrq_debugfs_request req = {
 526                .cmd = cpu_to_le32(CMD_DEBUGFS_WRITE),
 527                .fop = {
 528                        .fnameaddr = cpu_to_le32((uint32_t)name),
 529                        .fnamelen = cpu_to_le32((uint32_t)sz_name),
 530                        .dataaddr = cpu_to_le32((uint32_t)data),
 531                        .datalen = cpu_to_le32((uint32_t)sz_data),
 532                },
 533        };
 534        struct tegra_bpmp_message msg = {
 535                .mrq = MRQ_DEBUGFS,
 536                .tx = {
 537                        .data = &req,
 538                        .size = sizeof(req),
 539                },
 540        };
 541
 542        return tegra_bpmp_transfer(bpmp, &msg);
 543}
 544
 545static int mrq_debugfs_dumpdir(struct tegra_bpmp *bpmp, dma_addr_t addr,
 546                               size_t size, size_t *nbytes)
 547{
 548        const struct mrq_debugfs_request req = {
 549                .cmd = cpu_to_le32(CMD_DEBUGFS_DUMPDIR),
 550                .dumpdir = {
 551                        .dataaddr = cpu_to_le32((uint32_t)addr),
 552                        .datalen = cpu_to_le32((uint32_t)size),
 553                },
 554        };
 555        struct mrq_debugfs_response resp;
 556        struct tegra_bpmp_message msg = {
 557                .mrq = MRQ_DEBUGFS,
 558                .tx = {
 559                        .data = &req,
 560                        .size = sizeof(req),
 561                },
 562                .rx = {
 563                        .data = &resp,
 564                        .size = sizeof(resp),
 565                },
 566        };
 567        int err;
 568
 569        err = tegra_bpmp_transfer(bpmp, &msg);
 570        if (err < 0)
 571                return err;
 572        else if (msg.rx.ret < 0)
 573                return -EINVAL;
 574
 575        *nbytes = (size_t)resp.dumpdir.nbytes;
 576
 577        return 0;
 578}
 579
 580static int debugfs_show(struct seq_file *m, void *p)
 581{
 582        struct file *file = m->private;
 583        struct inode *inode = file_inode(file);
 584        struct tegra_bpmp *bpmp = inode->i_private;
 585        const size_t datasize = m->size;
 586        const size_t namesize = SZ_256;
 587        void *datavirt, *namevirt;
 588        dma_addr_t dataphys, namephys;
 589        char buf[256];
 590        const char *filename;
 591        size_t len, nbytes;
 592        int err;
 593
 594        filename = get_filename(bpmp, file, buf, sizeof(buf));
 595        if (!filename)
 596                return -ENOENT;
 597
 598        namevirt = dma_alloc_coherent(bpmp->dev, namesize, &namephys,
 599                                      GFP_KERNEL | GFP_DMA32);
 600        if (!namevirt)
 601                return -ENOMEM;
 602
 603        datavirt = dma_alloc_coherent(bpmp->dev, datasize, &dataphys,
 604                                      GFP_KERNEL | GFP_DMA32);
 605        if (!datavirt) {
 606                err = -ENOMEM;
 607                goto free_namebuf;
 608        }
 609
 610        len = strlen(filename);
 611        strncpy(namevirt, filename, namesize);
 612
 613        err = mrq_debugfs_read(bpmp, namephys, len, dataphys, datasize,
 614                               &nbytes);
 615
 616        if (!err)
 617                seq_write(m, datavirt, nbytes);
 618
 619        dma_free_coherent(bpmp->dev, datasize, datavirt, dataphys);
 620free_namebuf:
 621        dma_free_coherent(bpmp->dev, namesize, namevirt, namephys);
 622
 623        return err;
 624}
 625
 626static int debugfs_open(struct inode *inode, struct file *file)
 627{
 628        return single_open_size(file, debugfs_show, file, SZ_128K);
 629}
 630
 631static ssize_t debugfs_store(struct file *file, const char __user *buf,
 632                size_t count, loff_t *f_pos)
 633{
 634        struct inode *inode = file_inode(file);
 635        struct tegra_bpmp *bpmp = inode->i_private;
 636        const size_t datasize = count;
 637        const size_t namesize = SZ_256;
 638        void *datavirt, *namevirt;
 639        dma_addr_t dataphys, namephys;
 640        char fnamebuf[256];
 641        const char *filename;
 642        size_t len;
 643        int err;
 644
 645        filename = get_filename(bpmp, file, fnamebuf, sizeof(fnamebuf));
 646        if (!filename)
 647                return -ENOENT;
 648
 649        namevirt = dma_alloc_coherent(bpmp->dev, namesize, &namephys,
 650                                      GFP_KERNEL | GFP_DMA32);
 651        if (!namevirt)
 652                return -ENOMEM;
 653
 654        datavirt = dma_alloc_coherent(bpmp->dev, datasize, &dataphys,
 655                                      GFP_KERNEL | GFP_DMA32);
 656        if (!datavirt) {
 657                err = -ENOMEM;
 658                goto free_namebuf;
 659        }
 660
 661        len = strlen(filename);
 662        strncpy(namevirt, filename, namesize);
 663
 664        if (copy_from_user(datavirt, buf, count)) {
 665                err = -EFAULT;
 666                goto free_databuf;
 667        }
 668
 669        err = mrq_debugfs_write(bpmp, namephys, len, dataphys,
 670                                count);
 671
 672free_databuf:
 673        dma_free_coherent(bpmp->dev, datasize, datavirt, dataphys);
 674free_namebuf:
 675        dma_free_coherent(bpmp->dev, namesize, namevirt, namephys);
 676
 677        return err ?: count;
 678}
 679
 680static const struct file_operations debugfs_fops = {
 681        .open           = debugfs_open,
 682        .read           = seq_read,
 683        .llseek         = seq_lseek,
 684        .write          = debugfs_store,
 685        .release        = single_release,
 686};
 687
 688static int bpmp_populate_dir(struct tegra_bpmp *bpmp, struct seqbuf *seqbuf,
 689                             struct dentry *parent, uint32_t depth)
 690{
 691        int err;
 692        uint32_t d, t;
 693        const char *name;
 694        struct dentry *dentry;
 695
 696        while (!seqbuf_eof(seqbuf)) {
 697                err = seqbuf_read_u32(seqbuf, &d);
 698                if (err < 0)
 699                        return err;
 700
 701                if (d < depth) {
 702                        seqbuf_seek(seqbuf, -4);
 703                        /* go up a level */
 704                        return 0;
 705                } else if (d != depth) {
 706                        /* malformed data received from BPMP */
 707                        return -EIO;
 708                }
 709
 710                err = seqbuf_read_u32(seqbuf, &t);
 711                if (err < 0)
 712                        return err;
 713                err = seqbuf_read_str(seqbuf, &name);
 714                if (err < 0)
 715                        return err;
 716
 717                if (t & DEBUGFS_S_ISDIR) {
 718                        dentry = debugfs_create_dir(name, parent);
 719                        if (!dentry)
 720                                return -ENOMEM;
 721                        err = bpmp_populate_dir(bpmp, seqbuf, dentry, depth+1);
 722                        if (err < 0)
 723                                return err;
 724                } else {
 725                        umode_t mode;
 726
 727                        mode = t & DEBUGFS_S_IRUSR ? S_IRUSR : 0;
 728                        mode |= t & DEBUGFS_S_IWUSR ? S_IWUSR : 0;
 729                        dentry = debugfs_create_file(name, mode,
 730                                                     parent, bpmp,
 731                                                     &debugfs_fops);
 732                        if (!dentry)
 733                                return -ENOMEM;
 734                }
 735        }
 736
 737        return 0;
 738}
 739
 740static int bpmp_populate_debugfs_shmem(struct tegra_bpmp *bpmp)
 741{
 742        struct seqbuf seqbuf;
 743        const size_t sz = SZ_512K;
 744        dma_addr_t phys;
 745        size_t nbytes;
 746        void *virt;
 747        int err;
 748
 749        virt = dma_alloc_coherent(bpmp->dev, sz, &phys,
 750                                  GFP_KERNEL | GFP_DMA32);
 751        if (!virt)
 752                return -ENOMEM;
 753
 754        err = mrq_debugfs_dumpdir(bpmp, phys, sz, &nbytes);
 755        if (err < 0) {
 756                goto free;
 757        } else if (nbytes > sz) {
 758                err = -EINVAL;
 759                goto free;
 760        }
 761
 762        seqbuf_init(&seqbuf, virt, nbytes);
 763        err = bpmp_populate_dir(bpmp, &seqbuf, bpmp->debugfs_mirror, 0);
 764free:
 765        dma_free_coherent(bpmp->dev, sz, virt, phys);
 766
 767        return err;
 768}
 769
 770int tegra_bpmp_init_debugfs(struct tegra_bpmp *bpmp)
 771{
 772        struct dentry *root;
 773        bool inband;
 774        int err;
 775
 776        inband = tegra_bpmp_mrq_is_supported(bpmp, MRQ_DEBUG);
 777
 778        if (!inband && !tegra_bpmp_mrq_is_supported(bpmp, MRQ_DEBUGFS))
 779                return 0;
 780
 781        root = debugfs_create_dir("bpmp", NULL);
 782        if (!root)
 783                return -ENOMEM;
 784
 785        bpmp->debugfs_mirror = debugfs_create_dir("debug", root);
 786        if (!bpmp->debugfs_mirror) {
 787                err = -ENOMEM;
 788                goto out;
 789        }
 790
 791        if (inband)
 792                err = bpmp_populate_debugfs_inband(bpmp, bpmp->debugfs_mirror,
 793                                                   "/");
 794        else
 795                err = bpmp_populate_debugfs_shmem(bpmp);
 796
 797out:
 798        if (err < 0)
 799                debugfs_remove_recursive(root);
 800
 801        return err;
 802}
 803