]> git.kernelconcepts.de Git - karo-tx-linux.git/blobdiff - drivers/iommu/arm-smmu.c
Merge branch 'i2c/for-current' of git://git.kernel.org/pub/scm/linux/kernel/git/wsa...
[karo-tx-linux.git] / drivers / iommu / arm-smmu.c
index bc89b4d6c043dacee88463ba22edc8883f60385e..b97188acc4f1006185a5f8cb4fb3ee0e5cf735cf 100644 (file)
@@ -400,6 +400,8 @@ struct arm_smmu_device {
 
        u32                             cavium_id_base; /* Specific to Cavium */
 
+       spinlock_t                      global_sync_lock;
+
        /* IOMMU core code handle */
        struct iommu_device             iommu;
 };
@@ -436,7 +438,7 @@ struct arm_smmu_domain {
        struct arm_smmu_cfg             cfg;
        enum arm_smmu_domain_stage      stage;
        struct mutex                    init_mutex; /* Protects smmu pointer */
-       spinlock_t                      cb_lock; /* Serialises ATS1* ops */
+       spinlock_t                      cb_lock; /* Serialises ATS1* ops and TLB syncs */
        struct iommu_domain             domain;
 };
 
@@ -602,9 +604,12 @@ static void __arm_smmu_tlb_sync(struct arm_smmu_device *smmu,
 static void arm_smmu_tlb_sync_global(struct arm_smmu_device *smmu)
 {
        void __iomem *base = ARM_SMMU_GR0(smmu);
+       unsigned long flags;
 
+       spin_lock_irqsave(&smmu->global_sync_lock, flags);
        __arm_smmu_tlb_sync(smmu, base + ARM_SMMU_GR0_sTLBGSYNC,
                            base + ARM_SMMU_GR0_sTLBGSTATUS);
+       spin_unlock_irqrestore(&smmu->global_sync_lock, flags);
 }
 
 static void arm_smmu_tlb_sync_context(void *cookie)
@@ -612,9 +617,12 @@ static void arm_smmu_tlb_sync_context(void *cookie)
        struct arm_smmu_domain *smmu_domain = cookie;
        struct arm_smmu_device *smmu = smmu_domain->smmu;
        void __iomem *base = ARM_SMMU_CB(smmu, smmu_domain->cfg.cbndx);
+       unsigned long flags;
 
+       spin_lock_irqsave(&smmu_domain->cb_lock, flags);
        __arm_smmu_tlb_sync(smmu, base + ARM_SMMU_CB_TLBSYNC,
                            base + ARM_SMMU_CB_TLBSTATUS);
+       spin_unlock_irqrestore(&smmu_domain->cb_lock, flags);
 }
 
 static void arm_smmu_tlb_sync_vmid(void *cookie)
@@ -1511,7 +1519,6 @@ static int arm_smmu_add_device(struct device *dev)
 
        if (using_legacy_binding) {
                ret = arm_smmu_register_legacy_master(dev, &smmu);
-               fwspec = dev->iommu_fwspec;
                if (ret)
                        goto out_free;
        } else if (fwspec && fwspec->ops == &arm_smmu_ops) {
@@ -1550,15 +1557,15 @@ static int arm_smmu_add_device(struct device *dev)
 
        ret = arm_smmu_master_alloc_smes(dev);
        if (ret)
-               goto out_free;
+               goto out_cfg_free;
 
        iommu_device_link(&smmu->iommu, dev);
 
        return 0;
 
+out_cfg_free:
+       kfree(cfg);
 out_free:
-       if (fwspec)
-               kfree(fwspec->iommu_priv);
        iommu_fwspec_free(dev);
        return ret;
 }
@@ -1925,6 +1932,7 @@ static int arm_smmu_device_cfg_probe(struct arm_smmu_device *smmu)
 
        smmu->num_mapping_groups = size;
        mutex_init(&smmu->stream_map_mutex);
+       spin_lock_init(&smmu->global_sync_lock);
 
        if (smmu->version < ARM_SMMU_V2 || !(id & ID0_PTFS_NO_AARCH32)) {
                smmu->features |= ARM_SMMU_FEAT_FMT_AARCH32_L;