aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/iommu
diff options
context:
space:
mode:
authorCho KyongHo <pullip.cho@samsung.com>2014-05-12 02:14:48 -0400
committerJoerg Roedel <jroedel@suse.de>2014-05-13 13:12:52 -0400
commit734c3c732ca91adbe705f2a289509627810231a3 (patch)
tree126fab4005743d5a8821d5d14f44a0d4ea414be4 /drivers/iommu
parent61128f08fc110fc27cd50f5a8ca57c6a8c3bcddc (diff)
iommu/exynos: Allocate lv2 page table from own slab
Since kmalloc() does not guarantee that the allignment of 1KiB when it allocates 1KiB, it is required to allocate lv2 page table from own slab that guarantees alignment of 1KiB Signed-off-by: Cho KyongHo <pullip.cho@samsung.com> Signed-off-by: Shaik Ameer Basha <shaik.ameer@samsung.com> Signed-off-by: Joerg Roedel <jroedel@suse.de>
Diffstat (limited to 'drivers/iommu')
-rw-r--r--drivers/iommu/exynos-iommu.c34
1 files changed, 28 insertions, 6 deletions
diff --git a/drivers/iommu/exynos-iommu.c b/drivers/iommu/exynos-iommu.c
index aec7fd75f400..4ff4b0b81575 100644
--- a/drivers/iommu/exynos-iommu.c
+++ b/drivers/iommu/exynos-iommu.c
@@ -99,6 +99,8 @@
99#define REG_PB1_SADDR 0x054 99#define REG_PB1_SADDR 0x054
100#define REG_PB1_EADDR 0x058 100#define REG_PB1_EADDR 0x058
101 101
102static struct kmem_cache *lv2table_kmem_cache;
103
102static unsigned long *section_entry(unsigned long *pgtable, unsigned long iova) 104static unsigned long *section_entry(unsigned long *pgtable, unsigned long iova)
103{ 105{
104 return pgtable + lv1ent_offset(iova); 106 return pgtable + lv1ent_offset(iova);
@@ -637,7 +639,8 @@ static void exynos_iommu_domain_destroy(struct iommu_domain *domain)
637 639
638 for (i = 0; i < NUM_LV1ENTRIES; i++) 640 for (i = 0; i < NUM_LV1ENTRIES; i++)
639 if (lv1ent_page(priv->pgtable + i)) 641 if (lv1ent_page(priv->pgtable + i))
640 kfree(phys_to_virt(lv2table_base(priv->pgtable + i))); 642 kmem_cache_free(lv2table_kmem_cache,
643 phys_to_virt(lv2table_base(priv->pgtable + i)));
641 644
642 free_pages((unsigned long)priv->pgtable, 2); 645 free_pages((unsigned long)priv->pgtable, 2);
643 free_pages((unsigned long)priv->lv2entcnt, 1); 646 free_pages((unsigned long)priv->lv2entcnt, 1);
@@ -736,7 +739,7 @@ static unsigned long *alloc_lv2entry(unsigned long *sent, unsigned long iova,
736 if (lv1ent_fault(sent)) { 739 if (lv1ent_fault(sent)) {
737 unsigned long *pent; 740 unsigned long *pent;
738 741
739 pent = kzalloc(LV2TABLE_SIZE, GFP_ATOMIC); 742 pent = kmem_cache_zalloc(lv2table_kmem_cache, GFP_ATOMIC);
740 BUG_ON((unsigned long)pent & (LV2TABLE_SIZE - 1)); 743 BUG_ON((unsigned long)pent & (LV2TABLE_SIZE - 1));
741 if (!pent) 744 if (!pent)
742 return ERR_PTR(-ENOMEM); 745 return ERR_PTR(-ENOMEM);
@@ -766,8 +769,7 @@ static int lv1set_section(unsigned long *sent, unsigned long iova,
766 return -EADDRINUSE; 769 return -EADDRINUSE;
767 } 770 }
768 771
769 kfree(page_entry(sent, 0)); 772 kmem_cache_free(lv2table_kmem_cache, page_entry(sent, 0));
770
771 *pgcnt = 0; 773 *pgcnt = 0;
772 } 774 }
773 775
@@ -970,11 +972,31 @@ static int __init exynos_iommu_init(void)
970{ 972{
971 int ret; 973 int ret;
972 974
975 lv2table_kmem_cache = kmem_cache_create("exynos-iommu-lv2table",
976 LV2TABLE_SIZE, LV2TABLE_SIZE, 0, NULL);
977 if (!lv2table_kmem_cache) {
978 pr_err("%s: Failed to create kmem cache\n", __func__);
979 return -ENOMEM;
980 }
981
973 ret = platform_driver_register(&exynos_sysmmu_driver); 982 ret = platform_driver_register(&exynos_sysmmu_driver);
983 if (ret) {
984 pr_err("%s: Failed to register driver\n", __func__);
985 goto err_reg_driver;
986 }
974 987
975 if (ret == 0) 988 ret = bus_set_iommu(&platform_bus_type, &exynos_iommu_ops);
976 bus_set_iommu(&platform_bus_type, &exynos_iommu_ops); 989 if (ret) {
990 pr_err("%s: Failed to register exynos-iommu driver.\n",
991 __func__);
992 goto err_set_iommu;
993 }
977 994
995 return 0;
996err_set_iommu:
997 platform_driver_unregister(&exynos_sysmmu_driver);
998err_reg_driver:
999 kmem_cache_destroy(lv2table_kmem_cache);
978 return ret; 1000 return ret;
979} 1001}
980subsys_initcall(exynos_iommu_init); 1002subsys_initcall(exynos_iommu_init);