1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33#ifndef _DRM_MM_H_
34#define _DRM_MM_H_
35
36
37
38
39#include <linux/bug.h>
40#include <linux/kernel.h>
41#include <linux/list.h>
42#include <linux/spinlock.h>
43#ifdef CONFIG_DEBUG_FS
44#include <linux/seq_file.h>
45#endif
46
47enum drm_mm_search_flags {
48 DRM_MM_SEARCH_DEFAULT = 0,
49 DRM_MM_SEARCH_BEST = 1 << 0,
50 DRM_MM_SEARCH_BELOW = 1 << 1,
51};
52
53enum drm_mm_allocator_flags {
54 DRM_MM_CREATE_DEFAULT = 0,
55 DRM_MM_CREATE_TOP = 1 << 0,
56};
57
58#define DRM_MM_BOTTOMUP DRM_MM_SEARCH_DEFAULT, DRM_MM_CREATE_DEFAULT
59#define DRM_MM_TOPDOWN DRM_MM_SEARCH_BELOW, DRM_MM_CREATE_TOP
60
61struct drm_mm_node {
62 struct list_head node_list;
63 struct list_head hole_stack;
64 unsigned hole_follows : 1;
65 unsigned scanned_block : 1;
66 unsigned scanned_prev_free : 1;
67 unsigned scanned_next_free : 1;
68 unsigned scanned_preceeds_hole : 1;
69 unsigned allocated : 1;
70 unsigned long color;
71 u64 start;
72 u64 size;
73 struct drm_mm *mm;
74};
75
76struct drm_mm {
77
78 struct list_head hole_stack;
79
80
81 struct drm_mm_node head_node;
82 unsigned int scan_check_range : 1;
83 unsigned scan_alignment;
84 unsigned long scan_color;
85 u64 scan_size;
86 u64 scan_hit_start;
87 u64 scan_hit_end;
88 unsigned scanned_blocks;
89 u64 scan_start;
90 u64 scan_end;
91 struct drm_mm_node *prev_scanned_node;
92
93 void (*color_adjust)(struct drm_mm_node *node, unsigned long color,
94 u64 *start, u64 *end);
95};
96
97
98
99
100
101
102
103
104
105
106
107static inline bool drm_mm_node_allocated(struct drm_mm_node *node)
108{
109 return node->allocated;
110}
111
112
113
114
115
116
117
118
119
120
121
122static inline bool drm_mm_initialized(struct drm_mm *mm)
123{
124 return mm->hole_stack.next;
125}
126
127static inline u64 __drm_mm_hole_node_start(struct drm_mm_node *hole_node)
128{
129 return hole_node->start + hole_node->size;
130}
131
132
133
134
135
136
137
138
139
140
141
142
143static inline u64 drm_mm_hole_node_start(struct drm_mm_node *hole_node)
144{
145 BUG_ON(!hole_node->hole_follows);
146 return __drm_mm_hole_node_start(hole_node);
147}
148
149static inline u64 __drm_mm_hole_node_end(struct drm_mm_node *hole_node)
150{
151 return list_entry(hole_node->node_list.next,
152 struct drm_mm_node, node_list)->start;
153}
154
155
156
157
158
159
160
161
162
163
164
165
166static inline u64 drm_mm_hole_node_end(struct drm_mm_node *hole_node)
167{
168 return __drm_mm_hole_node_end(hole_node);
169}
170
171
172
173
174
175
176
177
178
179#define drm_mm_for_each_node(entry, mm) list_for_each_entry(entry, \
180 &(mm)->head_node.node_list, \
181 node_list)
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202#define drm_mm_for_each_hole(entry, mm, hole_start, hole_end) \
203 for (entry = list_entry((mm)->hole_stack.next, struct drm_mm_node, hole_stack); \
204 &entry->hole_stack != &(mm)->hole_stack ? \
205 hole_start = drm_mm_hole_node_start(entry), \
206 hole_end = drm_mm_hole_node_end(entry), \
207 1 : 0; \
208 entry = list_entry(entry->hole_stack.next, struct drm_mm_node, hole_stack))
209
210#define __drm_mm_for_each_hole(entry, mm, hole_start, hole_end, backwards) \
211 for (entry = list_entry((backwards) ? (mm)->hole_stack.prev : (mm)->hole_stack.next, struct drm_mm_node, hole_stack); \
212 &entry->hole_stack != &(mm)->hole_stack ? \
213 hole_start = drm_mm_hole_node_start(entry), \
214 hole_end = drm_mm_hole_node_end(entry), \
215 1 : 0; \
216 entry = list_entry((backwards) ? entry->hole_stack.prev : entry->hole_stack.next, struct drm_mm_node, hole_stack))
217
218
219
220
221int drm_mm_reserve_node(struct drm_mm *mm, struct drm_mm_node *node);
222
223int drm_mm_insert_node_generic(struct drm_mm *mm,
224 struct drm_mm_node *node,
225 u64 size,
226 unsigned alignment,
227 unsigned long color,
228 enum drm_mm_search_flags sflags,
229 enum drm_mm_allocator_flags aflags);
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246static inline int drm_mm_insert_node(struct drm_mm *mm,
247 struct drm_mm_node *node,
248 u64 size,
249 unsigned alignment,
250 enum drm_mm_search_flags flags)
251{
252 return drm_mm_insert_node_generic(mm, node, size, alignment, 0, flags,
253 DRM_MM_CREATE_DEFAULT);
254}
255
256int drm_mm_insert_node_in_range_generic(struct drm_mm *mm,
257 struct drm_mm_node *node,
258 u64 size,
259 unsigned alignment,
260 unsigned long color,
261 u64 start,
262 u64 end,
263 enum drm_mm_search_flags sflags,
264 enum drm_mm_allocator_flags aflags);
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283static inline int drm_mm_insert_node_in_range(struct drm_mm *mm,
284 struct drm_mm_node *node,
285 u64 size,
286 unsigned alignment,
287 u64 start,
288 u64 end,
289 enum drm_mm_search_flags flags)
290{
291 return drm_mm_insert_node_in_range_generic(mm, node, size, alignment,
292 0, start, end, flags,
293 DRM_MM_CREATE_DEFAULT);
294}
295
296void drm_mm_remove_node(struct drm_mm_node *node);
297void drm_mm_replace_node(struct drm_mm_node *old, struct drm_mm_node *new);
298void drm_mm_init(struct drm_mm *mm,
299 u64 start,
300 u64 size);
301void drm_mm_takedown(struct drm_mm *mm);
302bool drm_mm_clean(struct drm_mm *mm);
303
304void drm_mm_init_scan(struct drm_mm *mm,
305 u64 size,
306 unsigned alignment,
307 unsigned long color);
308void drm_mm_init_scan_with_range(struct drm_mm *mm,
309 u64 size,
310 unsigned alignment,
311 unsigned long color,
312 u64 start,
313 u64 end);
314bool drm_mm_scan_add_block(struct drm_mm_node *node);
315bool drm_mm_scan_remove_block(struct drm_mm_node *node);
316
317void drm_mm_debug_table(struct drm_mm *mm, const char *prefix);
318#ifdef CONFIG_DEBUG_FS
319int drm_mm_dump_table(struct seq_file *m, struct drm_mm *mm);
320#endif
321
322#endif
323