| From foo@baz Thu Nov 9 09:48:01 CET 2017 |
| From: Will Deacon <will.deacon@arm.com> |
| Date: Fri, 6 Jan 2017 10:49:12 +0000 |
| Subject: arm64: dma-mapping: Only swizzle DMA ops for IOMMU_DOMAIN_DMA |
| |
| From: Will Deacon <will.deacon@arm.com> |
| |
| |
| [ Upstream commit 4a8d8a14c0d08c2437cb80c05e88f6cc1ca3fb2c ] |
| |
| The arm64 DMA-mapping implementation sets the DMA ops to the IOMMU DMA |
| ops if we detect that an IOMMU is present for the master and the DMA |
| ranges are valid. |
| |
| In the case when the IOMMU domain for the device is not of type |
| IOMMU_DOMAIN_DMA, then we have no business swizzling the ops, since |
| we're not in control of the underlying address space. This patch leaves |
| the DMA ops alone for masters attached to non-DMA IOMMU domains. |
| |
| Reviewed-by: Robin Murphy <robin.murphy@arm.com> |
| Signed-off-by: Will Deacon <will.deacon@arm.com> |
| Signed-off-by: Sasha Levin <alexander.levin@verizon.com> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| --- |
| arch/arm64/mm/dma-mapping.c | 17 ++++++++++++----- |
| 1 file changed, 12 insertions(+), 5 deletions(-) |
| |
| --- a/arch/arm64/mm/dma-mapping.c |
| +++ b/arch/arm64/mm/dma-mapping.c |
| @@ -836,14 +836,21 @@ static bool do_iommu_attach(struct devic |
| * then the IOMMU core will have already configured a group for this |
| * device, and allocated the default domain for that group. |
| */ |
| - if (!domain || iommu_dma_init_domain(domain, dma_base, size, dev)) { |
| - pr_warn("Failed to set up IOMMU for device %s; retaining platform DMA ops\n", |
| - dev_name(dev)); |
| - return false; |
| + if (!domain) |
| + goto out_err; |
| + |
| + if (domain->type == IOMMU_DOMAIN_DMA) { |
| + if (iommu_dma_init_domain(domain, dma_base, size, dev)) |
| + goto out_err; |
| + |
| + dev->archdata.dma_ops = &iommu_dma_ops; |
| } |
| |
| - dev->archdata.dma_ops = &iommu_dma_ops; |
| return true; |
| +out_err: |
| + pr_warn("Failed to set up IOMMU for device %s; retaining platform DMA ops\n", |
| + dev_name(dev)); |
| + return false; |
| } |
| |
| static void queue_iommu_attach(struct device *dev, const struct iommu_ops *ops, |