|
@@ -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);
|
|
@@ -2025,7 +2048,7 @@ static void arm_teardown_iommu_dma_ops(struct device *dev)
|
|
|
{
|
|
|
struct dma_iommu_mapping *mapping = dev->archdata.mapping;
|
|
|
|
|
|
- arm_iommu_detach_device(dev);
|
|
|
+ __arm_iommu_detach_device(dev);
|
|
|
arm_iommu_release_mapping(mapping);
|
|
|
}
|
|
|
|