linux-sh.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 02/03] iommu/ipmmu-vmsa: Create mapping via group notifier
@ 2014-09-16 11:20 Magnus Damm
  0 siblings, 0 replies; only message in thread
From: Magnus Damm @ 2014-09-16 11:20 UTC (permalink / raw)
  To: linux-sh

From: Magnus Damm <damm+renesas@opensource.se>

Extend the IPMMU-VMSA driver to use a notifier
together with IOMMU groups to hook in all devices
in the same IOMMU group to the same IOMMU.

This patch introduces an assumption that all devices
in one IOMMU group share the same UTLB number.

Tested with USB Host 2.0 on r8a7790 Lager.

Signed-off-by: Magnus Damm <damm+renesas@opensource.se>
---

 drivers/iommu/ipmmu-vmsa.c |  121 +++++++++++++++++++++++++++-----------------
 1 file changed, 75 insertions(+), 46 deletions(-)

--- 0001/drivers/iommu/ipmmu-vmsa.c
+++ work/drivers/iommu/ipmmu-vmsa.c	2014-09-16 16:52:21.000000000 +0900
@@ -33,6 +33,7 @@ struct ipmmu_vmsa_device {
 	unsigned int num_utlbs;
 
 	struct dma_iommu_mapping *mapping;
+	struct notifier_block group_notifier;
 };
 
 struct ipmmu_vmsa_domain {
@@ -1013,9 +1014,79 @@ static int ipmmu_find_utlb(struct ipmmu_
 	return -1;
 }
 
-static int ipmmu_add_device(struct device *dev)
+static int ipmmu_add_device_mapping(struct device *dev,
+				    struct ipmmu_vmsa_device *mmu,
+				    int utlb)
 {
 	struct ipmmu_vmsa_archdata *archdata;
+	int ret;
+
+	archdata = kzalloc(sizeof(*archdata), GFP_KERNEL);
+	if (!archdata)
+		return -ENOMEM;
+
+	archdata->mmu = mmu;
+	archdata->utlb = utlb;
+	dev->archdata.iommu = archdata;
+
+	/*
+	 * Create the ARM mapping, used by the ARM DMA mapping core to allocate
+	 * VAs. This will allocate a corresponding IOMMU domain.
+	 *
+	 * TODO:
+	 * - Create one mapping per context (TLB).
+	 * - Make the mapping size configurable ? We currently use a 2GB mapping
+	 *   at a 1GB offset to ensure that NULL VAs will fault.
+	 */
+	if (!mmu->mapping) {
+		struct dma_iommu_mapping *mapping;
+
+		mapping = arm_iommu_create_mapping(&platform_bus_type,
+						   SZ_1G, SZ_2G);
+		if (IS_ERR(mapping)) {
+			dev_err(mmu->dev, "failed to create ARM IOMMU mapping\n");
+			return PTR_ERR(mapping);
+		}
+
+		mmu->mapping = mapping;
+	}
+
+	/* Attach the ARM VA mapping to the device. */
+	ret = arm_iommu_attach_device(dev, mmu->mapping);
+	if (ret < 0) {
+		dev_err(dev, "Failed to attach device to VA mapping\n");
+		goto error;
+	}
+	return 0;
+
+error:
+	kfree(archdata);
+	dev->archdata.iommu = NULL;
+	return ret;
+}
+
+static int ipmmu_group_notify(struct notifier_block *nb,
+			      unsigned long action, void *data)
+{
+	struct ipmmu_vmsa_device *mmu;
+	struct device *dev = data;
+	struct iommu_group *group = iommu_group_get(dev);
+	int utlb = (int)iommu_group_get_iommudata(group);
+
+	mmu = container_of(nb, struct ipmmu_vmsa_device, group_notifier);
+
+	/* TODO: remove device */
+	switch (action) {
+	case IOMMU_GROUP_NOTIFY_ADD_DEVICE:
+		ipmmu_add_device_mapping(dev, mmu, utlb);
+		break;
+	}
+
+	return NOTIFY_OK;
+}
+
+static int ipmmu_add_device(struct device *dev)
+{
 	struct ipmmu_vmsa_device *mmu;
 	struct iommu_group *group;
 	int utlb = -1;
@@ -1056,6 +1127,8 @@ static int ipmmu_add_device(struct devic
 		return PTR_ERR(group);
 	}
 
+	iommu_group_set_iommudata(group, (void *)utlb, NULL);
+	iommu_group_register_notifier(group, &mmu->group_notifier);
 	ret = iommu_group_add_device(group, dev);
 	iommu_group_put(group);
 
@@ -1064,51 +1137,6 @@ static int ipmmu_add_device(struct devic
 		return ret;
 	}
 
-	archdata = kzalloc(sizeof(*archdata), GFP_KERNEL);
-	if (!archdata) {
-		ret = -ENOMEM;
-		goto error;
-	}
-
-	archdata->mmu = mmu;
-	archdata->utlb = utlb;
-	dev->archdata.iommu = archdata;
-
-	/*
-	 * Create the ARM mapping, used by the ARM DMA mapping core to allocate
-	 * VAs. This will allocate a corresponding IOMMU domain.
-	 *
-	 * TODO:
-	 * - Create one mapping per context (TLB).
-	 * - Make the mapping size configurable ? We currently use a 2GB mapping
-	 *   at a 1GB offset to ensure that NULL VAs will fault.
-	 */
-	if (!mmu->mapping) {
-		struct dma_iommu_mapping *mapping;
-
-		mapping = arm_iommu_create_mapping(&platform_bus_type,
-						   SZ_1G, SZ_2G);
-		if (IS_ERR(mapping)) {
-			dev_err(mmu->dev, "failed to create ARM IOMMU mapping\n");
-			return PTR_ERR(mapping);
-		}
-
-		mmu->mapping = mapping;
-	}
-
-	/* Attach the ARM VA mapping to the device. */
-	ret = arm_iommu_attach_device(dev, mmu->mapping);
-	if (ret < 0) {
-		dev_err(dev, "Failed to attach device to VA mapping\n");
-		goto error;
-	}
-
-	return 0;
-
-error:
-	kfree(dev->archdata.iommu);
-	dev->archdata.iommu = NULL;
-	iommu_group_remove_device(dev);
 	return ret;
 }
 
@@ -1167,6 +1195,7 @@ static int ipmmu_probe(struct platform_d
 	mmu->dev = &pdev->dev;
 	mmu->pdata = pdev->dev.platform_data;
 	mmu->num_utlbs = 32;
+	mmu->group_notifier.notifier_call = ipmmu_group_notify;
 
 	/* Map I/O memory and request IRQ. */
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);

^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2014-09-16 11:20 UTC | newest]

Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2014-09-16 11:20 [PATCH 02/03] iommu/ipmmu-vmsa: Create mapping via group notifier Magnus Damm

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).