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

Commit f709a7bf authored by Santhosh Punugu's avatar Santhosh Punugu
Browse files

msm: kgsl: use seq_file for mem_entry debugfs



A process may have many kgsl mem entries in use. Outputing all of them
as a single debugfs seq_file record takes twice as long as necessary
because seq_file must retry higher order page allocations for the output
buffer until it is large enough to hold all mem entries.

Additionally, process_mem_print() currently holds the spinlock
private->mem_lock during this process. This is too much time to
disable interrupts, and prevents locking mutex in print_mem_entry.

Change the kgsl_mem_entry debugfs functions to output one entry at a
time. Then the seq_file only need to kmalloc one page regardless of
the number of kgsl_mem_entries.

CRs-Fixed: 1073673
Change-Id: I2907495b65e62d95a892741aed008048bb86aced
Signed-off-by: default avatarSanthosh Punugu <spunug@codeaurora.org>
parent 44521c71
Loading
Loading
Loading
Loading
+71 −9
Original line number Diff line number Diff line
@@ -125,7 +125,7 @@ static char get_cacheflag(const struct kgsl_memdesc *m)
}


static int print_mem_entry(int id, void *ptr, void *data)
static int print_mem_entry(void *data, void *ptr)
{
	struct seq_file *s = data;
	struct kgsl_mem_entry *entry = ptr;
@@ -160,25 +160,83 @@ static int print_mem_entry(int id, void *ptr, void *data)
	return 0;
}

static int process_mem_print(struct seq_file *s, void *unused)
static struct kgsl_mem_entry *process_mem_seq_find(struct seq_file *s,
						void *ptr, loff_t pos)
{
	struct kgsl_mem_entry *entry = ptr;
	struct kgsl_process_private *private = s->private;
	int id = 0;
	loff_t temp_pos = 1;

	seq_printf(s, "%16s %16s %16s %5s %9s %10s %16s %5s %16s\n",
		   "gpuaddr", "useraddr", "size", "id", "flags", "type",
		   "usage", "sglen", "mapsize");
	if (entry != SEQ_START_TOKEN)
		id = entry->id + 1;

	spin_lock(&private->mem_lock);
	idr_for_each(&private->mem_idr, print_mem_entry, s);
	for (entry = idr_get_next(&private->mem_idr, &id); entry;
		id++, entry = idr_get_next(&private->mem_idr, &id),
							temp_pos++) {
		if (temp_pos == pos && kgsl_mem_entry_get(entry)) {
			spin_unlock(&private->mem_lock);
			goto found;
		}
	}
	spin_unlock(&private->mem_lock);

	entry = NULL;
found:
	if (ptr != SEQ_START_TOKEN)
		kgsl_mem_entry_put(ptr);

	return entry;
}

static void *process_mem_seq_start(struct seq_file *s, loff_t *pos)
{
	loff_t seq_file_offset = *pos;

	if (seq_file_offset == 0)
		return SEQ_START_TOKEN;
	else
		return process_mem_seq_find(s, SEQ_START_TOKEN,
						seq_file_offset);
}

static void process_mem_seq_stop(struct seq_file *s, void *ptr)
{
	if (ptr && ptr != SEQ_START_TOKEN)
		kgsl_mem_entry_put(ptr);
}

static void *process_mem_seq_next(struct seq_file *s, void *ptr,
							loff_t *pos)
{
	++*pos;
	return process_mem_seq_find(s, ptr, 1);
}

static int process_mem_seq_show(struct seq_file *s, void *ptr)
{
	if (ptr == SEQ_START_TOKEN) {
		seq_printf(s, "%16s %16s %16s %5s %9s %10s %16s %5s %16s\n",
				"gpuaddr", "useraddr", "size", "id", "flags",
				"type", "usage", "sglen", "mapsize");
		return 0;
	} else
		return print_mem_entry(s, ptr);
}

static const struct seq_operations process_mem_seq_fops = {
	.start = process_mem_seq_start,
	.stop = process_mem_seq_stop,
	.next = process_mem_seq_next,
	.show = process_mem_seq_show,
};

static int process_mem_open(struct inode *inode, struct file *file)
{
	int ret;
	pid_t pid = (pid_t) (unsigned long) inode->i_private;
	struct seq_file *s = NULL;
	struct kgsl_process_private *private = NULL;

	private = kgsl_process_private_find(pid);
@@ -186,9 +244,13 @@ static int process_mem_open(struct inode *inode, struct file *file)
	if (!private)
		return -ENODEV;

	ret = single_open(file, process_mem_print, private);
	ret = seq_open(file, &process_mem_seq_fops);
	if (ret)
		kgsl_process_private_put(private);
	else {
		s = file->private_data;
		s->private = private;
	}

	return ret;
}
@@ -201,7 +263,7 @@ static int process_mem_release(struct inode *inode, struct file *file)
	if (private)
		kgsl_process_private_put(private);

	return single_release(inode, file);
	return seq_release(inode, file);
}

static const struct file_operations process_mem_fops = {