diff options
| author | Jerome Glisse <jglisse@redhat.com> | 2009-12-07 15:52:56 +0100 | 
|---|---|---|
| committer | Dave Airlie <airlied@redhat.com> | 2009-12-10 15:09:01 +1000 | 
| commit | a2e68e92d384d37c8cc6bb7206d43b1eb9bc3f08 (patch) | |
| tree | 5050cb18d00830a3f80ad650f8c16ed40953399c /drivers | |
| parent | cf2f05d30dacab32e6866347be6cbfa4030b33b7 (diff) | |
| download | olio-linux-3.10-a2e68e92d384d37c8cc6bb7206d43b1eb9bc3f08.tar.xz olio-linux-3.10-a2e68e92d384d37c8cc6bb7206d43b1eb9bc3f08.zip  | |
drm: Add search/get functions to get a block in a specific range
These are required for changes to TTM.
Signed-off-by: Jerome Glisse <jglisse@redhat.com>
Signed-off-by: Dave Airlie <airlied@redhat.com>
Diffstat (limited to 'drivers')
| -rw-r--r-- | drivers/gpu/drm/drm_mm.c | 88 | 
1 files changed, 88 insertions, 0 deletions
diff --git a/drivers/gpu/drm/drm_mm.c b/drivers/gpu/drm/drm_mm.c index 1f0d717dbad..a5c2773ccf2 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;  |