diff options
author | Joerg Roedel <jroedel@suse.de> | 2015-03-26 08:43:11 -0400 |
---|---|---|
committer | Joerg Roedel <jroedel@suse.de> | 2015-03-31 09:32:11 -0400 |
commit | e1fd1eaa3323b3ea68f2ad3116b8cbe1f34cb2a2 (patch) | |
tree | a62ea243156f8c671580d8f63f2561adf2d9289b | |
parent | 1d672638fca24db2a66101c2109d94dbee084e96 (diff) |
iommu/exynos: Make use of domain_alloc and domain_free
Implement domain_alloc and domain_free iommu-ops as a
replacement for domain_init/domain_destroy.
Signed-off-by: Joerg Roedel <jroedel@suse.de>
-rw-r--r-- | drivers/iommu/exynos-iommu.c | 87 |
1 files changed, 47 insertions, 40 deletions
diff --git a/drivers/iommu/exynos-iommu.c b/drivers/iommu/exynos-iommu.c index dc14fec4ede1..3e898504a7c4 100644 --- a/drivers/iommu/exynos-iommu.c +++ b/drivers/iommu/exynos-iommu.c | |||
@@ -200,6 +200,7 @@ struct exynos_iommu_domain { | |||
200 | short *lv2entcnt; /* free lv2 entry counter for each section */ | 200 | short *lv2entcnt; /* free lv2 entry counter for each section */ |
201 | spinlock_t lock; /* lock for this structure */ | 201 | spinlock_t lock; /* lock for this structure */ |
202 | spinlock_t pgtablelock; /* lock for modifying page table @ pgtable */ | 202 | spinlock_t pgtablelock; /* lock for modifying page table @ pgtable */ |
203 | struct iommu_domain domain; /* generic domain data structure */ | ||
203 | }; | 204 | }; |
204 | 205 | ||
205 | struct sysmmu_drvdata { | 206 | struct sysmmu_drvdata { |
@@ -214,6 +215,11 @@ struct sysmmu_drvdata { | |||
214 | phys_addr_t pgtable; | 215 | phys_addr_t pgtable; |
215 | }; | 216 | }; |
216 | 217 | ||
218 | static struct exynos_iommu_domain *to_exynos_domain(struct iommu_domain *dom) | ||
219 | { | ||
220 | return container_of(dom, struct exynos_iommu_domain, domain); | ||
221 | } | ||
222 | |||
217 | static bool set_sysmmu_active(struct sysmmu_drvdata *data) | 223 | static bool set_sysmmu_active(struct sysmmu_drvdata *data) |
218 | { | 224 | { |
219 | /* return true if the System MMU was not active previously | 225 | /* return true if the System MMU was not active previously |
@@ -696,58 +702,60 @@ static inline void pgtable_flush(void *vastart, void *vaend) | |||
696 | virt_to_phys(vaend)); | 702 | virt_to_phys(vaend)); |
697 | } | 703 | } |
698 | 704 | ||
699 | static int exynos_iommu_domain_init(struct iommu_domain *domain) | 705 | static struct iommu_domain *exynos_iommu_domain_alloc(unsigned type) |
700 | { | 706 | { |
701 | struct exynos_iommu_domain *priv; | 707 | struct exynos_iommu_domain *exynos_domain; |
702 | int i; | 708 | int i; |
703 | 709 | ||
704 | priv = kzalloc(sizeof(*priv), GFP_KERNEL); | 710 | if (type != IOMMU_DOMAIN_UNMANAGED) |
705 | if (!priv) | 711 | return NULL; |
706 | return -ENOMEM; | 712 | |
713 | exynos_domain = kzalloc(sizeof(*exynos_domain), GFP_KERNEL); | ||
714 | if (!exynos_domain) | ||
715 | return NULL; | ||
707 | 716 | ||
708 | priv->pgtable = (sysmmu_pte_t *)__get_free_pages(GFP_KERNEL, 2); | 717 | exynos_domain->pgtable = (sysmmu_pte_t *)__get_free_pages(GFP_KERNEL, 2); |
709 | if (!priv->pgtable) | 718 | if (!exynos_domain->pgtable) |
710 | goto err_pgtable; | 719 | goto err_pgtable; |
711 | 720 | ||
712 | priv->lv2entcnt = (short *)__get_free_pages(GFP_KERNEL | __GFP_ZERO, 1); | 721 | exynos_domain->lv2entcnt = (short *)__get_free_pages(GFP_KERNEL | __GFP_ZERO, 1); |
713 | if (!priv->lv2entcnt) | 722 | if (!exynos_domain->lv2entcnt) |
714 | goto err_counter; | 723 | goto err_counter; |
715 | 724 | ||
716 | /* Workaround for System MMU v3.3 to prevent caching 1MiB mapping */ | 725 | /* Workaround for System MMU v3.3 to prevent caching 1MiB mapping */ |
717 | for (i = 0; i < NUM_LV1ENTRIES; i += 8) { | 726 | for (i = 0; i < NUM_LV1ENTRIES; i += 8) { |
718 | priv->pgtable[i + 0] = ZERO_LV2LINK; | 727 | exynos_domain->pgtable[i + 0] = ZERO_LV2LINK; |
719 | priv->pgtable[i + 1] = ZERO_LV2LINK; | 728 | exynos_domain->pgtable[i + 1] = ZERO_LV2LINK; |
720 | priv->pgtable[i + 2] = ZERO_LV2LINK; | 729 | exynos_domain->pgtable[i + 2] = ZERO_LV2LINK; |
721 | priv->pgtable[i + 3] = ZERO_LV2LINK; | 730 | exynos_domain->pgtable[i + 3] = ZERO_LV2LINK; |
722 | priv->pgtable[i + 4] = ZERO_LV2LINK; | 731 | exynos_domain->pgtable[i + 4] = ZERO_LV2LINK; |
723 | priv->pgtable[i + 5] = ZERO_LV2LINK; | 732 | exynos_domain->pgtable[i + 5] = ZERO_LV2LINK; |
724 | priv->pgtable[i + 6] = ZERO_LV2LINK; | 733 | exynos_domain->pgtable[i + 6] = ZERO_LV2LINK; |
725 | priv->pgtable[i + 7] = ZERO_LV2LINK; | 734 | exynos_domain->pgtable[i + 7] = ZERO_LV2LINK; |
726 | } | 735 | } |
727 | 736 | ||
728 | pgtable_flush(priv->pgtable, priv->pgtable + NUM_LV1ENTRIES); | 737 | pgtable_flush(exynos_domain->pgtable, exynos_domain->pgtable + NUM_LV1ENTRIES); |
729 | 738 | ||
730 | spin_lock_init(&priv->lock); | 739 | spin_lock_init(&exynos_domain->lock); |
731 | spin_lock_init(&priv->pgtablelock); | 740 | spin_lock_init(&exynos_domain->pgtablelock); |
732 | INIT_LIST_HEAD(&priv->clients); | 741 | INIT_LIST_HEAD(&exynos_domain->clients); |
733 | 742 | ||
734 | domain->geometry.aperture_start = 0; | 743 | exynos_domain->domain.geometry.aperture_start = 0; |
735 | domain->geometry.aperture_end = ~0UL; | 744 | exynos_domain->domain.geometry.aperture_end = ~0UL; |
736 | domain->geometry.force_aperture = true; | 745 | exynos_domain->domain.geometry.force_aperture = true; |
737 | 746 | ||
738 | domain->priv = priv; | 747 | return &exynos_domain->domain; |
739 | return 0; | ||
740 | 748 | ||
741 | err_counter: | 749 | err_counter: |
742 | free_pages((unsigned long)priv->pgtable, 2); | 750 | free_pages((unsigned long)exynos_domain->pgtable, 2); |
743 | err_pgtable: | 751 | err_pgtable: |
744 | kfree(priv); | 752 | kfree(exynos_domain); |
745 | return -ENOMEM; | 753 | return NULL; |
746 | } | 754 | } |
747 | 755 | ||
748 | static void exynos_iommu_domain_destroy(struct iommu_domain *domain) | 756 | static void exynos_iommu_domain_free(struct iommu_domain *domain) |
749 | { | 757 | { |
750 | struct exynos_iommu_domain *priv = domain->priv; | 758 | struct exynos_iommu_domain *priv = to_exynos_domain(domain); |
751 | struct exynos_iommu_owner *owner; | 759 | struct exynos_iommu_owner *owner; |
752 | unsigned long flags; | 760 | unsigned long flags; |
753 | int i; | 761 | int i; |
@@ -773,15 +781,14 @@ static void exynos_iommu_domain_destroy(struct iommu_domain *domain) | |||
773 | 781 | ||
774 | free_pages((unsigned long)priv->pgtable, 2); | 782 | free_pages((unsigned long)priv->pgtable, 2); |
775 | free_pages((unsigned long)priv->lv2entcnt, 1); | 783 | free_pages((unsigned long)priv->lv2entcnt, 1); |
776 | kfree(domain->priv); | 784 | kfree(priv); |
777 | domain->priv = NULL; | ||
778 | } | 785 | } |
779 | 786 | ||
780 | static int exynos_iommu_attach_device(struct iommu_domain *domain, | 787 | static int exynos_iommu_attach_device(struct iommu_domain *domain, |
781 | struct device *dev) | 788 | struct device *dev) |
782 | { | 789 | { |
783 | struct exynos_iommu_owner *owner = dev->archdata.iommu; | 790 | struct exynos_iommu_owner *owner = dev->archdata.iommu; |
784 | struct exynos_iommu_domain *priv = domain->priv; | 791 | struct exynos_iommu_domain *priv = to_exynos_domain(domain); |
785 | phys_addr_t pagetable = virt_to_phys(priv->pgtable); | 792 | phys_addr_t pagetable = virt_to_phys(priv->pgtable); |
786 | unsigned long flags; | 793 | unsigned long flags; |
787 | int ret; | 794 | int ret; |
@@ -812,7 +819,7 @@ static void exynos_iommu_detach_device(struct iommu_domain *domain, | |||
812 | struct device *dev) | 819 | struct device *dev) |
813 | { | 820 | { |
814 | struct exynos_iommu_owner *owner; | 821 | struct exynos_iommu_owner *owner; |
815 | struct exynos_iommu_domain *priv = domain->priv; | 822 | struct exynos_iommu_domain *priv = to_exynos_domain(domain); |
816 | phys_addr_t pagetable = virt_to_phys(priv->pgtable); | 823 | phys_addr_t pagetable = virt_to_phys(priv->pgtable); |
817 | unsigned long flags; | 824 | unsigned long flags; |
818 | 825 | ||
@@ -988,7 +995,7 @@ static int lv2set_page(sysmmu_pte_t *pent, phys_addr_t paddr, size_t size, | |||
988 | static int exynos_iommu_map(struct iommu_domain *domain, unsigned long l_iova, | 995 | static int exynos_iommu_map(struct iommu_domain *domain, unsigned long l_iova, |
989 | phys_addr_t paddr, size_t size, int prot) | 996 | phys_addr_t paddr, size_t size, int prot) |
990 | { | 997 | { |
991 | struct exynos_iommu_domain *priv = domain->priv; | 998 | struct exynos_iommu_domain *priv = to_exynos_domain(domain); |
992 | sysmmu_pte_t *entry; | 999 | sysmmu_pte_t *entry; |
993 | sysmmu_iova_t iova = (sysmmu_iova_t)l_iova; | 1000 | sysmmu_iova_t iova = (sysmmu_iova_t)l_iova; |
994 | unsigned long flags; | 1001 | unsigned long flags; |
@@ -1042,7 +1049,7 @@ static void exynos_iommu_tlb_invalidate_entry(struct exynos_iommu_domain *priv, | |||
1042 | static size_t exynos_iommu_unmap(struct iommu_domain *domain, | 1049 | static size_t exynos_iommu_unmap(struct iommu_domain *domain, |
1043 | unsigned long l_iova, size_t size) | 1050 | unsigned long l_iova, size_t size) |
1044 | { | 1051 | { |
1045 | struct exynos_iommu_domain *priv = domain->priv; | 1052 | struct exynos_iommu_domain *priv = to_exynos_domain(domain); |
1046 | sysmmu_iova_t iova = (sysmmu_iova_t)l_iova; | 1053 | sysmmu_iova_t iova = (sysmmu_iova_t)l_iova; |
1047 | sysmmu_pte_t *ent; | 1054 | sysmmu_pte_t *ent; |
1048 | size_t err_pgsize; | 1055 | size_t err_pgsize; |
@@ -1119,7 +1126,7 @@ err: | |||
1119 | static phys_addr_t exynos_iommu_iova_to_phys(struct iommu_domain *domain, | 1126 | static phys_addr_t exynos_iommu_iova_to_phys(struct iommu_domain *domain, |
1120 | dma_addr_t iova) | 1127 | dma_addr_t iova) |
1121 | { | 1128 | { |
1122 | struct exynos_iommu_domain *priv = domain->priv; | 1129 | struct exynos_iommu_domain *priv = to_exynos_domain(domain); |
1123 | sysmmu_pte_t *entry; | 1130 | sysmmu_pte_t *entry; |
1124 | unsigned long flags; | 1131 | unsigned long flags; |
1125 | phys_addr_t phys = 0; | 1132 | phys_addr_t phys = 0; |
@@ -1171,8 +1178,8 @@ static void exynos_iommu_remove_device(struct device *dev) | |||
1171 | } | 1178 | } |
1172 | 1179 | ||
1173 | static const struct iommu_ops exynos_iommu_ops = { | 1180 | static const struct iommu_ops exynos_iommu_ops = { |
1174 | .domain_init = exynos_iommu_domain_init, | 1181 | .domain_alloc = exynos_iommu_domain_alloc, |
1175 | .domain_destroy = exynos_iommu_domain_destroy, | 1182 | .domain_free = exynos_iommu_domain_free, |
1176 | .attach_dev = exynos_iommu_attach_device, | 1183 | .attach_dev = exynos_iommu_attach_device, |
1177 | .detach_dev = exynos_iommu_detach_device, | 1184 | .detach_dev = exynos_iommu_detach_device, |
1178 | .map = exynos_iommu_map, | 1185 | .map = exynos_iommu_map, |