1*592ffb21SWarner Losh /**************************************************************************
2*592ffb21SWarner Losh *
3*592ffb21SWarner Losh * Copyright 2006-2008 Tungsten Graphics, Inc., Cedar Park, TX. USA.
4*592ffb21SWarner Losh * All Rights Reserved.
5*592ffb21SWarner Losh *
6*592ffb21SWarner Losh * Permission is hereby granted, free of charge, to any person obtaining a
7*592ffb21SWarner Losh * copy of this software and associated documentation files (the
8*592ffb21SWarner Losh * "Software"), to deal in the Software without restriction, including
9*592ffb21SWarner Losh * without limitation the rights to use, copy, modify, merge, publish,
10*592ffb21SWarner Losh * distribute, sub license, and/or sell copies of the Software, and to
11*592ffb21SWarner Losh * permit persons to whom the Software is furnished to do so, subject to
12*592ffb21SWarner Losh * the following conditions:
13*592ffb21SWarner Losh *
14*592ffb21SWarner Losh * The above copyright notice and this permission notice (including the
15*592ffb21SWarner Losh * next paragraph) shall be included in all copies or substantial portions
16*592ffb21SWarner Losh * of the Software.
17*592ffb21SWarner Losh *
18*592ffb21SWarner Losh * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19*592ffb21SWarner Losh * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20*592ffb21SWarner Losh * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
21*592ffb21SWarner Losh * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
22*592ffb21SWarner Losh * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
23*592ffb21SWarner Losh * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
24*592ffb21SWarner Losh * USE OR OTHER DEALINGS IN THE SOFTWARE.
25*592ffb21SWarner Losh *
26*592ffb21SWarner Losh *
27*592ffb21SWarner Losh **************************************************************************/
28*592ffb21SWarner Losh /*
29*592ffb21SWarner Losh * Authors:
30*592ffb21SWarner Losh * Thomas Hellstrom <thomas-at-tungstengraphics-dot-com>
31*592ffb21SWarner Losh */
32*592ffb21SWarner Losh
33*592ffb21SWarner Losh #include <sys/cdefs.h>
34*592ffb21SWarner Losh #ifndef _DRM_MM_H_
35*592ffb21SWarner Losh #define _DRM_MM_H_
36*592ffb21SWarner Losh
37*592ffb21SWarner Losh /*
38*592ffb21SWarner Losh * Generic range manager structs
39*592ffb21SWarner Losh */
40*592ffb21SWarner Losh #include <dev/drm2/drm_linux_list.h>
41*592ffb21SWarner Losh
42*592ffb21SWarner Losh struct drm_mm_node {
43*592ffb21SWarner Losh struct list_head node_list;
44*592ffb21SWarner Losh struct list_head hole_stack;
45*592ffb21SWarner Losh unsigned hole_follows : 1;
46*592ffb21SWarner Losh unsigned scanned_block : 1;
47*592ffb21SWarner Losh unsigned scanned_prev_free : 1;
48*592ffb21SWarner Losh unsigned scanned_next_free : 1;
49*592ffb21SWarner Losh unsigned scanned_preceeds_hole : 1;
50*592ffb21SWarner Losh unsigned allocated : 1;
51*592ffb21SWarner Losh unsigned long color;
52*592ffb21SWarner Losh unsigned long start;
53*592ffb21SWarner Losh unsigned long size;
54*592ffb21SWarner Losh struct drm_mm *mm;
55*592ffb21SWarner Losh };
56*592ffb21SWarner Losh
57*592ffb21SWarner Losh struct drm_mm {
58*592ffb21SWarner Losh /* List of all memory nodes that immediately precede a free hole. */
59*592ffb21SWarner Losh struct list_head hole_stack;
60*592ffb21SWarner Losh /* head_node.node_list is the list of all memory nodes, ordered
61*592ffb21SWarner Losh * according to the (increasing) start address of the memory node. */
62*592ffb21SWarner Losh struct drm_mm_node head_node;
63*592ffb21SWarner Losh struct list_head unused_nodes;
64*592ffb21SWarner Losh int num_unused;
65*592ffb21SWarner Losh struct mtx unused_lock;
66*592ffb21SWarner Losh unsigned int scan_check_range : 1;
67*592ffb21SWarner Losh unsigned scan_alignment;
68*592ffb21SWarner Losh unsigned long scan_color;
69*592ffb21SWarner Losh unsigned long scan_size;
70*592ffb21SWarner Losh unsigned long scan_hit_start;
71*592ffb21SWarner Losh unsigned long scan_hit_end;
72*592ffb21SWarner Losh unsigned scanned_blocks;
73*592ffb21SWarner Losh unsigned long scan_start;
74*592ffb21SWarner Losh unsigned long scan_end;
75*592ffb21SWarner Losh struct drm_mm_node *prev_scanned_node;
76*592ffb21SWarner Losh
77*592ffb21SWarner Losh void (*color_adjust)(struct drm_mm_node *node, unsigned long color,
78*592ffb21SWarner Losh unsigned long *start, unsigned long *end);
79*592ffb21SWarner Losh };
80*592ffb21SWarner Losh
drm_mm_node_allocated(struct drm_mm_node * node)81*592ffb21SWarner Losh static inline bool drm_mm_node_allocated(struct drm_mm_node *node)
82*592ffb21SWarner Losh {
83*592ffb21SWarner Losh return node->allocated;
84*592ffb21SWarner Losh }
85*592ffb21SWarner Losh
drm_mm_initialized(struct drm_mm * mm)86*592ffb21SWarner Losh static inline bool drm_mm_initialized(struct drm_mm *mm)
87*592ffb21SWarner Losh {
88*592ffb21SWarner Losh return mm->hole_stack.next;
89*592ffb21SWarner Losh }
90*592ffb21SWarner Losh #define drm_mm_for_each_node(entry, mm) list_for_each_entry(entry, \
91*592ffb21SWarner Losh &(mm)->head_node.node_list, \
92*592ffb21SWarner Losh node_list)
93*592ffb21SWarner Losh #define drm_mm_for_each_scanned_node_reverse(entry, n, mm) \
94*592ffb21SWarner Losh for (entry = (mm)->prev_scanned_node, \
95*592ffb21SWarner Losh next = entry ? list_entry(entry->node_list.next, \
96*592ffb21SWarner Losh struct drm_mm_node, node_list) : NULL; \
97*592ffb21SWarner Losh entry != NULL; entry = next, \
98*592ffb21SWarner Losh next = entry ? list_entry(entry->node_list.next, \
99*592ffb21SWarner Losh struct drm_mm_node, node_list) : NULL) \
100*592ffb21SWarner Losh /*
101*592ffb21SWarner Losh * Basic range manager support (drm_mm.c)
102*592ffb21SWarner Losh */
103*592ffb21SWarner Losh extern struct drm_mm_node *drm_mm_get_block_generic(struct drm_mm_node *node,
104*592ffb21SWarner Losh unsigned long size,
105*592ffb21SWarner Losh unsigned alignment,
106*592ffb21SWarner Losh unsigned long color,
107*592ffb21SWarner Losh int atomic);
108*592ffb21SWarner Losh extern struct drm_mm_node *drm_mm_get_block_range_generic(
109*592ffb21SWarner Losh struct drm_mm_node *node,
110*592ffb21SWarner Losh unsigned long size,
111*592ffb21SWarner Losh unsigned alignment,
112*592ffb21SWarner Losh unsigned long color,
113*592ffb21SWarner Losh unsigned long start,
114*592ffb21SWarner Losh unsigned long end,
115*592ffb21SWarner Losh int atomic);
drm_mm_get_block(struct drm_mm_node * parent,unsigned long size,unsigned alignment)116*592ffb21SWarner Losh static inline struct drm_mm_node *drm_mm_get_block(struct drm_mm_node *parent,
117*592ffb21SWarner Losh unsigned long size,
118*592ffb21SWarner Losh unsigned alignment)
119*592ffb21SWarner Losh {
120*592ffb21SWarner Losh return drm_mm_get_block_generic(parent, size, alignment, 0, 0);
121*592ffb21SWarner Losh }
drm_mm_get_block_atomic(struct drm_mm_node * parent,unsigned long size,unsigned alignment)122*592ffb21SWarner Losh static inline struct drm_mm_node *drm_mm_get_block_atomic(struct drm_mm_node *parent,
123*592ffb21SWarner Losh unsigned long size,
124*592ffb21SWarner Losh unsigned alignment)
125*592ffb21SWarner Losh {
126*592ffb21SWarner Losh return drm_mm_get_block_generic(parent, size, alignment, 0, 1);
127*592ffb21SWarner Losh }
drm_mm_get_block_range(struct drm_mm_node * parent,unsigned long size,unsigned alignment,unsigned long start,unsigned long end)128*592ffb21SWarner Losh static inline struct drm_mm_node *drm_mm_get_block_range(
129*592ffb21SWarner Losh struct drm_mm_node *parent,
130*592ffb21SWarner Losh unsigned long size,
131*592ffb21SWarner Losh unsigned alignment,
132*592ffb21SWarner Losh unsigned long start,
133*592ffb21SWarner Losh unsigned long end)
134*592ffb21SWarner Losh {
135*592ffb21SWarner Losh return drm_mm_get_block_range_generic(parent, size, alignment, 0,
136*592ffb21SWarner Losh start, end, 0);
137*592ffb21SWarner Losh }
drm_mm_get_color_block_range(struct drm_mm_node * parent,unsigned long size,unsigned alignment,unsigned long color,unsigned long start,unsigned long end)138*592ffb21SWarner Losh static inline struct drm_mm_node *drm_mm_get_color_block_range(
139*592ffb21SWarner Losh struct drm_mm_node *parent,
140*592ffb21SWarner Losh unsigned long size,
141*592ffb21SWarner Losh unsigned alignment,
142*592ffb21SWarner Losh unsigned long color,
143*592ffb21SWarner Losh unsigned long start,
144*592ffb21SWarner Losh unsigned long end)
145*592ffb21SWarner Losh {
146*592ffb21SWarner Losh return drm_mm_get_block_range_generic(parent, size, alignment, color,
147*592ffb21SWarner Losh start, end, 0);
148*592ffb21SWarner Losh }
drm_mm_get_block_atomic_range(struct drm_mm_node * parent,unsigned long size,unsigned alignment,unsigned long start,unsigned long end)149*592ffb21SWarner Losh static inline struct drm_mm_node *drm_mm_get_block_atomic_range(
150*592ffb21SWarner Losh struct drm_mm_node *parent,
151*592ffb21SWarner Losh unsigned long size,
152*592ffb21SWarner Losh unsigned alignment,
153*592ffb21SWarner Losh unsigned long start,
154*592ffb21SWarner Losh unsigned long end)
155*592ffb21SWarner Losh {
156*592ffb21SWarner Losh return drm_mm_get_block_range_generic(parent, size, alignment, 0,
157*592ffb21SWarner Losh start, end, 1);
158*592ffb21SWarner Losh }
159*592ffb21SWarner Losh
160*592ffb21SWarner Losh extern int drm_mm_insert_node(struct drm_mm *mm,
161*592ffb21SWarner Losh struct drm_mm_node *node,
162*592ffb21SWarner Losh unsigned long size,
163*592ffb21SWarner Losh unsigned alignment);
164*592ffb21SWarner Losh extern int drm_mm_insert_node_in_range(struct drm_mm *mm,
165*592ffb21SWarner Losh struct drm_mm_node *node,
166*592ffb21SWarner Losh unsigned long size,
167*592ffb21SWarner Losh unsigned alignment,
168*592ffb21SWarner Losh unsigned long start,
169*592ffb21SWarner Losh unsigned long end);
170*592ffb21SWarner Losh extern int drm_mm_insert_node_generic(struct drm_mm *mm,
171*592ffb21SWarner Losh struct drm_mm_node *node,
172*592ffb21SWarner Losh unsigned long size,
173*592ffb21SWarner Losh unsigned alignment,
174*592ffb21SWarner Losh unsigned long color);
175*592ffb21SWarner Losh extern int drm_mm_insert_node_in_range_generic(struct drm_mm *mm,
176*592ffb21SWarner Losh struct drm_mm_node *node,
177*592ffb21SWarner Losh unsigned long size,
178*592ffb21SWarner Losh unsigned alignment,
179*592ffb21SWarner Losh unsigned long color,
180*592ffb21SWarner Losh unsigned long start,
181*592ffb21SWarner Losh unsigned long end);
182*592ffb21SWarner Losh extern void drm_mm_put_block(struct drm_mm_node *cur);
183*592ffb21SWarner Losh extern void drm_mm_remove_node(struct drm_mm_node *node);
184*592ffb21SWarner Losh extern void drm_mm_replace_node(struct drm_mm_node *old, struct drm_mm_node *new);
185*592ffb21SWarner Losh extern struct drm_mm_node *drm_mm_search_free_generic(const struct drm_mm *mm,
186*592ffb21SWarner Losh unsigned long size,
187*592ffb21SWarner Losh unsigned alignment,
188*592ffb21SWarner Losh unsigned long color,
189*592ffb21SWarner Losh bool best_match);
190*592ffb21SWarner Losh extern struct drm_mm_node *drm_mm_search_free_in_range_generic(
191*592ffb21SWarner Losh const struct drm_mm *mm,
192*592ffb21SWarner Losh unsigned long size,
193*592ffb21SWarner Losh unsigned alignment,
194*592ffb21SWarner Losh unsigned long color,
195*592ffb21SWarner Losh unsigned long start,
196*592ffb21SWarner Losh unsigned long end,
197*592ffb21SWarner Losh bool best_match);
drm_mm_search_free(const struct drm_mm * mm,unsigned long size,unsigned alignment,bool best_match)198*592ffb21SWarner Losh static inline struct drm_mm_node *drm_mm_search_free(const struct drm_mm *mm,
199*592ffb21SWarner Losh unsigned long size,
200*592ffb21SWarner Losh unsigned alignment,
201*592ffb21SWarner Losh bool best_match)
202*592ffb21SWarner Losh {
203*592ffb21SWarner Losh return drm_mm_search_free_generic(mm,size, alignment, 0, best_match);
204*592ffb21SWarner Losh }
drm_mm_search_free_in_range(const struct drm_mm * mm,unsigned long size,unsigned alignment,unsigned long start,unsigned long end,bool best_match)205*592ffb21SWarner Losh static inline struct drm_mm_node *drm_mm_search_free_in_range(
206*592ffb21SWarner Losh const struct drm_mm *mm,
207*592ffb21SWarner Losh unsigned long size,
208*592ffb21SWarner Losh unsigned alignment,
209*592ffb21SWarner Losh unsigned long start,
210*592ffb21SWarner Losh unsigned long end,
211*592ffb21SWarner Losh bool best_match)
212*592ffb21SWarner Losh {
213*592ffb21SWarner Losh return drm_mm_search_free_in_range_generic(mm, size, alignment, 0,
214*592ffb21SWarner Losh start, end, best_match);
215*592ffb21SWarner Losh }
drm_mm_search_free_color(const struct drm_mm * mm,unsigned long size,unsigned alignment,unsigned long color,bool best_match)216*592ffb21SWarner Losh static inline struct drm_mm_node *drm_mm_search_free_color(const struct drm_mm *mm,
217*592ffb21SWarner Losh unsigned long size,
218*592ffb21SWarner Losh unsigned alignment,
219*592ffb21SWarner Losh unsigned long color,
220*592ffb21SWarner Losh bool best_match)
221*592ffb21SWarner Losh {
222*592ffb21SWarner Losh return drm_mm_search_free_generic(mm,size, alignment, color, best_match);
223*592ffb21SWarner Losh }
drm_mm_search_free_in_range_color(const struct drm_mm * mm,unsigned long size,unsigned alignment,unsigned long color,unsigned long start,unsigned long end,bool best_match)224*592ffb21SWarner Losh static inline struct drm_mm_node *drm_mm_search_free_in_range_color(
225*592ffb21SWarner Losh const struct drm_mm *mm,
226*592ffb21SWarner Losh unsigned long size,
227*592ffb21SWarner Losh unsigned alignment,
228*592ffb21SWarner Losh unsigned long color,
229*592ffb21SWarner Losh unsigned long start,
230*592ffb21SWarner Losh unsigned long end,
231*592ffb21SWarner Losh bool best_match)
232*592ffb21SWarner Losh {
233*592ffb21SWarner Losh return drm_mm_search_free_in_range_generic(mm, size, alignment, color,
234*592ffb21SWarner Losh start, end, best_match);
235*592ffb21SWarner Losh }
236*592ffb21SWarner Losh extern int drm_mm_init(struct drm_mm *mm,
237*592ffb21SWarner Losh unsigned long start,
238*592ffb21SWarner Losh unsigned long size);
239*592ffb21SWarner Losh extern void drm_mm_takedown(struct drm_mm *mm);
240*592ffb21SWarner Losh extern int drm_mm_clean(struct drm_mm *mm);
241*592ffb21SWarner Losh extern int drm_mm_pre_get(struct drm_mm *mm);
242*592ffb21SWarner Losh
drm_get_mm(struct drm_mm_node * block)243*592ffb21SWarner Losh static inline struct drm_mm *drm_get_mm(struct drm_mm_node *block)
244*592ffb21SWarner Losh {
245*592ffb21SWarner Losh return block->mm;
246*592ffb21SWarner Losh }
247*592ffb21SWarner Losh
248*592ffb21SWarner Losh void drm_mm_init_scan(struct drm_mm *mm,
249*592ffb21SWarner Losh unsigned long size,
250*592ffb21SWarner Losh unsigned alignment,
251*592ffb21SWarner Losh unsigned long color);
252*592ffb21SWarner Losh void drm_mm_init_scan_with_range(struct drm_mm *mm,
253*592ffb21SWarner Losh unsigned long size,
254*592ffb21SWarner Losh unsigned alignment,
255*592ffb21SWarner Losh unsigned long color,
256*592ffb21SWarner Losh unsigned long start,
257*592ffb21SWarner Losh unsigned long end);
258*592ffb21SWarner Losh int drm_mm_scan_add_block(struct drm_mm_node *node);
259*592ffb21SWarner Losh int drm_mm_scan_remove_block(struct drm_mm_node *node);
260*592ffb21SWarner Losh
261*592ffb21SWarner Losh extern void drm_mm_debug_table(struct drm_mm *mm, const char *prefix);
262*592ffb21SWarner Losh
263*592ffb21SWarner Losh #endif
264