Loading drivers/gpu/drm/drm_mm.c +88 −0 Original line number Diff line number Diff line Loading @@ -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. Loading Loading @@ -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; Loading include/drm/drm_mm.h +34 −0 Original line number Diff line number Diff line Loading @@ -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) Loading @@ -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); Loading Loading
drivers/gpu/drm/drm_mm.c +88 −0 Original line number Diff line number Diff line Loading @@ -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. Loading Loading @@ -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; Loading
include/drm/drm_mm.h +34 −0 Original line number Diff line number Diff line Loading @@ -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) Loading @@ -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); Loading