aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMarek Szyprowski <m.szyprowski@samsung.com>2016-11-14 05:08:10 -0500
committerJoerg Roedel <jroedel@suse.de>2016-11-14 11:11:59 -0500
commite11723000f16419f9b0f69f15d99cf7ab37edc24 (patch)
tree7decd469bc4a25d5b64c64d035c629b5e9d33c8f
parent92798b4566b1adcf2e259b3116c38553fe655852 (diff)
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 <m.szyprowski@samsung.com> Signed-off-by: Joerg Roedel <jroedel@suse.de>
-rw-r--r--drivers/iommu/exynos-iommu.c27
1 files changed, 19 insertions, 8 deletions
diff --git a/drivers/iommu/exynos-iommu.c b/drivers/iommu/exynos-iommu.c
index 52ded8461a74..0423dff206d4 100644
--- a/drivers/iommu/exynos-iommu.c
+++ b/drivers/iommu/exynos-iommu.c
@@ -769,10 +769,12 @@ static void exynos_iommu_domain_free(struct iommu_domain *iommu_domain)
769 spin_lock_irqsave(&domain->lock, flags); 769 spin_lock_irqsave(&domain->lock, flags);
770 770
771 list_for_each_entry_safe(data, next, &domain->clients, domain_node) { 771 list_for_each_entry_safe(data, next, &domain->clients, domain_node) {
772 spin_lock(&data->lock);
772 __sysmmu_disable(data); 773 __sysmmu_disable(data);
773 data->pgtable = 0; 774 data->pgtable = 0;
774 data->domain = NULL; 775 data->domain = NULL;
775 list_del_init(&data->domain_node); 776 list_del_init(&data->domain_node);
777 spin_unlock(&data->lock);
776 } 778 }
777 779
778 spin_unlock_irqrestore(&domain->lock, flags); 780 spin_unlock_irqrestore(&domain->lock, flags);
@@ -810,17 +812,22 @@ static void exynos_iommu_detach_device(struct iommu_domain *iommu_domain,
810 if (!has_sysmmu(dev) || owner->domain != iommu_domain) 812 if (!has_sysmmu(dev) || owner->domain != iommu_domain)
811 return; 813 return;
812 814
815 list_for_each_entry(data, &owner->controllers, owner_node) {
816 __sysmmu_disable(data);
817 pm_runtime_put(data->sysmmu);
818 }
819
813 spin_lock_irqsave(&domain->lock, flags); 820 spin_lock_irqsave(&domain->lock, flags);
814 list_for_each_entry_safe(data, next, &domain->clients, domain_node) { 821 list_for_each_entry_safe(data, next, &domain->clients, domain_node) {
815 __sysmmu_disable(data); 822 spin_lock(&data->lock);
816 data->pgtable = 0; 823 data->pgtable = 0;
817 data->domain = NULL; 824 data->domain = NULL;
818 list_del_init(&data->domain_node); 825 list_del_init(&data->domain_node);
819 pm_runtime_put(data->sysmmu); 826 spin_unlock(&data->lock);
820 } 827 }
828 owner->domain = NULL;
821 spin_unlock_irqrestore(&domain->lock, flags); 829 spin_unlock_irqrestore(&domain->lock, flags);
822 830
823 owner->domain = NULL;
824 831
825 dev_dbg(dev, "%s: Detached IOMMU with pgtable %pa\n", __func__, 832 dev_dbg(dev, "%s: Detached IOMMU with pgtable %pa\n", __func__,
826 &pagetable); 833 &pagetable);
@@ -841,18 +848,22 @@ static int exynos_iommu_attach_device(struct iommu_domain *iommu_domain,
841 if (owner->domain) 848 if (owner->domain)
842 exynos_iommu_detach_device(owner->domain, dev); 849 exynos_iommu_detach_device(owner->domain, dev);
843 850
851 spin_lock_irqsave(&domain->lock, flags);
844 list_for_each_entry(data, &owner->controllers, owner_node) { 852 list_for_each_entry(data, &owner->controllers, owner_node) {
853 spin_lock(&data->lock);
845 data->pgtable = pagetable; 854 data->pgtable = pagetable;
846 data->domain = domain; 855 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) {
847 pm_runtime_get_sync(data->sysmmu); 863 pm_runtime_get_sync(data->sysmmu);
848 __sysmmu_enable(data); 864 __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);
853 } 865 }
854 866
855 owner->domain = iommu_domain;
856 dev_dbg(dev, "%s: Attached IOMMU with pgtable %pa\n", __func__, 867 dev_dbg(dev, "%s: Attached IOMMU with pgtable %pa\n", __func__,
857 &pagetable); 868 &pagetable);
858 869