ANDROID: integrate GCMA with CMA using dt-bindings
This patch introduces a new "guarantee" property for shared-dma-pool. With the property, admin can create specific memory pool as GCMA-based-CMA if they care about allocation success rate and latency without reserving a dedicated memory area. Bug: 236887352 Bug: 270089503 Bug: 391879760 Change-Id: I3a019f889f7ffa4d2255609c19b15078b9c5b6a4 Signed-off-by: Minchan Kim <minchan@google.com> Signed-off-by: Suren Baghdasaryan <surenb@google.com>
This commit is contained in:
committed by
Carlos Llamas
parent
80a603a57a
commit
0dad457899
@@ -95,7 +95,7 @@ void __init fadump_cma_init(void)
|
||||
base = fw_dump.reserve_dump_area_start;
|
||||
size = fw_dump.boot_memory_size;
|
||||
|
||||
rc = cma_init_reserved_mem(base, size, 0, "fadump_cma", &fadump_cma);
|
||||
rc = cma_init_reserved_mem(base, size, 0, "fadump_cma", &fadump_cma, false);
|
||||
if (rc) {
|
||||
pr_err("Failed to init cma area for firmware-assisted dump,%d\n", rc);
|
||||
/*
|
||||
|
||||
+2
-1
@@ -43,7 +43,8 @@ static inline int __init cma_declare_contiguous(phys_addr_t base,
|
||||
extern int cma_init_reserved_mem(phys_addr_t base, phys_addr_t size,
|
||||
unsigned int order_per_bit,
|
||||
const char *name,
|
||||
struct cma **res_cma);
|
||||
struct cma **res_cma,
|
||||
bool gcma);
|
||||
extern struct page *__cma_alloc(struct cma *cma, unsigned long count, unsigned int align,
|
||||
gfp_t gfp_mask);
|
||||
extern struct page *cma_alloc(struct cma *cma, unsigned long count, unsigned int align,
|
||||
|
||||
+10
-1
@@ -465,6 +465,7 @@ static int __init rmem_cma_setup(struct reserved_mem *rmem)
|
||||
unsigned long node = rmem->fdt_node;
|
||||
bool default_cma = of_get_flat_dt_prop(node, "linux,cma-default", NULL);
|
||||
struct cma *cma;
|
||||
bool gcma;
|
||||
int err;
|
||||
|
||||
if (size_cmdline != -1 && default_cma) {
|
||||
@@ -482,7 +483,15 @@ static int __init rmem_cma_setup(struct reserved_mem *rmem)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
err = cma_init_reserved_mem(rmem->base, rmem->size, 0, rmem->name, &cma);
|
||||
gcma = !!of_get_flat_dt_prop(node, "guarantee", NULL);
|
||||
#ifndef CONFIG_GCMA
|
||||
if (gcma) {
|
||||
pr_err("Reserved memory: unable to setup GCMA region, GCMA is not enabled\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
#endif
|
||||
err = cma_init_reserved_mem(rmem->base, rmem->size, 0, rmem->name,
|
||||
&cma, gcma);
|
||||
if (err) {
|
||||
pr_err("Reserved memory: unable to setup CMA region\n");
|
||||
return err;
|
||||
|
||||
@@ -29,6 +29,7 @@
|
||||
#include <linux/kmemleak.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/jiffies.h>
|
||||
#include <linux/gcma.h>
|
||||
#define CREATE_TRACE_POINTS
|
||||
#include <trace/events/cma.h>
|
||||
#undef CREATE_TRACE_POINTS
|
||||
@@ -126,9 +127,14 @@ static void __init cma_activate_area(struct cma *cma)
|
||||
goto not_in_zone;
|
||||
}
|
||||
|
||||
for (pfn = base_pfn; pfn < base_pfn + cma->count;
|
||||
pfn += pageblock_nr_pages)
|
||||
init_cma_reserved_pageblock(pfn_to_page(pfn));
|
||||
if (cma->gcma) {
|
||||
register_gcma_area(cma->name, PFN_PHYS(base_pfn),
|
||||
cma->count << PAGE_SHIFT);
|
||||
} else {
|
||||
for (pfn = base_pfn; pfn < base_pfn + cma->count;
|
||||
pfn += pageblock_nr_pages)
|
||||
init_cma_reserved_pageblock(pfn_to_page(pfn));
|
||||
}
|
||||
|
||||
spin_lock_init(&cma->lock);
|
||||
|
||||
@@ -186,7 +192,7 @@ void __init cma_reserve_pages_on_error(struct cma *cma)
|
||||
int __init cma_init_reserved_mem(phys_addr_t base, phys_addr_t size,
|
||||
unsigned int order_per_bit,
|
||||
const char *name,
|
||||
struct cma **res_cma)
|
||||
struct cma **res_cma, bool gcma)
|
||||
{
|
||||
struct cma *cma;
|
||||
|
||||
@@ -212,11 +218,13 @@ int __init cma_init_reserved_mem(phys_addr_t base, phys_addr_t size,
|
||||
if (name)
|
||||
snprintf(cma->name, CMA_MAX_NAME, name);
|
||||
else
|
||||
snprintf(cma->name, CMA_MAX_NAME, "cma%d\n", cma_area_count);
|
||||
snprintf(cma->name, CMA_MAX_NAME,
|
||||
gcma ? "gcma%d\n" : "cma%d\n", cma_area_count);
|
||||
|
||||
cma->base_pfn = PFN_DOWN(base);
|
||||
cma->count = size >> PAGE_SHIFT;
|
||||
cma->order_per_bit = order_per_bit;
|
||||
cma->gcma = gcma;
|
||||
*res_cma = cma;
|
||||
cma_area_count++;
|
||||
totalcma_pages += cma->count;
|
||||
@@ -379,7 +387,8 @@ int __init cma_declare_contiguous_nid(phys_addr_t base,
|
||||
base = addr;
|
||||
}
|
||||
|
||||
ret = cma_init_reserved_mem(base, size, order_per_bit, name, res_cma);
|
||||
ret = cma_init_reserved_mem(base, size, order_per_bit, name, res_cma,
|
||||
false);
|
||||
if (ret)
|
||||
goto free_mem;
|
||||
|
||||
@@ -509,7 +518,12 @@ struct page *__cma_alloc(struct cma *cma, unsigned long count,
|
||||
|
||||
pfn = cma->base_pfn + (bitmap_no << cma->order_per_bit);
|
||||
mutex_lock(&cma_mutex);
|
||||
ret = alloc_contig_range(pfn, pfn + count, MIGRATE_CMA, gfp);
|
||||
if (cma->gcma) {
|
||||
gcma_alloc_range(pfn, pfn + count - 1);
|
||||
ret = 0;
|
||||
} else {
|
||||
ret = alloc_contig_range(pfn, pfn + count, MIGRATE_CMA, gfp);
|
||||
}
|
||||
mutex_unlock(&cma_mutex);
|
||||
if (ret == 0) {
|
||||
page = pfn_to_page(pfn);
|
||||
@@ -632,7 +646,10 @@ bool cma_release(struct cma *cma, const struct page *pages,
|
||||
|
||||
VM_BUG_ON(pfn + count > cma->base_pfn + cma->count);
|
||||
|
||||
free_contig_range(pfn, count);
|
||||
if (cma->gcma)
|
||||
gcma_free_range(pfn, pfn + count - 1);
|
||||
else
|
||||
free_contig_range(pfn, count);
|
||||
cma_clear_bitmap(cma, pfn, count);
|
||||
cma_sysfs_account_release_pages(cma, count);
|
||||
trace_cma_release(cma->name, pfn, pages, count);
|
||||
|
||||
@@ -23,6 +23,7 @@ struct cma {
|
||||
struct debugfs_u32_array dfs_bitmap;
|
||||
#endif
|
||||
char name[CMA_MAX_NAME];
|
||||
bool gcma;
|
||||
#ifdef CONFIG_CMA_SYSFS
|
||||
/* the number of CMA page successful allocations */
|
||||
atomic64_t nr_pages_succeeded;
|
||||
|
||||
@@ -62,6 +62,15 @@ static ssize_t release_pages_success_show(struct kobject *kobj,
|
||||
}
|
||||
CMA_ATTR_RO(release_pages_success);
|
||||
|
||||
static ssize_t gcma_show(struct kobject *kobj,
|
||||
struct kobj_attribute *attr, char *buf)
|
||||
{
|
||||
struct cma *cma = cma_from_kobj(kobj);
|
||||
|
||||
return sysfs_emit(buf, "%d\n", cma->gcma);
|
||||
}
|
||||
CMA_ATTR_RO(gcma);
|
||||
|
||||
static void cma_kobj_release(struct kobject *kobj)
|
||||
{
|
||||
struct cma *cma = cma_from_kobj(kobj);
|
||||
@@ -75,6 +84,7 @@ static struct attribute *cma_attrs[] = {
|
||||
&alloc_pages_success_attr.attr,
|
||||
&alloc_pages_fail_attr.attr,
|
||||
&release_pages_success_attr.attr,
|
||||
&gcma_attr.attr,
|
||||
NULL,
|
||||
};
|
||||
ATTRIBUTE_GROUPS(cma);
|
||||
|
||||
Reference in New Issue
Block a user