[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-devel] [PATCH V2 5/6] iommu/arm: Introduce iommu_add_dt_device API



From: Oleksandr Tyshchenko <oleksandr_tyshchenko@xxxxxxxx>

This patch adds new iommu_add_dt_device API for adding DT device
to the IOMMU using generic IOMMU DT binding [1] and previously
added "iommu_fwspec" support.

New function parses the DT binding, prepares "dev->iommu_fwspec"
with correct information and calls the IOMMU driver using "add_device"
callback to register new DT device.
The IOMMU driver's responsibility is to check whether "dev->iommu_fwspec"
is initialized and mark that device as protected.

The additional benefit here is to avoid to go through the whole DT
multiple times in IOMMU driver trying to locate master devices which
belong to each IOMMU device being probed.

The upcoming IPMMU driver will have "add_device" callback implemented.

I hope, this patch won't break SMMU driver's functionality,
which doesn't have this callback implemented.

[1] https://www.kernel.org/doc/Documentation/devicetree/bindings/iommu/iommu.txt

Signed-off-by: Oleksandr Tyshchenko <oleksandr_tyshchenko@xxxxxxxx>
---
 xen/arch/arm/domain_build.c         | 12 ++++++++++
 xen/drivers/passthrough/arm/iommu.c | 45 +++++++++++++++++++++++++++++++++++++
 xen/include/asm-arm/iommu.h         |  3 +++
 3 files changed, 60 insertions(+)

diff --git a/xen/arch/arm/domain_build.c b/xen/arch/arm/domain_build.c
index d983677..d67f7d4 100644
--- a/xen/arch/arm/domain_build.c
+++ b/xen/arch/arm/domain_build.c
@@ -1241,6 +1241,18 @@ static int __init handle_device(struct domain *d, struct 
dt_device_node *dev,
     u64 addr, size;
     bool need_mapping = !dt_device_for_passthrough(dev);
 
+    if ( dt_parse_phandle(dev, "iommus", 0) )
+    {
+        dt_dprintk("%s add to iommu\n", dt_node_full_name(dev));
+        res = iommu_add_dt_device(dev);
+        if ( res )
+        {
+            printk(XENLOG_ERR "Failed to add %s to the IOMMU\n",
+                   dt_node_full_name(dev));
+            return res;
+        }
+    }
+
     nirq = dt_number_of_irq(dev);
     naddr = dt_number_of_address(dev);
 
diff --git a/xen/drivers/passthrough/arm/iommu.c 
b/xen/drivers/passthrough/arm/iommu.c
index 3195919..19516af 100644
--- a/xen/drivers/passthrough/arm/iommu.c
+++ b/xen/drivers/passthrough/arm/iommu.c
@@ -113,3 +113,48 @@ int arch_iommu_populate_page_table(struct domain *d)
 void __hwdom_init arch_iommu_hwdom_init(struct domain *d)
 {
 }
+
+int __init iommu_add_dt_device(struct dt_device_node *np)
+{
+    const struct iommu_ops *ops = iommu_get_ops();
+    struct dt_phandle_args iommu_spec;
+    struct device *dev = dt_to_dev(np);
+    int rc = 1, index = 0;
+
+    if ( !iommu_enabled || !ops || !ops->add_device )
+        return 0;
+
+    if ( dev_iommu_fwspec_get(dev) )
+        return -EEXIST;
+
+    /* According to the Documentation/devicetree/bindings/iommu/iommu.txt */
+    while ( !dt_parse_phandle_with_args(np, "iommus", "#iommu-cells",
+                                        index, &iommu_spec) )
+    {
+        if ( !dt_device_is_available(iommu_spec.np) )
+            break;
+
+        rc = iommu_fwspec_init(dev, &iommu_spec.np->dev);
+        if ( rc )
+            break;
+
+        rc = iommu_fwspec_add_ids(dev, iommu_spec.args, 1);
+        if ( rc )
+            break;
+
+        index++;
+    }
+
+    /*
+     * Add DT device to the IOMMU if latter is present and available.
+     * The IOMMU driver's responsibility is to check whether dev->iommu_fwspec
+     * field is initialized and mark that device as protected.
+     */
+    if ( !rc )
+        rc = ops->add_device(0, dev);
+
+    if ( rc < 0 )
+        iommu_fwspec_free(dev);
+
+    return rc < 0 ? rc : 0;
+}
diff --git a/xen/include/asm-arm/iommu.h b/xen/include/asm-arm/iommu.h
index 1853bd9..06b07fa 100644
--- a/xen/include/asm-arm/iommu.h
+++ b/xen/include/asm-arm/iommu.h
@@ -28,6 +28,9 @@ struct arch_iommu
 const struct iommu_ops *iommu_get_ops(void);
 void iommu_set_ops(const struct iommu_ops *ops);
 
+/* helper to add DT device to the IOMMU */
+int iommu_add_dt_device(struct dt_device_node *np);
+
 /* mapping helpers */
 int __must_check arm_iommu_map_page(struct domain *d, dfn_t dfn, mfn_t mfn,
                                     unsigned int flags,
-- 
2.7.4


_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxxx
https://lists.xenproject.org/mailman/listinfo/xen-devel

 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.