[PATCH v2 2/5] iommu: Implement of_iommu_get_resv_regions()
From: Thierry Reding <hidden>
Date: 2021-04-23 16:31:57
Also in:
linux-iommu, linux-tegra
Subsystem:
iommu subsystem, open firmware and flattened device tree, the rest · Maintainers:
Joerg Roedel, Will Deacon, Rob Herring, Saravana Kannan, Linus Torvalds
From: Thierry Reding <redacted> This is an implementation that IOMMU drivers can use to obtain reserved memory regions from a device tree node. It uses the reserved-memory DT bindings to find the regions associated with a given device. If these regions are marked accordingly, identity mappings will be created for them in the IOMMU domain that the devices will be attached to. Cc: Frank Rowand <redacted> Cc: devicetree@vger.kernel.org Reviewed-by: Rob Herring <robh@kernel.org> Signed-off-by: Thierry Reding <redacted> --- Changes in v3: - change "active" property to identity mapping flag that is part of the memory region specifier (as defined by #memory-region-cells) to allow per-reference flags to be used Changes in v2: - use "active" property to determine whether direct mappings are needed --- drivers/iommu/of_iommu.c | 54 ++++++++++++++++++++++++++++++++++++++++ include/linux/of_iommu.h | 8 ++++++ 2 files changed, 62 insertions(+)
diff --git a/drivers/iommu/of_iommu.c b/drivers/iommu/of_iommu.c
index a9d2df001149..321ebd5fdaba 100644
--- a/drivers/iommu/of_iommu.c
+++ b/drivers/iommu/of_iommu.c@@ -11,12 +11,15 @@ #include <linux/module.h> #include <linux/msi.h> #include <linux/of.h> +#include <linux/of_address.h> #include <linux/of_iommu.h> #include <linux/of_pci.h> #include <linux/pci.h> #include <linux/slab.h> #include <linux/fsl/mc.h> +#include <dt-bindings/reserved-memory.h> + #define NO_IOMMU 1 /**
@@ -240,3 +243,54 @@ const struct iommu_ops *of_iommu_configure(struct device *dev, return ops; } + +/** + * of_iommu_get_resv_regions - reserved region driver helper for device tree + * @dev: device for which to get reserved regions + * @list: reserved region list + * + * IOMMU drivers can use this to implement their .get_resv_regions() callback + * for memory regions attached to a device tree node. See the reserved-memory + * device tree bindings on how to use these: + * + * Documentation/devicetree/bindings/reserved-memory/reserved-memory.txt + */ +void of_iommu_get_resv_regions(struct device *dev, struct list_head *list) +{ + struct of_phandle_iterator it; + int err; + + of_for_each_phandle(&it, err, dev->of_node, "memory-region", "#memory-region-cells", 0) { + struct iommu_resv_region *region; + struct of_phandle_args args; + struct resource res; + + args.args_count = of_phandle_iterator_args(&it, args.args, MAX_PHANDLE_ARGS); + + err = of_address_to_resource(it.node, 0, &res); + if (err < 0) { + dev_err(dev, "failed to parse memory region %pOF: %d\n", + it.node, err); + continue; + } + + if (args.args_count > 0) { + /* + * Active memory regions are expected to be accessed by hardware during + * boot and must therefore have an identity mapping created prior to the + * driver taking control of the hardware. This ensures that non-quiescent + * hardware doesn't cause IOMMU faults during boot. + */ + if (args.args[0] & MEMORY_REGION_IDENTITY_MAPPING) { + region = iommu_alloc_resv_region(res.start, resource_size(&res), + IOMMU_READ | IOMMU_WRITE, + IOMMU_RESV_DIRECT_RELAXABLE); + if (!region) + continue; + + list_add_tail(®ion->list, list); + } + } + } +} +EXPORT_SYMBOL(of_iommu_get_resv_regions);
diff --git a/include/linux/of_iommu.h b/include/linux/of_iommu.h
index 16f4b3e87f20..8412437acaac 100644
--- a/include/linux/of_iommu.h
+++ b/include/linux/of_iommu.h@@ -16,6 +16,9 @@ extern const struct iommu_ops *of_iommu_configure(struct device *dev, struct device_node *master_np, const u32 *id); +extern void of_iommu_get_resv_regions(struct device *dev, + struct list_head *list); + #else static inline int of_get_dma_window(struct device_node *dn, const char *prefix,
@@ -32,6 +35,11 @@ static inline const struct iommu_ops *of_iommu_configure(struct device *dev, return NULL; } +static inline void of_iommu_get_resv_regions(struct device *dev, + struct list_head *list) +{ +} + #endif /* CONFIG_OF_IOMMU */ #endif /* __OF_IOMMU_H */
--
2.30.2