Skip to content

Commit

Permalink
iommu: store DT-probed IOMMU data privately
Browse files Browse the repository at this point in the history
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 <[email protected]>
Signed-off-by: Robin Murphy <[email protected]>
[will: added missing #include and missing ')']
Signed-off-by: Will Deacon <[email protected]>
  • Loading branch information
rmurphy-arm authored and wildea01 committed Dec 5, 2014
1 parent 4bb2578 commit a42a7a1
Show file tree
Hide file tree
Showing 2 changed files with 41 additions and 10 deletions.
39 changes: 39 additions & 0 deletions drivers/iommu/of_iommu.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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;
Expand Down
12 changes: 2 additions & 10 deletions include/linux/of_iommu.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down

0 comments on commit a42a7a1

Please sign in to comment.