|
@@ -99,6 +99,8 @@
|
|
#define REG_PB1_SADDR 0x054
|
|
#define REG_PB1_SADDR 0x054
|
|
#define REG_PB1_EADDR 0x058
|
|
#define REG_PB1_EADDR 0x058
|
|
|
|
|
|
|
|
+static struct kmem_cache *lv2table_kmem_cache;
|
|
|
|
+
|
|
static unsigned long *section_entry(unsigned long *pgtable, unsigned long iova)
|
|
static unsigned long *section_entry(unsigned long *pgtable, unsigned long iova)
|
|
{
|
|
{
|
|
return pgtable + lv1ent_offset(iova);
|
|
return pgtable + lv1ent_offset(iova);
|
|
@@ -637,7 +639,8 @@ static void exynos_iommu_domain_destroy(struct iommu_domain *domain)
|
|
|
|
|
|
for (i = 0; i < NUM_LV1ENTRIES; i++)
|
|
for (i = 0; i < NUM_LV1ENTRIES; i++)
|
|
if (lv1ent_page(priv->pgtable + i))
|
|
if (lv1ent_page(priv->pgtable + i))
|
|
- kfree(phys_to_virt(lv2table_base(priv->pgtable + i)));
|
|
|
|
|
|
+ kmem_cache_free(lv2table_kmem_cache,
|
|
|
|
+ phys_to_virt(lv2table_base(priv->pgtable + i)));
|
|
|
|
|
|
free_pages((unsigned long)priv->pgtable, 2);
|
|
free_pages((unsigned long)priv->pgtable, 2);
|
|
free_pages((unsigned long)priv->lv2entcnt, 1);
|
|
free_pages((unsigned long)priv->lv2entcnt, 1);
|
|
@@ -736,7 +739,7 @@ static unsigned long *alloc_lv2entry(unsigned long *sent, unsigned long iova,
|
|
if (lv1ent_fault(sent)) {
|
|
if (lv1ent_fault(sent)) {
|
|
unsigned long *pent;
|
|
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));
|
|
BUG_ON((unsigned long)pent & (LV2TABLE_SIZE - 1));
|
|
if (!pent)
|
|
if (!pent)
|
|
return ERR_PTR(-ENOMEM);
|
|
return ERR_PTR(-ENOMEM);
|
|
@@ -766,8 +769,7 @@ static int lv1set_section(unsigned long *sent, unsigned long iova,
|
|
return -EADDRINUSE;
|
|
return -EADDRINUSE;
|
|
}
|
|
}
|
|
|
|
|
|
- kfree(page_entry(sent, 0));
|
|
|
|
-
|
|
|
|
|
|
+ kmem_cache_free(lv2table_kmem_cache, page_entry(sent, 0));
|
|
*pgcnt = 0;
|
|
*pgcnt = 0;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -970,11 +972,31 @@ static int __init exynos_iommu_init(void)
|
|
{
|
|
{
|
|
int ret;
|
|
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);
|
|
ret = platform_driver_register(&exynos_sysmmu_driver);
|
|
|
|
+ if (ret) {
|
|
|
|
+ pr_err("%s: Failed to register driver\n", __func__);
|
|
|
|
+ goto err_reg_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__);
|
|
|
|
+ goto err_set_iommu;
|
|
|
|
+ }
|
|
|
|
|
|
|
|
+ return 0;
|
|
|
|
+err_set_iommu:
|
|
|
|
+ platform_driver_unregister(&exynos_sysmmu_driver);
|
|
|
|
+err_reg_driver:
|
|
|
|
+ kmem_cache_destroy(lv2table_kmem_cache);
|
|
return ret;
|
|
return ret;
|
|
}
|
|
}
|
|
subsys_initcall(exynos_iommu_init);
|
|
subsys_initcall(exynos_iommu_init);
|