[RFC][PATCHv3+ 1/2] driver/core: Add of_iommu_attach()

Hiroshi Doyu hdoyu at nvidia.com
Wed Nov 6 14:06:23 UTC 2013


Hi,

Experimentally I have implemented "of_iommu_attach()" called from
drvier/core to control the order of device instanciation.

In the Tegra SMMU PATCHv3, we've discussed how to control the order of
device instanciation. Thierry/Stephen proposed to insert a hook in
driver/core to control this order, depending on whether an iommu
device is ready or not."of_iommu_attach()" is implement for that
purpose now. Along with this patch, I attached DT part of modication
to this mail. I used the same iommu bindings which arm,smmu uses.

[RFC][PATCHv3+ 2/2] ARM: DT: tegra30: iommu: Add "stream-id-cells"/"mmu-masters"

"#stream-id-cells" is used to identify whether a device is IOMMU'able
or not. If a device is IOMMU'able, we'll defer to instanciate that
device till an iommu device is instanciated/ready. Once an iommu device
is instanciated, "dev->bus->iommu_ops" is set in the bus. After an
iommu device is instanciated, those defered devices are instanciated
as IOMMU'able with help of the iommu driver via iommu_ops->add_device().

We don't call bus_set_iommu() until an iommu device is instanciated
because we need to support 2 kind of IOMMU drivers, SMMU and GART so
that this bus_set_iommu() needs to be defered till an iommu device is
instanciated. So the single image can support 2 iommu drivers at once.

With this patch, the following HACK patches in v3[1] are not needed
anymore.

  patch 1: [HACK] of: dev_node has struct device pointer
  patch 2: [HACK] ARM: tegra: Populate AHB/IOMMU earlier than others
  patch 3: [HACK] amba: Move AHB to core_initcall
  patch 4: [HACK] iommu/tegra: smmu: Move IOMMU to core_initcall

Any comment would be really appreciated.

[1] Original v3:
http://lists.linuxfoundation.org/pipermail/iommu/2013-October/006724.html

[2]
http://lists.linuxfoundation.org/pipermail/iommu/2013-November/006864.html

Signed-off-by: Hiroshi Doyu <hdoyu at nvidia.com>
---
 drivers/base/dd.c        |  5 +++++
 drivers/iommu/of_iommu.c | 34 ++++++++++++++++++++++++++++++++++
 include/linux/iommu.h    |  7 +++++++
 3 files changed, 46 insertions(+)

diff --git a/drivers/base/dd.c b/drivers/base/dd.c
index 35fa368..ca76290 100644
--- a/drivers/base/dd.c
+++ b/drivers/base/dd.c
@@ -25,6 +25,7 @@
 #include <linux/async.h>
 #include <linux/pm_runtime.h>
 #include <linux/pinctrl/devinfo.h>
+#include <linux/iommu.h>
 
 #include "base.h"
 #include "power/power.h"
@@ -273,6 +274,10 @@ static int really_probe(struct device *dev, struct device_driver *drv)
 
 	dev->driver = drv;
 
+	ret = of_iommu_attach(dev);
+	if (ret)
+		goto probe_failed;
+
 	/* If using pinctrl, bind pins now before probing */
 	ret = pinctrl_bind_pins(dev);
 	if (ret)
diff --git a/drivers/iommu/of_iommu.c b/drivers/iommu/of_iommu.c
index ee249bc..f211cdc 100644
--- a/drivers/iommu/of_iommu.c
+++ b/drivers/iommu/of_iommu.c
@@ -20,6 +20,9 @@
 #include <linux/export.h>
 #include <linux/limits.h>
 #include <linux/of.h>
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/iommu.h>
 
 /**
  * of_get_dma_window - Parse *dma-window property and returns 0 if found.
@@ -88,3 +91,34 @@ int of_get_dma_window(struct device_node *dn, const char *prefix, int index,
 	return 0;
 }
 EXPORT_SYMBOL_GPL(of_get_dma_window);
+
+static bool of_is_iommuable(struct device *dev)
+{
+	size_t bytes;
+	const __be32 *prop;
+	const char *propname = "#stream-id-cells";
+
+	prop = of_get_property(dev->of_node, propname, &bytes);
+	if (!prop || !bytes)
+		return false;
+
+	pr_debug("%s=%d %s\n", propname, bytes, dev_name(dev));
+	return true;
+}
+
+int of_iommu_attach(struct device *dev)
+{
+	struct iommu_ops *ops;
+
+	if (!of_is_iommuable(dev))
+		return 0;
+
+	ops = dev->bus->iommu_ops;
+	if (!ops)
+		return -EPROBE_DEFER;
+
+	if (ops->add_device)
+		return ops->add_device(dev);
+
+	return 0;
+}
diff --git a/include/linux/iommu.h b/include/linux/iommu.h
index a444c79..de16bf2 100644
--- a/include/linux/iommu.h
+++ b/include/linux/iommu.h
@@ -232,6 +232,8 @@ static inline int report_iommu_fault(struct iommu_domain *domain,
 	return ret;
 }
 
+extern int of_iommu_attach(struct device *dev);
+
 #else /* CONFIG_IOMMU_API */
 
 struct iommu_ops {};
@@ -390,6 +392,11 @@ static inline int iommu_domain_set_attr(struct iommu_domain *domain,
 	return -EINVAL;
 }
 
+static inline int of_iommu_attach(struct device *dev)
+{
+	return 0;
+}
+
 #endif /* CONFIG_IOMMU_API */
 
 #endif /* __LINUX_IOMMU_H */
-- 
1.8.1.5

-------------- next part --------------
A non-text attachment was scrubbed...
Name: 0002-ARM-DT-tegra30-iommu-Add-stream-id-cells-mmu-masters.patch
Type: text/x-diff
Size: 7124 bytes
Desc: not available
URL: <http://lists.linuxfoundation.org/pipermail/iommu/attachments/20131106/572fa2ad/attachment.bin>


More information about the iommu mailing list