Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions drivers/iommu/riscv/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,14 @@ config RISCV_IOMMU_PCI
def_bool y if RISCV_IOMMU && PCI_MSI
help
Support for the PCIe implementation of RISC-V IOMMU architecture.

config RISCV_IOMMU_DEBUGFS
bool "RISC-V IOMMU Debugfs Support"
depends on RISCV_IOMMU
depends on IOMMU_DEBUGFS
help
Expose RISC-V IOMMU internals via debugfs. This includes
register dumps, queue status, and other hardware-specific
information useful for debugging.

If unsure, say N.
1 change: 1 addition & 0 deletions drivers/iommu/riscv/Makefile
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
# SPDX-License-Identifier: GPL-2.0-only
obj-y += iommu.o iommu-platform.o
obj-$(CONFIG_RISCV_IOMMU_PCI) += iommu-pci.o
obj-$(CONFIG_RISCV_IOMMU_DEBUGFS) += debugfs.o
53 changes: 53 additions & 0 deletions drivers/iommu/riscv/debugfs.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
// SPDX-License-Identifier: GPL-2.0-only
#include <linux/debugfs.h>
#include <linux/device.h>
#include <linux/kernel.h>

#include "iommu.h"

static const struct debugfs_reg32 riscv_iommu_regs[] = {
/* --- Global Configuration --- */
{ .name = "capabilities", .offset = RISCV_IOMMU_REG_CAPABILITIES },
{ .name = "fctl", .offset = RISCV_IOMMU_REG_FCTL },
{ .name = "ddtp", .offset = RISCV_IOMMU_REG_DDTP },
/* --- Command Queue --- */
{ .name = "cqb", .offset = RISCV_IOMMU_REG_CQB },
{ .name = "cqh", .offset = RISCV_IOMMU_REG_CQH },
{ .name = "cqt", .offset = RISCV_IOMMU_REG_CQT },
{ .name = "cqcsr", .offset = RISCV_IOMMU_REG_CQCSR },
/* --- Fault Queue --- */
{ .name = "fqb", .offset = RISCV_IOMMU_REG_FQB },
{ .name = "fqh", .offset = RISCV_IOMMU_REG_FQH },
{ .name = "fqt", .offset = RISCV_IOMMU_REG_FQT },
{ .name = "fqcsr", .offset = RISCV_IOMMU_REG_FQCSR },
/* --- Interrupts --- */
{ .name = "ipsr", .offset = RISCV_IOMMU_REG_IPSR },
{ .name = "icvec", .offset = RISCV_IOMMU_REG_ICVEC },
};

void riscv_iommu_debugfs_init(struct riscv_iommu_device *iommu)
{
struct debugfs_regset32 *regset;

if (!iommu_debugfs_dir)
return;

iommu->debugfs_dir = debugfs_create_dir(dev_name(iommu->dev), iommu_debugfs_dir);
if (IS_ERR_OR_NULL(iommu->debugfs_dir))
return;

regset = devm_kzalloc(iommu->dev, sizeof(*regset), GFP_KERNEL);
if (!regset)
return;

regset->regs = riscv_iommu_regs;
regset->nregs = ARRAY_SIZE(riscv_iommu_regs);
regset->base = iommu->reg;

debugfs_create_regset32("registers", 0444, iommu->debugfs_dir, regset);
}

void riscv_iommu_debugfs_remove(struct riscv_iommu_device *iommu)
{
debugfs_remove_recursive(iommu->debugfs_dir);
}
3 changes: 3 additions & 0 deletions drivers/iommu/riscv/iommu.c
Original file line number Diff line number Diff line change
Expand Up @@ -1609,6 +1609,7 @@ void riscv_iommu_remove(struct riscv_iommu_device *iommu)
riscv_iommu_iodir_set_mode(iommu, RISCV_IOMMU_DDTP_IOMMU_MODE_OFF);
riscv_iommu_queue_disable(&iommu->cmdq);
riscv_iommu_queue_disable(&iommu->fltq);
riscv_iommu_debugfs_remove(iommu);
}

int riscv_iommu_init(struct riscv_iommu_device *iommu)
Expand Down Expand Up @@ -1669,6 +1670,8 @@ int riscv_iommu_init(struct riscv_iommu_device *iommu)
goto err_remove_sysfs;
}

riscv_iommu_debugfs_init(iommu);

return 0;

err_remove_sysfs:
Expand Down
12 changes: 12 additions & 0 deletions drivers/iommu/riscv/iommu.h
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,10 @@ struct riscv_iommu_device {
unsigned int ddt_mode;
dma_addr_t ddt_phys;
u64 *ddt_root;

#ifdef CONFIG_RISCV_IOMMU_DEBUGFS
struct dentry *debugfs_dir;
#endif
};

int riscv_iommu_init(struct riscv_iommu_device *iommu);
Expand All @@ -86,4 +90,12 @@ void riscv_iommu_disable(struct riscv_iommu_device *iommu);
readx_poll_timeout(readl_relaxed, (iommu)->reg + (addr), val, cond, \
delay_us, timeout_us)

#ifdef CONFIG_RISCV_IOMMU_DEBUGFS
void riscv_iommu_debugfs_init(struct riscv_iommu_device *iommu);
void riscv_iommu_debugfs_remove(struct riscv_iommu_device *iommu);
#else
static inline void riscv_iommu_debugfs_init(struct riscv_iommu_device *iommu) { }
static inline void riscv_iommu_debugfs_remove(struct riscv_iommu_device *iommu) { }
#endif

#endif
Loading