aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSasha Levin <sasha.levin@oracle.com>2015-04-14 18:45:02 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2015-04-14 19:49:00 -0400
commit8325330b026509127d4541e0f511c0c10648c2d5 (patch)
tree1db659fbd241f7810c44cfd4e1db22887a04fb73
parent26b02a1f9670862c51b3ff63a6128589866f5c71 (diff)
mm: cma: release trigger
Provides a userspace interface to trigger a CMA release. Usage: echo [pages] > free This would provide testing/fuzzing access to the CMA release paths. [akpm@linux-foundation.org: coding-style fixes] [mhocko@suse.cz: fix build] Signed-off-by: Sasha Levin <sasha.levin@oracle.com> Acked-by: Joonsoo Kim <iamjoonsoo.kim@lge.com> Cc: Marek Szyprowski <m.szyprowski@samsung.com> Cc: Laura Abbott <lauraa@codeaurora.org> Cc: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com> Signed-off-by: Michal Hocko <mhocko@suse.cz> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r--mm/cma_debug.c58
1 files changed, 58 insertions, 0 deletions
diff --git a/mm/cma_debug.c b/mm/cma_debug.c
index f3baa413ab33..ae41faeed596 100644
--- a/mm/cma_debug.c
+++ b/mm/cma_debug.c
@@ -10,6 +10,7 @@
10#include <linux/list.h> 10#include <linux/list.h>
11#include <linux/kernel.h> 11#include <linux/kernel.h>
12#include <linux/slab.h> 12#include <linux/slab.h>
13#include <linux/mm_types.h>
13 14
14#include "cma.h" 15#include "cma.h"
15 16
@@ -39,6 +40,60 @@ static void cma_add_to_cma_mem_list(struct cma *cma, struct cma_mem *mem)
39 spin_unlock(&cma->mem_head_lock); 40 spin_unlock(&cma->mem_head_lock);
40} 41}
41 42
43static struct cma_mem *cma_get_entry_from_list(struct cma *cma)
44{
45 struct cma_mem *mem = NULL;
46
47 spin_lock(&cma->mem_head_lock);
48 if (!hlist_empty(&cma->mem_head)) {
49 mem = hlist_entry(cma->mem_head.first, struct cma_mem, node);
50 hlist_del_init(&mem->node);
51 }
52 spin_unlock(&cma->mem_head_lock);
53
54 return mem;
55}
56
57static int cma_free_mem(struct cma *cma, int count)
58{
59 struct cma_mem *mem = NULL;
60
61 while (count) {
62 mem = cma_get_entry_from_list(cma);
63 if (mem == NULL)
64 return 0;
65
66 if (mem->n <= count) {
67 cma_release(cma, mem->p, mem->n);
68 count -= mem->n;
69 kfree(mem);
70 } else if (cma->order_per_bit == 0) {
71 cma_release(cma, mem->p, count);
72 mem->p += count;
73 mem->n -= count;
74 count = 0;
75 cma_add_to_cma_mem_list(cma, mem);
76 } else {
77 pr_debug("cma: cannot release partial block when order_per_bit != 0\n");
78 cma_add_to_cma_mem_list(cma, mem);
79 break;
80 }
81 }
82
83 return 0;
84
85}
86
87static int cma_free_write(void *data, u64 val)
88{
89 int pages = val;
90 struct cma *cma = data;
91
92 return cma_free_mem(cma, pages);
93}
94
95DEFINE_SIMPLE_ATTRIBUTE(cma_free_fops, NULL, cma_free_write, "%llu\n");
96
42static int cma_alloc_mem(struct cma *cma, int count) 97static int cma_alloc_mem(struct cma *cma, int count)
43{ 98{
44 struct cma_mem *mem; 99 struct cma_mem *mem;
@@ -85,6 +140,9 @@ static void cma_debugfs_add_one(struct cma *cma, int idx)
85 debugfs_create_file("alloc", S_IWUSR, cma_debugfs_root, cma, 140 debugfs_create_file("alloc", S_IWUSR, cma_debugfs_root, cma,
86 &cma_alloc_fops); 141 &cma_alloc_fops);
87 142
143 debugfs_create_file("free", S_IWUSR, cma_debugfs_root, cma,
144 &cma_free_fops);
145
88 debugfs_create_file("base_pfn", S_IRUGO, tmp, 146 debugfs_create_file("base_pfn", S_IRUGO, tmp,
89 &cma->base_pfn, &cma_debugfs_fops); 147 &cma->base_pfn, &cma_debugfs_fops);
90 debugfs_create_file("count", S_IRUGO, tmp, 148 debugfs_create_file("count", S_IRUGO, tmp,