@@ -148,6 +148,13 @@ arm_64_lpae_alloc_pgtable_s1(struct io_pgtable_cfg *cfg, void *cookie)
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)
{
@@ -178,6 +185,13 @@ arm_64_lpae_alloc_pgtable_s2(struct io_pgtable_cfg *cfg, void *cookie)
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)
{
@@ -264,12 +278,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 = {
@@ -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);
@@ -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;
};