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

Commit 63871f89 authored by Dave Airlie's avatar Dave Airlie
Browse files

Merge branch 'drm-mm-cleanup' into drm-next

* drm-mm-cleanup:
  radeon: move blit functions to radeon_asic.h
  radeon: kill decls for inline functions
  radeon: consolidate asic-specific function decls for r600 & later
  drm/radeon: kill radeon_bo->gobj pointer
  drm/radeon: introduce gem_to_radeon_bo helper
  drm/radeon: embed struct drm_gem_object
  drm: mm: add helper to unwind scan state
  drm: mm: add api for embedding struct drm_mm_node
  drm: mm: extract node insert helper functions
  drm: mm: track free areas implicitly
  drm/nouveau: don't munge in drm_mm internals
parents de1e7cd6 4546b2c1
Loading
Loading
Loading
Loading
+314 −256
Original line number Diff line number Diff line
@@ -64,8 +64,8 @@ static struct drm_mm_node *drm_mm_kmalloc(struct drm_mm *mm, int atomic)
		else {
			child =
			    list_entry(mm->unused_nodes.next,
				       struct drm_mm_node, free_stack);
			list_del(&child->free_stack);
				       struct drm_mm_node, node_list);
			list_del(&child->node_list);
			--mm->num_unused;
		}
		spin_unlock(&mm->unused_lock);
@@ -94,195 +94,242 @@ int drm_mm_pre_get(struct drm_mm *mm)
			return ret;
		}
		++mm->num_unused;
		list_add_tail(&node->free_stack, &mm->unused_nodes);
		list_add_tail(&node->node_list, &mm->unused_nodes);
	}
	spin_unlock(&mm->unused_lock);
	return 0;
}
EXPORT_SYMBOL(drm_mm_pre_get);

static int drm_mm_create_tail_node(struct drm_mm *mm,
				   unsigned long start,
				   unsigned long size, int atomic)
static inline unsigned long drm_mm_hole_node_start(struct drm_mm_node *hole_node)
{
	struct drm_mm_node *child;
	return hole_node->start + hole_node->size;
}

	child = drm_mm_kmalloc(mm, atomic);
	if (unlikely(child == NULL))
		return -ENOMEM;
static inline unsigned long drm_mm_hole_node_end(struct drm_mm_node *hole_node)
{
	struct drm_mm_node *next_node =
		list_entry(hole_node->node_list.next, struct drm_mm_node,
			   node_list);

	child->free = 1;
	child->size = size;
	child->start = start;
	child->mm = mm;
	return next_node->start;
}

	list_add_tail(&child->node_list, &mm->node_list);
	list_add_tail(&child->free_stack, &mm->free_stack);
static void drm_mm_insert_helper(struct drm_mm_node *hole_node,
				 struct drm_mm_node *node,
				 unsigned long size, unsigned alignment)
{
	struct drm_mm *mm = hole_node->mm;
	unsigned long tmp = 0, wasted = 0;
	unsigned long hole_start = drm_mm_hole_node_start(hole_node);
	unsigned long hole_end = drm_mm_hole_node_end(hole_node);

	return 0;
	BUG_ON(!hole_node->hole_follows || node->allocated);

	if (alignment)
		tmp = hole_start % alignment;

	if (!tmp) {
		hole_node->hole_follows = 0;
		list_del_init(&hole_node->hole_stack);
	} else
		wasted = alignment - tmp;

	node->start = hole_start + wasted;
	node->size = size;
	node->mm = mm;
	node->allocated = 1;

	INIT_LIST_HEAD(&node->hole_stack);
	list_add(&node->node_list, &hole_node->node_list);

	BUG_ON(node->start + node->size > hole_end);

	if (node->start + node->size < hole_end) {
		list_add(&node->hole_stack, &mm->hole_stack);
		node->hole_follows = 1;
	} else {
		node->hole_follows = 0;
	}
}

static struct drm_mm_node *drm_mm_split_at_start(struct drm_mm_node *parent,
struct drm_mm_node *drm_mm_get_block_generic(struct drm_mm_node *hole_node,
					     unsigned long size,
					     unsigned alignment,
					     int atomic)
{
	struct drm_mm_node *child;
	struct drm_mm_node *node;

	child = drm_mm_kmalloc(parent->mm, atomic);
	if (unlikely(child == NULL))
	node = drm_mm_kmalloc(hole_node->mm, atomic);
	if (unlikely(node == NULL))
		return NULL;

	INIT_LIST_HEAD(&child->free_stack);
	drm_mm_insert_helper(hole_node, node, size, alignment);

	child->size = size;
	child->start = parent->start;
	child->mm = parent->mm;
	return node;
}
EXPORT_SYMBOL(drm_mm_get_block_generic);

	list_add_tail(&child->node_list, &parent->node_list);
	INIT_LIST_HEAD(&child->free_stack);
/**
 * Search for free space and insert a preallocated memory node. Returns
 * -ENOSPC if no suitable free area is available. The preallocated memory node
 * must be cleared.
 */
int drm_mm_insert_node(struct drm_mm *mm, struct drm_mm_node *node,
		       unsigned long size, unsigned alignment)
{
	struct drm_mm_node *hole_node;

	parent->size -= size;
	parent->start += size;
	return child;
}
	hole_node = drm_mm_search_free(mm, size, alignment, 0);
	if (!hole_node)
		return -ENOSPC;

	drm_mm_insert_helper(hole_node, node, size, alignment);

struct drm_mm_node *drm_mm_get_block_generic(struct drm_mm_node *node,
					     unsigned long size,
					     unsigned alignment,
					     int atomic)
	return 0;
}
EXPORT_SYMBOL(drm_mm_insert_node);

static void drm_mm_insert_helper_range(struct drm_mm_node *hole_node,
				       struct drm_mm_node *node,
				       unsigned long size, unsigned alignment,
				       unsigned long start, unsigned long end)
{
	struct drm_mm *mm = hole_node->mm;
	unsigned long tmp = 0, wasted = 0;
	unsigned long hole_start = drm_mm_hole_node_start(hole_node);
	unsigned long hole_end = drm_mm_hole_node_end(hole_node);

	struct drm_mm_node *align_splitoff = NULL;
	unsigned tmp = 0;
	BUG_ON(!hole_node->hole_follows || node->allocated);

	if (hole_start < start)
		wasted += start - hole_start;
	if (alignment)
		tmp = node->start % alignment;
		tmp = (hole_start + wasted) % alignment;

	if (tmp) {
		align_splitoff =
		    drm_mm_split_at_start(node, alignment - tmp, atomic);
		if (unlikely(align_splitoff == NULL))
			return NULL;
	}
	if (tmp)
		wasted += alignment - tmp;

	if (node->size == size) {
		list_del_init(&node->free_stack);
		node->free = 0;
	} else {
		node = drm_mm_split_at_start(node, size, atomic);
	if (!wasted) {
		hole_node->hole_follows = 0;
		list_del_init(&hole_node->hole_stack);
	}

	if (align_splitoff)
		drm_mm_put_block(align_splitoff);
	node->start = hole_start + wasted;
	node->size = size;
	node->mm = mm;
	node->allocated = 1;

	return node;
	INIT_LIST_HEAD(&node->hole_stack);
	list_add(&node->node_list, &hole_node->node_list);

	BUG_ON(node->start + node->size > hole_end);
	BUG_ON(node->start + node->size > end);

	if (node->start + node->size < hole_end) {
		list_add(&node->hole_stack, &mm->hole_stack);
		node->hole_follows = 1;
	} else {
		node->hole_follows = 0;
	}
}
EXPORT_SYMBOL(drm_mm_get_block_generic);

struct drm_mm_node *drm_mm_get_block_range_generic(struct drm_mm_node *node,
struct drm_mm_node *drm_mm_get_block_range_generic(struct drm_mm_node *hole_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);
	struct drm_mm_node *node;

	if (tmp)
		wasted += alignment - tmp;
	if (wasted) {
		align_splitoff = drm_mm_split_at_start(node, wasted, atomic);
		if (unlikely(align_splitoff == NULL))
	node = drm_mm_kmalloc(hole_node->mm, atomic);
	if (unlikely(node == NULL))
		return NULL;
	}

	if (node->size == size) {
		list_del_init(&node->free_stack);
		node->free = 0;
	} else {
		node = drm_mm_split_at_start(node, size, atomic);
	}

	if (align_splitoff)
		drm_mm_put_block(align_splitoff);
	drm_mm_insert_helper_range(hole_node, node, size, alignment,
				   start, end);

	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.
/**
 * Search for free space and insert a preallocated memory node. Returns
 * -ENOSPC if no suitable free area is available. This is for range
 * restricted allocations. The preallocated memory node must be cleared.
 */

void drm_mm_put_block(struct drm_mm_node *cur)
int drm_mm_insert_node_in_range(struct drm_mm *mm, struct drm_mm_node *node,
				unsigned long size, unsigned alignment,
				unsigned long start, unsigned long end)
{
	struct drm_mm_node *hole_node;

	struct drm_mm *mm = cur->mm;
	struct list_head *cur_head = &cur->node_list;
	struct list_head *root_head = &mm->node_list;
	struct drm_mm_node *prev_node = NULL;
	struct drm_mm_node *next_node;
	hole_node = drm_mm_search_free_in_range(mm, size, alignment,
						start, end, 0);
	if (!hole_node)
		return -ENOSPC;

	int merged = 0;
	drm_mm_insert_helper_range(hole_node, node, size, alignment,
				   start, end);

	return 0;
}
EXPORT_SYMBOL(drm_mm_insert_node_in_range);

/**
 * Remove a memory node from the allocator.
 */
void drm_mm_remove_node(struct drm_mm_node *node)
{
	struct drm_mm *mm = node->mm;
	struct drm_mm_node *prev_node;

	BUG_ON(cur->scanned_block || cur->scanned_prev_free
				  || cur->scanned_next_free);
	BUG_ON(node->scanned_block || node->scanned_prev_free
				   || node->scanned_next_free);

	if (cur_head->prev != root_head) {
	prev_node =
		    list_entry(cur_head->prev, struct drm_mm_node, node_list);
		if (prev_node->free) {
			prev_node->size += cur->size;
			merged = 1;
		}
	}
	if (cur_head->next != root_head) {
		next_node =
		    list_entry(cur_head->next, struct drm_mm_node, node_list);
		if (next_node->free) {
			if (merged) {
				prev_node->size += next_node->size;
				list_del(&next_node->node_list);
				list_del(&next_node->free_stack);
				spin_lock(&mm->unused_lock);
				if (mm->num_unused < MM_UNUSED_TARGET) {
					list_add(&next_node->free_stack,
						 &mm->unused_nodes);
					++mm->num_unused;
	    list_entry(node->node_list.prev, struct drm_mm_node, node_list);

	if (node->hole_follows) {
		BUG_ON(drm_mm_hole_node_start(node)
				== drm_mm_hole_node_end(node));
		list_del(&node->hole_stack);
	} else
					kfree(next_node);
				spin_unlock(&mm->unused_lock);
			} else {
				next_node->size += cur->size;
				next_node->start = cur->start;
				merged = 1;
			}
		}
		BUG_ON(drm_mm_hole_node_start(node)
				!= drm_mm_hole_node_end(node));

	if (!prev_node->hole_follows) {
		prev_node->hole_follows = 1;
		list_add(&prev_node->hole_stack, &mm->hole_stack);
	} else
		list_move(&prev_node->hole_stack, &mm->hole_stack);

	list_del(&node->node_list);
	node->allocated = 0;
}
	if (!merged) {
		cur->free = 1;
		list_add(&cur->free_stack, &mm->free_stack);
	} else {
		list_del(&cur->node_list);
EXPORT_SYMBOL(drm_mm_remove_node);

/*
 * Remove a memory node from the allocator and free the allocated struct
 * drm_mm_node. Only to be used on a struct drm_mm_node obtained by one of the
 * drm_mm_get_block functions.
 */
void drm_mm_put_block(struct drm_mm_node *node)
{

	struct drm_mm *mm = node->mm;

	drm_mm_remove_node(node);

	spin_lock(&mm->unused_lock);
	if (mm->num_unused < MM_UNUSED_TARGET) {
			list_add(&cur->free_stack, &mm->unused_nodes);
		list_add(&node->node_list, &mm->unused_nodes);
		++mm->num_unused;
	} else
			kfree(cur);
		kfree(node);
	spin_unlock(&mm->unused_lock);
}
}

EXPORT_SYMBOL(drm_mm_put_block);

static int check_free_hole(unsigned long start, unsigned long end,
@@ -319,8 +366,10 @@ struct drm_mm_node *drm_mm_search_free(const struct drm_mm *mm,
	best = NULL;
	best_size = ~0UL;

	list_for_each_entry(entry, &mm->free_stack, free_stack) {
		if (!check_free_hole(entry->start, entry->start + entry->size,
	list_for_each_entry(entry, &mm->hole_stack, hole_stack) {
		BUG_ON(!entry->hole_follows);
		if (!check_free_hole(drm_mm_hole_node_start(entry),
				     drm_mm_hole_node_end(entry),
				     size, alignment))
			continue;

@@ -353,12 +402,13 @@ struct drm_mm_node *drm_mm_search_free_in_range(const struct drm_mm *mm,
	best = NULL;
	best_size = ~0UL;

	list_for_each_entry(entry, &mm->free_stack, free_stack) {
		unsigned long adj_start = entry->start < start ?
			start : entry->start;
		unsigned long adj_end = entry->start + entry->size > end ?
			end : entry->start + entry->size;
	list_for_each_entry(entry, &mm->hole_stack, hole_stack) {
		unsigned long adj_start = drm_mm_hole_node_start(entry) < start ?
			start : drm_mm_hole_node_start(entry);
		unsigned long adj_end = drm_mm_hole_node_end(entry) > end ?
			end : drm_mm_hole_node_end(entry);

		BUG_ON(!entry->hole_follows);
		if (!check_free_hole(adj_start, adj_end, size, alignment))
			continue;

@@ -375,6 +425,23 @@ struct drm_mm_node *drm_mm_search_free_in_range(const struct drm_mm *mm,
}
EXPORT_SYMBOL(drm_mm_search_free_in_range);

/**
 * Moves an allocation. To be used with embedded struct drm_mm_node.
 */
void drm_mm_replace_node(struct drm_mm_node *old, struct drm_mm_node *new)
{
	list_replace(&old->node_list, &new->node_list);
	list_replace(&old->node_list, &new->hole_stack);
	new->hole_follows = old->hole_follows;
	new->mm = old->mm;
	new->start = old->start;
	new->size = old->size;

	old->allocated = 0;
	new->allocated = 1;
}
EXPORT_SYMBOL(drm_mm_replace_node);

/**
 * Initializa lru scanning.
 *
@@ -393,6 +460,7 @@ void drm_mm_init_scan(struct drm_mm *mm, unsigned long size,
	mm->scan_hit_start = 0;
	mm->scan_hit_size = 0;
	mm->scan_check_range = 0;
	mm->prev_scanned_node = NULL;
}
EXPORT_SYMBOL(drm_mm_init_scan);

@@ -418,6 +486,7 @@ void drm_mm_init_scan_with_range(struct drm_mm *mm, unsigned long size,
	mm->scan_start = start;
	mm->scan_end = end;
	mm->scan_check_range = 1;
	mm->prev_scanned_node = NULL;
}
EXPORT_SYMBOL(drm_mm_init_scan_with_range);

@@ -430,70 +499,42 @@ EXPORT_SYMBOL(drm_mm_init_scan_with_range);
int drm_mm_scan_add_block(struct drm_mm_node *node)
{
	struct drm_mm *mm = node->mm;
	struct list_head *prev_free, *next_free;
	struct drm_mm_node *prev_node, *next_node;
	struct drm_mm_node *prev_node;
	unsigned long hole_start, hole_end;
	unsigned long adj_start;
	unsigned long adj_end;

	mm->scanned_blocks++;

	prev_free = next_free = NULL;

	BUG_ON(node->free);
	BUG_ON(node->scanned_block);
	node->scanned_block = 1;
	node->free = 1;

	if (node->node_list.prev != &mm->node_list) {
	prev_node = list_entry(node->node_list.prev, struct drm_mm_node,
			       node_list);

		if (prev_node->free) {
			list_del(&prev_node->node_list);

			node->start = prev_node->start;
			node->size += prev_node->size;

			prev_node->scanned_prev_free = 1;

			prev_free = &prev_node->free_stack;
		}
	}

	if (node->node_list.next != &mm->node_list) {
		next_node = list_entry(node->node_list.next, struct drm_mm_node,
				       node_list);

		if (next_node->free) {
			list_del(&next_node->node_list);

			node->size += next_node->size;

			next_node->scanned_next_free = 1;

			next_free = &next_node->free_stack;
		}
	}

	/* The free_stack list is not used for allocated objects, so these two
	 * pointers can be abused (as long as no allocations in this memory
	 * manager happens). */
	node->free_stack.prev = prev_free;
	node->free_stack.next = next_free;
	node->scanned_preceeds_hole = prev_node->hole_follows;
	prev_node->hole_follows = 1;
	list_del(&node->node_list);
	node->node_list.prev = &prev_node->node_list;
	node->node_list.next = &mm->prev_scanned_node->node_list;
	mm->prev_scanned_node = node;

	hole_start = drm_mm_hole_node_start(prev_node);
	hole_end = drm_mm_hole_node_end(prev_node);
	if (mm->scan_check_range) {
		adj_start = node->start < mm->scan_start ?
			mm->scan_start : node->start;
		adj_end = node->start + node->size > mm->scan_end ?
			mm->scan_end : node->start + node->size;
		adj_start = hole_start < mm->scan_start ?
			mm->scan_start : hole_start;
		adj_end = hole_end > mm->scan_end ?
			mm->scan_end : hole_end;
	} else {
		adj_start = node->start;
		adj_end = node->start + node->size;
		adj_start = hole_start;
		adj_end = hole_end;
	}

	if (check_free_hole(adj_start , adj_end,
			    mm->scan_size, mm->scan_alignment)) {
		mm->scan_hit_start = node->start;
		mm->scan_hit_size = node->size;
		mm->scan_hit_start = hole_start;
		mm->scan_hit_size = hole_end;

		return 1;
	}
@@ -519,39 +560,19 @@ EXPORT_SYMBOL(drm_mm_scan_add_block);
int drm_mm_scan_remove_block(struct drm_mm_node *node)
{
	struct drm_mm *mm = node->mm;
	struct drm_mm_node *prev_node, *next_node;
	struct drm_mm_node *prev_node;

	mm->scanned_blocks--;

	BUG_ON(!node->scanned_block);
	node->scanned_block = 0;
	node->free = 0;

	prev_node = list_entry(node->free_stack.prev, struct drm_mm_node,
			       free_stack);
	next_node = list_entry(node->free_stack.next, struct drm_mm_node,
			       free_stack);

	if (prev_node) {
		BUG_ON(!prev_node->scanned_prev_free);
		prev_node->scanned_prev_free = 0;

		list_add_tail(&prev_node->node_list, &node->node_list);

		node->start = prev_node->start + prev_node->size;
		node->size -= prev_node->size;
	}

	if (next_node) {
		BUG_ON(!next_node->scanned_next_free);
		next_node->scanned_next_free = 0;

		list_add(&next_node->node_list, &node->node_list);

		node->size -= next_node->size;
	}
	prev_node = list_entry(node->node_list.prev, struct drm_mm_node,
			       node_list);

	INIT_LIST_HEAD(&node->free_stack);
	prev_node->hole_follows = node->scanned_preceeds_hole;
	INIT_LIST_HEAD(&node->node_list);
	list_add(&node->node_list, &prev_node->node_list);

	/* Only need to check for containement because start&size for the
	 * complete resulting free block (not just the desired part) is
@@ -568,7 +589,7 @@ EXPORT_SYMBOL(drm_mm_scan_remove_block);

int drm_mm_clean(struct drm_mm * mm)
{
	struct list_head *head = &mm->node_list;
	struct list_head *head = &mm->head_node.node_list;

	return (head->next->next == head);
}
@@ -576,38 +597,40 @@ EXPORT_SYMBOL(drm_mm_clean);

int drm_mm_init(struct drm_mm * mm, unsigned long start, unsigned long size)
{
	INIT_LIST_HEAD(&mm->node_list);
	INIT_LIST_HEAD(&mm->free_stack);
	INIT_LIST_HEAD(&mm->hole_stack);
	INIT_LIST_HEAD(&mm->unused_nodes);
	mm->num_unused = 0;
	mm->scanned_blocks = 0;
	spin_lock_init(&mm->unused_lock);

	return drm_mm_create_tail_node(mm, start, size, 0);
	/* Clever trick to avoid a special case in the free hole tracking. */
	INIT_LIST_HEAD(&mm->head_node.node_list);
	INIT_LIST_HEAD(&mm->head_node.hole_stack);
	mm->head_node.hole_follows = 1;
	mm->head_node.scanned_block = 0;
	mm->head_node.scanned_prev_free = 0;
	mm->head_node.scanned_next_free = 0;
	mm->head_node.mm = mm;
	mm->head_node.start = start + size;
	mm->head_node.size = start - mm->head_node.start;
	list_add_tail(&mm->head_node.hole_stack, &mm->hole_stack);

	return 0;
}
EXPORT_SYMBOL(drm_mm_init);

void drm_mm_takedown(struct drm_mm * mm)
{
	struct list_head *bnode = mm->free_stack.next;
	struct drm_mm_node *entry;
	struct drm_mm_node *next;
	struct drm_mm_node *entry, *next;

	entry = list_entry(bnode, struct drm_mm_node, free_stack);

	if (entry->node_list.next != &mm->node_list ||
	    entry->free_stack.next != &mm->free_stack) {
	if (!list_empty(&mm->head_node.node_list)) {
		DRM_ERROR("Memory manager not clean. Delaying takedown\n");
		return;
	}

	list_del(&entry->free_stack);
	list_del(&entry->node_list);
	kfree(entry);

	spin_lock(&mm->unused_lock);
	list_for_each_entry_safe(entry, next, &mm->unused_nodes, free_stack) {
		list_del(&entry->free_stack);
	list_for_each_entry_safe(entry, next, &mm->unused_nodes, node_list) {
		list_del(&entry->node_list);
		kfree(entry);
		--mm->num_unused;
	}
@@ -620,19 +643,37 @@ EXPORT_SYMBOL(drm_mm_takedown);
void drm_mm_debug_table(struct drm_mm *mm, const char *prefix)
{
	struct drm_mm_node *entry;
	int total_used = 0, total_free = 0, total = 0;

	list_for_each_entry(entry, &mm->node_list, node_list) {
		printk(KERN_DEBUG "%s 0x%08lx-0x%08lx: %8ld: %s\n",
	unsigned long total_used = 0, total_free = 0, total = 0;
	unsigned long hole_start, hole_end, hole_size;

	hole_start = drm_mm_hole_node_start(&mm->head_node);
	hole_end = drm_mm_hole_node_end(&mm->head_node);
	hole_size = hole_end - hole_start;
	if (hole_size)
		printk(KERN_DEBUG "%s 0x%08lx-0x%08lx: %8lu: free\n",
			prefix, hole_start, hole_end,
			hole_size);
	total_free += hole_size;

	drm_mm_for_each_node(entry, mm) {
		printk(KERN_DEBUG "%s 0x%08lx-0x%08lx: %8lu: used\n",
			prefix, entry->start, entry->start + entry->size,
			entry->size, entry->free ? "free" : "used");
		total += entry->size;
		if (entry->free)
			total_free += entry->size;
		else
			entry->size);
		total_used += entry->size;

		if (entry->hole_follows) {
			hole_start = drm_mm_hole_node_start(entry);
			hole_end = drm_mm_hole_node_end(entry);
			hole_size = hole_end - hole_start;
			printk(KERN_DEBUG "%s 0x%08lx-0x%08lx: %8lu: free\n",
				prefix, hole_start, hole_end,
				hole_size);
			total_free += hole_size;
		}
	printk(KERN_DEBUG "%s total: %d, used %d free %d\n", prefix, total,
	}
	total = total_free + total_used;

	printk(KERN_DEBUG "%s total: %lu, used %lu free %lu\n", prefix, total,
		total_used, total_free);
}
EXPORT_SYMBOL(drm_mm_debug_table);
@@ -641,17 +682,34 @@ EXPORT_SYMBOL(drm_mm_debug_table);
int drm_mm_dump_table(struct seq_file *m, struct drm_mm *mm)
{
	struct drm_mm_node *entry;
	int total_used = 0, total_free = 0, total = 0;

	list_for_each_entry(entry, &mm->node_list, node_list) {
		seq_printf(m, "0x%08lx-0x%08lx: 0x%08lx: %s\n", entry->start, entry->start + entry->size, entry->size, entry->free ? "free" : "used");
		total += entry->size;
		if (entry->free)
			total_free += entry->size;
		else
	unsigned long total_used = 0, total_free = 0, total = 0;
	unsigned long hole_start, hole_end, hole_size;

	hole_start = drm_mm_hole_node_start(&mm->head_node);
	hole_end = drm_mm_hole_node_end(&mm->head_node);
	hole_size = hole_end - hole_start;
	if (hole_size)
		seq_printf(m, "0x%08lx-0x%08lx: 0x%08lx: free\n",
				hole_start, hole_end, hole_size);
	total_free += hole_size;

	drm_mm_for_each_node(entry, mm) {
		seq_printf(m, "0x%08lx-0x%08lx: 0x%08lx: used\n",
				entry->start, entry->start + entry->size,
				entry->size);
		total_used += entry->size;
		if (entry->hole_follows) {
			hole_start = drm_mm_hole_node_start(&mm->head_node);
			hole_end = drm_mm_hole_node_end(&mm->head_node);
			hole_size = hole_end - hole_start;
			seq_printf(m, "0x%08lx-0x%08lx: 0x%08lx: free\n",
					hole_start, hole_end, hole_size);
			total_free += hole_size;
		}
	seq_printf(m, "total: %d, used %d free %d\n", total, total_used, total_free);
	}
	total = total_free + total_used;

	seq_printf(m, "total: %lu, used %lu free %lu\n", total, total_used, total_free);
	return 0;
}
EXPORT_SYMBOL(drm_mm_dump_table);
+1 −1
Original line number Diff line number Diff line
@@ -909,7 +909,7 @@ nouveau_gpuobj_channel_takedown(struct nouveau_channel *chan)
	nouveau_vm_ref(NULL, &chan->vm, chan->vm_pd);
	nouveau_gpuobj_ref(NULL, &chan->vm_pd);

	if (chan->ramin_heap.free_stack.next)
	if (drm_mm_initialized(&chan->ramin_heap))
		drm_mm_takedown(&chan->ramin_heap);
	nouveau_gpuobj_ref(NULL, &chan->ramin);
}
+2 −2
Original line number Diff line number Diff line
@@ -56,7 +56,7 @@ nv50_channel_del(struct nouveau_channel **pchan)
	nouveau_gpuobj_ref(NULL, &chan->ramfc);
	nouveau_vm_ref(NULL, &chan->vm, chan->vm_pd);
	nouveau_gpuobj_ref(NULL, &chan->vm_pd);
	if (chan->ramin_heap.free_stack.next)
	if (drm_mm_initialized(&chan->ramin_heap))
		drm_mm_takedown(&chan->ramin_heap);
	nouveau_gpuobj_ref(NULL, &chan->ramin);
	kfree(chan);
@@ -259,7 +259,7 @@ nv50_instmem_takedown(struct drm_device *dev)
	nouveau_gpuobj_ref(NULL, &dev_priv->bar3_vm->pgt[0].obj[0]);
	nouveau_vm_ref(NULL, &dev_priv->bar3_vm, NULL);

	if (dev_priv->ramin_heap.free_stack.next)
	if (drm_mm_initialized(&dev_priv->ramin_heap))
		drm_mm_takedown(&dev_priv->ramin_heap);

	dev_priv->engine.instmem.priv = NULL;
+1 −1
Original line number Diff line number Diff line
@@ -67,7 +67,7 @@ nvc0_channel_del(struct nouveau_channel **pchan)
		return;

	nouveau_vm_ref(NULL, &chan->vm, NULL);
	if (chan->ramin_heap.free_stack.next)
	if (drm_mm_initialized(&chan->ramin_heap))
		drm_mm_takedown(&chan->ramin_heap);
	nouveau_gpuobj_ref(NULL, &chan->ramin);
	kfree(chan);
+4 −4
Original line number Diff line number Diff line
@@ -1030,7 +1030,7 @@ static int evergreen_crtc_do_set_base(struct drm_crtc *crtc,
	 * just update base pointers
	 */
	obj = radeon_fb->obj;
	rbo = obj->driver_private;
	rbo = gem_to_radeon_bo(obj);
	r = radeon_bo_reserve(rbo, false);
	if (unlikely(r != 0))
		return r;
@@ -1145,7 +1145,7 @@ static int evergreen_crtc_do_set_base(struct drm_crtc *crtc,

	if (!atomic && fb && fb != crtc->fb) {
		radeon_fb = to_radeon_framebuffer(fb);
		rbo = radeon_fb->obj->driver_private;
		rbo = gem_to_radeon_bo(radeon_fb->obj);
		r = radeon_bo_reserve(rbo, false);
		if (unlikely(r != 0))
			return r;
@@ -1191,7 +1191,7 @@ static int avivo_crtc_do_set_base(struct drm_crtc *crtc,
	}

	obj = radeon_fb->obj;
	rbo = obj->driver_private;
	rbo = gem_to_radeon_bo(obj);
	r = radeon_bo_reserve(rbo, false);
	if (unlikely(r != 0))
		return r;
@@ -1308,7 +1308,7 @@ static int avivo_crtc_do_set_base(struct drm_crtc *crtc,

	if (!atomic && fb && fb != crtc->fb) {
		radeon_fb = to_radeon_framebuffer(fb);
		rbo = radeon_fb->obj->driver_private;
		rbo = gem_to_radeon_bo(radeon_fb->obj);
		r = radeon_bo_reserve(rbo, false);
		if (unlikely(r != 0))
			return r;
Loading