Merge branch 'fixes' of git://ftp.arm.linux.org.uk/~rmk/linux-arm
[sfrench/cifs-2.6.git] / arch / arm / mm / dma-mapping.c
index 50ffaed44ec044411636f58cacb1e6dd4fcad52f..170a116d1b298c1befb81efdeaee49735362fd26 100644 (file)
@@ -1940,13 +1940,32 @@ void arm_iommu_release_mapping(struct dma_iommu_mapping *mapping)
 }
 EXPORT_SYMBOL_GPL(arm_iommu_release_mapping);
 
+static int __arm_iommu_attach_device(struct device *dev,
+                                    struct dma_iommu_mapping *mapping)
+{
+       int err;
+
+       err = iommu_attach_device(mapping->domain, dev);
+       if (err)
+               return err;
+
+       kref_get(&mapping->kref);
+       dev->archdata.mapping = mapping;
+
+       pr_debug("Attached IOMMU controller to %s device.\n", dev_name(dev));
+       return 0;
+}
+
 /**
  * arm_iommu_attach_device
  * @dev: valid struct device pointer
  * @mapping: io address space mapping structure (returned from
  *     arm_iommu_create_mapping)
  *
- * Attaches specified io address space mapping to the provided device,
+ * Attaches specified io address space mapping to the provided device.
+ * This replaces the dma operations (dma_map_ops pointer) with the
+ * IOMMU aware version.
+ *
  * More than one client might be attached to the same io address space
  * mapping.
  */
@@ -1955,25 +1974,16 @@ int arm_iommu_attach_device(struct device *dev,
 {
        int err;
 
-       err = iommu_attach_device(mapping->domain, dev);
+       err = __arm_iommu_attach_device(dev, mapping);
        if (err)
                return err;
 
-       kref_get(&mapping->kref);
-       dev->archdata.mapping = mapping;
-
-       pr_debug("Attached IOMMU controller to %s device.\n", dev_name(dev));
+       set_dma_ops(dev, &iommu_ops);
        return 0;
 }
 EXPORT_SYMBOL_GPL(arm_iommu_attach_device);
 
-/**
- * arm_iommu_detach_device
- * @dev: valid struct device pointer
- *
- * Detaches the provided device from a previously attached map.
- */
-void arm_iommu_detach_device(struct device *dev)
+static void __arm_iommu_detach_device(struct device *dev)
 {
        struct dma_iommu_mapping *mapping;
 
@@ -1989,6 +1999,19 @@ void arm_iommu_detach_device(struct device *dev)
 
        pr_debug("Detached IOMMU controller from %s device.\n", dev_name(dev));
 }
+
+/**
+ * arm_iommu_detach_device
+ * @dev: valid struct device pointer
+ *
+ * Detaches the provided device from a previously attached map.
+ * This voids the dma operations (dma_map_ops pointer)
+ */
+void arm_iommu_detach_device(struct device *dev)
+{
+       __arm_iommu_detach_device(dev);
+       set_dma_ops(dev, NULL);
+}
 EXPORT_SYMBOL_GPL(arm_iommu_detach_device);
 
 static struct dma_map_ops *arm_get_iommu_dma_map_ops(bool coherent)
@@ -2011,7 +2034,7 @@ static bool arm_setup_iommu_dma_ops(struct device *dev, u64 dma_base, u64 size,
                return false;
        }
 
-       if (arm_iommu_attach_device(dev, mapping)) {
+       if (__arm_iommu_attach_device(dev, mapping)) {
                pr_warn("Failed to attached device %s to IOMMU_mapping\n",
                                dev_name(dev));
                arm_iommu_release_mapping(mapping);
@@ -2028,7 +2051,7 @@ static void arm_teardown_iommu_dma_ops(struct device *dev)
        if (!mapping)
                return;
 
-       arm_iommu_detach_device(dev);
+       __arm_iommu_detach_device(dev);
        arm_iommu_release_mapping(mapping);
 }