mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-07 19:30:30 +09:00
codec_mm: add reserved & cma support for 4.9. [1/1]
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>
This commit is contained in:
@@ -121,6 +121,7 @@
|
||||
size = <0x0 0x13400000>;
|
||||
alignment = <0x0 0x400000>;
|
||||
linux,contiguous-region;
|
||||
clear-map;
|
||||
};
|
||||
/* codec shared reserved */
|
||||
codec_mm_reserved:linux,codec_mm_reserved {
|
||||
|
||||
@@ -683,6 +683,7 @@
|
||||
compatible = "amlogic, codec, mm";
|
||||
memory-region = <&codec_mm_cma &codec_mm_reserved>;
|
||||
dev_name = "codec_mm";
|
||||
/*no-cmatvp;*/
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
103
mm/cma.c
103
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);
|
||||
|
||||
Reference in New Issue
Block a user