aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRobin Murphy <Robin.Murphy@arm.com>2014-12-05 08:41:02 -0500
committerWill Deacon <will.deacon@arm.com>2014-12-05 09:35:52 -0500
commita42a7a1fb5f1f9004b023594609dc22da02fc08b (patch)
treee6f54fe900945b7c1939757a59aeabc510605a27
parent4bb25789ed28228a52c030bf28edb2fcdb214be8 (diff)
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>
-rw-r--r--drivers/iommu/of_iommu.c39
-rw-r--r--include/linux/of_iommu.h12
2 files changed, 41 insertions, 10 deletions
diff --git a/drivers/iommu/of_iommu.c b/drivers/iommu/of_iommu.c
index 73236d3cc955..af1dc6a1c0a1 100644
--- a/drivers/iommu/of_iommu.c
+++ b/drivers/iommu/of_iommu.c
@@ -22,6 +22,7 @@
22#include <linux/limits.h> 22#include <linux/limits.h>
23#include <linux/of.h> 23#include <linux/of.h>
24#include <linux/of_iommu.h> 24#include <linux/of_iommu.h>
25#include <linux/slab.h>
25 26
26static const struct of_device_id __iommu_of_table_sentinel 27static const struct of_device_id __iommu_of_table_sentinel
27 __used __section(__iommu_of_table_end); 28 __used __section(__iommu_of_table_end);
@@ -94,6 +95,44 @@ int of_get_dma_window(struct device_node *dn, const char *prefix, int index,
94} 95}
95EXPORT_SYMBOL_GPL(of_get_dma_window); 96EXPORT_SYMBOL_GPL(of_get_dma_window);
96 97
98struct of_iommu_node {
99 struct list_head list;
100 struct device_node *np;
101 struct iommu_ops *ops;
102};
103static LIST_HEAD(of_iommu_list);
104static DEFINE_SPINLOCK(of_iommu_lock);
105
106void of_iommu_set_ops(struct device_node *np, struct iommu_ops *ops)
107{
108 struct of_iommu_node *iommu = kzalloc(sizeof(*iommu), GFP_KERNEL);
109
110 if (WARN_ON(!iommu))
111 return;
112
113 INIT_LIST_HEAD(&iommu->list);
114 iommu->np = np;
115 iommu->ops = ops;
116 spin_lock(&of_iommu_lock);
117 list_add_tail(&iommu->list, &of_iommu_list);
118 spin_unlock(&of_iommu_lock);
119}
120
121struct iommu_ops *of_iommu_get_ops(struct device_node *np)
122{
123 struct of_iommu_node *node;
124 struct iommu_ops *ops = NULL;
125
126 spin_lock(&of_iommu_lock);
127 list_for_each_entry(node, &of_iommu_list, list)
128 if (node->np == np) {
129 ops = node->ops;
130 break;
131 }
132 spin_unlock(&of_iommu_lock);
133 return ops;
134}
135
97struct iommu_ops *of_iommu_configure(struct device *dev) 136struct iommu_ops *of_iommu_configure(struct device *dev)
98{ 137{
99 struct of_phandle_args iommu_spec; 138 struct of_phandle_args iommu_spec;
diff --git a/include/linux/of_iommu.h b/include/linux/of_iommu.h
index d03abbb11c34..16c75547d725 100644
--- a/include/linux/of_iommu.h
+++ b/include/linux/of_iommu.h
@@ -31,16 +31,8 @@ static inline struct iommu_ops *of_iommu_configure(struct device *dev)
31 31
32#endif /* CONFIG_OF_IOMMU */ 32#endif /* CONFIG_OF_IOMMU */
33 33
34static inline void of_iommu_set_ops(struct device_node *np, 34void of_iommu_set_ops(struct device_node *np, struct iommu_ops *ops);
35 const struct iommu_ops *ops) 35struct iommu_ops *of_iommu_get_ops(struct device_node *np);
36{
37 np->data = (struct iommu_ops *)ops;
38}
39
40static inline struct iommu_ops *of_iommu_get_ops(struct device_node *np)
41{
42 return np->data;
43}
44 36
45extern struct of_device_id __iommu_of_table; 37extern struct of_device_id __iommu_of_table;
46 38