OSDN Git Service

arm64: dma-mapping: Attach IOMMUs as groups
authorMitchel Humpherys <mitchelh@codeaurora.org>
Fri, 27 May 2016 21:58:31 +0000 (14:58 -0700)
committerKyle Yan <kyan@codeaurora.org>
Thu, 2 Jun 2016 23:12:47 +0000 (16:12 -0700)
Some devices behind IOMMUs might end up in IOMMU groups due to DMA
aliasing.  The iommu_attach_device API expects a single device in a
group all by its lonesome, so it fails when a device is passed in that's
part of a group.  Use iommu_attach_group to accommodate these types of
devices.

CRs-Fixed: 1023180
Change-Id: I9601efd300c7f428c4576e6ecf6d31791d0b47bd
Signed-off-by: Mitchel Humpherys <mitchelh@codeaurora.org>
arch/arm64/mm/dma-mapping.c

index c2819df..6b151d4 100644 (file)
@@ -2114,12 +2114,19 @@ int arm_iommu_attach_device(struct device *dev,
 {
        int err;
        int s1_bypass = 0, is_fast = 0;
+       struct iommu_group *group;
 
        iommu_domain_get_attr(mapping->domain, DOMAIN_ATTR_FAST, &is_fast);
        if (is_fast)
                return fast_smmu_attach_device(dev, mapping);
 
-       err = iommu_attach_device(mapping->domain, dev);
+       group = iommu_group_get(dev);
+       if (!group) {
+               dev_err(dev, "Couldn't get group\n");
+               return -ENODEV;
+       }
+
+       err = iommu_attach_group(mapping->domain, group);
        if (err)
                return err;
 
@@ -2147,6 +2154,7 @@ void arm_iommu_detach_device(struct device *dev)
 {
        struct dma_iommu_mapping *mapping;
        int is_fast;
+       struct iommu_group *group;
 
        mapping = to_dma_iommu_mapping(dev);
        if (!mapping) {
@@ -2160,7 +2168,13 @@ void arm_iommu_detach_device(struct device *dev)
                return;
        }
 
-       iommu_detach_device(mapping->domain, dev);
+       group = iommu_group_get(dev);
+       if (!group) {
+               dev_err(dev, "Couldn't get group\n");
+               return;
+       }
+
+       iommu_detach_group(mapping->domain, group);
        kref_put(&mapping->kref, release_iommu_mapping);
        dev->archdata.mapping = NULL;
        set_dma_ops(dev, NULL);