summaryrefslogtreecommitdiffstats
path: root/drivers/gpu
diff options
context:
space:
mode:
authorNitin Kumbhar <nkumbhar@nvidia.com>2018-09-04 06:49:47 -0400
committermobile promotions <svcmobile_promotions@nvidia.com>2018-09-09 20:22:24 -0400
commite93a4ca50b6b24d3db1f8fdc0e5030fecb5ea8d2 (patch)
tree204853d4398aaab0a5d69bbc4426e7f78d1753a7 /drivers/gpu
parentb2ba12ed55e9b7079b4216d091003ad6f49a4433 (diff)
gpu: nvgpu: move fecs trace debugfs to linux
Add fecs trace debugfs initialization as an os op. The debugfs nodes are set up for gpu versions which call gk20a_fecs_trace_init(). JIRA NVGPU-602 Change-Id: I606ec31acbf04f633500be4c342db32f3f537794 Signed-off-by: Nitin Kumbhar <nkumbhar@nvidia.com> Reviewed-on: https://git-master.nvidia.com/r/1812449 Reviewed-by: Deepak Nibade <dnibade@nvidia.com> GVS: Gerrit_Virtual_Submit Reviewed-by: svc-misra-checker <svc-misra-checker@nvidia.com> Reviewed-by: Alex Waterman <alexw@nvidia.com> Reviewed-by: mobile promotions <svcmobile_promotions@nvidia.com> Tested-by: mobile promotions <svcmobile_promotions@nvidia.com>
Diffstat (limited to 'drivers/gpu')
-rw-r--r--drivers/gpu/nvgpu/Makefile7
-rw-r--r--drivers/gpu/nvgpu/gk20a/fecs_trace_gk20a.c188
-rw-r--r--drivers/gpu/nvgpu/include/nvgpu/fecs_trace.h60
-rw-r--r--drivers/gpu/nvgpu/os/linux/debug_fecs_trace.c154
-rw-r--r--drivers/gpu/nvgpu/os/linux/debug_fecs_trace.h30
-rw-r--r--drivers/gpu/nvgpu/os/linux/module.c8
-rw-r--r--drivers/gpu/nvgpu/os/linux/os_linux.h4
-rw-r--r--drivers/gpu/nvgpu/os/linux/os_ops.c4
-rw-r--r--drivers/gpu/nvgpu/os/linux/os_ops_gp106.c5
-rw-r--r--drivers/gpu/nvgpu/os/linux/os_ops_gp10b.c5
-rw-r--r--drivers/gpu/nvgpu/os/linux/os_ops_gv100.c5
-rw-r--r--drivers/gpu/nvgpu/os/linux/os_ops_gv11b.c30
-rw-r--r--drivers/gpu/nvgpu/os/linux/os_ops_gv11b.h24
13 files changed, 349 insertions, 175 deletions
diff --git a/drivers/gpu/nvgpu/Makefile b/drivers/gpu/nvgpu/Makefile
index a3372cef..3b6a022a 100644
--- a/drivers/gpu/nvgpu/Makefile
+++ b/drivers/gpu/nvgpu/Makefile
@@ -53,6 +53,7 @@ nvgpu-y += \
53 os/linux/os_ops_gp10b.o \ 53 os/linux/os_ops_gp10b.o \
54 os/linux/os_ops_gp106.o \ 54 os/linux/os_ops_gp106.o \
55 os/linux/os_ops_gv100.o \ 55 os/linux/os_ops_gv100.o \
56 os/linux/os_ops_gv11b.o \
56 os/linux/kmem.o \ 57 os/linux/kmem.o \
57 os/linux/timers.o \ 58 os/linux/timers.o \
58 os/linux/ioctl.o \ 59 os/linux/ioctl.o \
@@ -115,6 +116,12 @@ endif
115nvgpu-$(CONFIG_GK20A_CTXSW_TRACE) += \ 116nvgpu-$(CONFIG_GK20A_CTXSW_TRACE) += \
116 os/linux/ctxsw_trace.o 117 os/linux/ctxsw_trace.o
117 118
119ifeq ($(CONFIG_GK20A_CTXSW_TRACE),y)
120nvgpu-$(CONFIG_DEBUG_FS) += \
121 os/linux/debug_fecs_trace.o
122endif
123
124
118nvgpu-$(CONFIG_TEGRA_GK20A) += \ 125nvgpu-$(CONFIG_TEGRA_GK20A) += \
119 os/linux/module.o \ 126 os/linux/module.o \
120 os/linux/module_usermode.o \ 127 os/linux/module_usermode.o \
diff --git a/drivers/gpu/nvgpu/gk20a/fecs_trace_gk20a.c b/drivers/gpu/nvgpu/gk20a/fecs_trace_gk20a.c
index 3134df4d..b30d1743 100644
--- a/drivers/gpu/nvgpu/gk20a/fecs_trace_gk20a.c
+++ b/drivers/gpu/nvgpu/gk20a/fecs_trace_gk20a.c
@@ -20,10 +20,6 @@
20 * DEALINGS IN THE SOFTWARE. 20 * DEALINGS IN THE SOFTWARE.
21 */ 21 */
22 22
23#ifdef CONFIG_DEBUG_FS
24#include <linux/debugfs.h>
25#endif
26
27#include <nvgpu/kmem.h> 23#include <nvgpu/kmem.h>
28#include <nvgpu/dma.h> 24#include <nvgpu/dma.h>
29#include <nvgpu/enabled.h> 25#include <nvgpu/enabled.h>
@@ -43,32 +39,13 @@
43#include "fecs_trace_gk20a.h" 39#include "fecs_trace_gk20a.h"
44#include "gk20a.h" 40#include "gk20a.h"
45#include "gr_gk20a.h" 41#include "gr_gk20a.h"
46#include "os/linux/os_linux.h"
47 42
48#include <nvgpu/log.h> 43#include <nvgpu/log.h>
44#include <nvgpu/fecs_trace.h>
49 45
50#include <nvgpu/hw/gk20a/hw_ctxsw_prog_gk20a.h> 46#include <nvgpu/hw/gk20a/hw_ctxsw_prog_gk20a.h>
51#include <nvgpu/hw/gk20a/hw_gr_gk20a.h> 47#include <nvgpu/hw/gk20a/hw_gr_gk20a.h>
52 48
53/*
54 * If HW circular buffer is getting too many "buffer full" conditions,
55 * increasing this constant should help (it drives Linux' internal buffer size).
56 */
57#define GK20A_FECS_TRACE_NUM_RECORDS (1 << 10)
58#define GK20A_FECS_TRACE_HASH_BITS 8 /* 2^8 */
59#define GK20A_FECS_TRACE_FRAME_PERIOD_US (1000000ULL/60ULL)
60#define GK20A_FECS_TRACE_PTIMER_SHIFT 5
61
62struct gk20a_fecs_trace_record {
63 u32 magic_lo;
64 u32 magic_hi;
65 u32 context_id;
66 u32 context_ptr;
67 u32 new_context_id;
68 u32 new_context_ptr;
69 u64 ts[];
70};
71
72struct gk20a_fecs_trace_hash_ent { 49struct gk20a_fecs_trace_hash_ent {
73 u32 context_ptr; 50 u32 context_ptr;
74 pid_t pid; 51 pid_t pid;
@@ -85,29 +62,33 @@ struct gk20a_fecs_trace {
85}; 62};
86 63
87#ifdef CONFIG_GK20A_CTXSW_TRACE 64#ifdef CONFIG_GK20A_CTXSW_TRACE
88static inline u32 gk20a_fecs_trace_record_ts_tag_v(u64 ts) 65u32 gk20a_fecs_trace_record_ts_tag_invalid_ts_v(void)
66{
67 return ctxsw_prog_record_timestamp_timestamp_hi_tag_invalid_timestamp_v();
68}
69
70u32 gk20a_fecs_trace_record_ts_tag_v(u64 ts)
89{ 71{
90 return ctxsw_prog_record_timestamp_timestamp_hi_tag_v((u32) (ts >> 32)); 72 return ctxsw_prog_record_timestamp_timestamp_hi_tag_v((u32) (ts >> 32));
91} 73}
92 74
93static inline u64 gk20a_fecs_trace_record_ts_timestamp_v(u64 ts) 75u64 gk20a_fecs_trace_record_ts_timestamp_v(u64 ts)
94{ 76{
95 return ts & ~(((u64)ctxsw_prog_record_timestamp_timestamp_hi_tag_m()) << 32); 77 return ts & ~(((u64)ctxsw_prog_record_timestamp_timestamp_hi_tag_m()) << 32);
96} 78}
97 79
98
99static u32 gk20a_fecs_trace_fecs_context_ptr(struct gk20a *g, struct channel_gk20a *ch) 80static u32 gk20a_fecs_trace_fecs_context_ptr(struct gk20a *g, struct channel_gk20a *ch)
100{ 81{
101 return (u32) (nvgpu_inst_block_addr(g, &ch->inst_block) >> 12LL); 82 return (u32) (nvgpu_inst_block_addr(g, &ch->inst_block) >> 12LL);
102} 83}
103 84
104static inline int gk20a_fecs_trace_num_ts(void) 85int gk20a_fecs_trace_num_ts(void)
105{ 86{
106 return (ctxsw_prog_record_timestamp_record_size_in_bytes_v() 87 return (ctxsw_prog_record_timestamp_record_size_in_bytes_v()
107 - sizeof(struct gk20a_fecs_trace_record)) / sizeof(u64); 88 - sizeof(struct gk20a_fecs_trace_record)) / sizeof(u64);
108} 89}
109 90
110static struct gk20a_fecs_trace_record *gk20a_fecs_trace_get_record( 91struct gk20a_fecs_trace_record *gk20a_fecs_trace_get_record(
111 struct gk20a *g, int idx) 92 struct gk20a *g, int idx)
112{ 93{
113 struct nvgpu_mem *mem = &g->gr.global_ctx_buffer[FECS_TRACE_BUFFER].mem; 94 struct nvgpu_mem *mem = &g->gr.global_ctx_buffer[FECS_TRACE_BUFFER].mem;
@@ -117,7 +98,7 @@ static struct gk20a_fecs_trace_record *gk20a_fecs_trace_get_record(
117 + (idx * ctxsw_prog_record_timestamp_record_size_in_bytes_v())); 98 + (idx * ctxsw_prog_record_timestamp_record_size_in_bytes_v()));
118} 99}
119 100
120static bool gk20a_fecs_trace_is_valid_record(struct gk20a_fecs_trace_record *r) 101bool gk20a_fecs_trace_is_valid_record(struct gk20a_fecs_trace_record *r)
121{ 102{
122 /* 103 /*
123 * testing magic_hi should suffice. magic_lo is sometimes used 104 * testing magic_hi should suffice. magic_lo is sometimes used
@@ -127,13 +108,13 @@ static bool gk20a_fecs_trace_is_valid_record(struct gk20a_fecs_trace_record *r)
127 == ctxsw_prog_record_timestamp_magic_value_hi_v_value_v()); 108 == ctxsw_prog_record_timestamp_magic_value_hi_v_value_v());
128} 109}
129 110
130static int gk20a_fecs_trace_get_read_index(struct gk20a *g) 111int gk20a_fecs_trace_get_read_index(struct gk20a *g)
131{ 112{
132 return gr_gk20a_elpg_protected_call(g, 113 return gr_gk20a_elpg_protected_call(g,
133 gk20a_readl(g, gr_fecs_mailbox1_r())); 114 gk20a_readl(g, gr_fecs_mailbox1_r()));
134} 115}
135 116
136static int gk20a_fecs_trace_get_write_index(struct gk20a *g) 117int gk20a_fecs_trace_get_write_index(struct gk20a *g)
137{ 118{
138 return gr_gk20a_elpg_protected_call(g, 119 return gr_gk20a_elpg_protected_call(g,
139 gk20a_readl(g, gr_fecs_mailbox0_r())); 120 gk20a_readl(g, gr_fecs_mailbox0_r()));
@@ -424,147 +405,6 @@ size_t gk20a_fecs_trace_buffer_size(struct gk20a *g)
424 * ctxsw_prog_record_timestamp_record_size_in_bytes_v(); 405 * ctxsw_prog_record_timestamp_record_size_in_bytes_v();
425} 406}
426 407
427#ifdef CONFIG_DEBUG_FS
428/*
429 * The sequence iterator functions. We simply use the count of the
430 * next line as our internal position.
431 */
432static void *gk20a_fecs_trace_debugfs_ring_seq_start(
433 struct seq_file *s, loff_t *pos)
434{
435 if (*pos >= GK20A_FECS_TRACE_NUM_RECORDS)
436 return NULL;
437
438 return pos;
439}
440
441static void *gk20a_fecs_trace_debugfs_ring_seq_next(
442 struct seq_file *s, void *v, loff_t *pos)
443{
444 ++(*pos);
445 if (*pos >= GK20A_FECS_TRACE_NUM_RECORDS)
446 return NULL;
447 return pos;
448}
449
450static void gk20a_fecs_trace_debugfs_ring_seq_stop(
451 struct seq_file *s, void *v)
452{
453}
454
455static int gk20a_fecs_trace_debugfs_ring_seq_show(
456 struct seq_file *s, void *v)
457{
458 loff_t *pos = (loff_t *) v;
459 struct gk20a *g = *(struct gk20a **)s->private;
460 struct gk20a_fecs_trace_record *r =
461 gk20a_fecs_trace_get_record(g, *pos);
462 int i;
463 const u32 invalid_tag =
464 ctxsw_prog_record_timestamp_timestamp_hi_tag_invalid_timestamp_v();
465 u32 tag;
466 u64 timestamp;
467
468 seq_printf(s, "record #%lld (%p)\n", *pos, r);
469 seq_printf(s, "\tmagic_lo=%08x\n", r->magic_lo);
470 seq_printf(s, "\tmagic_hi=%08x\n", r->magic_hi);
471 if (gk20a_fecs_trace_is_valid_record(r)) {
472 seq_printf(s, "\tcontext_ptr=%08x\n", r->context_ptr);
473 seq_printf(s, "\tcontext_id=%08x\n", r->context_id);
474 seq_printf(s, "\tnew_context_ptr=%08x\n", r->new_context_ptr);
475 seq_printf(s, "\tnew_context_id=%08x\n", r->new_context_id);
476 for (i = 0; i < gk20a_fecs_trace_num_ts(); i++) {
477 tag = gk20a_fecs_trace_record_ts_tag_v(r->ts[i]);
478 if (tag == invalid_tag)
479 continue;
480 timestamp = gk20a_fecs_trace_record_ts_timestamp_v(r->ts[i]);
481 timestamp <<= GK20A_FECS_TRACE_PTIMER_SHIFT;
482 seq_printf(s, "\ttag=%02x timestamp=%012llx\n", tag, timestamp);
483 }
484 }
485 return 0;
486}
487
488/*
489 * Tie them all together into a set of seq_operations.
490 */
491static const struct seq_operations gk20a_fecs_trace_debugfs_ring_seq_ops = {
492 .start = gk20a_fecs_trace_debugfs_ring_seq_start,
493 .next = gk20a_fecs_trace_debugfs_ring_seq_next,
494 .stop = gk20a_fecs_trace_debugfs_ring_seq_stop,
495 .show = gk20a_fecs_trace_debugfs_ring_seq_show
496};
497
498/*
499 * Time to set up the file operations for our /proc file. In this case,
500 * all we need is an open function which sets up the sequence ops.
501 */
502
503static int gk20a_ctxsw_debugfs_ring_open(struct inode *inode,
504 struct file *file)
505{
506 struct gk20a **p;
507
508 if (!capable(CAP_SYS_ADMIN))
509 return -EPERM;
510
511 p = __seq_open_private(file, &gk20a_fecs_trace_debugfs_ring_seq_ops,
512 sizeof(struct gk20a *));
513 if (!p)
514 return -ENOMEM;
515
516 *p = (struct gk20a *)inode->i_private;
517 return 0;
518};
519
520/*
521 * The file operations structure contains our open function along with
522 * set of the canned seq_ ops.
523 */
524static const struct file_operations gk20a_fecs_trace_debugfs_ring_fops = {
525 .owner = THIS_MODULE,
526 .open = gk20a_ctxsw_debugfs_ring_open,
527 .read = seq_read,
528 .llseek = seq_lseek,
529 .release = seq_release_private
530};
531
532static int gk20a_fecs_trace_debugfs_read(void *arg, u64 *val)
533{
534 *val = gk20a_fecs_trace_get_read_index((struct gk20a *)arg);
535 return 0;
536}
537DEFINE_SIMPLE_ATTRIBUTE(gk20a_fecs_trace_debugfs_read_fops,
538 gk20a_fecs_trace_debugfs_read, NULL, "%llu\n");
539
540static int gk20a_fecs_trace_debugfs_write(void *arg, u64 *val)
541{
542 *val = gk20a_fecs_trace_get_write_index((struct gk20a *)arg);
543 return 0;
544}
545DEFINE_SIMPLE_ATTRIBUTE(gk20a_fecs_trace_debugfs_write_fops,
546 gk20a_fecs_trace_debugfs_write, NULL, "%llu\n");
547
548static void gk20a_fecs_trace_debugfs_init(struct gk20a *g)
549{
550 struct nvgpu_os_linux *l = nvgpu_os_linux_from_gk20a(g);
551
552 debugfs_create_file("ctxsw_trace_read", 0600, l->debugfs, g,
553 &gk20a_fecs_trace_debugfs_read_fops);
554 debugfs_create_file("ctxsw_trace_write", 0600, l->debugfs, g,
555 &gk20a_fecs_trace_debugfs_write_fops);
556 debugfs_create_file("ctxsw_trace_ring", 0600, l->debugfs, g,
557 &gk20a_fecs_trace_debugfs_ring_fops);
558}
559
560#else
561
562static void gk20a_fecs_trace_debugfs_init(struct gk20a *g)
563{
564}
565
566#endif /* CONFIG_DEBUG_FS */
567
568int gk20a_fecs_trace_init(struct gk20a *g) 408int gk20a_fecs_trace_init(struct gk20a *g)
569{ 409{
570 struct gk20a_fecs_trace *trace; 410 struct gk20a_fecs_trace *trace;
@@ -589,8 +429,6 @@ int gk20a_fecs_trace_init(struct gk20a *g)
589 429
590 __nvgpu_set_enabled(g, NVGPU_SUPPORT_FECS_CTXSW_TRACE, true); 430 __nvgpu_set_enabled(g, NVGPU_SUPPORT_FECS_CTXSW_TRACE, true);
591 431
592 gk20a_fecs_trace_debugfs_init(g);
593
594 trace->init = true; 432 trace->init = true;
595 433
596 return 0; 434 return 0;
diff --git a/drivers/gpu/nvgpu/include/nvgpu/fecs_trace.h b/drivers/gpu/nvgpu/include/nvgpu/fecs_trace.h
new file mode 100644
index 00000000..5dc35302
--- /dev/null
+++ b/drivers/gpu/nvgpu/include/nvgpu/fecs_trace.h
@@ -0,0 +1,60 @@
1/*
2 * Copyright (c) 2018, NVIDIA CORPORATION. All rights reserved.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
20 * DEALINGS IN THE SOFTWARE.
21 */
22
23#ifndef NVGPU_FECS_TRACE_H
24#define NVGPU_FECS_TRACE_H
25
26struct gk20a;
27
28/*
29 * If HW circular buffer is getting too many "buffer full" conditions,
30 * increasing this constant should help (it drives Linux' internal buffer size).
31 */
32#define GK20A_FECS_TRACE_NUM_RECORDS (1 << 10)
33#define GK20A_FECS_TRACE_HASH_BITS 8 /* 2^8 */
34#define GK20A_FECS_TRACE_FRAME_PERIOD_US (1000000ULL/60ULL)
35#define GK20A_FECS_TRACE_PTIMER_SHIFT 5
36
37struct gk20a_fecs_trace_record {
38 u32 magic_lo;
39 u32 magic_hi;
40 u32 context_id;
41 u32 context_ptr;
42 u32 new_context_id;
43 u32 new_context_ptr;
44 u64 ts[];
45};
46
47#ifdef CONFIG_GK20A_CTXSW_TRACE
48u32 gk20a_fecs_trace_record_ts_tag_invalid_ts_v(void);
49u32 gk20a_fecs_trace_record_ts_tag_v(u64 ts);
50u64 gk20a_fecs_trace_record_ts_timestamp_v(u64 ts);
51int gk20a_fecs_trace_num_ts(void);
52struct gk20a_fecs_trace_record *gk20a_fecs_trace_get_record(struct gk20a *g,
53 int idx);
54bool gk20a_fecs_trace_is_valid_record(struct gk20a_fecs_trace_record *r);
55int gk20a_fecs_trace_get_read_index(struct gk20a *g);
56int gk20a_fecs_trace_get_write_index(struct gk20a *g);
57
58#endif /* CONFIG_GK20A_CTXSW_TRACE */
59
60#endif
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}
diff --git a/drivers/gpu/nvgpu/os/linux/debug_fecs_trace.h b/drivers/gpu/nvgpu/os/linux/debug_fecs_trace.h
new file mode 100644
index 00000000..a545f2db
--- /dev/null
+++ b/drivers/gpu/nvgpu/os/linux/debug_fecs_trace.h
@@ -0,0 +1,30 @@
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#ifndef LINUX_DEBUG_FECS_TRACE_H
18#define LINUX_DEBUG_FECS_TRACE_H
19
20struct gk20a;
21
22#if defined(CONFIG_DEBUG_FS) && defined(CONFIG_GK20A_CTXSW_TRACE)
23int nvgpu_fecs_trace_init_debugfs(struct gk20a *g);
24#else
25int nvgpu_fecs_trace_init_debugfs(struct gk20a *g)
26{
27 return 0;
28}
29#endif
30#endif
diff --git a/drivers/gpu/nvgpu/os/linux/module.c b/drivers/gpu/nvgpu/os/linux/module.c
index 85439b88..ff4d9a4c 100644
--- a/drivers/gpu/nvgpu/os/linux/module.c
+++ b/drivers/gpu/nvgpu/os/linux/module.c
@@ -216,6 +216,14 @@ int nvgpu_finalize_poweron_linux(struct nvgpu_os_linux *l)
216 } 216 }
217 } 217 }
218 218
219 if (l->ops.fecs_trace.init_debugfs) {
220 err = l->ops.fecs_trace.init_debugfs(g);
221 if (err) {
222 nvgpu_err(g, "failed to init linux fecs trace debugfs");
223 return err;
224 }
225 }
226
219 err = nvgpu_pmgr_init_debugfs_linux(l); 227 err = nvgpu_pmgr_init_debugfs_linux(l);
220 if (err) { 228 if (err) {
221 nvgpu_err(g, "failed to init linux pmgr debugfs"); 229 nvgpu_err(g, "failed to init linux pmgr debugfs");
diff --git a/drivers/gpu/nvgpu/os/linux/os_linux.h b/drivers/gpu/nvgpu/os/linux/os_linux.h
index ff871fe5..a9a9ebb6 100644
--- a/drivers/gpu/nvgpu/os/linux/os_linux.h
+++ b/drivers/gpu/nvgpu/os/linux/os_linux.h
@@ -46,6 +46,10 @@ struct nvgpu_os_linux_ops {
46 struct { 46 struct {
47 int (*init_debugfs)(struct gk20a *g); 47 int (*init_debugfs)(struct gk20a *g);
48 } therm; 48 } therm;
49
50 struct {
51 int (*init_debugfs)(struct gk20a *g);
52 } fecs_trace;
49}; 53};
50 54
51struct nvgpu_os_linux { 55struct nvgpu_os_linux {
diff --git a/drivers/gpu/nvgpu/os/linux/os_ops.c b/drivers/gpu/nvgpu/os/linux/os_ops.c
index 5c2eb25c..f1ab4b15 100644
--- a/drivers/gpu/nvgpu/os/linux/os_ops.c
+++ b/drivers/gpu/nvgpu/os/linux/os_ops.c
@@ -19,6 +19,7 @@
19#include "os_ops_gm20b.h" 19#include "os_ops_gm20b.h"
20#include "os_ops_gp10b.h" 20#include "os_ops_gp10b.h"
21#include "os_ops_gp106.h" 21#include "os_ops_gp106.h"
22#include "os_ops_gv11b.h"
22#include "os_ops_gv100.h" 23#include "os_ops_gv100.h"
23 24
24#if defined(CONFIG_TEGRA_GPU_NEXT) 25#if defined(CONFIG_TEGRA_GPU_NEXT)
@@ -44,6 +45,9 @@ int nvgpu_init_os_linux_ops(struct nvgpu_os_linux *l)
44 case NVGPU_GPUID_GV100: 45 case NVGPU_GPUID_GV100:
45 nvgpu_gv100_init_os_ops(l); 46 nvgpu_gv100_init_os_ops(l);
46 break; 47 break;
48 case NVGPU_GPUID_GV11B:
49 nvgpu_gv11b_init_os_ops(l);
50 break;
47#if defined(CONFIG_TEGRA_GPU_NEXT) 51#if defined(CONFIG_TEGRA_GPU_NEXT)
48 case NVGPU_GPUID_NEXT: 52 case NVGPU_GPUID_NEXT:
49 NVGPU_NEXT_INIT_OS_OPS(l); 53 NVGPU_NEXT_INIT_OS_OPS(l);
diff --git a/drivers/gpu/nvgpu/os/linux/os_ops_gp106.c b/drivers/gpu/nvgpu/os/linux/os_ops_gp106.c
index 662f4551..14f1b004 100644
--- a/drivers/gpu/nvgpu/os/linux/os_ops_gp106.c
+++ b/drivers/gpu/nvgpu/os/linux/os_ops_gp106.c
@@ -18,6 +18,7 @@
18 18
19#include "debug_clk_gp106.h" 19#include "debug_clk_gp106.h"
20#include "debug_therm_gp106.h" 20#include "debug_therm_gp106.h"
21#include "debug_fecs_trace.h"
21 22
22static struct nvgpu_os_linux_ops gp106_os_linux_ops = { 23static struct nvgpu_os_linux_ops gp106_os_linux_ops = {
23 .clk = { 24 .clk = {
@@ -26,10 +27,14 @@ static struct nvgpu_os_linux_ops gp106_os_linux_ops = {
26 .therm = { 27 .therm = {
27 .init_debugfs = gp106_therm_init_debugfs, 28 .init_debugfs = gp106_therm_init_debugfs,
28 }, 29 },
30 .fecs_trace = {
31 .init_debugfs = nvgpu_fecs_trace_init_debugfs,
32 },
29}; 33};
30 34
31void nvgpu_gp106_init_os_ops(struct nvgpu_os_linux *l) 35void nvgpu_gp106_init_os_ops(struct nvgpu_os_linux *l)
32{ 36{
33 l->ops.clk = gp106_os_linux_ops.clk; 37 l->ops.clk = gp106_os_linux_ops.clk;
34 l->ops.therm = gp106_os_linux_ops.therm; 38 l->ops.therm = gp106_os_linux_ops.therm;
39 l->ops.fecs_trace = gp106_os_linux_ops.fecs_trace;
35} 40}
diff --git a/drivers/gpu/nvgpu/os/linux/os_ops_gp10b.c b/drivers/gpu/nvgpu/os/linux/os_ops_gp10b.c
index 984dcdc0..e2891f73 100644
--- a/drivers/gpu/nvgpu/os/linux/os_ops_gp10b.c
+++ b/drivers/gpu/nvgpu/os/linux/os_ops_gp10b.c
@@ -17,6 +17,7 @@
17#include "os_linux.h" 17#include "os_linux.h"
18 18
19#include "cde_gp10b.h" 19#include "cde_gp10b.h"
20#include "debug_fecs_trace.h"
20 21
21static struct nvgpu_os_linux_ops gp10b_os_linux_ops = { 22static struct nvgpu_os_linux_ops gp10b_os_linux_ops = {
22#ifdef CONFIG_NVGPU_SUPPORT_CDE 23#ifdef CONFIG_NVGPU_SUPPORT_CDE
@@ -26,6 +27,9 @@ static struct nvgpu_os_linux_ops gp10b_os_linux_ops = {
26 .populate_scatter_buffer = gp10b_populate_scatter_buffer, 27 .populate_scatter_buffer = gp10b_populate_scatter_buffer,
27 }, 28 },
28#endif 29#endif
30 .fecs_trace = {
31 .init_debugfs = nvgpu_fecs_trace_init_debugfs,
32 },
29}; 33};
30 34
31void nvgpu_gp10b_init_os_ops(struct nvgpu_os_linux *l) 35void nvgpu_gp10b_init_os_ops(struct nvgpu_os_linux *l)
@@ -33,4 +37,5 @@ void nvgpu_gp10b_init_os_ops(struct nvgpu_os_linux *l)
33#ifdef CONFIG_NVGPU_SUPPORT_CDE 37#ifdef CONFIG_NVGPU_SUPPORT_CDE
34 l->ops.cde = gp10b_os_linux_ops.cde; 38 l->ops.cde = gp10b_os_linux_ops.cde;
35#endif 39#endif
40 l->ops.fecs_trace = gp10b_os_linux_ops.fecs_trace;
36} 41}
diff --git a/drivers/gpu/nvgpu/os/linux/os_ops_gv100.c b/drivers/gpu/nvgpu/os/linux/os_ops_gv100.c
index 7a5174a4..f5c5a604 100644
--- a/drivers/gpu/nvgpu/os/linux/os_ops_gv100.c
+++ b/drivers/gpu/nvgpu/os/linux/os_ops_gv100.c
@@ -18,6 +18,7 @@
18 18
19#include "debug_clk_gp106.h" 19#include "debug_clk_gp106.h"
20#include "debug_therm_gp106.h" 20#include "debug_therm_gp106.h"
21#include "debug_fecs_trace.h"
21 22
22static struct nvgpu_os_linux_ops gv100_os_linux_ops = { 23static struct nvgpu_os_linux_ops gv100_os_linux_ops = {
23 .clk = { 24 .clk = {
@@ -26,10 +27,14 @@ static struct nvgpu_os_linux_ops gv100_os_linux_ops = {
26 .therm = { 27 .therm = {
27 .init_debugfs = gp106_therm_init_debugfs, 28 .init_debugfs = gp106_therm_init_debugfs,
28 }, 29 },
30 .fecs_trace = {
31 .init_debugfs = nvgpu_fecs_trace_init_debugfs,
32 },
29}; 33};
30 34
31void nvgpu_gv100_init_os_ops(struct nvgpu_os_linux *l) 35void nvgpu_gv100_init_os_ops(struct nvgpu_os_linux *l)
32{ 36{
33 l->ops.clk = gv100_os_linux_ops.clk; 37 l->ops.clk = gv100_os_linux_ops.clk;
34 l->ops.therm = gv100_os_linux_ops.therm; 38 l->ops.therm = gv100_os_linux_ops.therm;
39 l->ops.fecs_trace = gv100_os_linux_ops.fecs_trace;
35} 40}
diff --git a/drivers/gpu/nvgpu/os/linux/os_ops_gv11b.c b/drivers/gpu/nvgpu/os/linux/os_ops_gv11b.c
new file mode 100644
index 00000000..a82ad0ab
--- /dev/null
+++ b/drivers/gpu/nvgpu/os/linux/os_ops_gv11b.c
@@ -0,0 +1,30 @@
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 "os_linux.h"
18
19#include "debug_fecs_trace.h"
20
21static struct nvgpu_os_linux_ops gv11b_os_linux_ops = {
22 .fecs_trace = {
23 .init_debugfs = nvgpu_fecs_trace_init_debugfs,
24 },
25};
26
27void nvgpu_gv11b_init_os_ops(struct nvgpu_os_linux *l)
28{
29 l->ops.fecs_trace = gv11b_os_linux_ops.fecs_trace;
30}
diff --git a/drivers/gpu/nvgpu/os/linux/os_ops_gv11b.h b/drivers/gpu/nvgpu/os/linux/os_ops_gv11b.h
new file mode 100644
index 00000000..eef6c4ac
--- /dev/null
+++ b/drivers/gpu/nvgpu/os/linux/os_ops_gv11b.h
@@ -0,0 +1,24 @@
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#ifndef LINUX_OS_OPS_GV11B_H
18#define LINUX_OS_OPS_GV11B_H
19
20struct nvgpu_os_linux;
21
22void nvgpu_gv11b_init_os_ops(struct nvgpu_os_linux *l);
23
24#endif