diff --git a/drivers/iommu/io-pgtable-arm.c b/drivers/iommu/io-pgtable-arm.c index 1b3672733082..715d2e032f0a 100644 --- a/drivers/iommu/io-pgtable-arm.c +++ b/drivers/iommu/io-pgtable-arm.c @@ -194,6 +194,13 @@ out_free_data: return NULL; } +static int arm_64_lpae_configure_s1(struct io_pgtable_cfg *cfg) +{ + struct arm_lpae_io_pgtable data = {}; + + return arm_lpae_init_pgtable_s1(cfg, &data); +} + static struct io_pgtable * arm_64_lpae_alloc_pgtable_s2(struct io_pgtable_cfg *cfg, void *cookie) { @@ -225,6 +232,13 @@ out_free_data: return NULL; } +static int arm_64_lpae_configure_s2(struct io_pgtable_cfg *cfg) +{ + struct arm_lpae_io_pgtable data = {}; + + return arm_lpae_init_pgtable_s2(cfg, &data); +} + static struct io_pgtable * arm_32_lpae_alloc_pgtable_s1(struct io_pgtable_cfg *cfg, void *cookie) { @@ -312,12 +326,14 @@ struct io_pgtable_init_fns io_pgtable_arm_64_lpae_s1_init_fns = { .caps = IO_PGTABLE_CAP_CUSTOM_ALLOCATOR, .alloc = arm_64_lpae_alloc_pgtable_s1, .free = arm_lpae_free_pgtable, + .configure = arm_64_lpae_configure_s1, }; struct io_pgtable_init_fns io_pgtable_arm_64_lpae_s2_init_fns = { .caps = IO_PGTABLE_CAP_CUSTOM_ALLOCATOR, .alloc = arm_64_lpae_alloc_pgtable_s2, .free = arm_lpae_free_pgtable, + .configure = arm_64_lpae_configure_s2, }; struct io_pgtable_init_fns io_pgtable_arm_32_lpae_s1_init_fns = { diff --git a/drivers/iommu/io-pgtable.c b/drivers/iommu/io-pgtable.c index 8841c1487f00..be65f70ec2a6 100644 --- a/drivers/iommu/io-pgtable.c +++ b/drivers/iommu/io-pgtable.c @@ -99,3 +99,18 @@ void free_io_pgtable_ops(struct io_pgtable_ops *ops) io_pgtable_init_table[iop->fmt]->free(iop); } EXPORT_SYMBOL_GPL(free_io_pgtable_ops); + +int io_pgtable_configure(struct io_pgtable_cfg *cfg) +{ + const struct io_pgtable_init_fns *fns; + + if (cfg->fmt >= IO_PGTABLE_NUM_FMTS) + return -EINVAL; + + fns = io_pgtable_init_table[cfg->fmt]; + if (!fns || !fns->configure) + return -EOPNOTSUPP; + + return fns->configure(cfg); +} +EXPORT_SYMBOL_GPL(io_pgtable_configure); diff --git a/include/linux/io-pgtable.h b/include/linux/io-pgtable.h index d7bfbf351975..f789234c703b 100644 --- a/include/linux/io-pgtable.h +++ b/include/linux/io-pgtable.h @@ -49,6 +49,7 @@ struct iommu_flush_ops { /** * struct io_pgtable_cfg - Configuration data for a set of page tables. * + * @fmt: Format used for these page tables * @quirks: A bitmap of hardware quirks that require some special * action by the low-level page table allocator. * @pgsize_bitmap: A bitmap of page sizes supported by this set of page @@ -62,6 +63,7 @@ struct iommu_flush_ops { * page table walker. */ struct io_pgtable_cfg { + enum io_pgtable_fmt fmt; /* * IO_PGTABLE_QUIRK_ARM_NS: (ARM formats) Set NS and NSTABLE bits in * stage 1 PTEs, for hardware which insists on validating them @@ -241,6 +243,17 @@ struct io_pgtable_ops *alloc_io_pgtable_ops(enum io_pgtable_fmt fmt, */ void free_io_pgtable_ops(struct io_pgtable_ops *ops); +/** + * io_pgtable_configure - Create page table config + * + * @cfg: The page table configuration. + * + * Initialize @cfg in the same way as alloc_io_pgtable_ops(), without allocating + * anything. + * + * Not all io_pgtable drivers implement this operation. + */ +int io_pgtable_configure(struct io_pgtable_cfg *cfg); /* * Internal structures for page table allocator implementations. @@ -301,11 +314,13 @@ enum io_pgtable_caps { * * @alloc: Allocate a set of page tables described by cfg. * @free: Free the page tables associated with iop. + * @configure: Create the configuration without allocating anything. Optional. * @caps: Combination of @io_pgtable_caps flags encoding the backend capabilities. */ struct io_pgtable_init_fns { struct io_pgtable *(*alloc)(struct io_pgtable_cfg *cfg, void *cookie); void (*free)(struct io_pgtable *iop); + int (*configure)(struct io_pgtable_cfg *cfg); u32 caps; };