xref: /openbmc/linux/drivers/gpu/host1x/debug.c (revision 9a87ffc99ec8eb8d35eed7c4f816d75f5cc9662e)
19c92ab61SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
26236451dSTerje Bergstrom /*
36236451dSTerje Bergstrom  * Copyright (C) 2010 Google, Inc.
46236451dSTerje Bergstrom  * Author: Erik Gilling <konkers@android.com>
56236451dSTerje Bergstrom  *
66236451dSTerje Bergstrom  * Copyright (C) 2011-2013 NVIDIA Corporation
76236451dSTerje Bergstrom  */
86236451dSTerje Bergstrom 
96236451dSTerje Bergstrom #include <linux/debugfs.h>
106b6776e2SDmitry Osipenko #include <linux/pm_runtime.h>
116236451dSTerje Bergstrom #include <linux/seq_file.h>
126236451dSTerje Bergstrom #include <linux/uaccess.h>
136236451dSTerje Bergstrom 
146236451dSTerje Bergstrom #include <linux/io.h>
156236451dSTerje Bergstrom 
166236451dSTerje Bergstrom #include "dev.h"
176236451dSTerje Bergstrom #include "debug.h"
186236451dSTerje Bergstrom #include "channel.h"
196236451dSTerje Bergstrom 
2035681862SDmitry Osipenko static DEFINE_MUTEX(debug_lock);
2135681862SDmitry Osipenko 
226236451dSTerje Bergstrom unsigned int host1x_debug_trace_cmdbuf;
236236451dSTerje Bergstrom 
246236451dSTerje Bergstrom static pid_t host1x_debug_force_timeout_pid;
256236451dSTerje Bergstrom static u32 host1x_debug_force_timeout_val;
266236451dSTerje Bergstrom static u32 host1x_debug_force_timeout_channel;
276236451dSTerje Bergstrom 
host1x_debug_output(struct output * o,const char * fmt,...)286236451dSTerje Bergstrom void host1x_debug_output(struct output *o, const char *fmt, ...)
296236451dSTerje Bergstrom {
306236451dSTerje Bergstrom 	va_list args;
316236451dSTerje Bergstrom 	int len;
326236451dSTerje Bergstrom 
336236451dSTerje Bergstrom 	va_start(args, fmt);
346236451dSTerje Bergstrom 	len = vsnprintf(o->buf, sizeof(o->buf), fmt, args);
356236451dSTerje Bergstrom 	va_end(args);
360b8070d1SThierry Reding 
37eb2ee1a2SMikko Perttunen 	o->fn(o->ctx, o->buf, len, false);
38eb2ee1a2SMikko Perttunen }
39eb2ee1a2SMikko Perttunen 
host1x_debug_cont(struct output * o,const char * fmt,...)40eb2ee1a2SMikko Perttunen void host1x_debug_cont(struct output *o, const char *fmt, ...)
41eb2ee1a2SMikko Perttunen {
42eb2ee1a2SMikko Perttunen 	va_list args;
43eb2ee1a2SMikko Perttunen 	int len;
44eb2ee1a2SMikko Perttunen 
45eb2ee1a2SMikko Perttunen 	va_start(args, fmt);
46eb2ee1a2SMikko Perttunen 	len = vsnprintf(o->buf, sizeof(o->buf), fmt, args);
47eb2ee1a2SMikko Perttunen 	va_end(args);
48eb2ee1a2SMikko Perttunen 
49eb2ee1a2SMikko Perttunen 	o->fn(o->ctx, o->buf, len, true);
506236451dSTerje Bergstrom }
516236451dSTerje Bergstrom 
show_channel(struct host1x_channel * ch,void * data,bool show_fifo)528474b025SMikko Perttunen static int show_channel(struct host1x_channel *ch, void *data, bool show_fifo)
536236451dSTerje Bergstrom {
546236451dSTerje Bergstrom 	struct host1x *m = dev_get_drvdata(ch->dev->parent);
556236451dSTerje Bergstrom 	struct output *o = data;
566b6776e2SDmitry Osipenko 	int err;
576b6776e2SDmitry Osipenko 
586b6776e2SDmitry Osipenko 	err = pm_runtime_resume_and_get(m->dev);
596b6776e2SDmitry Osipenko 	if (err < 0)
606b6776e2SDmitry Osipenko 		return err;
616236451dSTerje Bergstrom 
626236451dSTerje Bergstrom 	mutex_lock(&ch->cdma.lock);
6335681862SDmitry Osipenko 	mutex_lock(&debug_lock);
640b8070d1SThierry Reding 
656236451dSTerje Bergstrom 	if (show_fifo)
666236451dSTerje Bergstrom 		host1x_hw_show_channel_fifo(m, ch, o);
670b8070d1SThierry Reding 
686236451dSTerje Bergstrom 	host1x_hw_show_channel_cdma(m, ch, o);
690b8070d1SThierry Reding 
7035681862SDmitry Osipenko 	mutex_unlock(&debug_lock);
718474b025SMikko Perttunen 	mutex_unlock(&ch->cdma.lock);
726236451dSTerje Bergstrom 
736b6776e2SDmitry Osipenko 	pm_runtime_put(m->dev);
746b6776e2SDmitry Osipenko 
756236451dSTerje Bergstrom 	return 0;
766236451dSTerje Bergstrom }
776236451dSTerje Bergstrom 
show_syncpts(struct host1x * m,struct output * o,bool show_all)7874bb98ddSJon Hunter static void show_syncpts(struct host1x *m, struct output *o, bool show_all)
796236451dSTerje Bergstrom {
80*625d4ffbSMikko Perttunen 	unsigned long irqflags;
8149a5fb16SMikko Perttunen 	struct list_head *pos;
8214c95fc8SThierry Reding 	unsigned int i;
836b6776e2SDmitry Osipenko 	int err;
846df633d0SThierry Reding 
856236451dSTerje Bergstrom 	host1x_debug_output(o, "---- syncpts ----\n");
860b8070d1SThierry Reding 
876b6776e2SDmitry Osipenko 	err = pm_runtime_resume_and_get(m->dev);
886b6776e2SDmitry Osipenko 	if (err < 0)
896b6776e2SDmitry Osipenko 		return;
906b6776e2SDmitry Osipenko 
916236451dSTerje Bergstrom 	for (i = 0; i < host1x_syncpt_nb_pts(m); i++) {
926236451dSTerje Bergstrom 		u32 max = host1x_syncpt_read_max(m->syncpt + i);
936236451dSTerje Bergstrom 		u32 min = host1x_syncpt_load(m->syncpt + i);
9449a5fb16SMikko Perttunen 		unsigned int waiters = 0;
956df633d0SThierry Reding 
96*625d4ffbSMikko Perttunen 		spin_lock_irqsave(&m->syncpt[i].fences.lock, irqflags);
97*625d4ffbSMikko Perttunen 		list_for_each(pos, &m->syncpt[i].fences.list)
9849a5fb16SMikko Perttunen 			waiters++;
99*625d4ffbSMikko Perttunen 		spin_unlock_irqrestore(&m->syncpt[i].fences.lock, irqflags);
10049a5fb16SMikko Perttunen 
10174bb98ddSJon Hunter 		if (!kref_read(&m->syncpt[i].ref))
10274bb98ddSJon Hunter 			continue;
10374bb98ddSJon Hunter 
10474bb98ddSJon Hunter 		if (!show_all && !min && !max && !waiters)
1056236451dSTerje Bergstrom 			continue;
10614c95fc8SThierry Reding 
10749a5fb16SMikko Perttunen 		host1x_debug_output(o,
10849a5fb16SMikko Perttunen 				    "id %u (%s) min %d max %d (%d waiters)\n",
10949a5fb16SMikko Perttunen 				    i, m->syncpt[i].name, min, max, waiters);
1106236451dSTerje Bergstrom 	}
1116236451dSTerje Bergstrom 
1126236451dSTerje Bergstrom 	for (i = 0; i < host1x_syncpt_nb_bases(m); i++) {
1136236451dSTerje Bergstrom 		u32 base_val;
1146df633d0SThierry Reding 
1156236451dSTerje Bergstrom 		base_val = host1x_syncpt_load_wait_base(m->syncpt + i);
1166236451dSTerje Bergstrom 		if (base_val)
11714c95fc8SThierry Reding 			host1x_debug_output(o, "waitbase id %u val %d\n", i,
1186236451dSTerje Bergstrom 					    base_val);
1196236451dSTerje Bergstrom 	}
1206236451dSTerje Bergstrom 
1216b6776e2SDmitry Osipenko 	pm_runtime_put(m->dev);
1226b6776e2SDmitry Osipenko 
1236236451dSTerje Bergstrom 	host1x_debug_output(o, "\n");
1246236451dSTerje Bergstrom }
1256236451dSTerje Bergstrom 
show_all(struct host1x * m,struct output * o,bool show_fifo)1268474b025SMikko Perttunen static void show_all(struct host1x *m, struct output *o, bool show_fifo)
1276236451dSTerje Bergstrom {
128d4ad3ad9SThierry Reding 	unsigned int i;
1296236451dSTerje Bergstrom 
1306236451dSTerje Bergstrom 	host1x_hw_show_mlocks(m, o);
13174bb98ddSJon Hunter 	show_syncpts(m, o, true);
1326236451dSTerje Bergstrom 	host1x_debug_output(o, "---- channels ----\n");
1336236451dSTerje Bergstrom 
1348474b025SMikko Perttunen 	for (i = 0; i < m->info->nb_channels; ++i) {
1358474b025SMikko Perttunen 		struct host1x_channel *ch = host1x_channel_get_index(m, i);
1368474b025SMikko Perttunen 
1378474b025SMikko Perttunen 		if (ch) {
1388474b025SMikko Perttunen 			show_channel(ch, o, show_fifo);
1398474b025SMikko Perttunen 			host1x_channel_put(ch);
1406236451dSTerje Bergstrom 		}
1418474b025SMikko Perttunen 	}
1426236451dSTerje Bergstrom }
1436236451dSTerje Bergstrom 
host1x_debug_all_show(struct seq_file * s,void * unused)144a624bd9cSLiu Shixin static int host1x_debug_all_show(struct seq_file *s, void *unused)
1456236451dSTerje Bergstrom {
1466236451dSTerje Bergstrom 	struct output o = {
1476236451dSTerje Bergstrom 		.fn = write_to_seqfile,
1486236451dSTerje Bergstrom 		.ctx = s
1496236451dSTerje Bergstrom 	};
1500b8070d1SThierry Reding 
1518474b025SMikko Perttunen 	show_all(s->private, &o, true);
1520b8070d1SThierry Reding 
1536236451dSTerje Bergstrom 	return 0;
1546236451dSTerje Bergstrom }
155a624bd9cSLiu Shixin DEFINE_SHOW_ATTRIBUTE(host1x_debug_all);
1566236451dSTerje Bergstrom 
host1x_debug_show(struct seq_file * s,void * unused)1576236451dSTerje Bergstrom static int host1x_debug_show(struct seq_file *s, void *unused)
1586236451dSTerje Bergstrom {
1596236451dSTerje Bergstrom 	struct output o = {
1606236451dSTerje Bergstrom 		.fn = write_to_seqfile,
1616236451dSTerje Bergstrom 		.ctx = s
1626236451dSTerje Bergstrom 	};
1630b8070d1SThierry Reding 
1648474b025SMikko Perttunen 	show_all(s->private, &o, false);
1650b8070d1SThierry Reding 
1666236451dSTerje Bergstrom 	return 0;
1676236451dSTerje Bergstrom }
168a624bd9cSLiu Shixin DEFINE_SHOW_ATTRIBUTE(host1x_debug);
1696236451dSTerje Bergstrom 
host1x_debugfs_init(struct host1x * host1x)1708e0d788cSThierry Reding static void host1x_debugfs_init(struct host1x *host1x)
1716236451dSTerje Bergstrom {
1726236451dSTerje Bergstrom 	struct dentry *de = debugfs_create_dir("tegra-host1x", NULL);
1736236451dSTerje Bergstrom 
1746236451dSTerje Bergstrom 	/* Store the created entry */
1756236451dSTerje Bergstrom 	host1x->debugfs = de;
1766236451dSTerje Bergstrom 
1776236451dSTerje Bergstrom 	debugfs_create_file("status", S_IRUGO, de, host1x, &host1x_debug_fops);
1786236451dSTerje Bergstrom 	debugfs_create_file("status_all", S_IRUGO, de, host1x,
1796236451dSTerje Bergstrom 			    &host1x_debug_all_fops);
1806236451dSTerje Bergstrom 
1816236451dSTerje Bergstrom 	debugfs_create_u32("trace_cmdbuf", S_IRUGO|S_IWUSR, de,
1826236451dSTerje Bergstrom 			   &host1x_debug_trace_cmdbuf);
1836236451dSTerje Bergstrom 
1846236451dSTerje Bergstrom 	host1x_hw_debug_init(host1x, de);
1856236451dSTerje Bergstrom 
1866236451dSTerje Bergstrom 	debugfs_create_u32("force_timeout_pid", S_IRUGO|S_IWUSR, de,
1876236451dSTerje Bergstrom 			   &host1x_debug_force_timeout_pid);
1886236451dSTerje Bergstrom 	debugfs_create_u32("force_timeout_val", S_IRUGO|S_IWUSR, de,
1896236451dSTerje Bergstrom 			   &host1x_debug_force_timeout_val);
1906236451dSTerje Bergstrom 	debugfs_create_u32("force_timeout_channel", S_IRUGO|S_IWUSR, de,
1916236451dSTerje Bergstrom 			   &host1x_debug_force_timeout_channel);
1926236451dSTerje Bergstrom }
1936236451dSTerje Bergstrom 
host1x_debugfs_exit(struct host1x * host1x)1948e0d788cSThierry Reding static void host1x_debugfs_exit(struct host1x *host1x)
1956236451dSTerje Bergstrom {
1966236451dSTerje Bergstrom 	debugfs_remove_recursive(host1x->debugfs);
1976236451dSTerje Bergstrom }
1988e0d788cSThierry Reding 
host1x_debug_init(struct host1x * host1x)1996236451dSTerje Bergstrom void host1x_debug_init(struct host1x *host1x)
2006236451dSTerje Bergstrom {
2018e0d788cSThierry Reding 	if (IS_ENABLED(CONFIG_DEBUG_FS))
2028e0d788cSThierry Reding 		host1x_debugfs_init(host1x);
2036236451dSTerje Bergstrom }
2048e0d788cSThierry Reding 
host1x_debug_deinit(struct host1x * host1x)2056236451dSTerje Bergstrom void host1x_debug_deinit(struct host1x *host1x)
2066236451dSTerje Bergstrom {
2078e0d788cSThierry Reding 	if (IS_ENABLED(CONFIG_DEBUG_FS))
2088e0d788cSThierry Reding 		host1x_debugfs_exit(host1x);
2096236451dSTerje Bergstrom }
2106236451dSTerje Bergstrom 
host1x_debug_dump(struct host1x * host1x)2116236451dSTerje Bergstrom void host1x_debug_dump(struct host1x *host1x)
2126236451dSTerje Bergstrom {
2136236451dSTerje Bergstrom 	struct output o = {
2146236451dSTerje Bergstrom 		.fn = write_to_printk
2156236451dSTerje Bergstrom 	};
2160b8070d1SThierry Reding 
2178474b025SMikko Perttunen 	show_all(host1x, &o, true);
2186236451dSTerje Bergstrom }
2196236451dSTerje Bergstrom 
host1x_debug_dump_syncpts(struct host1x * host1x)2206236451dSTerje Bergstrom void host1x_debug_dump_syncpts(struct host1x *host1x)
2216236451dSTerje Bergstrom {
2226236451dSTerje Bergstrom 	struct output o = {
2236236451dSTerje Bergstrom 		.fn = write_to_printk
2246236451dSTerje Bergstrom 	};
2250b8070d1SThierry Reding 
22674bb98ddSJon Hunter 	show_syncpts(host1x, &o, false);
2276236451dSTerje Bergstrom }
228