diff options
author | Daniel Vetter <daniel.vetter@ffwll.ch> | 2011-02-18 11:59:12 -0500 |
---|---|---|
committer | Dave Airlie <airlied@redhat.com> | 2011-02-22 19:32:34 -0500 |
commit | ea7b1dd44867e9cd6bac67e7c9fc3f128b5b255c (patch) | |
tree | 2feb9852ab18e2f726136ae460e414ef40425129 /include/drm | |
parent | 31a5b8ce8f3bf20799eb68da9602de2bee58fdd3 (diff) |
drm: mm: track free areas implicitly
The idea is to track free holes implicitly by marking the allocation
immediatly preceeding a hole.
To avoid an ugly corner case add a dummy head_node to struct drm_mm
to track the hole that spans to complete allocation area when the
memory manager is empty.
To guarantee that there's always a preceeding/following node (that might
be marked as hole_follows == 1), move the mm->node_list list_head to the
head_node.
The main allocator and fair-lru scan code actually becomes simpler.
Only the debug code slightly suffers because free areas are no longer
explicit.
Also add drm_mm_for_each_node (which will be much more useful when
struct drm_mm_node is embeddable).
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
Signed-off-by: Dave Airlie <airlied@redhat.com>
Diffstat (limited to 'include/drm')
-rw-r--r-- | include/drm/drm_mm.h | 21 |
1 files changed, 12 insertions, 9 deletions
diff --git a/include/drm/drm_mm.h b/include/drm/drm_mm.h index 0d791462f7b2..34fa36f2de70 100644 --- a/include/drm/drm_mm.h +++ b/include/drm/drm_mm.h | |||
@@ -42,23 +42,24 @@ | |||
42 | #endif | 42 | #endif |
43 | 43 | ||
44 | struct drm_mm_node { | 44 | struct drm_mm_node { |
45 | struct list_head free_stack; | ||
46 | struct list_head node_list; | 45 | struct list_head node_list; |
47 | unsigned free : 1; | 46 | struct list_head hole_stack; |
47 | unsigned hole_follows : 1; | ||
48 | unsigned scanned_block : 1; | 48 | unsigned scanned_block : 1; |
49 | unsigned scanned_prev_free : 1; | 49 | unsigned scanned_prev_free : 1; |
50 | unsigned scanned_next_free : 1; | 50 | unsigned scanned_next_free : 1; |
51 | unsigned scanned_preceeds_hole : 1; | ||
51 | unsigned long start; | 52 | unsigned long start; |
52 | unsigned long size; | 53 | unsigned long size; |
53 | struct drm_mm *mm; | 54 | struct drm_mm *mm; |
54 | }; | 55 | }; |
55 | 56 | ||
56 | struct drm_mm { | 57 | struct drm_mm { |
57 | /* List of free memory blocks, most recently freed ordered. */ | 58 | /* List of all memory nodes that immediatly preceed a free hole. */ |
58 | struct list_head free_stack; | 59 | struct list_head hole_stack; |
59 | /* List of all memory nodes, ordered according to the (increasing) start | 60 | /* head_node.node_list is the list of all memory nodes, ordered |
60 | * address of the memory node. */ | 61 | * according to the (increasing) start address of the memory node. */ |
61 | struct list_head node_list; | 62 | struct drm_mm_node head_node; |
62 | struct list_head unused_nodes; | 63 | struct list_head unused_nodes; |
63 | int num_unused; | 64 | int num_unused; |
64 | spinlock_t unused_lock; | 65 | spinlock_t unused_lock; |
@@ -74,9 +75,11 @@ struct drm_mm { | |||
74 | 75 | ||
75 | static inline bool drm_mm_initialized(struct drm_mm *mm) | 76 | static inline bool drm_mm_initialized(struct drm_mm *mm) |
76 | { | 77 | { |
77 | return mm->free_stack.next; | 78 | return mm->hole_stack.next; |
78 | } | 79 | } |
79 | 80 | #define drm_mm_for_each_node(entry, mm) list_for_each_entry(entry, \ | |
81 | &(mm)->head_node.node_list, \ | ||
82 | node_list); | ||
80 | /* | 83 | /* |
81 | * Basic range manager support (drm_mm.c) | 84 | * Basic range manager support (drm_mm.c) |
82 | */ | 85 | */ |