Skip to content

Commit e117230

Browse files
mszyprowjoergroedel
authored andcommitted
iommu/exynos: Rework and fix internal locking
This patch reworks locking in the exynos_iommu_attach/detach_device functions to ensure that all entries of the sysmmu_drvdata and exynos_iommu_owner structure are updated under the respective spinlocks, while runtime pm functions are called without any spinlocks held. Signed-off-by: Marek Szyprowski <[email protected]> Signed-off-by: Joerg Roedel <[email protected]>
1 parent 92798b4 commit e117230

File tree

1 file changed

+19
-8
lines changed

1 file changed

+19
-8
lines changed

drivers/iommu/exynos-iommu.c

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -769,10 +769,12 @@ static void exynos_iommu_domain_free(struct iommu_domain *iommu_domain)
769769
spin_lock_irqsave(&domain->lock, flags);
770770

771771
list_for_each_entry_safe(data, next, &domain->clients, domain_node) {
772+
spin_lock(&data->lock);
772773
__sysmmu_disable(data);
773774
data->pgtable = 0;
774775
data->domain = NULL;
775776
list_del_init(&data->domain_node);
777+
spin_unlock(&data->lock);
776778
}
777779

778780
spin_unlock_irqrestore(&domain->lock, flags);
@@ -810,17 +812,22 @@ static void exynos_iommu_detach_device(struct iommu_domain *iommu_domain,
810812
if (!has_sysmmu(dev) || owner->domain != iommu_domain)
811813
return;
812814

815+
list_for_each_entry(data, &owner->controllers, owner_node) {
816+
__sysmmu_disable(data);
817+
pm_runtime_put(data->sysmmu);
818+
}
819+
813820
spin_lock_irqsave(&domain->lock, flags);
814821
list_for_each_entry_safe(data, next, &domain->clients, domain_node) {
815-
__sysmmu_disable(data);
822+
spin_lock(&data->lock);
816823
data->pgtable = 0;
817824
data->domain = NULL;
818825
list_del_init(&data->domain_node);
819-
pm_runtime_put(data->sysmmu);
826+
spin_unlock(&data->lock);
820827
}
828+
owner->domain = NULL;
821829
spin_unlock_irqrestore(&domain->lock, flags);
822830

823-
owner->domain = NULL;
824831

825832
dev_dbg(dev, "%s: Detached IOMMU with pgtable %pa\n", __func__,
826833
&pagetable);
@@ -841,18 +848,22 @@ static int exynos_iommu_attach_device(struct iommu_domain *iommu_domain,
841848
if (owner->domain)
842849
exynos_iommu_detach_device(owner->domain, dev);
843850

851+
spin_lock_irqsave(&domain->lock, flags);
844852
list_for_each_entry(data, &owner->controllers, owner_node) {
853+
spin_lock(&data->lock);
845854
data->pgtable = pagetable;
846855
data->domain = domain;
856+
list_add_tail(&data->domain_node, &domain->clients);
857+
spin_unlock(&data->lock);
858+
}
859+
owner->domain = iommu_domain;
860+
spin_unlock_irqrestore(&domain->lock, flags);
861+
862+
list_for_each_entry(data, &owner->controllers, owner_node) {
847863
pm_runtime_get_sync(data->sysmmu);
848864
__sysmmu_enable(data);
849-
850-
spin_lock_irqsave(&domain->lock, flags);
851-
list_add_tail(&data->domain_node, &domain->clients);
852-
spin_unlock_irqrestore(&domain->lock, flags);
853865
}
854866

855-
owner->domain = iommu_domain;
856867
dev_dbg(dev, "%s: Attached IOMMU with pgtable %pa\n", __func__,
857868
&pagetable);
858869

0 commit comments

Comments
 (0)