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

Reply via email to