All of lore.kernel.org
 help / color / mirror / Atom feed
From: Magnus Damm <magnus.damm@gmail.com>
To: linux-renesas-soc@vger.kernel.org
Cc: Magnus Damm <magnus.damm@gmail.com>
Subject: [PATCH/RFC] iommu/ipmmu-vmsa: IPMMU SYS-DMAC iova mapping workaround
Date: Tue, 20 Sep 2016 20:54:33 +0900	[thread overview]
Message-ID: <20160920115433.14772.84308.sendpatchset@little-apple> (raw)

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

Here's some prototype code that works around the lack of software
support for mapping I/O devices to the SYS-DMAC hardware via the
DMA Engine framework when using IOMMU.

The code itself is one big layering violation that goes through
the DT and unconditionally maps I/O devices using DMACs via the
IPMMU device instance into iova space with a 1:1 mapping.

This very short term prototype will for instance automatically make
the SCIF serial port function with the IPMMU hardware in case the
SYS-DMAC is hooked up to the IPMMU device.

Not to be confused with the more long term solution to allow the
DMA Engine framework to map I/O device memory dynamically.

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

 Applies on top of: renesas-drivers-2016-09-13-v4.8-rc6

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

--- 0001/drivers/iommu/ipmmu-vmsa.c
+++ work/drivers/iommu/ipmmu-vmsa.c	2016-09-20 20:03:37.620607110 +0900
@@ -19,6 +19,7 @@
 #include <linux/iommu.h>
 #include <linux/module.h>
 #include <linux/of.h>
+#include <linux/of_address.h>
 #include <linux/of_iommu.h>
 #include <linux/platform_device.h>
 #include <linux/sizes.h>
@@ -625,6 +626,78 @@ static void ipmmu_domain_free(struct iom
 	kfree(domain);
 }
 
+static void ipmmu_workaround_map(struct iommu_domain *io_domain,
+				 struct device *dma_dev, struct resource *res)
+{
+	phys_addr_t phys_addr;
+
+	dev_info(dma_dev, "map %pr\n", res);
+
+	phys_addr = iommu_iova_to_phys(io_domain, res->start);
+	if (phys_addr)
+		return;
+
+	iommu_map(io_domain, res->start, res->start,
+		  ALIGN(resource_size(res), SZ_4K),
+		  IOMMU_READ | IOMMU_WRITE);
+}
+
+static void ipmmu_workaround_dt(struct iommu_domain *io_domain,
+				struct device *dev,
+				void (*match)(struct iommu_domain *io_domain,
+					      struct device *dma_dev,
+					      struct resource *res))
+{
+	struct device_node *np = NULL;
+	struct of_phandle_args dma_spec;
+	struct resource r;
+	int i, cnt;
+	bool found;
+
+	/* Locate I/O devices using the DMAC and map their registers */
+	while ((np = of_find_all_nodes(np))) {
+		if (!of_find_property(np, "dmas", NULL))
+			continue;
+
+		cnt = of_property_count_strings(np, "dma-names");
+		if (cnt < 0)
+			continue;
+
+		found = false;
+		for (i = 0; i < cnt; i++) {
+			if (of_parse_phandle_with_args(np, "dmas",
+						       "#dma-cells", i,
+						       &dma_spec))
+				continue;
+
+			if (dma_spec.np == dev->of_node)
+				found = true;
+
+			of_node_put(dma_spec.np);
+		}
+
+		if (!found)
+			continue;
+
+		i = 0;
+		while (!of_address_to_resource(np, i, &r)) {
+			match(io_domain, dev, &r);
+			i++;
+		}
+	}
+}
+
+static void ipmmu_workaround(struct iommu_domain *io_domain,
+			     struct device *dev)
+{
+	/* only apply workaround for DMA controllers */
+	if (!strstr(dev_name(dev), "dma-controller"))
+		return;
+
+	dev_info(dev, "Adding iommu workaround to map I/O devices for DMACs\n");
+	ipmmu_workaround_dt(io_domain, dev, ipmmu_workaround_map);
+}
+
 static int ipmmu_attach_device(struct iommu_domain *io_domain,
 			       struct device *dev)
 {
@@ -678,6 +751,8 @@ static int ipmmu_attach_device(struct io
 	if (ret < 0)
 		return ret;
 
+	ipmmu_workaround(io_domain, dev);
+
 	for (i = 0; i < archdata->num_utlbs; ++i)
 		ipmmu_utlb_enable(domain, archdata->utlbs[i]);
 

             reply	other threads:[~2016-09-20 12:03 UTC|newest]

Thread overview: 4+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-09-20 11:54 Magnus Damm [this message]
2016-09-27  6:20 ` [PATCH/RFC] iommu/ipmmu-vmsa: IPMMU SYS-DMAC iova mapping workaround Niklas Söderlund
2016-09-27  6:43   ` Magnus Damm
2016-09-27 10:11     ` Niklas Söderlund

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20160920115433.14772.84308.sendpatchset@little-apple \
    --to=magnus.damm@gmail.com \
    --cc=linux-renesas-soc@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.