summaryrefslogtreecommitdiffstats
path: root/drivers/gpu/nvgpu/os/linux/debug_fecs_trace.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/nvgpu/os/linux/debug_fecs_trace.c')
-rw-r--r--drivers/gpu/nvgpu/os/linux/debug_fecs_trace.c154
1 files changed, 154 insertions, 0 deletions
diff --git a/drivers/gpu/nvgpu/os/linux/debug_fecs_trace.c b/drivers/gpu/nvgpu/os/linux/debug_fecs_trace.c
new file mode 100644
index 00000000..9e72d2ce
--- /dev/null
+++ b/drivers/gpu/nvgpu/os/linux/debug_fecs_trace.c
@@ -0,0 +1,154 @@
1/*
2 * Copyright (c) 2018, NVIDIA CORPORATION. All rights reserved.
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms and conditions of the GNU General Public License,
6 * version 2, as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope it will be useful, but WITHOUT
9 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
11 * more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
16
17#include <linux/debugfs.h>
18
19#include <nvgpu/fecs_trace.h>
20
21#include "os_linux.h"
22
23/*
24 * The sequence iterator functions. We simply use the count of the
25 * next line as our internal position.
26 */
27static void *gk20a_fecs_trace_debugfs_ring_seq_start(
28 struct seq_file *s, loff_t *pos)
29{
30 if (*pos >= GK20A_FECS_TRACE_NUM_RECORDS)
31 return NULL;
32
33 return pos;
34}
35
36static void *gk20a_fecs_trace_debugfs_ring_seq_next(
37 struct seq_file *s, void *v, loff_t *pos)
38{
39 ++(*pos);
40 if (*pos >= GK20A_FECS_TRACE_NUM_RECORDS)
41 return NULL;
42 return pos;
43}
44
45static void gk20a_fecs_trace_debugfs_ring_seq_stop(
46 struct seq_file *s, void *v)
47{
48}
49
50static int gk20a_fecs_trace_debugfs_ring_seq_show(
51 struct seq_file *s, void *v)
52{
53 loff_t *pos = (loff_t *) v;
54 struct gk20a *g = *(struct gk20a **)s->private;
55 struct gk20a_fecs_trace_record *r =
56 gk20a_fecs_trace_get_record(g, *pos);
57 int i;
58 const u32 invalid_tag = gk20a_fecs_trace_record_ts_tag_invalid_ts_v();
59 u32 tag;
60 u64 timestamp;
61
62 seq_printf(s, "record #%lld (%p)\n", *pos, r);
63 seq_printf(s, "\tmagic_lo=%08x\n", r->magic_lo);
64 seq_printf(s, "\tmagic_hi=%08x\n", r->magic_hi);
65 if (gk20a_fecs_trace_is_valid_record(r)) {
66 seq_printf(s, "\tcontext_ptr=%08x\n", r->context_ptr);
67 seq_printf(s, "\tcontext_id=%08x\n", r->context_id);
68 seq_printf(s, "\tnew_context_ptr=%08x\n", r->new_context_ptr);
69 seq_printf(s, "\tnew_context_id=%08x\n", r->new_context_id);
70 for (i = 0; i < gk20a_fecs_trace_num_ts(); i++) {
71 tag = gk20a_fecs_trace_record_ts_tag_v(r->ts[i]);
72 if (tag == invalid_tag)
73 continue;
74 timestamp = gk20a_fecs_trace_record_ts_timestamp_v(r->ts[i]);
75 timestamp <<= GK20A_FECS_TRACE_PTIMER_SHIFT;
76 seq_printf(s, "\ttag=%02x timestamp=%012llx\n", tag, timestamp);
77 }
78 }
79 return 0;
80}
81
82/*
83 * Tie them all together into a set of seq_operations.
84 */
85static const struct seq_operations gk20a_fecs_trace_debugfs_ring_seq_ops = {
86 .start = gk20a_fecs_trace_debugfs_ring_seq_start,
87 .next = gk20a_fecs_trace_debugfs_ring_seq_next,
88 .stop = gk20a_fecs_trace_debugfs_ring_seq_stop,
89 .show = gk20a_fecs_trace_debugfs_ring_seq_show
90};
91
92/*
93 * Time to set up the file operations for our /proc file. In this case,
94 * all we need is an open function which sets up the sequence ops.
95 */
96
97static int gk20a_ctxsw_debugfs_ring_open(struct inode *inode,
98 struct file *file)
99{
100 struct gk20a **p;
101
102 if (!capable(CAP_SYS_ADMIN))
103 return -EPERM;
104
105 p = __seq_open_private(file, &gk20a_fecs_trace_debugfs_ring_seq_ops,
106 sizeof(struct gk20a *));
107 if (!p)
108 return -ENOMEM;
109
110 *p = (struct gk20a *)inode->i_private;
111 return 0;
112};
113
114/*
115 * The file operations structure contains our open function along with
116 * set of the canned seq_ ops.
117 */
118static const struct file_operations gk20a_fecs_trace_debugfs_ring_fops = {
119 .owner = THIS_MODULE,
120 .open = gk20a_ctxsw_debugfs_ring_open,
121 .read = seq_read,
122 .llseek = seq_lseek,
123 .release = seq_release_private
124};
125
126static int gk20a_fecs_trace_debugfs_read(void *arg, u64 *val)
127{
128 *val = gk20a_fecs_trace_get_read_index((struct gk20a *)arg);
129 return 0;
130}
131DEFINE_SIMPLE_ATTRIBUTE(gk20a_fecs_trace_debugfs_read_fops,
132 gk20a_fecs_trace_debugfs_read, NULL, "%llu\n");
133
134static int gk20a_fecs_trace_debugfs_write(void *arg, u64 *val)
135{
136 *val = gk20a_fecs_trace_get_write_index((struct gk20a *)arg);
137 return 0;
138}
139DEFINE_SIMPLE_ATTRIBUTE(gk20a_fecs_trace_debugfs_write_fops,
140 gk20a_fecs_trace_debugfs_write, NULL, "%llu\n");
141
142int nvgpu_fecs_trace_init_debugfs(struct gk20a *g)
143{
144 struct nvgpu_os_linux *l = nvgpu_os_linux_from_gk20a(g);
145
146 debugfs_create_file("ctxsw_trace_read", 0600, l->debugfs, g,
147 &gk20a_fecs_trace_debugfs_read_fops);
148 debugfs_create_file("ctxsw_trace_write", 0600, l->debugfs, g,
149 &gk20a_fecs_trace_debugfs_write_fops);
150 debugfs_create_file("ctxsw_trace_ring", 0600, l->debugfs, g,
151 &gk20a_fecs_trace_debugfs_ring_fops);
152
153 return 0;
154}