[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