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..1010d388c9eb 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_dir); + 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); diff --git a/drivers/iommu/iommu-debug.c b/drivers/iommu/iommu-debug.c index dd1932f530d5..0abd5089f44b 100644 --- a/drivers/iommu/iommu-debug.c +++ b/drivers/iommu/iommu-debug.c @@ -2347,8 +2347,7 @@ err: static int iommu_debug_init_tests(void) { - debugfs_tests_dir = debugfs_create_dir("tests", - iommu_debugfs_top); + debugfs_tests_dir = debugfs_create_dir("tests", iommu_debugfs_dir); if (!debugfs_tests_dir) { pr_err_ratelimited("Couldn't create iommu/tests debugfs directory\n"); return -ENODEV; diff --git a/drivers/iommu/iommu-debugfs.c b/drivers/iommu/iommu-debugfs.c index 41ced5ab3bed..f03548942096 100644 --- a/drivers/iommu/iommu-debugfs.c +++ b/drivers/iommu/iommu-debugfs.c @@ -32,7 +32,6 @@ void iommu_debugfs_setup(void) { if (!iommu_debugfs_dir) { iommu_debugfs_dir = debugfs_create_dir("iommu", NULL); - iommu_debugfs_top = iommu_debugfs_dir; pr_warn("\n"); pr_warn("*************************************************************\n"); pr_warn("** NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE **\n"); diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c index 446b84be2f0a..76e14dc52edc 100644 --- a/drivers/iommu/iommu.c +++ b/drivers/iommu/iommu.c @@ -20,7 +20,6 @@ #include #include #include -#include #include #include #include @@ -2162,8 +2161,6 @@ int report_iommu_fault(struct iommu_domain *domain, struct device *dev, } EXPORT_SYMBOL_GPL(report_iommu_fault); -struct dentry *iommu_debugfs_top; - static int __init iommu_init(void) { iommu_group_kset = kset_create_and_add("iommu_groups", diff --git a/include/linux/iommu.h b/include/linux/iommu.h index adbf54c068f2..6038be82e671 100644 --- a/include/linux/iommu.h +++ b/include/linux/iommu.h @@ -227,7 +227,6 @@ struct iommu_resv_region { enum iommu_resv_type type; }; -extern struct dentry *iommu_debugfs_top; /* Per device IOMMU features */ enum iommu_dev_features { IOMMU_DEV_FEAT_AUX, /* Aux-domain feature */