aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/host1x/debug.c
diff options
context:
space:
mode:
authorDave Airlie <airlied@redhat.com>2013-04-22 06:49:07 -0400
committerDave Airlie <airlied@redhat.com>2013-04-22 06:49:07 -0400
commitf9df7ea33c87291365d943828bec852874f15c2f (patch)
tree53afb4d74f0af01555a13d440d978dff3318c6f3 /drivers/gpu/host1x/debug.c
parentce83adf78bbbe6bdcd99f0b97212337ce6b84940 (diff)
parente1041ca41670dc5502deee1fa3517dbaf9c0a09e (diff)
Merge tag 'drm/tegra/for-3.10' of git://anongit.freedesktop.org/tegra/linux into drm-next
drm/tegra: Changes for v3.10-rc1 The bulk of this pull-request is the host1x series that has been in the works for a few months. The current implementation looks good and has been tested by several independent parties. So far no issues have been found. To be on the safe side, the new Tegra-specific DRM IOCTLs depend on staging in order to give some amount of flexibility to change them just in case. The plan is to remove that dependency once more userspace exists to verify the adequacy of the IOCTLs. Currently only the 2D engine is supported, but patches are in the works to enable 3D support on top of this framework as well. Various bits of open-source userspace exist to test the 2D and 3D support[0]. This is still a bit immature but it allows to verify that the kernel interfaces work properly. To round things off there are two smaller cleanup patches, one of them adding a new pixel format and the other removing a redundent Kconfig dependency. [0]: https://github.com/grate-driver * tag 'drm/tegra/for-3.10' of git://anongit.freedesktop.org/tegra/linux: drm/tegra: don't depend on OF drm/tegra: Support the XBGR8888 pixelformat drm/tegra: Add gr2d device gpu: host1x: drm: Add memory manager and fb gpu: host1x: Remove second host1x driver gpu: host1x: drm: Rename host1x to host1x_drm drm/tegra: Move drm to live under host1x gpu: host1x: Add debug support gpu: host1x: Add channel support gpu: host1x: Add syncpoint wait and interrupts gpu: host1x: Add host1x driver
Diffstat (limited to 'drivers/gpu/host1x/debug.c')
-rw-r--r--drivers/gpu/host1x/debug.c210
1 files changed, 210 insertions, 0 deletions
diff --git a/drivers/gpu/host1x/debug.c b/drivers/gpu/host1x/debug.c
new file mode 100644
index 000000000000..3ec7d77de24d
--- /dev/null
+++ b/drivers/gpu/host1x/debug.c
@@ -0,0 +1,210 @@
1/*
2 * Copyright (C) 2010 Google, Inc.
3 * Author: Erik Gilling <konkers@android.com>
4 *
5 * Copyright (C) 2011-2013 NVIDIA Corporation
6 *
7 * This software is licensed under the terms of the GNU General Public
8 * License version 2, as published by the Free Software Foundation, and
9 * may be copied, distributed, and modified under those terms.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 */
17
18#include <linux/debugfs.h>
19#include <linux/seq_file.h>
20#include <linux/uaccess.h>
21
22#include <linux/io.h>
23
24#include "dev.h"
25#include "debug.h"
26#include "channel.h"
27
28unsigned int host1x_debug_trace_cmdbuf;
29
30static pid_t host1x_debug_force_timeout_pid;
31static u32 host1x_debug_force_timeout_val;
32static u32 host1x_debug_force_timeout_channel;
33
34void host1x_debug_output(struct output *o, const char *fmt, ...)
35{
36 va_list args;
37 int len;
38
39 va_start(args, fmt);
40 len = vsnprintf(o->buf, sizeof(o->buf), fmt, args);
41 va_end(args);
42 o->fn(o->ctx, o->buf, len);
43}
44
45static int show_channels(struct host1x_channel *ch, void *data, bool show_fifo)
46{
47 struct host1x *m = dev_get_drvdata(ch->dev->parent);
48 struct output *o = data;
49
50 mutex_lock(&ch->reflock);
51 if (ch->refcount) {
52 mutex_lock(&ch->cdma.lock);
53 if (show_fifo)
54 host1x_hw_show_channel_fifo(m, ch, o);
55 host1x_hw_show_channel_cdma(m, ch, o);
56 mutex_unlock(&ch->cdma.lock);
57 }
58 mutex_unlock(&ch->reflock);
59
60 return 0;
61}
62
63static void show_syncpts(struct host1x *m, struct output *o)
64{
65 int i;
66 host1x_debug_output(o, "---- syncpts ----\n");
67 for (i = 0; i < host1x_syncpt_nb_pts(m); i++) {
68 u32 max = host1x_syncpt_read_max(m->syncpt + i);
69 u32 min = host1x_syncpt_load(m->syncpt + i);
70 if (!min && !max)
71 continue;
72 host1x_debug_output(o, "id %d (%s) min %d max %d\n",
73 i, m->syncpt[i].name, min, max);
74 }
75
76 for (i = 0; i < host1x_syncpt_nb_bases(m); i++) {
77 u32 base_val;
78 base_val = host1x_syncpt_load_wait_base(m->syncpt + i);
79 if (base_val)
80 host1x_debug_output(o, "waitbase id %d val %d\n", i,
81 base_val);
82 }
83
84 host1x_debug_output(o, "\n");
85}
86
87static void show_all(struct host1x *m, struct output *o)
88{
89 struct host1x_channel *ch;
90
91 host1x_hw_show_mlocks(m, o);
92 show_syncpts(m, o);
93 host1x_debug_output(o, "---- channels ----\n");
94
95 host1x_for_each_channel(m, ch)
96 show_channels(ch, o, true);
97}
98
99#ifdef CONFIG_DEBUG_FS
100static void show_all_no_fifo(struct host1x *host1x, struct output *o)
101{
102 struct host1x_channel *ch;
103
104 host1x_hw_show_mlocks(host1x, o);
105 show_syncpts(host1x, o);
106 host1x_debug_output(o, "---- channels ----\n");
107
108 host1x_for_each_channel(host1x, ch)
109 show_channels(ch, o, false);
110}
111
112static int host1x_debug_show_all(struct seq_file *s, void *unused)
113{
114 struct output o = {
115 .fn = write_to_seqfile,
116 .ctx = s
117 };
118 show_all(s->private, &o);
119 return 0;
120}
121
122static int host1x_debug_show(struct seq_file *s, void *unused)
123{
124 struct output o = {
125 .fn = write_to_seqfile,
126 .ctx = s
127 };
128 show_all_no_fifo(s->private, &o);
129 return 0;
130}
131
132static int host1x_debug_open_all(struct inode *inode, struct file *file)
133{
134 return single_open(file, host1x_debug_show_all, inode->i_private);
135}
136
137static const struct file_operations host1x_debug_all_fops = {
138 .open = host1x_debug_open_all,
139 .read = seq_read,
140 .llseek = seq_lseek,
141 .release = single_release,
142};
143
144static int host1x_debug_open(struct inode *inode, struct file *file)
145{
146 return single_open(file, host1x_debug_show, inode->i_private);
147}
148
149static const struct file_operations host1x_debug_fops = {
150 .open = host1x_debug_open,
151 .read = seq_read,
152 .llseek = seq_lseek,
153 .release = single_release,
154};
155
156void host1x_debug_init(struct host1x *host1x)
157{
158 struct dentry *de = debugfs_create_dir("tegra-host1x", NULL);
159
160 if (!de)
161 return;
162
163 /* Store the created entry */
164 host1x->debugfs = de;
165
166 debugfs_create_file("status", S_IRUGO, de, host1x, &host1x_debug_fops);
167 debugfs_create_file("status_all", S_IRUGO, de, host1x,
168 &host1x_debug_all_fops);
169
170 debugfs_create_u32("trace_cmdbuf", S_IRUGO|S_IWUSR, de,
171 &host1x_debug_trace_cmdbuf);
172
173 host1x_hw_debug_init(host1x, de);
174
175 debugfs_create_u32("force_timeout_pid", S_IRUGO|S_IWUSR, de,
176 &host1x_debug_force_timeout_pid);
177 debugfs_create_u32("force_timeout_val", S_IRUGO|S_IWUSR, de,
178 &host1x_debug_force_timeout_val);
179 debugfs_create_u32("force_timeout_channel", S_IRUGO|S_IWUSR, de,
180 &host1x_debug_force_timeout_channel);
181}
182
183void host1x_debug_deinit(struct host1x *host1x)
184{
185 debugfs_remove_recursive(host1x->debugfs);
186}
187#else
188void host1x_debug_init(struct host1x *host1x)
189{
190}
191void host1x_debug_deinit(struct host1x *host1x)
192{
193}
194#endif
195
196void host1x_debug_dump(struct host1x *host1x)
197{
198 struct output o = {
199 .fn = write_to_printk
200 };
201 show_all(host1x, &o);
202}
203
204void host1x_debug_dump_syncpts(struct host1x *host1x)
205{
206 struct output o = {
207 .fn = write_to_printk
208 };
209 show_syncpts(host1x, &o);
210}