|
@@ -1780,3 +1780,69 @@ arm_iommu_create_mapping(struct bus_type *bus, dma_addr_t base, size_t size,
|
|
|
|
|
|
mapping->bitmap = kzalloc(bitmap_size, GFP_KERNEL);
|
|
|
if (!mapping->bitmap)
|
|
|
+ goto err2;
|
|
|
+
|
|
|
+ mapping->base = base;
|
|
|
+ mapping->bits = BITS_PER_BYTE * bitmap_size;
|
|
|
+ mapping->order = order;
|
|
|
+ spin_lock_init(&mapping->lock);
|
|
|
+
|
|
|
+ mapping->domain = iommu_domain_alloc(bus);
|
|
|
+ if (!mapping->domain)
|
|
|
+ goto err3;
|
|
|
+
|
|
|
+ kref_init(&mapping->kref);
|
|
|
+ return mapping;
|
|
|
+err3:
|
|
|
+ kfree(mapping->bitmap);
|
|
|
+err2:
|
|
|
+ kfree(mapping);
|
|
|
+err:
|
|
|
+ return ERR_PTR(err);
|
|
|
+}
|
|
|
+
|
|
|
+static void release_iommu_mapping(struct kref *kref)
|
|
|
+{
|
|
|
+ struct dma_iommu_mapping *mapping =
|
|
|
+ container_of(kref, struct dma_iommu_mapping, kref);
|
|
|
+
|
|
|
+ iommu_domain_free(mapping->domain);
|
|
|
+ kfree(mapping->bitmap);
|
|
|
+ kfree(mapping);
|
|
|
+}
|
|
|
+
|
|
|
+void arm_iommu_release_mapping(struct dma_iommu_mapping *mapping)
|
|
|
+{
|
|
|
+ if (mapping)
|
|
|
+ kref_put(&mapping->kref, release_iommu_mapping);
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * 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,
|
|
|
+ * 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.
|
|
|
+ */
|
|
|
+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;
|
|
|
+ set_dma_ops(dev, &iommu_ops);
|
|
|
+
|
|
|
+ pr_debug("Attached IOMMU controller to %s device.\n", dev_name(dev));
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+#endif
|