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

[Xen-devel] [RFC 2/2] smmu: add support for generic DT bindings


  • To: xen-devel@xxxxxxxxxxxxxxxxxxxx
  • From: Brian Woods <brian.woods@xxxxxxxxxx>
  • Date: Thu, 9 Jan 2020 17:26:30 -0800
  • Arc-authentication-results: i=1; mx.microsoft.com 1; spf=pass (sender ip is 149.199.60.83) smtp.rcpttodomain=lists.xenproject.org smtp.mailfrom=xilinx.com; dmarc=bestguesspass action=none header.from=xilinx.com; dkim=none (message not signed); arc=none
  • Arc-message-signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector9901; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=A4oZGAh4w8/PJh/tv/MXVBtSiUUq1DNE06HRbWgioLs=; b=ilrnmowBtYcfGWVZ43nLfLfiB75LJJnNdDMFKYYs6YzY7n7lI+5/GgIOzmkoxkhuqF41CzMmsJ5XMVPy95aXGKjodFhRHGQIrrV38sI9nqCXvVAI/WP2C6razWX2F91lOs/e/DDvYq5KvqDLpNDk2NDpCOCmrLLkXOgLrVZHhiS7h7rFBSjB4qyicuHC+/OCvGQcRYCceQSzTvq736S6O+A88wU0TOt8aKiFijUAO6iJfK4x+cV6p0/G11ceCc7AUW+OMHmo66IYPC5Pn1jeaLRyjJr3X41rxcWSo2SEmzE4fL9feYab+u3tkGGOttAUmgK2nElXDW093f5aLi3Bjw==
  • Arc-seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=H30bwx5nCV1Y9iRD/WNi0MMQ2qCw3BvzDDH4biw7ThdHXtJjLJ5JdtfhtSVybe0CW3zkpRd0wr3mKJH5cINa2IIDvF5rdo5py5bXZhB+bq6Q/TQAT5caE9y8u8Nal25f+DVfIjoDDcfv96FeISigc5svSzF+xHTAU5CyLXmM0hA6vvnrFhEmPY0jYuu28cXJSkfHmyVURiV2l2OB5JUxSbuqkJ2K8Q3vlZrSD/ljAEfdSGQGLlgsFGqFXyjNJW/fOURV+m8iVikLx2LgUyfMY46osxaobdm0O96tn4fwnJObHJGyICOBs+uNLco143V6X+fC45l9nRXLoeYqett0Jg==
  • Authentication-results: spf=pass (sender IP is 149.199.60.83) smtp.mailfrom=xilinx.com; lists.xenproject.org; dkim=none (message not signed) header.d=none;lists.xenproject.org; dmarc=bestguesspass action=none header.from=xilinx.com;
  • Cc: Volodymyr Babchuk <Volodymyr_Babchuk@xxxxxxxx>, Stefano Stabellini <sstabellini@xxxxxxxxxx>, Julien Grall <julien@xxxxxxx>, Brian Woods <brian.woods@xxxxxxxxxx>
  • Delivery-date: Fri, 10 Jan 2020 01:28:36 +0000
  • List-id: Xen developer discussion <xen-devel.lists.xenproject.org>

Restructure some of the code and add supporting functions for adding
generic device tree (DT) binding support.  The normal add_device and
dt_xlate functions are wrappers of the legacy functions due to legacy
calls needing more arguments because the find_smmu can't a smmu that
isn't initialized.

Signed-off-by: Brian Woods <brian.woods@xxxxxxxxxx>
---
RFC especially on:
   - Checks for the: arm_smmu_dt_add_device* and arm_smmu_dt_xlate*
     functions.

 xen/drivers/passthrough/arm/smmu.c    | 118 +++++++++++++++++++++++++---------
 xen/drivers/passthrough/device_tree.c |  17 +----
 2 files changed, 87 insertions(+), 48 deletions(-)

diff --git a/xen/drivers/passthrough/arm/smmu.c 
b/xen/drivers/passthrough/arm/smmu.c
index c5db5be..08787cd 100644
--- a/xen/drivers/passthrough/arm/smmu.c
+++ b/xen/drivers/passthrough/arm/smmu.c
@@ -251,6 +251,8 @@ struct iommu_group
        atomic_t ref;
 };
 
+static const struct arm_smmu_device *find_smmu(const struct device *dev);
+
 static struct iommu_group *iommu_group_alloc(void)
 {
        struct iommu_group *group = xzalloc(struct iommu_group);
@@ -775,64 +777,114 @@ static int insert_smmu_master(struct arm_smmu_device 
*smmu,
        return 0;
 }
 
-static int register_smmu_master(struct arm_smmu_device *smmu,
-                               struct device *dev,
-                               struct of_phandle_args *masterspec)
+/*
+ * Since smmu isn't done initializing before this is run in the legacy
+ * case, create a function where that's passed and then have the generic
+ * function just be a simple wrapper.
+ */
+static int arm_smmu_dt_xlate_legacy(struct device *dev,
+                                   const struct of_phandle_args *spec,
+                                   struct iommu_fwspec *fwspec)
+{
+       if ((spec->args_count + fwspec->num_ids) > MAX_MASTER_STREAMIDS) {
+               dev_err(dev,
+                       "reached maximum number (%d) of stream IDs for master 
device %s\n",
+                       MAX_MASTER_STREAMIDS, spec->np->name);
+               return -ENOSPC;
+       }
+
+       /* adding the ids here */
+       return iommu_fwspec_add_ids(dev,
+                                   spec->args,
+                                   spec->args_count);
+}
+
+static int arm_smmu_dt_xlate(struct device *dev,
+                            const struct dt_phandle_args *spec)
+{
+       return arm_smmu_dt_xlate_legacy(dev,
+                                       spec,
+                                       dev_iommu_fwspec_get(dev));
+}
+
+static int arm_smmu_dt_add_device_legacy(struct arm_smmu_device *smmu,
+                                        struct device *dev,
+                                        struct iommu_fwspec *fwspec)
 {
-       int i, ret = 0;
+       int i;
        struct arm_smmu_master *master;
+       struct device_node *dev_node = dev_get_dev_node(dev);
+
+       BUG_ON(dev == NULL);
+       BUG_ON(dev_node == NULL);
 
-       master = find_smmu_master(smmu, masterspec->np);
+       master = find_smmu_master(smmu, dev_node);
        if (master) {
                dev_err(dev,
                        "rejecting multiple registrations for master device 
%s\n",
-                       masterspec->np->name);
+                       dev_node->name);
                return -EBUSY;
        }
 
-       if (masterspec->args_count > MAX_MASTER_STREAMIDS) {
-               dev_err(dev,
-                       "reached maximum number (%d) of stream IDs for master 
device %s\n",
-                       MAX_MASTER_STREAMIDS, masterspec->np->name);
-               return -ENOSPC;
-       }
-
        master = devm_kzalloc(dev, sizeof(*master), GFP_KERNEL);
        if (!master) {
                return -ENOMEM;
        }
-       master->of_node = masterspec->np;
-
-       ret = iommu_fwspec_init(&master->of_node->dev, smmu->dev);
-       if (ret) {
-               kfree(master);
-               return ret;
-       }
-       master->cfg.fwspec = dev_iommu_fwspec_get(&master->of_node->dev);
+       master->of_node = dev_node;
 
-       /* adding the ids here */
-       ret = iommu_fwspec_add_ids(&masterspec->np->dev,
-                                  masterspec->args,
-                                  masterspec->args_count);
-       if (ret)
-               return ret;
+       master->cfg.fwspec = fwspec;
 
        /* Xen: Let Xen know that the device is protected by an SMMU */
-       dt_device_set_protected(masterspec->np);
+       dt_device_set_protected(dev_node);
 
        if (!(smmu->features & ARM_SMMU_FEAT_STREAM_MATCH)) {
-               for (i = 0; i < master->cfg.fwspec->num_ids; ++i) {
-                       if (masterspec->args[i] >= smmu->num_mapping_groups) {
+               for (i = 0; i < fwspec->num_ids; ++i) {
+                       if (fwspec->ids[i] >= smmu->num_mapping_groups) {
                                dev_err(dev,
                                        "stream ID for master device %s greater 
than maximum allowed (%d)\n",
-                                       masterspec->np->name, 
smmu->num_mapping_groups);
+                                       dev_node->name, 
smmu->num_mapping_groups);
                                return -ERANGE;
                        }
                }
        }
+
        return insert_smmu_master(smmu, master);
 }
 
+static int arm_smmu_dt_add_device(u8 devfn, struct device *dev)
+{
+       struct arm_smmu_device *smmu;
+       struct iommu_fwspec *fwspec = dev_iommu_fwspec_get(dev);
+
+       smmu = (struct arm_smmu_device *) find_smmu(fwspec->iommu_dev);
+
+       return arm_smmu_dt_add_device_legacy(smmu, dev, fwspec);
+}
+
+static int register_smmu_master(struct arm_smmu_device *smmu,
+                               struct device *dev,
+                               struct of_phandle_args *masterspec)
+{
+       int ret = 0;
+       struct iommu_fwspec *fwspec;
+
+       ret = iommu_fwspec_init(&masterspec->np->dev, smmu->dev);
+       if (ret)
+               return ret;
+
+       fwspec = dev_iommu_fwspec_get(&masterspec->np->dev);
+
+       ret = arm_smmu_dt_xlate_legacy(&masterspec->np->dev,
+                                      masterspec,
+                                      fwspec);
+       if (ret)
+               return ret;
+
+       return arm_smmu_dt_add_device_legacy(smmu,
+                                            &masterspec->np->dev,
+                                            fwspec);
+}
+
 static struct arm_smmu_device *find_smmu_for_device(struct device *dev)
 {
        struct arm_smmu_device *smmu;
@@ -2754,6 +2806,7 @@ static void arm_smmu_iommu_domain_teardown(struct domain 
*d)
 static const struct iommu_ops arm_smmu_iommu_ops = {
     .init = arm_smmu_iommu_domain_init,
     .hwdom_init = arm_smmu_iommu_hwdom_init,
+    .add_device = arm_smmu_dt_add_device,
     .teardown = arm_smmu_iommu_domain_teardown,
     .iotlb_flush = arm_smmu_iotlb_flush,
     .iotlb_flush_all = arm_smmu_iotlb_flush_all,
@@ -2761,9 +2814,10 @@ static const struct iommu_ops arm_smmu_iommu_ops = {
     .reassign_device = arm_smmu_reassign_dev,
     .map_page = arm_iommu_map_page,
     .unmap_page = arm_iommu_unmap_page,
+    .dt_xlate = arm_smmu_dt_xlate,
 };
 
-static __init const struct arm_smmu_device *find_smmu(const struct device *dev)
+static const struct arm_smmu_device *find_smmu(const struct device *dev)
 {
        struct arm_smmu_device *smmu;
        bool found = false;
diff --git a/xen/drivers/passthrough/device_tree.c 
b/xen/drivers/passthrough/device_tree.c
index acf6b62..dd9cf65 100644
--- a/xen/drivers/passthrough/device_tree.c
+++ b/xen/drivers/passthrough/device_tree.c
@@ -158,22 +158,7 @@ int iommu_add_dt_device(struct dt_device_node *np)
          * these callback implemented.
          */
         if ( !ops->add_device || !ops->dt_xlate )
-        {
-            /*
-             * Some Device Trees may expose both legacy SMMU and generic
-             * IOMMU bindings together. However, the SMMU driver is only
-             * supporting the former and will protect them during the
-             * initialization. So we need to skip them and not return
-             * error here.
-             *
-             * XXX: This can be dropped when the SMMU is able to deal
-             * with generic bindings.
-             */
-            if ( dt_device_is_protected(np) )
-                return 0;
-            else
-                return -EINVAL;
-        }
+            return -EINVAL;
 
         if ( !dt_device_is_available(iommu_spec.np) )
             break;
-- 
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®.