Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit a2e68e92 authored by Jerome Glisse's avatar Jerome Glisse Committed by Dave Airlie
Browse files

drm: Add search/get functions to get a block in a specific range



These are required for changes to TTM.

Signed-off-by: default avatarJerome Glisse <jglisse@redhat.com>
Signed-off-by: default avatarDave Airlie <airlied@redhat.com>
parent cf2f05d3
Loading
Loading
Loading
Loading
+88 −0
Original line number Diff line number Diff line
@@ -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;
+34 −0
Original line number Diff line number Diff line
@@ -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);