diff options
author | Robin Murphy <robin.murphy@arm.com> | 2016-09-12 12:13:41 -0400 |
---|---|---|
committer | Will Deacon <will.deacon@arm.com> | 2016-09-16 04:34:15 -0400 |
commit | b996444cf35e736621855e73f9d0762bd49f41f2 (patch) | |
tree | f35ef47f4ae8053f2ae6226e3229d3f874a032f7 /drivers/iommu/of_iommu.c | |
parent | 987068fcbdb7a085bb11151b91dc6f4c956c4a1b (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.c | 46 |
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 | ||
27 | static const struct of_device_id __iommu_of_table_sentinel | 28 | static 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 | ||
138 | static 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 | |||
146 | static 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 | |||
137 | const struct iommu_ops *of_iommu_configure(struct device *dev, | 177 | const 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. |