diff options
author | Chris Wilson <chris@chris-wilson.co.uk> | 2012-11-15 06:32:17 -0500 |
---|---|---|
committer | Daniel Vetter <daniel.vetter@ffwll.ch> | 2012-11-30 17:20:54 -0500 |
commit | 9e8944ab564f2e3dde90a518cd32048c58918608 (patch) | |
tree | 25a2dffcd1cfa8d01c50d03d8791817bafd05574 | |
parent | 5973c7ee519e2a240c68b290a1836bdb25ed3701 (diff) |
drm: Introduce an iterator over holes in the drm_mm range manager
This will be used i915 in forthcoming patches in order to measure the
largest contiguous chunk of memory available for enabling chipset
features.
v2: Try to make the macro marginally safer and more readable by not
depending upon the drm_mm_hole_node_end() being non-zero. Note that we
need to open code list_for_each() in order to update the hole_start,
hole_end variable on each iteration and keep the macro sane.
v3: Tidy up few BUG_ONs that fell foul of adding additional tests to
drm_mm_hole_node_start().
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Cc: Dave Airlie <airlied@redhat.com>
Acked-by: Dave Airlie <airlied@redhat.com>
Cc: dri-devel@lists.freedesktop.org
Reviewed-by: Ben Widawsky <ben@bwidawsk.net>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
-rw-r--r-- | drivers/gpu/drm/drm_mm.c | 62 | ||||
-rw-r--r-- | include/drm/drm_mm.h | 36 |
2 files changed, 57 insertions, 41 deletions
diff --git a/drivers/gpu/drm/drm_mm.c b/drivers/gpu/drm/drm_mm.c index bd203b61a72b..b751b8e1e205 100644 --- a/drivers/gpu/drm/drm_mm.c +++ b/drivers/gpu/drm/drm_mm.c | |||
@@ -102,20 +102,6 @@ int drm_mm_pre_get(struct drm_mm *mm) | |||
102 | } | 102 | } |
103 | EXPORT_SYMBOL(drm_mm_pre_get); | 103 | EXPORT_SYMBOL(drm_mm_pre_get); |
104 | 104 | ||
105 | static inline unsigned long drm_mm_hole_node_start(struct drm_mm_node *hole_node) | ||
106 | { | ||
107 | return hole_node->start + hole_node->size; | ||
108 | } | ||
109 | |||
110 | static inline unsigned long drm_mm_hole_node_end(struct drm_mm_node *hole_node) | ||
111 | { | ||
112 | struct drm_mm_node *next_node = | ||
113 | list_entry(hole_node->node_list.next, struct drm_mm_node, | ||
114 | node_list); | ||
115 | |||
116 | return next_node->start; | ||
117 | } | ||
118 | |||
119 | static void drm_mm_insert_helper(struct drm_mm_node *hole_node, | 105 | static void drm_mm_insert_helper(struct drm_mm_node *hole_node, |
120 | struct drm_mm_node *node, | 106 | struct drm_mm_node *node, |
121 | unsigned long size, unsigned alignment, | 107 | unsigned long size, unsigned alignment, |
@@ -127,7 +113,7 @@ static void drm_mm_insert_helper(struct drm_mm_node *hole_node, | |||
127 | unsigned long adj_start = hole_start; | 113 | unsigned long adj_start = hole_start; |
128 | unsigned long adj_end = hole_end; | 114 | unsigned long adj_end = hole_end; |
129 | 115 | ||
130 | BUG_ON(!hole_node->hole_follows || node->allocated); | 116 | BUG_ON(node->allocated); |
131 | 117 | ||
132 | if (mm->color_adjust) | 118 | if (mm->color_adjust) |
133 | mm->color_adjust(hole_node, color, &adj_start, &adj_end); | 119 | mm->color_adjust(hole_node, color, &adj_start, &adj_end); |
@@ -155,7 +141,7 @@ static void drm_mm_insert_helper(struct drm_mm_node *hole_node, | |||
155 | BUG_ON(node->start + node->size > adj_end); | 141 | BUG_ON(node->start + node->size > adj_end); |
156 | 142 | ||
157 | node->hole_follows = 0; | 143 | node->hole_follows = 0; |
158 | if (node->start + node->size < hole_end) { | 144 | if (__drm_mm_hole_node_start(node) < hole_end) { |
159 | list_add(&node->hole_stack, &mm->hole_stack); | 145 | list_add(&node->hole_stack, &mm->hole_stack); |
160 | node->hole_follows = 1; | 146 | node->hole_follows = 1; |
161 | } | 147 | } |
@@ -168,15 +154,10 @@ struct drm_mm_node *drm_mm_create_block(struct drm_mm *mm, | |||
168 | { | 154 | { |
169 | struct drm_mm_node *hole, *node; | 155 | struct drm_mm_node *hole, *node; |
170 | unsigned long end = start + size; | 156 | unsigned long end = start + size; |
157 | unsigned long hole_start; | ||
158 | unsigned long hole_end; | ||
171 | 159 | ||
172 | list_for_each_entry(hole, &mm->hole_stack, hole_stack) { | 160 | drm_mm_for_each_hole(hole, mm, hole_start, hole_end) { |
173 | unsigned long hole_start; | ||
174 | unsigned long hole_end; | ||
175 | |||
176 | BUG_ON(!hole->hole_follows); | ||
177 | hole_start = drm_mm_hole_node_start(hole); | ||
178 | hole_end = drm_mm_hole_node_end(hole); | ||
179 | |||
180 | if (hole_start > start || hole_end < end) | 161 | if (hole_start > start || hole_end < end) |
181 | continue; | 162 | continue; |
182 | 163 | ||
@@ -293,7 +274,7 @@ static void drm_mm_insert_helper_range(struct drm_mm_node *hole_node, | |||
293 | BUG_ON(node->start + node->size > end); | 274 | BUG_ON(node->start + node->size > end); |
294 | 275 | ||
295 | node->hole_follows = 0; | 276 | node->hole_follows = 0; |
296 | if (node->start + node->size < hole_end) { | 277 | if (__drm_mm_hole_node_start(node) < hole_end) { |
297 | list_add(&node->hole_stack, &mm->hole_stack); | 278 | list_add(&node->hole_stack, &mm->hole_stack); |
298 | node->hole_follows = 1; | 279 | node->hole_follows = 1; |
299 | } | 280 | } |
@@ -358,12 +339,13 @@ void drm_mm_remove_node(struct drm_mm_node *node) | |||
358 | list_entry(node->node_list.prev, struct drm_mm_node, node_list); | 339 | list_entry(node->node_list.prev, struct drm_mm_node, node_list); |
359 | 340 | ||
360 | if (node->hole_follows) { | 341 | if (node->hole_follows) { |
361 | BUG_ON(drm_mm_hole_node_start(node) | 342 | BUG_ON(__drm_mm_hole_node_start(node) == |
362 | == drm_mm_hole_node_end(node)); | 343 | __drm_mm_hole_node_end(node)); |
363 | list_del(&node->hole_stack); | 344 | list_del(&node->hole_stack); |
364 | } else | 345 | } else |
365 | BUG_ON(drm_mm_hole_node_start(node) | 346 | BUG_ON(__drm_mm_hole_node_start(node) != |
366 | != drm_mm_hole_node_end(node)); | 347 | __drm_mm_hole_node_end(node)); |
348 | |||
367 | 349 | ||
368 | if (!prev_node->hole_follows) { | 350 | if (!prev_node->hole_follows) { |
369 | prev_node->hole_follows = 1; | 351 | prev_node->hole_follows = 1; |
@@ -421,6 +403,8 @@ struct drm_mm_node *drm_mm_search_free_generic(const struct drm_mm *mm, | |||
421 | { | 403 | { |
422 | struct drm_mm_node *entry; | 404 | struct drm_mm_node *entry; |
423 | struct drm_mm_node *best; | 405 | struct drm_mm_node *best; |
406 | unsigned long adj_start; | ||
407 | unsigned long adj_end; | ||
424 | unsigned long best_size; | 408 | unsigned long best_size; |
425 | 409 | ||
426 | BUG_ON(mm->scanned_blocks); | 410 | BUG_ON(mm->scanned_blocks); |
@@ -428,17 +412,13 @@ struct drm_mm_node *drm_mm_search_free_generic(const struct drm_mm *mm, | |||
428 | best = NULL; | 412 | best = NULL; |
429 | best_size = ~0UL; | 413 | best_size = ~0UL; |
430 | 414 | ||
431 | list_for_each_entry(entry, &mm->hole_stack, hole_stack) { | 415 | drm_mm_for_each_hole(entry, mm, adj_start, adj_end) { |
432 | unsigned long adj_start = drm_mm_hole_node_start(entry); | ||
433 | unsigned long adj_end = drm_mm_hole_node_end(entry); | ||
434 | |||
435 | if (mm->color_adjust) { | 416 | if (mm->color_adjust) { |
436 | mm->color_adjust(entry, color, &adj_start, &adj_end); | 417 | mm->color_adjust(entry, color, &adj_start, &adj_end); |
437 | if (adj_end <= adj_start) | 418 | if (adj_end <= adj_start) |
438 | continue; | 419 | continue; |
439 | } | 420 | } |
440 | 421 | ||
441 | BUG_ON(!entry->hole_follows); | ||
442 | if (!check_free_hole(adj_start, adj_end, size, alignment)) | 422 | if (!check_free_hole(adj_start, adj_end, size, alignment)) |
443 | continue; | 423 | continue; |
444 | 424 | ||
@@ -465,6 +445,8 @@ struct drm_mm_node *drm_mm_search_free_in_range_generic(const struct drm_mm *mm, | |||
465 | { | 445 | { |
466 | struct drm_mm_node *entry; | 446 | struct drm_mm_node *entry; |
467 | struct drm_mm_node *best; | 447 | struct drm_mm_node *best; |
448 | unsigned long adj_start; | ||
449 | unsigned long adj_end; | ||
468 | unsigned long best_size; | 450 | unsigned long best_size; |
469 | 451 | ||
470 | BUG_ON(mm->scanned_blocks); | 452 | BUG_ON(mm->scanned_blocks); |
@@ -472,13 +454,11 @@ struct drm_mm_node *drm_mm_search_free_in_range_generic(const struct drm_mm *mm, | |||
472 | best = NULL; | 454 | best = NULL; |
473 | best_size = ~0UL; | 455 | best_size = ~0UL; |
474 | 456 | ||
475 | list_for_each_entry(entry, &mm->hole_stack, hole_stack) { | 457 | drm_mm_for_each_hole(entry, mm, adj_start, adj_end) { |
476 | unsigned long adj_start = drm_mm_hole_node_start(entry) < start ? | 458 | if (adj_start < start) |
477 | start : drm_mm_hole_node_start(entry); | 459 | adj_start = start; |
478 | unsigned long adj_end = drm_mm_hole_node_end(entry) > end ? | 460 | if (adj_end > end) |
479 | end : drm_mm_hole_node_end(entry); | 461 | adj_end = end; |
480 | |||
481 | BUG_ON(!entry->hole_follows); | ||
482 | 462 | ||
483 | if (mm->color_adjust) { | 463 | if (mm->color_adjust) { |
484 | mm->color_adjust(entry, color, &adj_start, &adj_end); | 464 | mm->color_adjust(entry, color, &adj_start, &adj_end); |
diff --git a/include/drm/drm_mm.h b/include/drm/drm_mm.h index 4020f9661c3c..cd453653f634 100644 --- a/include/drm/drm_mm.h +++ b/include/drm/drm_mm.h | |||
@@ -89,6 +89,29 @@ static inline bool drm_mm_initialized(struct drm_mm *mm) | |||
89 | { | 89 | { |
90 | return mm->hole_stack.next; | 90 | return mm->hole_stack.next; |
91 | } | 91 | } |
92 | |||
93 | static inline unsigned long __drm_mm_hole_node_start(struct drm_mm_node *hole_node) | ||
94 | { | ||
95 | return hole_node->start + hole_node->size; | ||
96 | } | ||
97 | |||
98 | static inline unsigned long drm_mm_hole_node_start(struct drm_mm_node *hole_node) | ||
99 | { | ||
100 | BUG_ON(!hole_node->hole_follows); | ||
101 | return __drm_mm_hole_node_start(hole_node); | ||
102 | } | ||
103 | |||
104 | static inline unsigned long __drm_mm_hole_node_end(struct drm_mm_node *hole_node) | ||
105 | { | ||
106 | return list_entry(hole_node->node_list.next, | ||
107 | struct drm_mm_node, node_list)->start; | ||
108 | } | ||
109 | |||
110 | static inline unsigned long drm_mm_hole_node_end(struct drm_mm_node *hole_node) | ||
111 | { | ||
112 | return __drm_mm_hole_node_end(hole_node); | ||
113 | } | ||
114 | |||
92 | #define drm_mm_for_each_node(entry, mm) list_for_each_entry(entry, \ | 115 | #define drm_mm_for_each_node(entry, mm) list_for_each_entry(entry, \ |
93 | &(mm)->head_node.node_list, \ | 116 | &(mm)->head_node.node_list, \ |
94 | node_list) | 117 | node_list) |
@@ -99,6 +122,19 @@ static inline bool drm_mm_initialized(struct drm_mm *mm) | |||
99 | entry != NULL; entry = next, \ | 122 | entry != NULL; entry = next, \ |
100 | next = entry ? list_entry(entry->node_list.next, \ | 123 | next = entry ? list_entry(entry->node_list.next, \ |
101 | struct drm_mm_node, node_list) : NULL) \ | 124 | struct drm_mm_node, node_list) : NULL) \ |
125 | |||
126 | /* Note that we need to unroll list_for_each_entry in order to inline | ||
127 | * setting hole_start and hole_end on each iteration and keep the | ||
128 | * macro sane. | ||
129 | */ | ||
130 | #define drm_mm_for_each_hole(entry, mm, hole_start, hole_end) \ | ||
131 | for (entry = list_entry((mm)->hole_stack.next, struct drm_mm_node, hole_stack); \ | ||
132 | &entry->hole_stack != &(mm)->hole_stack ? \ | ||
133 | hole_start = drm_mm_hole_node_start(entry), \ | ||
134 | hole_end = drm_mm_hole_node_end(entry), \ | ||
135 | 1 : 0; \ | ||
136 | entry = list_entry(entry->hole_stack.next, struct drm_mm_node, hole_stack)) | ||
137 | |||
102 | /* | 138 | /* |
103 | * Basic range manager support (drm_mm.c) | 139 | * Basic range manager support (drm_mm.c) |
104 | */ | 140 | */ |