aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJoerg Roedel <jroedel@suse.de>2015-03-26 08:43:11 -0400
committerJoerg Roedel <jroedel@suse.de>2015-03-31 09:32:11 -0400
commite1fd1eaa3323b3ea68f2ad3116b8cbe1f34cb2a2 (patch)
treea62ea243156f8c671580d8f63f2561adf2d9289b
parent1d672638fca24db2a66101c2109d94dbee084e96 (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.c87
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
205struct sysmmu_drvdata { 206struct sysmmu_drvdata {
@@ -214,6 +215,11 @@ struct sysmmu_drvdata {
214 phys_addr_t pgtable; 215 phys_addr_t pgtable;
215}; 216};
216 217
218static struct exynos_iommu_domain *to_exynos_domain(struct iommu_domain *dom)
219{
220 return container_of(dom, struct exynos_iommu_domain, domain);
221}
222
217static bool set_sysmmu_active(struct sysmmu_drvdata *data) 223static 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
699static int exynos_iommu_domain_init(struct iommu_domain *domain) 705static 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
741err_counter: 749err_counter:
742 free_pages((unsigned long)priv->pgtable, 2); 750 free_pages((unsigned long)exynos_domain->pgtable, 2);
743err_pgtable: 751err_pgtable:
744 kfree(priv); 752 kfree(exynos_domain);
745 return -ENOMEM; 753 return NULL;
746} 754}
747 755
748static void exynos_iommu_domain_destroy(struct iommu_domain *domain) 756static 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
780static int exynos_iommu_attach_device(struct iommu_domain *domain, 787static 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,
988static int exynos_iommu_map(struct iommu_domain *domain, unsigned long l_iova, 995static 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,
1042static size_t exynos_iommu_unmap(struct iommu_domain *domain, 1049static 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:
1119static phys_addr_t exynos_iommu_iova_to_phys(struct iommu_domain *domain, 1126static 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
1173static const struct iommu_ops exynos_iommu_ops = { 1180static 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,