aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/iommu/of_iommu.c
diff options
context:
space:
mode:
authorRobin Murphy <robin.murphy@arm.com>2016-09-12 12:13:41 -0400
committerWill Deacon <will.deacon@arm.com>2016-09-16 04:34:15 -0400
commitb996444cf35e736621855e73f9d0762bd49f41f2 (patch)
treef35ef47f4ae8053f2ae6226e3229d3f874a032f7 /drivers/iommu/of_iommu.c
parent987068fcbdb7a085bb11151b91dc6f4c956c4a1b (diff)
iommu/of: Handle iommu-map property for PCI
Now that we have a way to pick up the RID translation and target IOMMU, hook up of_iommu_configure() to bring PCI devices into the of_xlate mechanism and allow them IOMMU-backed DMA ops without the need for driver-specific handling. Reviewed-by: Will Deacon <will.deacon@arm.com> Signed-off-by: Robin Murphy <robin.murphy@arm.com> Signed-off-by: Will Deacon <will.deacon@arm.com>
Diffstat (limited to 'drivers/iommu/of_iommu.c')
-rw-r--r--drivers/iommu/of_iommu.c46
1 files changed, 41 insertions, 5 deletions
diff --git a/drivers/iommu/of_iommu.c b/drivers/iommu/of_iommu.c
index 57f23eaaa2f9..19e1e8f2f871 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/of_pci.h>
25#include <linux/slab.h> 26#include <linux/slab.h>
26 27
27static const struct of_device_id __iommu_of_table_sentinel 28static const struct of_device_id __iommu_of_table_sentinel
@@ -134,6 +135,45 @@ const struct iommu_ops *of_iommu_get_ops(struct device_node *np)
134 return ops; 135 return ops;
135} 136}
136 137
138static int __get_pci_rid(struct pci_dev *pdev, u16 alias, void *data)
139{
140 struct of_phandle_args *iommu_spec = data;
141
142 iommu_spec->args[0] = alias;
143 return iommu_spec->np == pdev->bus->dev.of_node;
144}
145
146static const struct iommu_ops
147*of_pci_iommu_configure(struct pci_dev *pdev, struct device_node *bridge_np)
148{
149 const struct iommu_ops *ops;
150 struct of_phandle_args iommu_spec;
151
152 /*
153 * Start by tracing the RID alias down the PCI topology as
154 * far as the host bridge whose OF node we have...
155 * (we're not even attempting to handle multi-alias devices yet)
156 */
157 iommu_spec.args_count = 1;
158 iommu_spec.np = bridge_np;
159 pci_for_each_dma_alias(pdev, __get_pci_rid, &iommu_spec);
160 /*
161 * ...then find out what that becomes once it escapes the PCI
162 * bus into the system beyond, and which IOMMU it ends up at.
163 */
164 iommu_spec.np = NULL;
165 if (of_pci_map_rid(bridge_np, iommu_spec.args[0], "iommu-map",
166 "iommu-map-mask", &iommu_spec.np, iommu_spec.args))
167 return NULL;
168
169 ops = of_iommu_get_ops(iommu_spec.np);
170 if (!ops || !ops->of_xlate || ops->of_xlate(&pdev->dev, &iommu_spec))
171 ops = NULL;
172
173 of_node_put(iommu_spec.np);
174 return ops;
175}
176
137const struct iommu_ops *of_iommu_configure(struct device *dev, 177const struct iommu_ops *of_iommu_configure(struct device *dev,
138 struct device_node *master_np) 178 struct device_node *master_np)
139{ 179{
@@ -142,12 +182,8 @@ const struct iommu_ops *of_iommu_configure(struct device *dev,
142 const struct iommu_ops *ops = NULL; 182 const struct iommu_ops *ops = NULL;
143 int idx = 0; 183 int idx = 0;
144 184
145 /*
146 * We can't do much for PCI devices without knowing how
147 * device IDs are wired up from the PCI bus to the IOMMU.
148 */
149 if (dev_is_pci(dev)) 185 if (dev_is_pci(dev))
150 return NULL; 186 return of_pci_iommu_configure(to_pci_dev(dev), master_np);
151 187
152 /* 188 /*
153 * We don't currently walk up the tree looking for a parent IOMMU. 189 * We don't currently walk up the tree looking for a parent IOMMU.