diff options
Diffstat (limited to 'drivers/iommu/exynos-iommu.c')
-rw-r--r-- | drivers/iommu/exynos-iommu.c | 65 |
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) | |||
541 | static int __sysmmu_enable(struct sysmmu_drvdata *data, phys_addr_t pgtable, | 538 | static 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 | ||
569 | static void sysmmu_tlb_invalidate_flpdcache(struct sysmmu_drvdata *data, | 555 | static 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 | ||
897 | static int exynos_iommu_attach_device(struct iommu_domain *iommu_domain, | 875 | static 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 | ||
938 | static sysmmu_pte_t *alloc_lv2entry(struct exynos_iommu_domain *domain, | 907 | static sysmmu_pte_t *alloc_lv2entry(struct exynos_iommu_domain *domain, |