video: tegra: host: Move device data to nvhost_device
[linux-2.6.git] / drivers / video / tegra / host / debug.c
1 /*
2  * drivers/video/tegra/host/debug.c
3  *
4  * Copyright (C) 2010 Google, Inc.
5  * Author: Erik Gilling <konkers@android.com>
6  *
7  * Copyright (C) 2011 NVIDIA Corporation
8  *
9  * This software is licensed under the terms of the GNU General Public
10  * License version 2, as published by the Free Software Foundation, and
11  * may be copied, distributed, and modified under those terms.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  */
19
20 #include <linux/debugfs.h>
21 #include <linux/seq_file.h>
22
23 #include <linux/io.h>
24
25 #include "dev.h"
26 #include "debug.h"
27
28 pid_t nvhost_debug_null_kickoff_pid;
29 unsigned int nvhost_debug_trace_cmdbuf;
30
31 pid_t nvhost_debug_force_timeout_pid;
32 u32 nvhost_debug_force_timeout_val;
33 u32 nvhost_debug_force_timeout_channel;
34
35 void nvhost_debug_output(struct output *o, const char* fmt, ...)
36 {
37         va_list args;
38         int len;
39
40         va_start(args, fmt);
41         len = vsnprintf(o->buf, sizeof(o->buf), fmt, args);
42         va_end(args);
43         o->fn(o->ctx, o->buf, len);
44 }
45
46
47 static void show_channels(struct nvhost_master *m, struct output *o)
48 {
49         int i;
50         nvhost_debug_output(o, "---- channels ----\n");
51         for (i = 0; i < m->nb_channels; i++) {
52                 struct nvhost_channel *ch = &m->channels[i];
53                 mutex_lock(&ch->reflock);
54                 if (ch->refcount) {
55                         mutex_lock(&ch->cdma.lock);
56                         m->op.debug.show_channel_fifo(m, o, i);
57                         m->op.debug.show_channel_cdma(m, o, i);
58                         mutex_unlock(&ch->cdma.lock);
59                 }
60                 mutex_unlock(&ch->reflock);
61         }
62 }
63
64
65 static void show_syncpts(struct nvhost_master *m, struct output *o)
66 {
67         int i;
68         BUG_ON(!m->op.syncpt.name);
69         nvhost_debug_output(o, "---- syncpts ----\n");
70         for (i = 0; i < m->syncpt.nb_pts; i++) {
71                 u32 max = nvhost_syncpt_read_max(&m->syncpt, i);
72                 if (!max)
73                         continue;
74                 nvhost_debug_output(o, "id %d (%s) min %d max %d\n",
75                                     i, m->op.syncpt.name(&m->syncpt, i),
76                         nvhost_syncpt_update_min(&m->syncpt, i), max);
77         }
78
79         for (i = 0; i < m->syncpt.nb_bases; i++) {
80                 u32 base_val;
81                 base_val = nvhost_syncpt_read_wait_base(&m->syncpt, i);
82                 if (base_val)
83                         nvhost_debug_output(o, "waitbase id %d val %d\n",
84                                         i, base_val);
85         }
86
87         nvhost_debug_output(o, "\n");
88 }
89
90 static void show_all(struct nvhost_master *m, struct output *o)
91 {
92         nvhost_module_busy(m->dev);
93
94         m->op.debug.show_mlocks(m, o);
95         show_syncpts(m, o);
96         show_channels(m, o);
97
98         nvhost_module_idle(m->dev);
99 }
100
101
102 #ifdef CONFIG_DEBUG_FS
103 static int nvhost_debug_show(struct seq_file *s, void *unused)
104 {
105         struct output o = {
106                 .fn = write_to_seqfile,
107                 .ctx = s
108         };
109         show_all(s->private, &o);
110         return 0;
111 }
112
113 static int nvhost_debug_open(struct inode *inode, struct file *file)
114 {
115         return single_open(file, nvhost_debug_show, inode->i_private);
116 }
117
118 static const struct file_operations nvhost_debug_fops = {
119         .open           = nvhost_debug_open,
120         .read           = seq_read,
121         .llseek         = seq_lseek,
122         .release        = single_release,
123 };
124
125 void nvhost_debug_init(struct nvhost_master *master)
126 {
127         struct dentry *de = debugfs_create_dir("tegra_host", NULL);
128
129         debugfs_create_file("status", S_IRUGO, de,
130                         master, &nvhost_debug_fops);
131
132         debugfs_create_u32("null_kickoff_pid", S_IRUGO|S_IWUSR, de,
133                         &nvhost_debug_null_kickoff_pid);
134         debugfs_create_u32("trace_cmdbuf", S_IRUGO|S_IWUSR, de,
135                         &nvhost_debug_trace_cmdbuf);
136
137         if (master->op.debug.debug_init)
138                 master->op.debug.debug_init(de);
139
140         debugfs_create_u32("force_timeout_pid", S_IRUGO|S_IWUSR, de,
141                         &nvhost_debug_force_timeout_pid);
142         debugfs_create_u32("force_timeout_val", S_IRUGO|S_IWUSR, de,
143                         &nvhost_debug_force_timeout_val);
144         debugfs_create_u32("force_timeout_channel", S_IRUGO|S_IWUSR, de,
145                         &nvhost_debug_force_timeout_channel);
146 }
147 #else
148 void nvhost_debug_init(struct nvhost_master *master)
149 {
150 }
151 #endif
152
153 void nvhost_debug_dump(struct nvhost_master *master)
154 {
155         struct output o = {
156                 .fn = write_to_printk
157         };
158         show_all(master, &o);
159 }