summaryrefslogtreecommitdiffstats
path: root/drivers/iommu/exynos-iommu.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/iommu/exynos-iommu.c')
-rw-r--r--drivers/iommu/exynos-iommu.c65
1 files changed, 17 insertions, 48 deletions
diff --git a/drivers/iommu/exynos-iommu.c b/drivers/iommu/exynos-iommu.c
index 65bf9372c890..33229853c70c 100644
--- a/drivers/iommu/exynos-iommu.c
+++ b/drivers/iommu/exynos-iommu.c
@@ -491,9 +491,6 @@ static bool __sysmmu_disable(struct sysmmu_drvdata *data)
491 __sysmmu_disable_nocount(data); 491 __sysmmu_disable_nocount(data);
492 492
493 dev_dbg(data->sysmmu, "Disabled\n"); 493 dev_dbg(data->sysmmu, "Disabled\n");
494 } else {
495 dev_dbg(data->sysmmu, "%d times left to disable\n",
496 data->activations);
497 } 494 }
498 495
499 spin_unlock_irqrestore(&data->lock, flags); 496 spin_unlock_irqrestore(&data->lock, flags);
@@ -541,29 +538,18 @@ static void __sysmmu_enable_nocount(struct sysmmu_drvdata *data)
541static int __sysmmu_enable(struct sysmmu_drvdata *data, phys_addr_t pgtable, 538static int __sysmmu_enable(struct sysmmu_drvdata *data, phys_addr_t pgtable,
542 struct exynos_iommu_domain *domain) 539 struct exynos_iommu_domain *domain)
543{ 540{
544 int ret = 0;
545 unsigned long flags; 541 unsigned long flags;
546 542
547 spin_lock_irqsave(&data->lock, flags); 543 spin_lock_irqsave(&data->lock, flags);
548 if (set_sysmmu_active(data)) { 544 if (set_sysmmu_active(data)) {
549 data->pgtable = pgtable; 545 data->pgtable = pgtable;
550 data->domain = domain; 546 data->domain = domain;
551
552 __sysmmu_enable_nocount(data); 547 __sysmmu_enable_nocount(data);
553
554 dev_dbg(data->sysmmu, "Enabled\n"); 548 dev_dbg(data->sysmmu, "Enabled\n");
555 } else {
556 ret = (pgtable == data->pgtable) ? 1 : -EBUSY;
557
558 dev_dbg(data->sysmmu, "already enabled\n");
559 } 549 }
560
561 if (WARN_ON(ret < 0))
562 set_sysmmu_inactive(data); /* decrement count */
563
564 spin_unlock_irqrestore(&data->lock, flags); 550 spin_unlock_irqrestore(&data->lock, flags);
565 551
566 return ret; 552 return 0;
567} 553}
568 554
569static void sysmmu_tlb_invalidate_flpdcache(struct sysmmu_drvdata *data, 555static void sysmmu_tlb_invalidate_flpdcache(struct sysmmu_drvdata *data,
@@ -831,8 +817,8 @@ static void exynos_iommu_domain_free(struct iommu_domain *iommu_domain)
831 spin_lock_irqsave(&domain->lock, flags); 817 spin_lock_irqsave(&domain->lock, flags);
832 818
833 list_for_each_entry_safe(data, next, &domain->clients, domain_node) { 819 list_for_each_entry_safe(data, next, &domain->clients, domain_node) {
834 if (__sysmmu_disable(data)) 820 __sysmmu_disable(data);
835 data->master = NULL; 821 data->master = NULL;
836 list_del_init(&data->domain_node); 822 list_del_init(&data->domain_node);
837 } 823 }
838 824
@@ -867,31 +853,23 @@ static void exynos_iommu_detach_device(struct iommu_domain *iommu_domain,
867 phys_addr_t pagetable = virt_to_phys(domain->pgtable); 853 phys_addr_t pagetable = virt_to_phys(domain->pgtable);
868 struct sysmmu_drvdata *data, *next; 854 struct sysmmu_drvdata *data, *next;
869 unsigned long flags; 855 unsigned long flags;
870 bool found = false;
871 856
872 if (!has_sysmmu(dev) || owner->domain != iommu_domain) 857 if (!has_sysmmu(dev) || owner->domain != iommu_domain)
873 return; 858 return;
874 859
875 spin_lock_irqsave(&domain->lock, flags); 860 spin_lock_irqsave(&domain->lock, flags);
876 list_for_each_entry_safe(data, next, &domain->clients, domain_node) { 861 list_for_each_entry_safe(data, next, &domain->clients, domain_node) {
877 if (data->master == dev) { 862 __sysmmu_disable(data);
878 if (__sysmmu_disable(data)) { 863 data->master = NULL;
879 data->master = NULL; 864 list_del_init(&data->domain_node);
880 list_del_init(&data->domain_node); 865 pm_runtime_put(data->sysmmu);
881 }
882 pm_runtime_put(data->sysmmu);
883 found = true;
884 }
885 } 866 }
886 spin_unlock_irqrestore(&domain->lock, flags); 867 spin_unlock_irqrestore(&domain->lock, flags);
887 868
888 owner->domain = NULL; 869 owner->domain = NULL;
889 870
890 if (found) 871 dev_dbg(dev, "%s: Detached IOMMU with pgtable %pa\n", __func__,
891 dev_dbg(dev, "%s: Detached IOMMU with pgtable %pa\n", 872 &pagetable);
892 __func__, &pagetable);
893 else
894 dev_err(dev, "%s: No IOMMU is attached\n", __func__);
895} 873}
896 874
897static int exynos_iommu_attach_device(struct iommu_domain *iommu_domain, 875static int exynos_iommu_attach_device(struct iommu_domain *iommu_domain,
@@ -902,7 +880,6 @@ static int exynos_iommu_attach_device(struct iommu_domain *iommu_domain,
902 struct sysmmu_drvdata *data; 880 struct sysmmu_drvdata *data;
903 phys_addr_t pagetable = virt_to_phys(domain->pgtable); 881 phys_addr_t pagetable = virt_to_phys(domain->pgtable);
904 unsigned long flags; 882 unsigned long flags;
905 int ret = -ENODEV;
906 883
907 if (!has_sysmmu(dev)) 884 if (!has_sysmmu(dev))
908 return -ENODEV; 885 return -ENODEV;
@@ -912,27 +889,19 @@ static int exynos_iommu_attach_device(struct iommu_domain *iommu_domain,
912 889
913 list_for_each_entry(data, &owner->controllers, owner_node) { 890 list_for_each_entry(data, &owner->controllers, owner_node) {
914 pm_runtime_get_sync(data->sysmmu); 891 pm_runtime_get_sync(data->sysmmu);
915 ret = __sysmmu_enable(data, pagetable, domain); 892 __sysmmu_enable(data, pagetable, domain);
916 if (ret >= 0) { 893 data->master = dev;
917 data->master = dev;
918 894
919 spin_lock_irqsave(&domain->lock, flags); 895 spin_lock_irqsave(&domain->lock, flags);
920 list_add_tail(&data->domain_node, &domain->clients); 896 list_add_tail(&data->domain_node, &domain->clients);
921 spin_unlock_irqrestore(&domain->lock, flags); 897 spin_unlock_irqrestore(&domain->lock, flags);
922 }
923 }
924
925 if (ret < 0) {
926 dev_err(dev, "%s: Failed to attach IOMMU with pgtable %pa\n",
927 __func__, &pagetable);
928 return ret;
929 } 898 }
930 899
931 owner->domain = iommu_domain; 900 owner->domain = iommu_domain;
932 dev_dbg(dev, "%s: Attached IOMMU with pgtable %pa %s\n", 901 dev_dbg(dev, "%s: Attached IOMMU with pgtable %pa\n", __func__,
933 __func__, &pagetable, (ret == 0) ? "" : ", again"); 902 &pagetable);
934 903
935 return ret; 904 return 0;
936} 905}
937 906
938static sysmmu_pte_t *alloc_lv2entry(struct exynos_iommu_domain *domain, 907static sysmmu_pte_t *alloc_lv2entry(struct exynos_iommu_domain *domain,