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

Commit 2c66e9f9 authored by Mitchel Humpherys's avatar Mitchel Humpherys
Browse files

gpu: ion: use a list instead of a tree for heap debug memory map



Currently we use an rb tree to store information about the memory map
which gets passed to the heap print_debug functions. The reason for
using a tree instead of a simple list is to maintain sortedness as we
build the memory map. However, it can be necessary to store multiple
entries for the same address in the memory map since there can be
multiple clients with handles to the same buffer. This information is
interesting and useful but we currently can't store and display it since
the rb tree requires that the key used for sorting (the physical address
in this case) be unique. Fix this by replacing the rb tree with a linked
list. In order to maintain sorted output of the print_debug functions,
sort the list by physical address after fully building the list.

This also has the positive side-effect of simplifying the code and
making future print_debug methods less error-prone.

CRs-Fixed: 571918
Change-Id: I5b129fd809fb53c66042eab10d096238a34c2b20
Signed-off-by: default avatarMitchel Humpherys <mitchelh@codeaurora.org>
parent 7452518e
Loading
Loading
Loading
Loading
+23 −31
Original line number Diff line number Diff line
@@ -24,6 +24,7 @@
#include <linux/ion.h>
#include <linux/kthread.h>
#include <linux/list.h>
#include <linux/list_sort.h>
#include <linux/memblock.h>
#include <linux/miscdevice.h>
#include <linux/export.h>
@@ -1446,33 +1447,15 @@ static int ion_debug_find_buffer_owner(const struct ion_client *client,
}

/**
 * Adds mem_map_data pointer to the tree of mem_map
 * Adds mem_map_data pointer to the list of mem_map
 * Used for debug output.
 * @param mem_map The mem_map tree
 * @param data The new data to add to the tree
 * @param mem_map The mem_map list
 * @param data The new data to add to the list
 */
static void ion_debug_mem_map_add(struct rb_root *mem_map,
static void ion_debug_mem_map_add(struct list_head *mem_map,
				  struct mem_map_data *data)
{
	struct rb_node **p = &mem_map->rb_node;
	struct rb_node *parent = NULL;
	struct mem_map_data *entry;

	while (*p) {
		parent = *p;
		entry = rb_entry(parent, struct mem_map_data, node);

		if (data->addr < entry->addr) {
			p = &(*p)->rb_left;
		} else if (data->addr > entry->addr) {
			p = &(*p)->rb_right;
		} else {
			pr_err("%s: mem_map_data already found.", __func__);
			BUG();
		}
	}
	rb_link_node(&data->node, parent, p);
	rb_insert_color(&data->node, mem_map);
	list_add(&data->node, mem_map);
}

/**
@@ -1504,7 +1487,7 @@ const char *ion_debug_locate_owner(const struct ion_device *dev,
 * @param mem_map The mem map to be created.
 */
void ion_debug_mem_map_create(struct seq_file *s, struct ion_heap *heap,
			      struct rb_root *mem_map)
			      struct list_head *mem_map)
{
	struct ion_device *dev = heap->dev;
	struct rb_node *n;
@@ -1539,19 +1522,27 @@ void ion_debug_mem_map_create(struct seq_file *s, struct ion_heap *heap,
 * Free the memory allocated by ion_debug_mem_map_create
 * @param mem_map The mem map to free.
 */
static void ion_debug_mem_map_destroy(struct rb_root *mem_map)
static void ion_debug_mem_map_destroy(struct list_head *mem_map)
{
	if (mem_map) {
		struct rb_node *n;
		while ((n = rb_first(mem_map)) != 0) {
			struct mem_map_data *data =
					rb_entry(n, struct mem_map_data, node);
			rb_erase(&data->node, mem_map);
		struct mem_map_data *data, *tmp;
		list_for_each_entry_safe(data, tmp, mem_map, node) {
			list_del(&data->node);
			kfree(data);
		}
	}
}

static int mem_map_cmp(void *priv, struct list_head *a, struct list_head *b)
{
	struct mem_map_data *d1, *d2;
	d1 = list_entry(a, struct mem_map_data, node);
	d2 = list_entry(b, struct mem_map_data, node);
	if (d1->addr == d2->addr)
		return d1->size - d2->size;
	return d1->addr - d2->addr;
}

/**
 * Print heap debug information.
 * @param s seq_file to log message to.
@@ -1560,8 +1551,9 @@ static void ion_debug_mem_map_destroy(struct rb_root *mem_map)
static void ion_heap_print_debug(struct seq_file *s, struct ion_heap *heap)
{
	if (heap->ops->print_debug) {
		struct rb_root mem_map = RB_ROOT;
		struct list_head mem_map = LIST_HEAD_INIT(mem_map);
		ion_debug_mem_map_create(s, heap, &mem_map);
		list_sort(NULL, &mem_map, mem_map_cmp);
		heap->ops->print_debug(heap, s, &mem_map);
		ion_debug_mem_map_destroy(&mem_map);
	}
+3 −5
Original line number Diff line number Diff line
@@ -162,7 +162,7 @@ int ion_carveout_heap_map_user(struct ion_heap *heap, struct ion_buffer *buffer,
}

static int ion_carveout_print_debug(struct ion_heap *heap, struct seq_file *s,
				    const struct rb_root *mem_map)
				    const struct list_head *mem_map)
{
	struct ion_carveout_heap *carveout_heap =
		container_of(heap, struct ion_carveout_heap, heap);
@@ -176,16 +176,14 @@ static int ion_carveout_print_debug(struct ion_heap *heap, struct seq_file *s,
		unsigned long size = carveout_heap->total_size;
		unsigned long end = base+size;
		unsigned long last_end = base;
		struct rb_node *n;
		struct mem_map_data *data;

		seq_printf(s, "\nMemory Map\n");
		seq_printf(s, "%16.s %14.s %14.s %14.s\n",
			   "client", "start address", "end address",
			   "size (hex)");

		for (n = rb_first(mem_map); n; n = rb_next(n)) {
			struct mem_map_data *data =
					rb_entry(n, struct mem_map_data, node);
		list_for_each_entry(data, mem_map, node) {
			const char *client_name = "(null)";

			if (last_end < data->addr) {
+3 −5
Original line number Diff line number Diff line
@@ -180,19 +180,17 @@ static void ion_cma_unmap_kernel(struct ion_heap *heap,
}

static int ion_cma_print_debug(struct ion_heap *heap, struct seq_file *s,
			const struct rb_root *mem_map)
			const struct list_head *mem_map)
{
	if (mem_map) {
		struct rb_node *n;
		struct mem_map_data *data;

		seq_printf(s, "\nMemory Map\n");
		seq_printf(s, "%16.s %14.s %14.s %14.s\n",
			   "client", "start address", "end address",
			   "size (hex)");

		for (n = rb_first(mem_map); n; n = rb_next(n)) {
			struct mem_map_data *data =
					rb_entry(n, struct mem_map_data, node);
		list_for_each_entry(data, mem_map, node) {
			const char *client_name = "(null)";


+3 −5
Original line number Diff line number Diff line
@@ -581,22 +581,20 @@ static void ion_secure_cma_unmap_kernel(struct ion_heap *heap,
}

static int ion_secure_cma_print_debug(struct ion_heap *heap, struct seq_file *s,
			const struct rb_root *mem_map)
			const struct list_head *mem_map)
{
	struct ion_cma_secure_heap *sheap =
		container_of(heap, struct ion_cma_secure_heap, heap);

	if (mem_map) {
		struct rb_node *n;
		struct mem_map_data *data;

		seq_printf(s, "\nMemory Map\n");
		seq_printf(s, "%16.s %14.s %14.s %14.s\n",
			   "client", "start address", "end address",
			   "size (hex)");

		for (n = rb_first(mem_map); n; n = rb_next(n)) {
			struct mem_map_data *data =
					rb_entry(n, struct mem_map_data, node);
		list_for_each_entry(data, mem_map, node) {
			const char *client_name = "(null)";


+3 −5
Original line number Diff line number Diff line
@@ -635,7 +635,7 @@ void ion_cp_heap_unmap_user(struct ion_heap *heap,
}

static int ion_cp_print_debug(struct ion_heap *heap, struct seq_file *s,
			      const struct rb_root *mem_map)
			      const struct list_head *mem_map)
{
	unsigned long total_alloc;
	unsigned long total_size;
@@ -664,16 +664,14 @@ static int ion_cp_print_debug(struct ion_heap *heap, struct seq_file *s,
		unsigned long size = cp_heap->total_size;
		unsigned long end = base+size;
		unsigned long last_end = base;
		struct rb_node *n;
		struct mem_map_data *data;

		seq_printf(s, "\nMemory Map\n");
		seq_printf(s, "%16.s %14.s %14.s %14.s\n",
			   "client", "start address", "end address",
			   "size (hex)");

		for (n = rb_first(mem_map); n; n = rb_next(n)) {
			struct mem_map_data *data =
					rb_entry(n, struct mem_map_data, node);
		list_for_each_entry(data, mem_map, node) {
			const char *client_name = "(null)";

			if (last_end < data->addr) {
Loading