diff --git a/drivers/iommu/Kconfig b/drivers/iommu/Kconfig index 0e6a77626aec..83c0b56b57f8 100644 --- a/drivers/iommu/Kconfig +++ b/drivers/iommu/Kconfig @@ -172,6 +172,15 @@ config IOMMU_DEBUGFS debug/iommu directory, and then populate a subdirectory with entries as required. +config IO_PGTABLE_PAGE_ACCOUNTING + bool "Export the number of pages allocated for IOMMU pagetables" + depends on IOMMU_DEBUGFS && QGKI + help + Allows exposure of the number of pages allocated for IOMMU + pagetables through DebugFS. This is particularly useful for + generating stats about the amount of memory consumed by IOMMU + page tables in the system. If unsure, say N here. + config IOMMU_DEFAULT_PASSTHROUGH bool "IOMMU passthrough by default" depends on IOMMU_API diff --git a/drivers/iommu/io-pgtable.c b/drivers/iommu/io-pgtable.c index 7412921de1c0..f3b31328e166 100644 --- a/drivers/iommu/io-pgtable.c +++ b/drivers/iommu/io-pgtable.c @@ -11,10 +11,12 @@ #include #include #include +#ifdef CONFIG_IO_PGTABLE_PAGE_ACCOUNTING #include #include #include #include +#endif static const struct io_pgtable_init_fns * io_pgtable_init_table[IO_PGTABLE_NUM_FMTS] = { @@ -33,8 +35,6 @@ io_pgtable_init_table[IO_PGTABLE_NUM_FMTS] = { #endif }; -static struct dentry *io_pgtable_top; - struct io_pgtable_ops *alloc_io_pgtable_ops(enum io_pgtable_fmt fmt, struct io_pgtable_cfg *cfg, void *cookie) @@ -78,8 +78,42 @@ void free_io_pgtable_ops(struct io_pgtable_ops *ops) } EXPORT_SYMBOL_GPL(free_io_pgtable_ops); +#ifdef CONFIG_IO_PGTABLE_PAGE_ACCOUNTING +static struct dentry *io_pgtable_top; static atomic_t pages_allocated; +static int io_pgtable_init(void) +{ + io_pgtable_top = debugfs_create_dir("io-pgtable", iommu_debugfs_top); + if (!io_pgtable_top) + return -ENODEV; + + if (!debugfs_create_atomic_t("pages", 0600, io_pgtable_top, + &pages_allocated)) { + debugfs_remove_recursive(io_pgtable_top); + return -ENODEV; + } + + return 0; +} +module_init(io_pgtable_init); + +static void io_pgtable_exit(void) +{ + debugfs_remove_recursive(io_pgtable_top); +} +module_exit(io_pgtable_exit); + +static void mod_pages_allocated(int nr_pages) +{ + atomic_add(nr_pages, &pages_allocated); +} +#else +static void mod_pages_allocated(int nr_pages) +{ +} +#endif + void *io_pgtable_alloc_pages_exact(struct io_pgtable_cfg *cfg, void *cookie, size_t size, gfp_t gfp_mask) { @@ -92,7 +126,7 @@ void *io_pgtable_alloc_pages_exact(struct io_pgtable_cfg *cfg, void *cookie, ret = alloc_pages_exact(size, gfp_mask); if (likely(ret)) - atomic_add(1 << get_order(size), &pages_allocated); + mod_pages_allocated(1 << get_order(size)); return ret; } @@ -107,29 +141,5 @@ void io_pgtable_free_pages_exact(struct io_pgtable_cfg *cfg, void *cookie, else free_pages_exact(virt, size); - atomic_sub(1 << get_order(size), &pages_allocated); + mod_pages_allocated(-(1 << get_order(size))); } - -static int io_pgtable_init(void) -{ - io_pgtable_top = debugfs_create_dir("io-pgtable", iommu_debugfs_top); - - if (!io_pgtable_top) - return -ENODEV; - - if (!debugfs_create_atomic_t("pages", 0600, - io_pgtable_top, &pages_allocated)) { - debugfs_remove_recursive(io_pgtable_top); - return -ENODEV; - } - - return 0; -} - -static void io_pgtable_exit(void) -{ - debugfs_remove_recursive(io_pgtable_top); -} - -module_init(io_pgtable_init); -module_exit(io_pgtable_exit);