diff options
Diffstat (limited to 'drivers/gpu/nvgpu/os/linux/debug_fecs_trace.c')
-rw-r--r-- | drivers/gpu/nvgpu/os/linux/debug_fecs_trace.c | 154 |
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 | */ | ||
27 | static 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 | |||
36 | static 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 | |||
45 | static void gk20a_fecs_trace_debugfs_ring_seq_stop( | ||
46 | struct seq_file *s, void *v) | ||
47 | { | ||
48 | } | ||
49 | |||
50 | static 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 | */ | ||
85 | static 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 | |||
97 | static 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 | */ | ||
118 | static 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 | |||
126 | static 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 | } | ||
131 | DEFINE_SIMPLE_ATTRIBUTE(gk20a_fecs_trace_debugfs_read_fops, | ||
132 | gk20a_fecs_trace_debugfs_read, NULL, "%llu\n"); | ||
133 | |||
134 | static 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 | } | ||
139 | DEFINE_SIMPLE_ATTRIBUTE(gk20a_fecs_trace_debugfs_write_fops, | ||
140 | gk20a_fecs_trace_debugfs_write, NULL, "%llu\n"); | ||
141 | |||
142 | int 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 | } | ||