Jerome Glisse wrote: > Signed-off-by: Jerome Glisse <jgli...@redhat.com> > --- > drivers/gpu/drm/drm_mm.c | 88 > ++++++++++++++++++++++++++++++++++++++++++++++ > include/drm/drm_mm.h | 34 ++++++++++++++++++ > 2 files changed, 122 insertions(+), 0 deletions(-) > > diff --git a/drivers/gpu/drm/drm_mm.c b/drivers/gpu/drm/drm_mm.c > index 97dc5a4..5a06efe 100644 > --- a/drivers/gpu/drm/drm_mm.c > +++ b/drivers/gpu/drm/drm_mm.c > @@ -226,6 +226,44 @@ struct drm_mm_node *drm_mm_get_block_generic(struct > drm_mm_node *node, > } > EXPORT_SYMBOL(drm_mm_get_block_generic); > > +struct drm_mm_node *drm_mm_get_block_range_generic(struct drm_mm_node *node, > + unsigned long size, > + unsigned alignment, > + unsigned long start, > + unsigned long end, > + int atomic) > +{ > + struct drm_mm_node *align_splitoff = NULL; > + unsigned tmp = 0; > + unsigned wasted = 0; > + > + if (node->start < start) > + wasted += start - node->start; > + if (alignment) > + tmp = ((node->start + wasted) % alignment); > + > + if (tmp) > + wasted += alignment - tmp; > + if (wasted) { > + align_splitoff = drm_mm_split_at_start(node, wasted, atomic); > + if (unlikely(align_splitoff == NULL)) > + return NULL; > + } > + > + if (node->size == size) { > + list_del_init(&node->fl_entry); > + node->free = 0; > + } else { > + node = drm_mm_split_at_start(node, size, atomic); > + } > + > + if (align_splitoff) > + drm_mm_put_block(align_splitoff); > + > + return node; > +} > +EXPORT_SYMBOL(drm_mm_get_block_range_generic); > + > /* > * Put a block. Merge with the previous and / or next block if they are free. > * Otherwise add to the free stack. > @@ -331,6 +369,56 @@ struct drm_mm_node *drm_mm_search_free(const struct > drm_mm *mm, > } > EXPORT_SYMBOL(drm_mm_search_free); > > +struct drm_mm_node *drm_mm_search_free_in_range(const struct drm_mm *mm, > + unsigned long size, > + unsigned alignment, > + unsigned long start, > + unsigned long end, > + int best_match) > +{ > + struct list_head *list; > + const struct list_head *free_stack = &mm->fl_entry; > + struct drm_mm_node *entry; > + struct drm_mm_node *best; > + unsigned long best_size; > + unsigned wasted; > + > + best = NULL; > + best_size = ~0UL; > + > + list_for_each(list, free_stack) { > + entry = list_entry(list, struct drm_mm_node, fl_entry); > + wasted = 0; > + > + if (entry->size < size) > + continue; > + > + if (entry->start > end || (entry->start+entry->size) < start) > + continue; > + > + if (entry->start < start) > + wasted += start - entry->start; > + > + if (alignment) { > + register unsigned tmp = (entry->start + wasted) % > alignment; > + if (tmp) > + wasted += alignment - tmp; > + } > + > + if (entry->size >= size + wasted) { > + if (!best_match) > + return entry; > + if (size < best_size) { > + best = entry; > + best_size = entry->size; > + } > + } > + } > + > + return best; > +} > +EXPORT_SYMBOL(drm_mm_search_free_in_range); > + > int drm_mm_clean(struct drm_mm * mm) > { > struct list_head *head = &mm->ml_entry; > diff --git a/include/drm/drm_mm.h b/include/drm/drm_mm.h > index 62329f9..b40b2f0 100644 > --- a/include/drm/drm_mm.h > +++ b/include/drm/drm_mm.h > @@ -66,6 +66,13 @@ extern struct drm_mm_node *drm_mm_get_block_generic(struct > drm_mm_node *node, > unsigned long size, > unsigned alignment, > int atomic); > +extern struct drm_mm_node *drm_mm_get_block_range_generic( > + struct drm_mm_node *node, > + unsigned long size, > + unsigned alignment, > + unsigned long start, > + unsigned long end, > + int atomic); > static inline struct drm_mm_node *drm_mm_get_block(struct drm_mm_node > *parent, > unsigned long size, > unsigned alignment) > @@ -78,11 +85,38 @@ static inline struct drm_mm_node > *drm_mm_get_block_atomic(struct drm_mm_node *pa > { > return drm_mm_get_block_generic(parent, size, alignment, 1); > } > +static inline struct drm_mm_node *drm_mm_get_block_range( > + struct drm_mm_node *parent, > + unsigned long size, > + unsigned alignment, > + unsigned long start, > + unsigned long end) > +{ > + return drm_mm_get_block_range_generic(parent, size, alignment, > + start, end, 0); > +} > +static inline struct drm_mm_node *drm_mm_get_block_atomic_range( > + struct drm_mm_node *parent, > + unsigned long size, > + unsigned alignment, > + unsigned long start, > + unsigned long end) > +{ > + return drm_mm_get_block_range_generic(parent, size, alignment, > + start, end, 1); > +} > extern void drm_mm_put_block(struct drm_mm_node *cur); > extern struct drm_mm_node *drm_mm_search_free(const struct drm_mm *mm, > unsigned long size, > unsigned alignment, > int best_match); > +extern struct drm_mm_node *drm_mm_search_free_in_range( > + const struct drm_mm *mm, > + unsigned long size, > + unsigned alignment, > + unsigned long start, > + unsigned long end, > + int best_match); > extern int drm_mm_init(struct drm_mm *mm, unsigned long start, > unsigned long size); > extern void drm_mm_takedown(struct drm_mm *mm); > Acked-By: Thomas Hellstrom <thellst...@vmware.com>
/Thomas ------------------------------------------------------------------------------ Join us December 9, 2009 for the Red Hat Virtual Experience, a free event focused on virtualization and cloud computing. Attend in-depth sessions from your desk. Your couch. Anywhere. http://p.sf.net/sfu/redhat-sfdev2dev -- _______________________________________________ Dri-devel mailing list Dri-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/dri-devel