diff options
-rw-r--r-- | drivers/iommu/amd/debugfs.c | 80 |
1 files changed, 80 insertions, 0 deletions
diff --git a/drivers/iommu/amd/debugfs.c b/drivers/iommu/amd/debugfs.c index e78f6b217a7b..065b150bba15 100644 --- a/drivers/iommu/amd/debugfs.c +++ b/drivers/iommu/amd/debugfs.c @@ -16,6 +16,9 @@ static struct dentry *amd_iommu_debugfs; #define MAX_NAME_LEN 20 #define OFS_IN_SZ 8 +#define DEVID_IN_SZ 16 + +static int sbdf = -1; static ssize_t iommu_mmio_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *ppos) @@ -131,6 +134,80 @@ static int iommu_cmdbuf_show(struct seq_file *m, void *unused) } DEFINE_SHOW_ATTRIBUTE(iommu_cmdbuf); +static ssize_t devid_write(struct file *filp, const char __user *ubuf, + size_t cnt, loff_t *ppos) +{ + struct amd_iommu_pci_seg *pci_seg; + int seg, bus, slot, func; + struct amd_iommu *iommu; + char *srcid_ptr; + u16 devid; + int i; + + sbdf = -1; + + if (cnt >= DEVID_IN_SZ) + return -EINVAL; + + srcid_ptr = memdup_user_nul(ubuf, cnt); + if (IS_ERR(srcid_ptr)) + return PTR_ERR(srcid_ptr); + + i = sscanf(srcid_ptr, "%x:%x:%x.%x", &seg, &bus, &slot, &func); + if (i != 4) { + i = sscanf(srcid_ptr, "%x:%x.%x", &bus, &slot, &func); + if (i != 3) { + kfree(srcid_ptr); + return -EINVAL; + } + seg = 0; + } + + devid = PCI_DEVID(bus, PCI_DEVFN(slot, func)); + + /* Check if user device id input is a valid input */ + for_each_pci_segment(pci_seg) { + if (pci_seg->id != seg) + continue; + if (devid > pci_seg->last_bdf) { + kfree(srcid_ptr); + return -EINVAL; + } + iommu = pci_seg->rlookup_table[devid]; + if (!iommu) { + kfree(srcid_ptr); + return -ENODEV; + } + break; + } + + if (pci_seg->id != seg) { + kfree(srcid_ptr); + return -EINVAL; + } + + sbdf = PCI_SEG_DEVID_TO_SBDF(seg, devid); + + kfree(srcid_ptr); + + return cnt; +} + +static int devid_show(struct seq_file *m, void *unused) +{ + u16 devid; + + if (sbdf >= 0) { + devid = PCI_SBDF_TO_DEVID(sbdf); + seq_printf(m, "%04x:%02x:%02x.%x\n", PCI_SBDF_TO_SEGID(sbdf), + PCI_BUS_NUM(devid), PCI_SLOT(devid), PCI_FUNC(devid)); + } else + seq_puts(m, "No or Invalid input provided\n"); + + return 0; +} +DEFINE_SHOW_STORE_ATTRIBUTE(devid); + void amd_iommu_debugfs_setup(void) { struct amd_iommu *iommu; @@ -152,4 +229,7 @@ void amd_iommu_debugfs_setup(void) debugfs_create_file("cmdbuf", 0444, iommu->debugfs, iommu, &iommu_cmdbuf_fops); } + + debugfs_create_file("devid", 0644, amd_iommu_debugfs, NULL, + &devid_fops); } |