codec_mm: add reserved & cma support for 4.9. [1/1]
authorZhi Zhou <zhi.zhou@amlogic.com>
Fri, 14 Sep 2018 07:32:06 +0000 (15:32 +0800)
committerJianxin Pan <jianxin.pan@amlogic.com>
Mon, 5 Nov 2018 12:36:36 +0000 (05:36 -0700)
PD#172483

Problem:
Add reserved & cma support for 4.9.

Solution:
1. add tvp padding, for test.
2. add no-cma-tvp,to force not used cma for tvp.
3. add nomap for reserved memroy detective.
4. add res & cma two mem region on same board.
5. add clear-map property for codec_mm_cma.

Verify:
Test this function with Android_O-MR1(GTVS) & ExoPlayer.

Change-Id: Ib20e0e9bc4725afb271de97543ce5ebf3bfcfb29
Signed-off-by: Zhi Zhou <zhi.zhou@amlogic.com>
arch/arm64/boot/dts/amlogic/g12b_a311d_w400.dts
arch/arm64/boot/dts/amlogic/gxl_p212_1g.dts
arch/arm64/mm/mmu.c
drivers/amlogic/media/common/codec_mm/codec_mm.c
drivers/base/dma-contiguous.c
include/linux/cma.h
mm/cma.c
mm/cma.h

index 7a6e8d3..9da3d75 100644 (file)
                        size = <0x0 0x13400000>;
                        alignment = <0x0 0x400000>;
                        linux,contiguous-region;
+                       clear-map;
                };
                /* codec shared reserved */
                codec_mm_reserved:linux,codec_mm_reserved {
index 5fa4dbc..34fe9b2 100644 (file)
                compatible = "amlogic, codec, mm";
                memory-region = <&codec_mm_cma &codec_mm_reserved>;
                dev_name = "codec_mm";
+               /*no-cmatvp;*/
                status = "okay";
        };
 
index 7362110..805d439 100644 (file)
@@ -181,6 +181,10 @@ static void alloc_init_pmd(pud_t *pud, unsigned long addr, unsigned long end,
 static inline bool use_1G_block(unsigned long addr, unsigned long next,
                        unsigned long phys)
 {
+#ifdef CONFIG_AMLOGIC_CMA
+       /* we need create full 2nd page table */
+       return false;
+#else
        if (PAGE_SHIFT != 12)
                return false;
 
@@ -188,6 +192,7 @@ static inline bool use_1G_block(unsigned long addr, unsigned long next,
                return false;
 
        return true;
+#endif
 }
 
 static void alloc_init_pud(pgd_t *pgd, unsigned long addr, unsigned long end,
index 8a4870c..ac9b810 100644 (file)
@@ -943,10 +943,20 @@ int codec_mm_extpool_pool_alloc(
                                        CODEC_MM_FLAGS_FOR_LOCAL_MGR |
                                        CODEC_MM_FLAGS_CMA);
                        if (mem) {
+                               if (for_tvp) {
+                                       cma_mmu_op(mem->mem_handle,
+                                               mem->page_count,
+                                               0);
+                               }
                                ret = codec_mm_init_tvp_pool(
                                        tvp_pool,
                                        mem);
                                if (ret < 0) {
+                                       if (for_tvp) {
+                                               cma_mmu_op(mem->mem_handle,
+                                                       mem->page_count,
+                                                       1);
+                                       }
                                        codec_mm_release(mem, TVP_POOL_NAME);
                                } else {
                                        alloced_size += try_alloced_size;
@@ -994,6 +1004,9 @@ static int codec_mm_extpool_pool_release(struct extpool_mgt_s *tvp_pool)
                        slot_mem_size = gen_pool_size(gpool);
                        gen_pool_destroy(tvp_pool->gen_pool[i]);
                        if (tvp_pool->mm[i]) {
+                               cma_mmu_op(tvp_pool->mm[i]->mem_handle,
+                                       tvp_pool->mm[i]->page_count,
+                                       1);
                                codec_mm_release(tvp_pool->mm[i],
                                        TVP_POOL_NAME);
                        }
index 0085c21..5fae019 100644 (file)
@@ -268,6 +268,10 @@ static int __init rmem_cma_setup(struct reserved_mem *rmem)
        }
        /* Architecture specific contiguous memory fixup. */
        dma_contiguous_early_fixup(rmem->base, rmem->size);
+#ifdef CONFIG_AMLOGIC_CMA
+       if (of_get_flat_dt_prop(node, "clear-map", NULL))
+               cma_init_clear(cma, 1);
+#endif
 
        if (of_get_flat_dt_prop(node, "linux,cma-default", NULL))
                dma_contiguous_set_default(cma);
index 29f9e77..1c93d65 100644 (file)
@@ -28,4 +28,10 @@ extern int cma_init_reserved_mem(phys_addr_t base, phys_addr_t size,
                                        struct cma **res_cma);
 extern struct page *cma_alloc(struct cma *cma, size_t count, unsigned int align);
 extern bool cma_release(struct cma *cma, const struct page *pages, unsigned int count);
+#ifdef CONFIG_AMLOGIC_CMA
+extern void cma_init_clear(struct cma *cma, bool clear);
+extern int setup_cma_full_pagemap(struct cma *cma);
+extern int cma_mmu_op(struct page *page, int count, bool set);
+#endif
+
 #endif
index 5c2c466..86b45e4 100644 (file)
--- a/mm/cma.c
+++ b/mm/cma.c
@@ -37,6 +37,7 @@
 #include <linux/io.h>
 #include <trace/events/cma.h>
 #ifdef CONFIG_AMLOGIC_CMA
+#include <asm/pgtable.h>
 #include <linux/amlogic/aml_cma.h>
 #endif /* CONFIG_AMLOGIC_CMA */
 
@@ -46,6 +47,103 @@ struct cma cma_areas[MAX_CMA_AREAS];
 unsigned cma_area_count;
 static DEFINE_MUTEX(cma_mutex);
 
+#ifdef CONFIG_AMLOGIC_CMA
+void cma_init_clear(struct cma *cma, bool clear)
+{
+       cma->clear_map = clear;
+}
+
+static int clear_cma_pagemap2(struct cma *cma)
+{
+       pgd_t *pgd;
+       pud_t *pud;
+       pmd_t *pmd;
+       unsigned long addr, end;
+       struct mm_struct *mm;
+
+       addr = (unsigned long)pfn_to_kaddr(cma->base_pfn);
+       end  = addr + cma->count * PAGE_SIZE;
+       mm = &init_mm;
+       pgd = pgd_offset(mm, addr);
+       for (; addr < end; addr += PMD_SIZE) {
+               if (pgd_none(*pgd) || pgd_bad(*pgd))
+                       break;
+
+               pud = pud_offset(pgd, addr);
+               if (pud_none(*pud) || pud_bad(*pud))
+                       break;
+
+               pmd = pmd_offset(pud, addr);
+               if (pmd_none(*pmd))
+                       break;
+
+               pmd_clear(pmd);
+       }
+
+       return 0;
+}
+
+int setup_cma_full_pagemap(struct cma *cma)
+{
+       struct vm_area_struct vma = {};
+       unsigned long addr, size;
+       int ret;
+
+       clear_cma_pagemap2(cma);
+       addr = (unsigned long)pfn_to_kaddr(cma->base_pfn);
+       size = cma->count * PAGE_SIZE;
+       vma.vm_mm    = &init_mm;
+       vma.vm_start = addr;
+       vma.vm_end   = addr + size;
+       vma.vm_page_prot = PAGE_KERNEL;
+       ret = remap_pfn_range(&vma, addr, cma->base_pfn,
+                             size, vma.vm_page_prot);
+       if (ret < 0)
+               pr_info("%s, remap pte failed:%d, cma:%lx\n",
+                       __func__, ret, cma->base_pfn);
+       return 0;
+}
+
+int cma_mmu_op(struct page *page, int count, bool set)
+{
+       pgd_t *pgd;
+       pud_t *pud;
+       pmd_t *pmd;
+       pte_t *pte;
+       unsigned long addr, end;
+       struct mm_struct *mm;
+
+       if (!page)
+               return -EINVAL;
+
+       addr = (unsigned long)page_address(page);
+       end  = addr + count * PAGE_SIZE;
+       mm = &init_mm;
+       pgd = pgd_offset(mm, addr);
+       for (; addr < end; addr += PAGE_SIZE) {
+               if (pgd_none(*pgd) || pgd_bad(*pgd))
+                       break;
+
+               pud = pud_offset(pgd, addr);
+               if (pud_none(*pud) || pud_bad(*pud))
+                       break;
+
+               pmd = pmd_offset(pud, addr);
+               if (pmd_none(*pmd))
+                       break;
+
+               pte = pte_offset_map(pmd, addr);
+               if (set)
+                       set_pte_at(mm, addr, pte, mk_pte(page, PAGE_KERNEL));
+               else
+                       pte_clear(mm, addr, pte);
+               pte_unmap(pte);
+               page++;
+       }
+       return 0;
+}
+#endif
+
 phys_addr_t cma_get_base(const struct cma *cma)
 {
        return PFN_PHYS(cma->base_pfn);
@@ -129,6 +227,11 @@ static int __init cma_activate_area(struct cma *cma)
 
        mutex_init(&cma->lock);
 
+#ifdef CONFIG_AMLOGIC_CMA
+       if (cma->clear_map)
+               setup_cma_full_pagemap(cma);
+#endif
+
 #ifdef CONFIG_CMA_DEBUGFS
        INIT_HLIST_HEAD(&cma->mem_head);
        spin_lock_init(&cma->mem_head_lock);
index 17c75a4..bd5a7a5 100644 (file)
--- a/mm/cma.h
+++ b/mm/cma.h
@@ -11,6 +11,11 @@ struct cma {
        struct hlist_head mem_head;
        spinlock_t mem_head_lock;
 #endif
+
+#ifdef CONFIG_AMLOGIC_CMA      /* clear kernel space mapping after driver it */
+       bool    clear_map;
+#endif
+
 };
 
 extern struct cma cma_areas[MAX_CMA_AREAS];