A master add into or remove from smmu_domain->devices only happened in
arm_smmu_attach_dev()/arm_smmu_detach_dev(), the frequency of these
operations is very low. But we traverse smmu_domain->devices list in
arm_smmu_atc_inv_domain() are frequent. So change the protection from
spinlock to rwlock can improve concurrency, especially for the smmu
domain without ATS masters.

By the way, the cmdq has its own lock, so this change is safe.

Here is the performance data tested on my board:
Before:
Jobs: 24 (f=24): [0.1% done] [9798M/0K /s] [2392K/0  iops] [09h:59m:13s]
Jobs: 24 (f=24): [0.1% done] [9782M/0K /s] [2388K/0  iops] [09h:59m:12s]
Jobs: 24 (f=24): [0.2% done] [9825M/0K /s] [2399K/0  iops] [09h:59m:11s]
Jobs: 24 (f=24): [0.2% done] [9836M/0K /s] [2401K/0  iops] [09h:59m:10s]

After:
Jobs: 24 (f=24): [0.1% done] [10996M/0K /s] [2685K/0  iops] [09h:59m:13s]
Jobs: 24 (f=24): [0.1% done] [10817M/0K /s] [2641K/0  iops] [09h:59m:12s]
Jobs: 24 (f=24): [0.2% done] [11083M/0K /s] [2706K/0  iops] [09h:59m:11s]
Jobs: 24 (f=24): [0.2% done] [10603M/0K /s] [2589K/0  iops] [09h:59m:10s]

Signed-off-by: Zhen Lei <thunder.leiz...@huawei.com>
Suggested-by: Will Deacon <w...@kernel.org>
---
 drivers/iommu/arm-smmu-v3.c | 16 ++++++++--------
 1 file changed, 8 insertions(+), 8 deletions(-)

diff --git a/drivers/iommu/arm-smmu-v3.c b/drivers/iommu/arm-smmu-v3.c
index e0dcc5d27291f8b..eded2e7a5a0c444 100644
--- a/drivers/iommu/arm-smmu-v3.c
+++ b/drivers/iommu/arm-smmu-v3.c
@@ -641,7 +641,7 @@ struct arm_smmu_domain {
        struct iommu_domain             domain;
 
        struct list_head                devices;
-       spinlock_t                      devices_lock;
+       rwlock_t                        devices_lock;
 };
 
 struct arm_smmu_option_prop {
@@ -1536,10 +1536,10 @@ static int arm_smmu_atc_inv_domain(struct 
arm_smmu_domain *smmu_domain,
 
        arm_smmu_atc_inv_to_cmd(ssid, iova, size, &cmd);
 
-       spin_lock_irqsave(&smmu_domain->devices_lock, flags);
+       read_lock_irqsave(&smmu_domain->devices_lock, flags);
        list_for_each_entry(master, &smmu_domain->devices, domain_head)
                ret |= arm_smmu_atc_inv_master(master, &cmd);
-       spin_unlock_irqrestore(&smmu_domain->devices_lock, flags);
+       read_unlock_irqrestore(&smmu_domain->devices_lock, flags);
 
        return ret ? -ETIMEDOUT : 0;
 }
@@ -1648,7 +1648,7 @@ static struct iommu_domain 
*arm_smmu_domain_alloc(unsigned type)
 
        mutex_init(&smmu_domain->init_mutex);
        INIT_LIST_HEAD(&smmu_domain->devices);
-       spin_lock_init(&smmu_domain->devices_lock);
+       rwlock_init(&smmu_domain->devices_lock);
 
        return &smmu_domain->domain;
 }
@@ -1911,9 +1911,9 @@ static void arm_smmu_detach_dev(struct arm_smmu_master 
*master)
        if (!smmu_domain)
                return;
 
-       spin_lock_irqsave(&smmu_domain->devices_lock, flags);
+       write_lock_irqsave(&smmu_domain->devices_lock, flags);
        list_del(&master->domain_head);
-       spin_unlock_irqrestore(&smmu_domain->devices_lock, flags);
+       write_unlock_irqrestore(&smmu_domain->devices_lock, flags);
 
        master->domain = NULL;
        arm_smmu_install_ste_for_dev(master);
@@ -1966,9 +1966,9 @@ static int arm_smmu_attach_dev(struct iommu_domain 
*domain, struct device *dev)
 
        arm_smmu_install_ste_for_dev(master);
 
-       spin_lock_irqsave(&smmu_domain->devices_lock, flags);
+       write_lock_irqsave(&smmu_domain->devices_lock, flags);
        list_add(&master->domain_head, &smmu_domain->devices);
-       spin_unlock_irqrestore(&smmu_domain->devices_lock, flags);
+       write_unlock_irqrestore(&smmu_domain->devices_lock, flags);
 out_unlock:
        mutex_unlock(&smmu_domain->init_mutex);
        return ret;
-- 
1.8.3


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

Reply via email to