diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2016-10-11 15:52:41 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2016-10-11 15:52:41 -0400 |
commit | 56e520c7a0a490b63b042b047ec9659fc08762a4 (patch) | |
tree | b20296f4b088d81aba3c41174d52afa209afff9b /drivers/iommu/of_iommu.c | |
parent | d09ba13110e303d7baa29d170da94cd24f7662b2 (diff) | |
parent | 13a08259187c5cd3f63d98efa159ab42976d85a4 (diff) |
Merge tag 'iommu-updates-v4.9' of git://git.kernel.org/pub/scm/linux/kernel/git/joro/iommu
Pull IOMMU updates from Joerg Roedel:
- support for interrupt virtualization in the AMD IOMMU driver. These
patches were shared with the KVM tree and are already merged through
that tree.
- generic DT-binding support for the ARM-SMMU driver. With this the
driver now makes use of the generic DMA-API code. This also required
some changes outside of the IOMMU code, but these are acked by the
respective maintainers.
- more cleanups and fixes all over the place.
* tag 'iommu-updates-v4.9' of git://git.kernel.org/pub/scm/linux/kernel/git/joro/iommu: (40 commits)
iommu/amd: No need to wait iommu completion if no dte irq entry change
iommu/amd: Free domain id when free a domain of struct dma_ops_domain
iommu/amd: Use standard bitmap operation to set bitmap
iommu/amd: Clean up the cmpxchg64 invocation
iommu/io-pgtable-arm: Check for v7s-incapable systems
iommu/dma: Avoid PCI host bridge windows
iommu/dma: Add support for mapping MSIs
iommu/arm-smmu: Set domain geometry
iommu/arm-smmu: Wire up generic configuration support
Docs: dt: document ARM SMMU generic binding usage
iommu/arm-smmu: Convert to iommu_fwspec
iommu/arm-smmu: Intelligent SMR allocation
iommu/arm-smmu: Add a stream map entry iterator
iommu/arm-smmu: Streamline SMMU data lookups
iommu/arm-smmu: Refactor mmu-masters handling
iommu/arm-smmu: Keep track of S2CR state
iommu/arm-smmu: Consolidate stream map entry state
iommu/arm-smmu: Handle stream IDs more dynamically
iommu/arm-smmu: Set PRIVCFG in stage 1 STEs
iommu/arm-smmu: Support non-PCI devices with SMMUv3
...
Diffstat (limited to 'drivers/iommu/of_iommu.c')
-rw-r--r-- | drivers/iommu/of_iommu.c | 52 |
1 files changed, 46 insertions, 6 deletions
diff --git a/drivers/iommu/of_iommu.c b/drivers/iommu/of_iommu.c index 57f23eaaa2f9..5b82862f571f 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,47 @@ 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 || | ||
171 | iommu_fwspec_init(&pdev->dev, &iommu_spec.np->fwnode, ops) || | ||
172 | ops->of_xlate(&pdev->dev, &iommu_spec)) | ||
173 | ops = NULL; | ||
174 | |||
175 | of_node_put(iommu_spec.np); | ||
176 | return ops; | ||
177 | } | ||
178 | |||
137 | const struct iommu_ops *of_iommu_configure(struct device *dev, | 179 | const struct iommu_ops *of_iommu_configure(struct device *dev, |
138 | struct device_node *master_np) | 180 | struct device_node *master_np) |
139 | { | 181 | { |
@@ -142,12 +184,8 @@ const struct iommu_ops *of_iommu_configure(struct device *dev, | |||
142 | const struct iommu_ops *ops = NULL; | 184 | const struct iommu_ops *ops = NULL; |
143 | int idx = 0; | 185 | int idx = 0; |
144 | 186 | ||
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)) | 187 | if (dev_is_pci(dev)) |
150 | return NULL; | 188 | return of_pci_iommu_configure(to_pci_dev(dev), master_np); |
151 | 189 | ||
152 | /* | 190 | /* |
153 | * We don't currently walk up the tree looking for a parent IOMMU. | 191 | * We don't currently walk up the tree looking for a parent IOMMU. |
@@ -160,7 +198,9 @@ const struct iommu_ops *of_iommu_configure(struct device *dev, | |||
160 | np = iommu_spec.np; | 198 | np = iommu_spec.np; |
161 | ops = of_iommu_get_ops(np); | 199 | ops = of_iommu_get_ops(np); |
162 | 200 | ||
163 | if (!ops || !ops->of_xlate || ops->of_xlate(dev, &iommu_spec)) | 201 | if (!ops || !ops->of_xlate || |
202 | iommu_fwspec_init(dev, &np->fwnode, ops) || | ||
203 | ops->of_xlate(dev, &iommu_spec)) | ||
164 | goto err_put_node; | 204 | goto err_put_node; |
165 | 205 | ||
166 | of_node_put(np); | 206 | of_node_put(np); |