46
46
#include <linux/slab.h>
47
47
#include <linux/seq_file.h>
48
48
#include <linux/export.h>
49
+ #include <linux/interval_tree_generic.h>
49
50
50
51
/**
51
52
* DOC: Overview
@@ -103,6 +104,72 @@ static struct drm_mm_node *drm_mm_search_free_in_range_generic(const struct drm_
103
104
u64 end ,
104
105
enum drm_mm_search_flags flags );
105
106
107
+ #define START (node ) ((node)->start)
108
+ #define LAST (node ) ((node)->start + (node)->size - 1)
109
+
110
+ INTERVAL_TREE_DEFINE (struct drm_mm_node , rb ,
111
+ u64 , __subtree_last ,
112
+ START , LAST , static inline , drm_mm_interval_tree )
113
+
114
+ struct drm_mm_node *
115
+ drm_mm_interval_first (struct drm_mm * mm , u64 start , u64 last )
116
+ {
117
+ return drm_mm_interval_tree_iter_first (& mm -> interval_tree ,
118
+ start , last );
119
+ }
120
+ EXPORT_SYMBOL (drm_mm_interval_first );
121
+
122
+ struct drm_mm_node *
123
+ drm_mm_interval_next (struct drm_mm_node * node , u64 start , u64 last )
124
+ {
125
+ return drm_mm_interval_tree_iter_next (node , start , last );
126
+ }
127
+ EXPORT_SYMBOL (drm_mm_interval_next );
128
+
129
+ static void drm_mm_interval_tree_add_node (struct drm_mm_node * hole_node ,
130
+ struct drm_mm_node * node )
131
+ {
132
+ struct drm_mm * mm = hole_node -> mm ;
133
+ struct rb_node * * link , * rb ;
134
+ struct drm_mm_node * parent ;
135
+
136
+ node -> __subtree_last = LAST (node );
137
+
138
+ if (hole_node -> allocated ) {
139
+ rb = & hole_node -> rb ;
140
+ while (rb ) {
141
+ parent = rb_entry (rb , struct drm_mm_node , rb );
142
+ if (parent -> __subtree_last >= node -> __subtree_last )
143
+ break ;
144
+
145
+ parent -> __subtree_last = node -> __subtree_last ;
146
+ rb = rb_parent (rb );
147
+ }
148
+
149
+ rb = & hole_node -> rb ;
150
+ link = & hole_node -> rb .rb_right ;
151
+ } else {
152
+ rb = NULL ;
153
+ link = & mm -> interval_tree .rb_node ;
154
+ }
155
+
156
+ while (* link ) {
157
+ rb = * link ;
158
+ parent = rb_entry (rb , struct drm_mm_node , rb );
159
+ if (parent -> __subtree_last < node -> __subtree_last )
160
+ parent -> __subtree_last = node -> __subtree_last ;
161
+ if (node -> start < parent -> start )
162
+ link = & parent -> rb .rb_left ;
163
+ else
164
+ link = & parent -> rb .rb_right ;
165
+ }
166
+
167
+ rb_link_node (& node -> rb , rb , link );
168
+ rb_insert_augmented (& node -> rb ,
169
+ & mm -> interval_tree ,
170
+ & drm_mm_interval_tree_augment );
171
+ }
172
+
106
173
static void drm_mm_insert_helper (struct drm_mm_node * hole_node ,
107
174
struct drm_mm_node * node ,
108
175
u64 size , unsigned alignment ,
@@ -153,6 +220,8 @@ static void drm_mm_insert_helper(struct drm_mm_node *hole_node,
153
220
INIT_LIST_HEAD (& node -> hole_stack );
154
221
list_add (& node -> node_list , & hole_node -> node_list );
155
222
223
+ drm_mm_interval_tree_add_node (hole_node , node );
224
+
156
225
BUG_ON (node -> start + node -> size > adj_end );
157
226
158
227
node -> hole_follows = 0 ;
@@ -178,41 +247,52 @@ static void drm_mm_insert_helper(struct drm_mm_node *hole_node,
178
247
*/
179
248
int drm_mm_reserve_node (struct drm_mm * mm , struct drm_mm_node * node )
180
249
{
250
+ u64 end = node -> start + node -> size ;
181
251
struct drm_mm_node * hole ;
182
- u64 end ;
183
- u64 hole_start ;
184
- u64 hole_end ;
185
-
186
- BUG_ON (node == NULL );
252
+ u64 hole_start , hole_end ;
187
253
188
254
end = node -> start + node -> size ;
189
255
190
256
/* Find the relevant hole to add our node to */
191
- drm_mm_for_each_hole (hole , mm , hole_start , hole_end ) {
192
- if (hole_start > node -> start || hole_end < end )
193
- continue ;
257
+ hole = drm_mm_interval_tree_iter_first (& mm -> interval_tree ,
258
+ node -> start , ~(u64 )0 );
259
+ if (hole ) {
260
+ if (hole -> start < end )
261
+ return - ENOSPC ;
262
+ } else {
263
+ hole = list_entry (& mm -> head_node .node_list ,
264
+ typeof (* hole ), node_list );
265
+ }
194
266
195
- node -> mm = mm ;
196
- node -> allocated = 1 ;
267
+ hole = list_last_entry (& hole -> node_list , typeof (* hole ), node_list );
268
+ if (!hole -> hole_follows )
269
+ return - ENOSPC ;
197
270
198
- INIT_LIST_HEAD (& node -> hole_stack );
199
- list_add (& node -> node_list , & hole -> node_list );
271
+ hole_start = __drm_mm_hole_node_start (hole );
272
+ hole_end = __drm_mm_hole_node_end (hole );
273
+ if (hole_start > node -> start || hole_end < end )
274
+ return - ENOSPC ;
200
275
201
- if (node -> start == hole_start ) {
202
- hole -> hole_follows = 0 ;
203
- list_del_init (& hole -> hole_stack );
204
- }
276
+ node -> mm = mm ;
277
+ node -> allocated = 1 ;
205
278
206
- node -> hole_follows = 0 ;
207
- if (end != hole_end ) {
208
- list_add (& node -> hole_stack , & mm -> hole_stack );
209
- node -> hole_follows = 1 ;
210
- }
279
+ INIT_LIST_HEAD (& node -> hole_stack );
280
+ list_add (& node -> node_list , & hole -> node_list );
211
281
212
- return 0 ;
282
+ drm_mm_interval_tree_add_node (hole , node );
283
+
284
+ if (node -> start == hole_start ) {
285
+ hole -> hole_follows = 0 ;
286
+ list_del_init (& hole -> hole_stack );
287
+ }
288
+
289
+ node -> hole_follows = 0 ;
290
+ if (end != hole_end ) {
291
+ list_add (& node -> hole_stack , & mm -> hole_stack );
292
+ node -> hole_follows = 1 ;
213
293
}
214
294
215
- return - ENOSPC ;
295
+ return 0 ;
216
296
}
217
297
EXPORT_SYMBOL (drm_mm_reserve_node );
218
298
@@ -302,6 +382,8 @@ static void drm_mm_insert_helper_range(struct drm_mm_node *hole_node,
302
382
INIT_LIST_HEAD (& node -> hole_stack );
303
383
list_add (& node -> node_list , & hole_node -> node_list );
304
384
385
+ drm_mm_interval_tree_add_node (hole_node , node );
386
+
305
387
BUG_ON (node -> start < start );
306
388
BUG_ON (node -> start < adj_start );
307
389
BUG_ON (node -> start + node -> size > adj_end );
@@ -390,6 +472,7 @@ void drm_mm_remove_node(struct drm_mm_node *node)
390
472
} else
391
473
list_move (& prev_node -> hole_stack , & mm -> hole_stack );
392
474
475
+ drm_mm_interval_tree_remove (node , & mm -> interval_tree );
393
476
list_del (& node -> node_list );
394
477
node -> allocated = 0 ;
395
478
}
@@ -516,11 +599,13 @@ void drm_mm_replace_node(struct drm_mm_node *old, struct drm_mm_node *new)
516
599
{
517
600
list_replace (& old -> node_list , & new -> node_list );
518
601
list_replace (& old -> hole_stack , & new -> hole_stack );
602
+ rb_replace_node (& old -> rb , & new -> rb , & old -> mm -> interval_tree );
519
603
new -> hole_follows = old -> hole_follows ;
520
604
new -> mm = old -> mm ;
521
605
new -> start = old -> start ;
522
606
new -> size = old -> size ;
523
607
new -> color = old -> color ;
608
+ new -> __subtree_last = old -> __subtree_last ;
524
609
525
610
old -> allocated = 0 ;
526
611
new -> allocated = 1 ;
@@ -758,6 +843,8 @@ void drm_mm_init(struct drm_mm * mm, u64 start, u64 size)
758
843
mm -> head_node .size = start - mm -> head_node .start ;
759
844
list_add_tail (& mm -> head_node .hole_stack , & mm -> hole_stack );
760
845
846
+ mm -> interval_tree = RB_ROOT ;
847
+
761
848
mm -> color_adjust = NULL ;
762
849
}
763
850
EXPORT_SYMBOL (drm_mm_init );
0 commit comments