Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit a42a7a1f authored by Robin Murphy's avatar Robin Murphy Committed by Will Deacon
Browse files

iommu: store DT-probed IOMMU data privately



Since the data pointer in the DT node is public and may be overwritten
by conflicting code, move the DT-probed IOMMU ops to a private list
where they will be safe.

Acked-by: default avatarGrant Likely <grant.likely@linaro.org>
Signed-off-by: default avatarRobin Murphy <robin.murphy@arm.com>
[will: added missing #include and missing ')']
Signed-off-by: default avatarWill Deacon <will.deacon@arm.com>
parent 4bb25789
Loading
Loading
Loading
Loading
+39 −0
Original line number Diff line number Diff line
@@ -22,6 +22,7 @@
#include <linux/limits.h>
#include <linux/of.h>
#include <linux/of_iommu.h>
#include <linux/slab.h>

static const struct of_device_id __iommu_of_table_sentinel
	__used __section(__iommu_of_table_end);
@@ -94,6 +95,44 @@ int of_get_dma_window(struct device_node *dn, const char *prefix, int index,
}
EXPORT_SYMBOL_GPL(of_get_dma_window);

struct of_iommu_node {
	struct list_head list;
	struct device_node *np;
	struct iommu_ops *ops;
};
static LIST_HEAD(of_iommu_list);
static DEFINE_SPINLOCK(of_iommu_lock);

void of_iommu_set_ops(struct device_node *np, struct iommu_ops *ops)
{
	struct of_iommu_node *iommu = kzalloc(sizeof(*iommu), GFP_KERNEL);

	if (WARN_ON(!iommu))
		return;

	INIT_LIST_HEAD(&iommu->list);
	iommu->np = np;
	iommu->ops = ops;
	spin_lock(&of_iommu_lock);
	list_add_tail(&iommu->list, &of_iommu_list);
	spin_unlock(&of_iommu_lock);
}

struct iommu_ops *of_iommu_get_ops(struct device_node *np)
{
	struct of_iommu_node *node;
	struct iommu_ops *ops = NULL;

	spin_lock(&of_iommu_lock);
	list_for_each_entry(node, &of_iommu_list, list)
		if (node->np == np) {
			ops = node->ops;
			break;
		}
	spin_unlock(&of_iommu_lock);
	return ops;
}

struct iommu_ops *of_iommu_configure(struct device *dev)
{
	struct of_phandle_args iommu_spec;
+2 −10
Original line number Diff line number Diff line
@@ -31,16 +31,8 @@ static inline struct iommu_ops *of_iommu_configure(struct device *dev)

#endif	/* CONFIG_OF_IOMMU */

static inline void of_iommu_set_ops(struct device_node *np,
				    const struct iommu_ops *ops)
{
	np->data = (struct iommu_ops *)ops;
}

static inline struct iommu_ops *of_iommu_get_ops(struct device_node *np)
{
	return np->data;
}
void of_iommu_set_ops(struct device_node *np, struct iommu_ops *ops);
struct iommu_ops *of_iommu_get_ops(struct device_node *np);

extern struct of_device_id __iommu_of_table;