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: Grant Likely <grant.likely@linaro.org> Signed-off-by: Robin Murphy <robin.murphy@arm.com> [will: added missing #include and missing ')'] Signed-off-by: Will Deacon <will.deacon@arm.com>
This commit is contained in:
parent
4bb25789ed
commit
a42a7a1fb5
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
Loading…
Reference in New Issue