Cc: Andreas Herrmann <herrmann.der.u...@googlemail.com>
Signed-off-by: Andreas Herrmann <andreas.herrm...@calxeda.com>
---
 drivers/iommu/arm-smmu.c |   25 ++++++++++++++++++++++---
 1 file changed, 22 insertions(+), 3 deletions(-)

diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c
index 02a871e..a4e0c93 100644
--- a/drivers/iommu/arm-smmu.c
+++ b/drivers/iommu/arm-smmu.c
@@ -56,6 +56,9 @@
 /* Maximum number of stream IDs assigned to a single device */
 #define MAX_MASTER_STREAMIDS           8
 
+/* Maximum stream ID */
+#define ARM_SMMU_MAX_STREAMID          (SZ_64K - 1)
+
 /* Maximum number of context banks per SMMU */
 #define ARM_SMMU_MAX_CBS               128
 
@@ -386,6 +389,8 @@ struct arm_smmu_device {
        u32                             smr_mask_mask;
        u32                             smr_id_mask;
 
+       unsigned long                   *sids;
+
        struct list_head                list;
        struct rb_root                  masters;
 };
@@ -491,7 +496,7 @@ static int register_smmu_master(struct arm_smmu_device 
*smmu,
                                struct device *dev,
                                struct of_phandle_args *masterspec)
 {
-       int i;
+       int i, sid;
        struct arm_smmu_master *master;
 
        master = find_smmu_master(smmu, masterspec->np);
@@ -516,8 +521,14 @@ static int register_smmu_master(struct arm_smmu_device 
*smmu,
        master->of_node         = masterspec->np;
        master->num_streamids   = masterspec->args_count;
 
-       for (i = 0; i < master->num_streamids; ++i)
-               master->streamids[i] = masterspec->args[i];
+       for (i = 0; i < master->num_streamids; ++i) {
+               sid = masterspec->args[i];
+               if (test_and_set_bit(sid, smmu->sids)) {
+                       dev_err(dev, "duplicate stream ID (%d)\n", sid);
+                       return -EEXIST;
+               }
+               master->streamids[i] = sid;
+       }
 
        return insert_smmu_master(smmu, master);
 }
@@ -1934,6 +1945,14 @@ static int arm_smmu_device_dt_probe(struct 
platform_device *pdev)
        }
        smmu->dev = dev;
 
+       smmu->sids = devm_kzalloc(dev, BITS_TO_LONGS(ARM_SMMU_MAX_STREAMID) *
+                               sizeof(long), GFP_KERNEL);
+       if (!smmu->sids) {
+               dev_err(dev,
+                       "failed to allocate bitmap for stream ID tracking\n");
+               return -ENOMEM;
+       }
+
        check_driver_options(smmu);
 
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-- 
1.7.9.5

_______________________________________________
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu

Reply via email to