summaryrefslogtreecommitdiff
path: root/patches.tizen/0018-iommu-exynos-allocate-lv2-page-table-from-own-slab.patch
diff options
context:
space:
mode:
Diffstat (limited to 'patches.tizen/0018-iommu-exynos-allocate-lv2-page-table-from-own-slab.patch')
-rw-r--r--patches.tizen/0018-iommu-exynos-allocate-lv2-page-table-from-own-slab.patch84
1 files changed, 84 insertions, 0 deletions
diff --git a/patches.tizen/0018-iommu-exynos-allocate-lv2-page-table-from-own-slab.patch b/patches.tizen/0018-iommu-exynos-allocate-lv2-page-table-from-own-slab.patch
new file mode 100644
index 00000000000..bb5a914a409
--- /dev/null
+++ b/patches.tizen/0018-iommu-exynos-allocate-lv2-page-table-from-own-slab.patch
@@ -0,0 +1,84 @@
+From 429942a268e534b39ddbe819cbd8c5641c7bbf38 Mon Sep 17 00:00:00 2001
+From: Cho KyongHo <pullip.cho@samsung.com>
+Date: Fri, 26 Jul 2013 20:27:29 +0900
+Subject: [PATCH 0018/1302] 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: MyungJoo Ham <myungjoo.ham@samsung.com>
+---
+ drivers/iommu/exynos-iommu.c | 24 ++++++++++++++++++++----
+ 1 file changed, 20 insertions(+), 4 deletions(-)
+
+diff --git a/drivers/iommu/exynos-iommu.c b/drivers/iommu/exynos-iommu.c
+index 6c4ecce..093eea5 100644
+--- a/drivers/iommu/exynos-iommu.c
++++ b/drivers/iommu/exynos-iommu.c
+@@ -100,6 +100,8 @@
+ #define REG_PB1_SADDR 0x054
+ #define REG_PB1_EADDR 0x058
+
++static struct kmem_cache *lv2table_kmem_cache;
++
+ static unsigned long *section_entry(unsigned long *pgtable, unsigned long iova)
+ {
+ return pgtable + lv1ent_offset(iova);
+@@ -765,7 +767,8 @@ static void exynos_iommu_domain_destroy(struct iommu_domain *domain)
+
+ for (i = 0; i < NUM_LV1ENTRIES; i++)
+ if (lv1ent_page(priv->pgtable + i))
+- kfree(__va(lv2table_base(priv->pgtable + i)));
++ kmem_cache_free(lv2table_kmem_cache,
++ __va(lv2table_base(priv->pgtable + i)));
+
+ free_pages((unsigned long)priv->pgtable, 2);
+ free_pages((unsigned long)priv->lv2entcnt, 1);
+@@ -859,7 +862,7 @@ static unsigned long *alloc_lv2entry(unsigned long *sent, unsigned long iova,
+ if (lv1ent_fault(sent)) {
+ unsigned long *pent;
+
+- pent = kzalloc(LV2TABLE_SIZE, GFP_ATOMIC);
++ pent = kmem_cache_zalloc(lv2table_kmem_cache, GFP_ATOMIC);
+ BUG_ON((unsigned long)pent & (LV2TABLE_SIZE - 1));
+ if (!pent)
+ return ERR_PTR(-ENOMEM);
+@@ -884,7 +887,7 @@ static int lv1set_section(unsigned long *sent, phys_addr_t paddr, short *pgcnt)
+ if (*pgcnt != NUM_LV2ENTRIES)
+ return -EADDRINUSE;
+
+- kfree(page_entry(sent, 0));
++ kmem_cache_free(lv2table_kmem_cache, page_entry(sent, 0));
+
+ *pgcnt = 0;
+ }
+@@ -1092,10 +1095,23 @@ static int __init exynos_iommu_init(void)
+ {
+ int ret;
+
++ lv2table_kmem_cache = kmem_cache_create("exynos-iommu-lv2table",
++ LV2TABLE_SIZE, LV2TABLE_SIZE, 0, NULL);
++ if (!lv2table_kmem_cache) {
++ pr_err("%s: Failed to create kmem cache\n", __func__);
++ return -ENOMEM;
++ }
++
+ ret = platform_driver_register(&exynos_sysmmu_driver);
+
+ if (ret == 0)
+- bus_set_iommu(&platform_bus_type, &exynos_iommu_ops);
++ ret = bus_set_iommu(&platform_bus_type, &exynos_iommu_ops);
++
++ if (ret) {
++ pr_err("%s: Failed to register exynos-iommu driver.\n",
++ __func__);
++ kmem_cache_destroy(lv2table_kmem_cache);
++ }
+
+ return ret;
+ }
+--
+1.8.3.2
+