Skip to content

Commit

Permalink
iommu/iova: add iova procfs for each dma iommu
Browse files Browse the repository at this point in the history
Tested on RK3588 EVB1:

localhost# ls /proc/iova/
av1d-master    fdb90000.jpegd       fdbb0000.iep          fdcb0000.rkisp
fdab0000.npu   fdba0000.jpege-core  fdbd0000.rkvenc-core  fdce0000.rkcif
fdb50400.vdpu  fdba4000.jpege-core  fdbe0000.rkvenc-core  fdd90000.vop
fdb60000.rga   fdba8000.jpege-core  fdc38100.rkvdec-core  rkcif-mipi-lvds
fdb70000.rga   fdbac000.jpege-core  fdc48100.rkvdec-core

localhost# cat /proc/iova/fdc38100.rkvdec-core/used
   0: [0x00000000ffe00000..0x00000000ffeff000]   1024KiB (4094 - 4095)MiB
   1: [0x00000000fff00000..0x00000000fffff000]   1024KiB (4095 - 4096)MiB
used: 2 MiB

Signed-off-by: Jianqun Xu <[email protected]>
Change-Id: I102e08243b5a0a4cd173e75e2e25f68f1f5b09b6
  • Loading branch information
jayxurockchip authored and rkhuangtao committed Jun 30, 2022
1 parent 02382af commit 4fe5523
Show file tree
Hide file tree
Showing 3 changed files with 72 additions and 0 deletions.
7 changes: 7 additions & 0 deletions drivers/iommu/dma-iommu.c
Original file line number Diff line number Diff line change
Expand Up @@ -1249,6 +1249,13 @@ void iommu_setup_dma_ops(struct device *dev, u64 dma_base, u64 size)
dev->dma_ops = &iommu_dma_ops;
}

if (domain->type == IOMMU_DOMAIN_DMA) {
struct iommu_dma_cookie *cookie = domain->iova_cookie;
struct iova_domain *iovad = &cookie->iovad;

init_iova_domain_procfs(iovad, dev_name(dev));
}

return;
out_err:
pr_warn("Failed to set up IOMMU for device %s; retaining platform DMA ops\n",
Expand Down
59 changes: 59 additions & 0 deletions drivers/iommu/iova.c
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@
#include <linux/smp.h>
#include <linux/bitops.h>
#include <linux/cpu.h>
#include <linux/proc_fs.h>
#include <linux/seq_file.h>

/* The anchor node sits above the top of the usable address space */
#define IOVA_ANCHOR ~0UL
Expand All @@ -27,6 +29,63 @@ static void fq_destroy_all_entries(struct iova_domain *iovad);
static void fq_flush_timeout(struct timer_list *t);
static void iova_dump(struct iova_domain *iovad);

static int iova_used_show(struct seq_file *s, void *v)
{
struct iova_domain *iovad = s->private;
struct iova *iova, *t;
unsigned long flags, cpu;
unsigned long used_pfn = 0;
int i = 0;

for_each_online_cpu(cpu)
free_cpu_cached_iovas(cpu, iovad);
free_global_cached_iovas(iovad);

spin_lock_irqsave(&iovad->iova_rbtree_lock, flags);
rbtree_postorder_for_each_entry_safe(iova, t, &iovad->rbroot, node) {
dma_addr_t start = iova->pfn_lo << iova_shift(iovad);
dma_addr_t end = iova->pfn_hi << iova_shift(iovad);
unsigned long pfn = iova->pfn_hi + 1 - iova->pfn_lo;

if ((iova->pfn_hi == IOVA_ANCHOR) || (iova->pfn_lo == IOVA_ANCHOR))
continue;

seq_printf(s, "%4d: [%pad..%pad] %6luKiB (%4lu - %4lu)MiB\n",
i++, &start, &end,
pfn << (PAGE_SHIFT - 10),
iova->pfn_lo >> (20 - PAGE_SHIFT),
(iova->pfn_hi + 1) >> (20 - PAGE_SHIFT));
used_pfn += pfn;
}
spin_unlock_irqrestore(&iovad->iova_rbtree_lock, flags);
seq_printf(s, "used: %lu MiB\n", used_pfn >> (20 - PAGE_SHIFT));

return 0;
}

static struct proc_dir_entry *iova_dir;

void init_iova_domain_procfs(struct iova_domain *iovad, const char *name)
{
struct proc_dir_entry *root;

root = proc_mkdir(name, iova_dir);
if (!root)
return;

proc_create_single_data("used", 0, root, iova_used_show, iovad);
}
EXPORT_SYMBOL_GPL(init_iova_domain_procfs);

static int __init iova_procfs_create(void)
{
if (!iova_dir)
iova_dir = proc_mkdir("iova", NULL);

return 0;
}
subsys_initcall(iova_procfs_create);

void
init_iova_domain(struct iova_domain *iovad, unsigned long granule,
unsigned long start_pfn)
Expand Down
6 changes: 6 additions & 0 deletions include/linux/iova.h
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,7 @@ struct iova *reserve_iova(struct iova_domain *iovad, unsigned long pfn_lo,
void copy_reserved_iova(struct iova_domain *from, struct iova_domain *to);
void init_iova_domain(struct iova_domain *iovad, unsigned long granule,
unsigned long start_pfn);
void init_iova_domain_procfs(struct iova_domain *iovad, const char *name);
bool has_iova_flush_queue(struct iova_domain *iovad);
int init_iova_flush_queue(struct iova_domain *iovad,
iova_flush_cb flush_cb, iova_entry_dtor entry_dtor);
Expand Down Expand Up @@ -238,6 +239,11 @@ static inline void init_iova_domain(struct iova_domain *iovad,
{
}

static inline void
init_iova_domain_procfs(struct iova_domain *iovad, const char *name)
{
}

static inline bool has_iova_flush_queue(struct iova_domain *iovad)
{
return false;
Expand Down

0 comments on commit 4fe5523

Please sign in to comment.