Blame view

mm/cma_debug.c 4.52 KB
b24413180   Greg Kroah-Hartman   License cleanup: ...
1
  // SPDX-License-Identifier: GPL-2.0
28b24c1fc   Sasha Levin   mm: cma: debugfs ...
2
3
4
5
6
7
8
9
10
  /*
   * CMA DebugFS Interface
   *
   * Copyright (c) 2015 Sasha Levin <sasha.levin@oracle.com>
   */
  
  
  #include <linux/debugfs.h>
  #include <linux/cma.h>
26b02a1f9   Sasha Levin   mm: cma: allocati...
11
12
13
  #include <linux/list.h>
  #include <linux/kernel.h>
  #include <linux/slab.h>
8325330b0   Sasha Levin   mm: cma: release ...
14
  #include <linux/mm_types.h>
28b24c1fc   Sasha Levin   mm: cma: debugfs ...
15
16
  
  #include "cma.h"
26b02a1f9   Sasha Levin   mm: cma: allocati...
17
18
19
20
21
  struct cma_mem {
  	struct hlist_node node;
  	struct page *p;
  	unsigned long n;
  };
28b24c1fc   Sasha Levin   mm: cma: debugfs ...
22
23
24
25
26
27
28
29
  static int cma_debugfs_get(void *data, u64 *val)
  {
  	unsigned long *p = data;
  
  	*val = *p;
  
  	return 0;
  }
a9ea242a0   zhong jiang   mm/cma_debug.c: u...
30
31
  DEFINE_DEBUGFS_ATTRIBUTE(cma_debugfs_fops, cma_debugfs_get, NULL, "%llu
  ");
28b24c1fc   Sasha Levin   mm: cma: debugfs ...
32

2e32b9476   Dmitry Safonov   mm: cma: add func...
33
34
35
36
37
38
39
  static int cma_used_get(void *data, u64 *val)
  {
  	struct cma *cma = data;
  	unsigned long used;
  
  	mutex_lock(&cma->lock);
  	/* pages counter is smaller than sizeof(int) */
d56e84b40   Joonsoo Kim   mm/cma_debug: cor...
40
  	used = bitmap_weight(cma->bitmap, (int)cma_bitmap_maxno(cma));
2e32b9476   Dmitry Safonov   mm: cma: add func...
41
42
43
44
45
  	mutex_unlock(&cma->lock);
  	*val = (u64)used << cma->order_per_bit;
  
  	return 0;
  }
a9ea242a0   zhong jiang   mm/cma_debug.c: u...
46
47
  DEFINE_DEBUGFS_ATTRIBUTE(cma_used_fops, cma_used_get, NULL, "%llu
  ");
2e32b9476   Dmitry Safonov   mm: cma: add func...
48
49
50
51
52
53
  
  static int cma_maxchunk_get(void *data, u64 *val)
  {
  	struct cma *cma = data;
  	unsigned long maxchunk = 0;
  	unsigned long start, end = 0;
d56e84b40   Joonsoo Kim   mm/cma_debug: cor...
54
  	unsigned long bitmap_maxno = cma_bitmap_maxno(cma);
2e32b9476   Dmitry Safonov   mm: cma: add func...
55
56
57
  
  	mutex_lock(&cma->lock);
  	for (;;) {
d56e84b40   Joonsoo Kim   mm/cma_debug: cor...
58
  		start = find_next_zero_bit(cma->bitmap, bitmap_maxno, end);
f0fd50504   Yue Hu   mm/cma_debug.c: f...
59
  		if (start >= bitmap_maxno)
2e32b9476   Dmitry Safonov   mm: cma: add func...
60
  			break;
d56e84b40   Joonsoo Kim   mm/cma_debug: cor...
61
  		end = find_next_bit(cma->bitmap, bitmap_maxno, start);
2e32b9476   Dmitry Safonov   mm: cma: add func...
62
63
64
65
66
67
68
  		maxchunk = max(end - start, maxchunk);
  	}
  	mutex_unlock(&cma->lock);
  	*val = (u64)maxchunk << cma->order_per_bit;
  
  	return 0;
  }
a9ea242a0   zhong jiang   mm/cma_debug.c: u...
69
70
  DEFINE_DEBUGFS_ATTRIBUTE(cma_maxchunk_fops, cma_maxchunk_get, NULL, "%llu
  ");
2e32b9476   Dmitry Safonov   mm: cma: add func...
71

26b02a1f9   Sasha Levin   mm: cma: allocati...
72
73
74
75
76
77
  static void cma_add_to_cma_mem_list(struct cma *cma, struct cma_mem *mem)
  {
  	spin_lock(&cma->mem_head_lock);
  	hlist_add_head(&mem->node, &cma->mem_head);
  	spin_unlock(&cma->mem_head_lock);
  }
8325330b0   Sasha Levin   mm: cma: release ...
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
  static struct cma_mem *cma_get_entry_from_list(struct cma *cma)
  {
  	struct cma_mem *mem = NULL;
  
  	spin_lock(&cma->mem_head_lock);
  	if (!hlist_empty(&cma->mem_head)) {
  		mem = hlist_entry(cma->mem_head.first, struct cma_mem, node);
  		hlist_del_init(&mem->node);
  	}
  	spin_unlock(&cma->mem_head_lock);
  
  	return mem;
  }
  
  static int cma_free_mem(struct cma *cma, int count)
  {
  	struct cma_mem *mem = NULL;
  
  	while (count) {
  		mem = cma_get_entry_from_list(cma);
  		if (mem == NULL)
  			return 0;
  
  		if (mem->n <= count) {
  			cma_release(cma, mem->p, mem->n);
  			count -= mem->n;
  			kfree(mem);
  		} else if (cma->order_per_bit == 0) {
  			cma_release(cma, mem->p, count);
  			mem->p += count;
  			mem->n -= count;
  			count = 0;
  			cma_add_to_cma_mem_list(cma, mem);
  		} else {
  			pr_debug("cma: cannot release partial block when order_per_bit != 0
  ");
  			cma_add_to_cma_mem_list(cma, mem);
  			break;
  		}
  	}
  
  	return 0;
  
  }
  
  static int cma_free_write(void *data, u64 val)
  {
  	int pages = val;
  	struct cma *cma = data;
  
  	return cma_free_mem(cma, pages);
  }
a9ea242a0   zhong jiang   mm/cma_debug.c: u...
130
131
  DEFINE_DEBUGFS_ATTRIBUTE(cma_free_fops, NULL, cma_free_write, "%llu
  ");
8325330b0   Sasha Levin   mm: cma: release ...
132

26b02a1f9   Sasha Levin   mm: cma: allocati...
133
134
135
136
137
138
139
140
  static int cma_alloc_mem(struct cma *cma, int count)
  {
  	struct cma_mem *mem;
  	struct page *p;
  
  	mem = kzalloc(sizeof(*mem), GFP_KERNEL);
  	if (!mem)
  		return -ENOMEM;
651820297   Marek Szyprowski   mm/cma: remove un...
141
  	p = cma_alloc(cma, count, 0, false);
26b02a1f9   Sasha Levin   mm: cma: allocati...
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
  	if (!p) {
  		kfree(mem);
  		return -ENOMEM;
  	}
  
  	mem->p = p;
  	mem->n = count;
  
  	cma_add_to_cma_mem_list(cma, mem);
  
  	return 0;
  }
  
  static int cma_alloc_write(void *data, u64 val)
  {
  	int pages = val;
  	struct cma *cma = data;
  
  	return cma_alloc_mem(cma, pages);
  }
a9ea242a0   zhong jiang   mm/cma_debug.c: u...
162
163
  DEFINE_DEBUGFS_ATTRIBUTE(cma_alloc_fops, NULL, cma_alloc_write, "%llu
  ");
26b02a1f9   Sasha Levin   mm: cma: allocati...
164

5a7f1b2f2   Yue Hu   mm/cma_debug.c: r...
165
  static void cma_debugfs_add_one(struct cma *cma, struct dentry *root_dentry)
28b24c1fc   Sasha Levin   mm: cma: debugfs ...
166
167
168
  {
  	struct dentry *tmp;
  	char name[16];
28b24c1fc   Sasha Levin   mm: cma: debugfs ...
169

da094e428   Prakash Gupta   mm/cma_debug.c: f...
170
  	scnprintf(name, sizeof(name), "cma-%s", cma->name);
28b24c1fc   Sasha Levin   mm: cma: debugfs ...
171

5a7f1b2f2   Yue Hu   mm/cma_debug.c: r...
172
  	tmp = debugfs_create_dir(name, root_dentry);
28b24c1fc   Sasha Levin   mm: cma: debugfs ...
173

0825a6f98   Joe Perches   mm: use octal not...
174
175
176
177
178
179
180
181
182
  	debugfs_create_file("alloc", 0200, tmp, cma, &cma_alloc_fops);
  	debugfs_create_file("free", 0200, tmp, cma, &cma_free_fops);
  	debugfs_create_file("base_pfn", 0444, tmp,
  			    &cma->base_pfn, &cma_debugfs_fops);
  	debugfs_create_file("count", 0444, tmp, &cma->count, &cma_debugfs_fops);
  	debugfs_create_file("order_per_bit", 0444, tmp,
  			    &cma->order_per_bit, &cma_debugfs_fops);
  	debugfs_create_file("used", 0444, tmp, cma, &cma_used_fops);
  	debugfs_create_file("maxchunk", 0444, tmp, cma, &cma_maxchunk_fops);
28b24c1fc   Sasha Levin   mm: cma: debugfs ...
183

a2b992c82   Jakub Kicinski   debugfs: make sur...
184
185
186
187
  	cma->dfs_bitmap.array = (u32 *)cma->bitmap;
  	cma->dfs_bitmap.n_elements = DIV_ROUND_UP(cma_bitmap_maxno(cma),
  						  BITS_PER_BYTE * sizeof(u32));
  	debugfs_create_u32_array("bitmap", 0444, tmp, &cma->dfs_bitmap);
28b24c1fc   Sasha Levin   mm: cma: debugfs ...
188
189
190
191
  }
  
  static int __init cma_debugfs_init(void)
  {
5a7f1b2f2   Yue Hu   mm/cma_debug.c: r...
192
  	struct dentry *cma_debugfs_root;
28b24c1fc   Sasha Levin   mm: cma: debugfs ...
193
194
195
  	int i;
  
  	cma_debugfs_root = debugfs_create_dir("cma", NULL);
28b24c1fc   Sasha Levin   mm: cma: debugfs ...
196
197
  
  	for (i = 0; i < cma_area_count; i++)
5a7f1b2f2   Yue Hu   mm/cma_debug.c: r...
198
  		cma_debugfs_add_one(&cma_areas[i], cma_debugfs_root);
28b24c1fc   Sasha Levin   mm: cma: debugfs ...
199
200
201
202
  
  	return 0;
  }
  late_initcall(cma_debugfs_init);