aboutsummaryrefslogtreecommitdiffstats
path: root/include/os/linux/debug_fecs_trace.c
diff options
context:
space:
mode:
Diffstat (limited to 'include/os/linux/debug_fecs_trace.c')
-rw-r--r--include/os/linux/debug_fecs_trace.c151
1 files changed, 151 insertions, 0 deletions
diff --git a/include/os/linux/debug_fecs_trace.c b/include/os/linux/debug_fecs_trace.c
new file mode 100644
index 0000000..7786053
--- /dev/null
+++ b/include/os/linux/debug_fecs_trace.c
@@ -0,0 +1,151 @@
1/*
2 * Copyright (c) 2018-2020, 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 p = __seq_open_private(file, &gk20a_fecs_trace_debugfs_ring_seq_ops,
103 sizeof(struct gk20a *));
104 if (!p)
105 return -ENOMEM;
106
107 *p = (struct gk20a *)inode->i_private;
108 return 0;
109};
110
111/*
112 * The file operations structure contains our open function along with
113 * set of the canned seq_ ops.
114 */
115static const struct file_operations gk20a_fecs_trace_debugfs_ring_fops = {
116 .owner = THIS_MODULE,
117 .open = gk20a_ctxsw_debugfs_ring_open,
118 .read = seq_read,
119 .llseek = seq_lseek,
120 .release = seq_release_private
121};
122
123static int gk20a_fecs_trace_debugfs_read(void *arg, u64 *val)
124{
125 *val = gk20a_fecs_trace_get_read_index((struct gk20a *)arg);
126 return 0;
127}
128DEFINE_SIMPLE_ATTRIBUTE(gk20a_fecs_trace_debugfs_read_fops,
129 gk20a_fecs_trace_debugfs_read, NULL, "%llu\n");
130
131static int gk20a_fecs_trace_debugfs_write(void *arg, u64 *val)
132{
133 *val = gk20a_fecs_trace_get_write_index((struct gk20a *)arg);
134 return 0;
135}
136DEFINE_SIMPLE_ATTRIBUTE(gk20a_fecs_trace_debugfs_write_fops,
137 gk20a_fecs_trace_debugfs_write, NULL, "%llu\n");
138
139int nvgpu_fecs_trace_init_debugfs(struct gk20a *g)
140{
141 struct nvgpu_os_linux *l = nvgpu_os_linux_from_gk20a(g);
142
143 debugfs_create_file("ctxsw_trace_read", 0600, l->debugfs, g,
144 &gk20a_fecs_trace_debugfs_read_fops);
145 debugfs_create_file("ctxsw_trace_write", 0600, l->debugfs, g,
146 &gk20a_fecs_trace_debugfs_write_fops);
147 debugfs_create_file("ctxsw_trace_ring", 0600, l->debugfs, g,
148 &gk20a_fecs_trace_debugfs_ring_fops);
149
150 return 0;
151}