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

[RFC v2 1/2] arm,smmu: switch to using iommu_fwspec functions


  • To: xen-devel <xen-devel@xxxxxxxxxxxxxxxxxxxx>
  • From: Brian Woods <brian.woods@xxxxxxxxxx>
  • Date: Tue, 21 Jul 2020 21:00:30 -0700
  • Arc-authentication-results: i=1; mx.microsoft.com 1; spf=pass (sender ip is 149.199.60.83) smtp.rcpttodomain=epam.com 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=lu6/sGI2fQO/GKysq+3npebONed5SiclapckpPkFhvQ=; b=UGqr855hhUf8FB47Rlkuhwm6DRwGcWrlfTajdO9gB/8RtrnP64ENiVFpj3do2ITz5hQqSuxF000LQmI//x8Q7tGj1F7xqHW1zP0BLCWenHxF1UqeD+hy0E9HPAHBnbAvK9ZJbimk8yW5nRk1+qSbnvjtb8r84YYHYdoXs8q89fv0th7ORtQbkMn8fxEtItbi9AqPoeIccjiKs2J4/hFHmvBjuxZjBxBkeIe2JDhUNVqNUOufwo0wE+GkM/OFc7PhLDyBbLUvVAhaZxyJg0ROmbuwY4zE3DMN3+nrMdTBo3AmqbFWMy6LMmpUP0mnFVXPMaGqx06I4N13sLOPFuCjCw==
  • Arc-seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=Ce2MugMj5Gi+e++p25NcYhkNyz+cJiWkYQhiEJx8Wkw3JKYLCCvIIROAxGF6wuMbcJ66UmDEiaSzoDClw3M5WAgk8W/1r6w+MAfuof/43qayzw4M/aPn+pWdtqlNxIpfJsX9woXS1chU0lf208qJN4a3tm+hf722J9/T84mgNcOkXhDmjpIrwRwjhWuzoWWh97OwJfP2g9C9fXeOLtF0DdcVDGJts3Z/uHePfgKe2oIXSKHcZc7qFjpNWC8pB8bXHBqyWbajEXHjqfA8f5m/kzOwXBSTmdBPkjr0m14pYi/UNjnN4VgyuT5dJYjCMLZCGsyOy3Xoy/+6ptZxrjzpIg==
  • Cc: Volodymyr Babchuk <Volodymyr_Babchuk@xxxxxxxx>, Stefano Stabellini <sstabellini@xxxxxxxxxx>, Julien Grall <julien@xxxxxxx>, Brian Woods <brian.woods@xxxxxxxxxx>
  • Delivery-date: Wed, 22 Jul 2020 04:01:05 +0000
  • List-id: Xen developer discussion <xen-devel.lists.xenproject.org>

Modify the smmu driver so that it uses the iommu_fwspec helper
functions.  This means both ARM IOMMU drivers will both use the
iommu_fwspec helper functions.

Signed-off-by: Brian Woods <brian.woods@xxxxxxxxxx>
---

Interested in if combining the legacy and generic bindings paths are
worth or if Xen plans to depreicate legacy bindings at some point.

v1 -> v2
    - removed MAX_MASTER_STREAMIDS
    - removed unneeded curly brackets

 xen/drivers/passthrough/arm/smmu.c    | 81 +++++++++++++++++++----------------
 xen/drivers/passthrough/device_tree.c |  3 ++
 2 files changed, 47 insertions(+), 37 deletions(-)

diff --git a/xen/drivers/passthrough/arm/smmu.c 
b/xen/drivers/passthrough/arm/smmu.c
index 94662a8..7a5c6cd 100644
--- a/xen/drivers/passthrough/arm/smmu.c
+++ b/xen/drivers/passthrough/arm/smmu.c
@@ -49,6 +49,7 @@
 #include <asm/atomic.h>
 #include <asm/device.h>
 #include <asm/io.h>
+#include <asm/iommu_fwspec.h>
 #include <asm/platform.h>
 
 /* Xen: The below defines are redefined within the file. Undef it */
@@ -302,9 +303,6 @@ static struct iommu_group *iommu_group_get(struct device 
*dev)
 
 /***** Start of Linux SMMU code *****/
 
-/* Maximum number of stream IDs assigned to a single device */
-#define MAX_MASTER_STREAMIDS           MAX_PHANDLE_ARGS
-
 /* Maximum number of context banks per SMMU */
 #define ARM_SMMU_MAX_CBS               128
 
@@ -597,8 +595,7 @@ struct arm_smmu_smr {
 };
 
 struct arm_smmu_master_cfg {
-       int                             num_streamids;
-       u16                             streamids[MAX_MASTER_STREAMIDS];
+       struct iommu_fwspec             *fwspec;
        struct arm_smmu_smr             *smrs;
 };
 
@@ -779,7 +776,7 @@ static int register_smmu_master(struct arm_smmu_device 
*smmu,
                                struct device *dev,
                                struct of_phandle_args *masterspec)
 {
-       int i;
+       int i, ret = 0;
        struct arm_smmu_master *master;
 
        master = find_smmu_master(smmu, masterspec->np);
@@ -790,34 +787,37 @@ static int register_smmu_master(struct arm_smmu_device 
*smmu,
                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;
 
-       master->of_node                 = masterspec->np;
-       master->cfg.num_streamids       = masterspec->args_count;
+       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);
+
+       /* adding the ids here */
+       ret = iommu_fwspec_add_ids(&masterspec->np->dev,
+                                  masterspec->args,
+                                  masterspec->args_count);
+       if (ret)
+               return ret;
 
        /* Xen: Let Xen know that the device is protected by an SMMU */
        dt_device_set_protected(masterspec->np);
 
-       for (i = 0; i < master->cfg.num_streamids; ++i) {
-               u16 streamid = masterspec->args[i];
-
-               if (!(smmu->features & ARM_SMMU_FEAT_STREAM_MATCH) &&
-                    (streamid >= 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);
-                       return -ERANGE;
+       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) {
+                               dev_err(dev,
+                                       "stream ID for master device %s greater 
than maximum allowed (%d)\n",
+                                       masterspec->np->name, 
smmu->num_mapping_groups);
+                               return -ERANGE;
+                       }
                }
-               master->cfg.streamids[i] = streamid;
        }
        return insert_smmu_master(smmu, master);
 }
@@ -1397,15 +1397,15 @@ static int arm_smmu_master_configure_smrs(struct 
arm_smmu_device *smmu,
        if (cfg->smrs)
                return -EEXIST;
 
-       smrs = kmalloc_array(cfg->num_streamids, sizeof(*smrs), GFP_KERNEL);
+       smrs = kmalloc_array(cfg->fwspec->num_ids, sizeof(*smrs), GFP_KERNEL);
        if (!smrs) {
                dev_err(smmu->dev, "failed to allocate %d SMRs\n",
-                       cfg->num_streamids);
+                       cfg->fwspec->num_ids);
                return -ENOMEM;
        }
 
        /* Allocate the SMRs on the SMMU */
-       for (i = 0; i < cfg->num_streamids; ++i) {
+       for (i = 0; i < cfg->fwspec->num_ids; ++i) {
                int idx = __arm_smmu_alloc_bitmap(smmu->smr_map, 0,
                                                  smmu->num_mapping_groups);
                if (IS_ERR_VALUE(idx)) {
@@ -1416,12 +1416,12 @@ static int arm_smmu_master_configure_smrs(struct 
arm_smmu_device *smmu,
                smrs[i] = (struct arm_smmu_smr) {
                        .idx    = idx,
                        .mask   = 0, /* We don't currently share SMRs */
-                       .id     = cfg->streamids[i],
+                       .id     = cfg->fwspec->ids[i],
                };
        }
 
        /* It worked! Now, poke the actual hardware */
-       for (i = 0; i < cfg->num_streamids; ++i) {
+       for (i = 0; i < cfg->fwspec->num_ids; ++i) {
                u32 reg = SMR_VALID | smrs[i].id << SMR_ID_SHIFT |
                          smrs[i].mask << SMR_MASK_SHIFT;
                writel_relaxed(reg, gr0_base + ARM_SMMU_GR0_SMR(smrs[i].idx));
@@ -1448,7 +1448,7 @@ static void arm_smmu_master_free_smrs(struct 
arm_smmu_device *smmu,
                return;
 
        /* Invalidate the SMRs before freeing back to the allocator */
-       for (i = 0; i < cfg->num_streamids; ++i) {
+       for (i = 0; i < cfg->fwspec->num_ids; ++i) {
                u8 idx = smrs[i].idx;
 
                writel_relaxed(~SMR_VALID, gr0_base + ARM_SMMU_GR0_SMR(idx));
@@ -1471,10 +1471,10 @@ static int arm_smmu_domain_add_master(struct 
arm_smmu_domain *smmu_domain,
        if (ret)
                return ret == -EEXIST ? 0 : ret;
 
-       for (i = 0; i < cfg->num_streamids; ++i) {
+       for (i = 0; i < cfg->fwspec->num_ids; ++i) {
                u32 idx, s2cr;
 
-               idx = cfg->smrs ? cfg->smrs[i].idx : cfg->streamids[i];
+               idx = cfg->smrs ? cfg->smrs[i].idx : cfg->fwspec->ids[i];
                s2cr = S2CR_TYPE_TRANS |
                       (smmu_domain->cfg.cbndx << S2CR_CBNDX_SHIFT);
                writel_relaxed(s2cr, gr0_base + ARM_SMMU_GR0_S2CR(idx));
@@ -1499,8 +1499,8 @@ static void arm_smmu_domain_remove_master(struct 
arm_smmu_domain *smmu_domain,
         * that it can be re-allocated immediately.
         * Xen: Unlike Linux, any access to non-configured stream will fault.
         */
-       for (i = 0; i < cfg->num_streamids; ++i) {
-               u32 idx = cfg->smrs ? cfg->smrs[i].idx : cfg->streamids[i];
+       for (i = 0; i < cfg->fwspec->num_ids; ++i) {
+               u32 idx = cfg->smrs ? cfg->smrs[i].idx : cfg->fwspec->ids[i];
 
                writel_relaxed(S2CR_TYPE_FAULT,
                               gr0_base + ARM_SMMU_GR0_S2CR(idx));
@@ -1924,14 +1924,21 @@ static int arm_smmu_add_device(struct device *dev)
                        ret = -ENOMEM;
                        goto out_put_group;
                }
+               cfg->fwspec = kzalloc(sizeof(struct iommu_fwspec), GFP_KERNEL);
+               if (!cfg->fwspec) {
+                       kfree(cfg);
+                       ret = -ENOMEM;
+                       goto out_put_group;
+               }
+               iommu_fwspec_init(dev, smmu->dev);
 
-               cfg->num_streamids = 1;
+               cfg->fwspec->num_ids = 1;
                /*
                 * Assume Stream ID == Requester ID for now.
                 * We need a way to describe the ID mappings in FDT.
                 */
                pci_for_each_dma_alias(pdev, __arm_smmu_get_pci_sid,
-                                      &cfg->streamids[0]);
+                                      &cfg->fwspec->ids[0]);
                releasefn = __arm_smmu_release_pci_iommudata;
        } else {
                struct arm_smmu_master *master;
diff --git a/xen/drivers/passthrough/device_tree.c 
b/xen/drivers/passthrough/device_tree.c
index 999b831..acf6b62 100644
--- a/xen/drivers/passthrough/device_tree.c
+++ b/xen/drivers/passthrough/device_tree.c
@@ -140,6 +140,9 @@ int iommu_add_dt_device(struct dt_device_node *np)
     if ( !ops )
         return -EINVAL;
 
+    if ( dt_device_is_protected(np) )
+        return 0;
+
     if ( dev_iommu_fwspec_get(dev) )
         return -EEXIST;
 
-- 
2.7.4




 


Rackspace

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