Commit 9e8944ab authored by Chris Wilson's avatar Chris Wilson Committed by Daniel Vetter

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: default avatarChris Wilson <chris@chris-wilson.co.uk>
Cc: Dave Airlie <airlied@redhat.com>
Acked-by: default avatarDave Airlie <airlied@redhat.com>
Cc: dri-devel@lists.freedesktop.org
Reviewed-by: default avatarBen Widawsky <ben@bwidawsk.net>
Signed-off-by: default avatarDaniel Vetter <daniel.vetter@ffwll.ch>
parent 5973c7ee
...@@ -102,20 +102,6 @@ int drm_mm_pre_get(struct drm_mm *mm) ...@@ -102,20 +102,6 @@ int drm_mm_pre_get(struct drm_mm *mm)
} }
EXPORT_SYMBOL(drm_mm_pre_get); EXPORT_SYMBOL(drm_mm_pre_get);
static inline unsigned long drm_mm_hole_node_start(struct drm_mm_node *hole_node)
{
return hole_node->start + hole_node->size;
}
static inline unsigned long drm_mm_hole_node_end(struct drm_mm_node *hole_node)
{
struct drm_mm_node *next_node =
list_entry(hole_node->node_list.next, struct drm_mm_node,
node_list);
return next_node->start;
}
static void drm_mm_insert_helper(struct drm_mm_node *hole_node, static void drm_mm_insert_helper(struct drm_mm_node *hole_node,
struct drm_mm_node *node, struct drm_mm_node *node,
unsigned long size, unsigned alignment, unsigned long size, unsigned alignment,
...@@ -127,7 +113,7 @@ static void drm_mm_insert_helper(struct drm_mm_node *hole_node, ...@@ -127,7 +113,7 @@ static void drm_mm_insert_helper(struct drm_mm_node *hole_node,
unsigned long adj_start = hole_start; unsigned long adj_start = hole_start;
unsigned long adj_end = hole_end; unsigned long adj_end = hole_end;
BUG_ON(!hole_node->hole_follows || node->allocated); BUG_ON(node->allocated);
if (mm->color_adjust) if (mm->color_adjust)
mm->color_adjust(hole_node, color, &adj_start, &adj_end); 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,7 +141,7 @@ static void drm_mm_insert_helper(struct drm_mm_node *hole_node,
BUG_ON(node->start + node->size > adj_end); BUG_ON(node->start + node->size > adj_end);
node->hole_follows = 0; node->hole_follows = 0;
if (node->start + node->size < hole_end) { if (__drm_mm_hole_node_start(node) < hole_end) {
list_add(&node->hole_stack, &mm->hole_stack); list_add(&node->hole_stack, &mm->hole_stack);
node->hole_follows = 1; node->hole_follows = 1;
} }
...@@ -168,15 +154,10 @@ struct drm_mm_node *drm_mm_create_block(struct drm_mm *mm, ...@@ -168,15 +154,10 @@ struct drm_mm_node *drm_mm_create_block(struct drm_mm *mm,
{ {
struct drm_mm_node *hole, *node; struct drm_mm_node *hole, *node;
unsigned long end = start + size; unsigned long end = start + size;
unsigned long hole_start;
unsigned long hole_end;
list_for_each_entry(hole, &mm->hole_stack, hole_stack) { drm_mm_for_each_hole(hole, mm, hole_start, hole_end) {
unsigned long hole_start;
unsigned long hole_end;
BUG_ON(!hole->hole_follows);
hole_start = drm_mm_hole_node_start(hole);
hole_end = drm_mm_hole_node_end(hole);
if (hole_start > start || hole_end < end) if (hole_start > start || hole_end < end)
continue; continue;
...@@ -293,7 +274,7 @@ static void drm_mm_insert_helper_range(struct drm_mm_node *hole_node, ...@@ -293,7 +274,7 @@ static void drm_mm_insert_helper_range(struct drm_mm_node *hole_node,
BUG_ON(node->start + node->size > end); BUG_ON(node->start + node->size > end);
node->hole_follows = 0; node->hole_follows = 0;
if (node->start + node->size < hole_end) { if (__drm_mm_hole_node_start(node) < hole_end) {
list_add(&node->hole_stack, &mm->hole_stack); list_add(&node->hole_stack, &mm->hole_stack);
node->hole_follows = 1; node->hole_follows = 1;
} }
...@@ -358,12 +339,13 @@ void drm_mm_remove_node(struct drm_mm_node *node) ...@@ -358,12 +339,13 @@ void drm_mm_remove_node(struct drm_mm_node *node)
list_entry(node->node_list.prev, struct drm_mm_node, node_list); list_entry(node->node_list.prev, struct drm_mm_node, node_list);
if (node->hole_follows) { if (node->hole_follows) {
BUG_ON(drm_mm_hole_node_start(node) BUG_ON(__drm_mm_hole_node_start(node) ==
== drm_mm_hole_node_end(node)); __drm_mm_hole_node_end(node));
list_del(&node->hole_stack); list_del(&node->hole_stack);
} else } else
BUG_ON(drm_mm_hole_node_start(node) BUG_ON(__drm_mm_hole_node_start(node) !=
!= drm_mm_hole_node_end(node)); __drm_mm_hole_node_end(node));
if (!prev_node->hole_follows) { if (!prev_node->hole_follows) {
prev_node->hole_follows = 1; prev_node->hole_follows = 1;
...@@ -421,6 +403,8 @@ struct drm_mm_node *drm_mm_search_free_generic(const struct drm_mm *mm, ...@@ -421,6 +403,8 @@ struct drm_mm_node *drm_mm_search_free_generic(const struct drm_mm *mm,
{ {
struct drm_mm_node *entry; struct drm_mm_node *entry;
struct drm_mm_node *best; struct drm_mm_node *best;
unsigned long adj_start;
unsigned long adj_end;
unsigned long best_size; unsigned long best_size;
BUG_ON(mm->scanned_blocks); BUG_ON(mm->scanned_blocks);
...@@ -428,17 +412,13 @@ struct drm_mm_node *drm_mm_search_free_generic(const struct drm_mm *mm, ...@@ -428,17 +412,13 @@ struct drm_mm_node *drm_mm_search_free_generic(const struct drm_mm *mm,
best = NULL; best = NULL;
best_size = ~0UL; best_size = ~0UL;
list_for_each_entry(entry, &mm->hole_stack, hole_stack) { drm_mm_for_each_hole(entry, mm, adj_start, adj_end) {
unsigned long adj_start = drm_mm_hole_node_start(entry);
unsigned long adj_end = drm_mm_hole_node_end(entry);
if (mm->color_adjust) { if (mm->color_adjust) {
mm->color_adjust(entry, color, &adj_start, &adj_end); mm->color_adjust(entry, color, &adj_start, &adj_end);
if (adj_end <= adj_start) if (adj_end <= adj_start)
continue; continue;
} }
BUG_ON(!entry->hole_follows);
if (!check_free_hole(adj_start, adj_end, size, alignment)) if (!check_free_hole(adj_start, adj_end, size, alignment))
continue; continue;
...@@ -465,6 +445,8 @@ struct drm_mm_node *drm_mm_search_free_in_range_generic(const struct drm_mm *mm, ...@@ -465,6 +445,8 @@ struct drm_mm_node *drm_mm_search_free_in_range_generic(const struct drm_mm *mm,
{ {
struct drm_mm_node *entry; struct drm_mm_node *entry;
struct drm_mm_node *best; struct drm_mm_node *best;
unsigned long adj_start;
unsigned long adj_end;
unsigned long best_size; unsigned long best_size;
BUG_ON(mm->scanned_blocks); 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,13 +454,11 @@ struct drm_mm_node *drm_mm_search_free_in_range_generic(const struct drm_mm *mm,
best = NULL; best = NULL;
best_size = ~0UL; best_size = ~0UL;
list_for_each_entry(entry, &mm->hole_stack, hole_stack) { drm_mm_for_each_hole(entry, mm, adj_start, adj_end) {
unsigned long adj_start = drm_mm_hole_node_start(entry) < start ? if (adj_start < start)
start : drm_mm_hole_node_start(entry); adj_start = start;
unsigned long adj_end = drm_mm_hole_node_end(entry) > end ? if (adj_end > end)
end : drm_mm_hole_node_end(entry); adj_end = end;
BUG_ON(!entry->hole_follows);
if (mm->color_adjust) { if (mm->color_adjust) {
mm->color_adjust(entry, color, &adj_start, &adj_end); mm->color_adjust(entry, color, &adj_start, &adj_end);
......
...@@ -89,6 +89,29 @@ static inline bool drm_mm_initialized(struct drm_mm *mm) ...@@ -89,6 +89,29 @@ static inline bool drm_mm_initialized(struct drm_mm *mm)
{ {
return mm->hole_stack.next; return mm->hole_stack.next;
} }
static inline unsigned long __drm_mm_hole_node_start(struct drm_mm_node *hole_node)
{
return hole_node->start + hole_node->size;
}
static inline unsigned long drm_mm_hole_node_start(struct drm_mm_node *hole_node)
{
BUG_ON(!hole_node->hole_follows);
return __drm_mm_hole_node_start(hole_node);
}
static inline unsigned long __drm_mm_hole_node_end(struct drm_mm_node *hole_node)
{
return list_entry(hole_node->node_list.next,
struct drm_mm_node, node_list)->start;
}
static inline unsigned long drm_mm_hole_node_end(struct drm_mm_node *hole_node)
{
return __drm_mm_hole_node_end(hole_node);
}
#define drm_mm_for_each_node(entry, mm) list_for_each_entry(entry, \ #define drm_mm_for_each_node(entry, mm) list_for_each_entry(entry, \
&(mm)->head_node.node_list, \ &(mm)->head_node.node_list, \
node_list) node_list)
...@@ -99,6 +122,19 @@ static inline bool drm_mm_initialized(struct drm_mm *mm) ...@@ -99,6 +122,19 @@ static inline bool drm_mm_initialized(struct drm_mm *mm)
entry != NULL; entry = next, \ entry != NULL; entry = next, \
next = entry ? list_entry(entry->node_list.next, \ next = entry ? list_entry(entry->node_list.next, \
struct drm_mm_node, node_list) : NULL) \ struct drm_mm_node, node_list) : NULL) \
/* Note that we need to unroll list_for_each_entry in order to inline
* setting hole_start and hole_end on each iteration and keep the
* macro sane.
*/
#define drm_mm_for_each_hole(entry, mm, hole_start, hole_end) \
for (entry = list_entry((mm)->hole_stack.next, struct drm_mm_node, hole_stack); \
&entry->hole_stack != &(mm)->hole_stack ? \
hole_start = drm_mm_hole_node_start(entry), \
hole_end = drm_mm_hole_node_end(entry), \
1 : 0; \
entry = list_entry(entry->hole_stack.next, struct drm_mm_node, hole_stack))
/* /*
* Basic range manager support (drm_mm.c) * Basic range manager support (drm_mm.c)
*/ */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment