]>
Commit | Line | Data |
---|---|---|
28b24c1f SL |
1 | /* |
2 | * CMA DebugFS Interface | |
3 | * | |
4 | * Copyright (c) 2015 Sasha Levin <sasha.levin@oracle.com> | |
5 | */ | |
6 | ||
7 | ||
8 | #include <linux/debugfs.h> | |
9 | #include <linux/cma.h> | |
26b02a1f SL |
10 | #include <linux/list.h> |
11 | #include <linux/kernel.h> | |
12 | #include <linux/slab.h> | |
28b24c1f SL |
13 | |
14 | #include "cma.h" | |
15 | ||
26b02a1f SL |
16 | struct cma_mem { |
17 | struct hlist_node node; | |
18 | struct page *p; | |
19 | unsigned long n; | |
20 | }; | |
21 | ||
28b24c1f SL |
22 | static struct dentry *cma_debugfs_root; |
23 | ||
24 | static int cma_debugfs_get(void *data, u64 *val) | |
25 | { | |
26 | unsigned long *p = data; | |
27 | ||
28 | *val = *p; | |
29 | ||
30 | return 0; | |
31 | } | |
32 | ||
33 | DEFINE_SIMPLE_ATTRIBUTE(cma_debugfs_fops, cma_debugfs_get, NULL, "%llu\n"); | |
34 | ||
26b02a1f SL |
35 | static void cma_add_to_cma_mem_list(struct cma *cma, struct cma_mem *mem) |
36 | { | |
37 | spin_lock(&cma->mem_head_lock); | |
38 | hlist_add_head(&mem->node, &cma->mem_head); | |
39 | spin_unlock(&cma->mem_head_lock); | |
40 | } | |
41 | ||
42 | static int cma_alloc_mem(struct cma *cma, int count) | |
43 | { | |
44 | struct cma_mem *mem; | |
45 | struct page *p; | |
46 | ||
47 | mem = kzalloc(sizeof(*mem), GFP_KERNEL); | |
48 | if (!mem) | |
49 | return -ENOMEM; | |
50 | ||
51 | p = cma_alloc(cma, count, CONFIG_CMA_ALIGNMENT); | |
52 | if (!p) { | |
53 | kfree(mem); | |
54 | return -ENOMEM; | |
55 | } | |
56 | ||
57 | mem->p = p; | |
58 | mem->n = count; | |
59 | ||
60 | cma_add_to_cma_mem_list(cma, mem); | |
61 | ||
62 | return 0; | |
63 | } | |
64 | ||
65 | static int cma_alloc_write(void *data, u64 val) | |
66 | { | |
67 | int pages = val; | |
68 | struct cma *cma = data; | |
69 | ||
70 | return cma_alloc_mem(cma, pages); | |
71 | } | |
72 | ||
73 | DEFINE_SIMPLE_ATTRIBUTE(cma_alloc_fops, NULL, cma_alloc_write, "%llu\n"); | |
74 | ||
28b24c1f SL |
75 | static void cma_debugfs_add_one(struct cma *cma, int idx) |
76 | { | |
77 | struct dentry *tmp; | |
78 | char name[16]; | |
79 | int u32s; | |
80 | ||
81 | sprintf(name, "cma-%d", idx); | |
82 | ||
83 | tmp = debugfs_create_dir(name, cma_debugfs_root); | |
84 | ||
26b02a1f SL |
85 | debugfs_create_file("alloc", S_IWUSR, cma_debugfs_root, cma, |
86 | &cma_alloc_fops); | |
87 | ||
28b24c1f SL |
88 | debugfs_create_file("base_pfn", S_IRUGO, tmp, |
89 | &cma->base_pfn, &cma_debugfs_fops); | |
90 | debugfs_create_file("count", S_IRUGO, tmp, | |
91 | &cma->count, &cma_debugfs_fops); | |
92 | debugfs_create_file("order_per_bit", S_IRUGO, tmp, | |
26b02a1f | 93 | &cma->order_per_bit, &cma_debugfs_fops); |
28b24c1f SL |
94 | |
95 | u32s = DIV_ROUND_UP(cma_bitmap_maxno(cma), BITS_PER_BYTE * sizeof(u32)); | |
96 | debugfs_create_u32_array("bitmap", S_IRUGO, tmp, (u32*)cma->bitmap, u32s); | |
97 | } | |
98 | ||
99 | static int __init cma_debugfs_init(void) | |
100 | { | |
101 | int i; | |
102 | ||
103 | cma_debugfs_root = debugfs_create_dir("cma", NULL); | |
104 | if (!cma_debugfs_root) | |
105 | return -ENOMEM; | |
106 | ||
107 | for (i = 0; i < cma_area_count; i++) | |
108 | cma_debugfs_add_one(&cma_areas[i], i); | |
109 | ||
110 | return 0; | |
111 | } | |
112 | late_initcall(cma_debugfs_init); |