Skip to content

Commit

Permalink
drm: Introduce an iterator over holes in the drm_mm range manager
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Chris Wilson authored and Daniel Vetter committed Nov 30, 2012
1 parent 5973c7e commit 9e8944a
Show file tree
Hide file tree
Showing 2 changed files with 57 additions and 41 deletions.
62 changes: 21 additions & 41 deletions drivers/gpu/drm/drm_mm.c
Original file line number Diff line number Diff line change
Expand Up @@ -102,20 +102,6 @@ int drm_mm_pre_get(struct drm_mm *mm)
}
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,
struct drm_mm_node *node,
unsigned long size, unsigned alignment,
Expand All @@ -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_end = hole_end;

BUG_ON(!hole_node->hole_follows || node->allocated);
BUG_ON(node->allocated);

if (mm->color_adjust)
mm->color_adjust(hole_node, color, &adj_start, &adj_end);
Expand Down Expand Up @@ -155,7 +141,7 @@ static void drm_mm_insert_helper(struct drm_mm_node *hole_node,
BUG_ON(node->start + node->size > adj_end);

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);
node->hole_follows = 1;
}
Expand All @@ -168,15 +154,10 @@ struct drm_mm_node *drm_mm_create_block(struct drm_mm *mm,
{
struct drm_mm_node *hole, *node;
unsigned long end = start + size;
unsigned long hole_start;
unsigned long hole_end;

list_for_each_entry(hole, &mm->hole_stack, hole_stack) {
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);

drm_mm_for_each_hole(hole, mm, hole_start, hole_end) {
if (hole_start > start || hole_end < end)
continue;

Expand Down Expand Up @@ -293,7 +274,7 @@ static void drm_mm_insert_helper_range(struct drm_mm_node *hole_node,
BUG_ON(node->start + node->size > end);

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);
node->hole_follows = 1;
}
Expand Down Expand Up @@ -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);

if (node->hole_follows) {
BUG_ON(drm_mm_hole_node_start(node)
== drm_mm_hole_node_end(node));
BUG_ON(__drm_mm_hole_node_start(node) ==
__drm_mm_hole_node_end(node));
list_del(&node->hole_stack);
} else
BUG_ON(drm_mm_hole_node_start(node)
!= drm_mm_hole_node_end(node));
BUG_ON(__drm_mm_hole_node_start(node) !=
__drm_mm_hole_node_end(node));


if (!prev_node->hole_follows) {
prev_node->hole_follows = 1;
Expand Down Expand Up @@ -421,24 +403,22 @@ struct drm_mm_node *drm_mm_search_free_generic(const struct drm_mm *mm,
{
struct drm_mm_node *entry;
struct drm_mm_node *best;
unsigned long adj_start;
unsigned long adj_end;
unsigned long best_size;

BUG_ON(mm->scanned_blocks);

best = NULL;
best_size = ~0UL;

list_for_each_entry(entry, &mm->hole_stack, hole_stack) {
unsigned long adj_start = drm_mm_hole_node_start(entry);
unsigned long adj_end = drm_mm_hole_node_end(entry);

drm_mm_for_each_hole(entry, mm, adj_start, adj_end) {
if (mm->color_adjust) {
mm->color_adjust(entry, color, &adj_start, &adj_end);
if (adj_end <= adj_start)
continue;
}

BUG_ON(!entry->hole_follows);
if (!check_free_hole(adj_start, adj_end, size, alignment))
continue;

Expand All @@ -465,20 +445,20 @@ 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 *best;
unsigned long adj_start;
unsigned long adj_end;
unsigned long best_size;

BUG_ON(mm->scanned_blocks);

best = NULL;
best_size = ~0UL;

list_for_each_entry(entry, &mm->hole_stack, hole_stack) {
unsigned long adj_start = drm_mm_hole_node_start(entry) < start ?
start : drm_mm_hole_node_start(entry);
unsigned long adj_end = drm_mm_hole_node_end(entry) > end ?
end : drm_mm_hole_node_end(entry);

BUG_ON(!entry->hole_follows);
drm_mm_for_each_hole(entry, mm, adj_start, adj_end) {
if (adj_start < start)
adj_start = start;
if (adj_end > end)
adj_end = end;

if (mm->color_adjust) {
mm->color_adjust(entry, color, &adj_start, &adj_end);
Expand Down
36 changes: 36 additions & 0 deletions include/drm/drm_mm.h
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,29 @@ static inline bool drm_mm_initialized(struct drm_mm *mm)
{
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, \
&(mm)->head_node.node_list, \
node_list)
Expand All @@ -99,6 +122,19 @@ static inline bool drm_mm_initialized(struct drm_mm *mm)
entry != NULL; entry = next, \
next = entry ? list_entry(entry->node_list.next, \
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)
*/
Expand Down

0 comments on commit 9e8944a

Please sign in to comment.