aboutsummaryrefslogtreecommitdiffstats
path: root/runlist_procfs.c
diff options
context:
space:
mode:
authorJoshua Bakita <jbakita@cs.unc.edu>2021-09-22 11:02:45 -0400
committerJoshua Bakita <jbakita@cs.unc.edu>2021-09-22 11:16:58 -0400
commitb69863043538d9fd4590acb249124526772a80ea (patch)
tree5f1329a97c7c1ff80823362e7538ab5fc6ea6eaf /runlist_procfs.c
parent54e783959b5d3622556bbf34a3a7ad8e481d9e25 (diff)
Fix a pre-4.19 bug in seq procfs files and add detailed channel print
- The sequence file infrastructure prior to kernel version 4.19 has a bug in the retry code when the write buffer overflows that causes our private iterator state to be corrupted. Work around this by tracking some info out-of-band. - Now supports including detailed channel status information from channel RAM when printing the runlist. - Adds helper function to probe for and return struct gk20a*.
Diffstat (limited to 'runlist_procfs.c')
-rw-r--r--runlist_procfs.c87
1 files changed, 69 insertions, 18 deletions
diff --git a/runlist_procfs.c b/runlist_procfs.c
index 2107bd4..183eab6 100644
--- a/runlist_procfs.c
+++ b/runlist_procfs.c
@@ -1,12 +1,46 @@
1#include <linux/seq_file.h> // For seq_* functions and types 1#include <linux/seq_file.h> // For seq_* functions and types
2#include <linux/version.h> // Macros to detect kernel version
2 3
3#include "nvdebug.h" 4#include "nvdebug.h"
4 5
5#define RUNLIST_PROCFS_NAME "runlist" 6#define RUNLIST_PROCFS_NAME "runlist"
7#define DETAILED_CHANNEL_INFO
8
9static int runlist_detail_seq_show_chan(struct seq_file *s, struct gk20a *g, uint32_t chid) {
10 channel_ctrl_t chan;
11 char *loc_txt;
12 u64 instance_ptr;
13 chan.raw = nvdebug_readq(g, NV_PCCSR_CHANNEL_INST(chid));
14 loc_txt = target_to_text(chan.inst_target);
15 if (!loc_txt)
16 return -EIO;
17 instance_ptr = chan.inst_ptr;
18 instance_ptr <<= 12;
19 seq_printf(s, " +- Channel Info %-4d -+\n", chid);
20 seq_printf(s, " | Enabled: %d|\n", chan.enable);
21 seq_printf(s, " | Next: %d|\n", chan.next);
22 seq_printf(s, " | Force CTX Reload: %d|\n", chan.force_ctx_reload);
23 seq_printf(s, " | Enable set: %d|\n", chan.enable_set);
24 seq_printf(s, " | Enable clear: %d|\n", chan.enable_clear);
25 seq_printf(s, " | PBDMA Faulted: %d|\n", chan.pbdma_faulted);
26 seq_printf(s, " | ENG Faulted: %d|\n", chan.eng_faulted);
27 seq_printf(s, " | Status: %2d|\n", chan.status);
28 seq_printf(s, " | Busy: %d|\n", chan.busy);
29 seq_printf(s, " | Instance PTR: |\n");
30 seq_printf(s, " | %#018llx |\n", instance_ptr);
31 seq_printf(s, " | %-20s|\n", loc_txt);
32 seq_printf(s, " | Instance bound: %d|\n", chan.inst_bind);
33 seq_printf(s, " +---------------------+\n");
34 return 0;
35}
36
37#if LINUX_VERSION_CODE < KERNEL_VERSION(4,19,0)
38// Bug workaround. See comment in runlist_file_seq_start()
39static loff_t pos_fixup;
40#endif
6 41
7static void *runlist_file_seq_start(struct seq_file *s, loff_t *pos) { 42static void *runlist_file_seq_start(struct seq_file *s, loff_t *pos) {
8 static struct runlist_iter rl_iter; 43 static struct runlist_iter rl_iter;
9
10 // *pos == 0 for first call after read of file 44 // *pos == 0 for first call after read of file
11 if (*pos == 0) { 45 if (*pos == 0) {
12 int err = get_runlist_iter(&rl_iter); 46 int err = get_runlist_iter(&rl_iter);
@@ -14,6 +48,18 @@ static void *runlist_file_seq_start(struct seq_file *s, loff_t *pos) {
14 return NULL; 48 return NULL;
15 return &rl_iter; 49 return &rl_iter;
16 } 50 }
51 // If we're resuming an earlier print
52 if (*pos < rl_iter.rl_info.len) {
53#if LINUX_VERSION_CODE < KERNEL_VERSION(4,19,0)
54 // There's a nasty bug prior to 4.19-rc1 that if the buffer overflows, the
55 // last update to `pos` is not saved. Work around that here by reloading a
56 // saved copy of `pos`.
57 if (!pos_fixup)
58 return NULL;
59 *pos = pos_fixup;
60#endif
61 return &rl_iter;
62 }
17 // When called with *pos != 0, we already traversed the runlist 63 // When called with *pos != 0, we already traversed the runlist
18 return NULL; 64 return NULL;
19} 65}
@@ -21,15 +67,20 @@ static void *runlist_file_seq_start(struct seq_file *s, loff_t *pos) {
21static void* runlist_file_seq_next(struct seq_file *s, void *raw_rl_iter, 67static void* runlist_file_seq_next(struct seq_file *s, void *raw_rl_iter,
22 loff_t *pos) { 68 loff_t *pos) {
23 struct runlist_iter* rl_iter = raw_rl_iter; 69 struct runlist_iter* rl_iter = raw_rl_iter;
70 void *ret = NULL;
24 // Advance by one TSG + channels under last TSG 71 // Advance by one TSG + channels under last TSG
25 *pos += 1 + rl_iter->curr_tsg->tsg_length; 72 *pos += 1 + rl_iter->curr_tsg->tsg_length;
26 // Verify we haven't reached the end of the runlist 73 // Verify we haven't reached the end of the runlist
27 // rl_info.len is the num of tsg entries + total num of channel entries 74 // rl_info.len is the num of tsg entries + total num of channel entries
28 if (*pos < rl_iter->rl_info.len) { 75 if (*pos < rl_iter->rl_info.len) {
29 rl_iter->curr_tsg = next_tsg(rl_iter->curr_tsg); 76 rl_iter->curr_tsg = next_tsg(rl_iter->curr_tsg);
30 return rl_iter; 77 ret = rl_iter;
31 } 78 }
32 return NULL; 79#if LINUX_VERSION_CODE < KERNEL_VERSION(4,19,0)
80 // Bug workaround. See comment in runlist_file_seq_start()
81 pos_fixup = ret ? *pos : 0;
82#endif
83 return ret;
33} 84}
34 85
35static void runlist_file_seq_stop(struct seq_file *s, void *raw_rl_iter) { 86static void runlist_file_seq_stop(struct seq_file *s, void *raw_rl_iter) {
@@ -39,8 +90,11 @@ static void runlist_file_seq_stop(struct seq_file *s, void *raw_rl_iter) {
39static int runlist_file_seq_show(struct seq_file *s, void *raw_rl_iter) { 90static int runlist_file_seq_show(struct seq_file *s, void *raw_rl_iter) {
40 struct entry_tsg* tsg = ((struct runlist_iter*)raw_rl_iter)->curr_tsg; 91 struct entry_tsg* tsg = ((struct runlist_iter*)raw_rl_iter)->curr_tsg;
41 struct runlist_chan* chan; 92 struct runlist_chan* chan;
93 struct gk20a *g = get_live_gk20a();
94 if (!g)
95 return -EIO;
42 if (tsg->entry_type != ENTRY_TYPE_TSG) { 96 if (tsg->entry_type != ENTRY_TYPE_TSG) {
43 printk(KERN_WARNING "[nvdebug] Attempted to print non-TSG in nvdebug_print_tsg()!\n"); 97 printk(KERN_WARNING "[nvdebug] Attempted to print non-TSG in tsg print logic!\n");
44 return -EIO; 98 return -EIO;
45 } 99 }
46 seq_printf(s, "+---- TSG Entry %-2d----+\n", tsg->tsgid); 100 seq_printf(s, "+---- TSG Entry %-2d----+\n", tsg->tsgid);
@@ -48,25 +102,21 @@ static int runlist_file_seq_show(struct seq_file *s, void *raw_rl_iter) {
48 seq_printf(s, "| Timeout: %-11d|\n", tsg->timeslice_timeout); 102 seq_printf(s, "| Timeout: %-11d|\n", tsg->timeslice_timeout);
49 seq_printf(s, "+---------------------+\n"); 103 seq_printf(s, "+---------------------+\n");
50 for_chan_in_tsg(chan, tsg) { 104 for_chan_in_tsg(chan, tsg) {
105#ifndef DETAILED_CHANNEL_INFO
51 char* loc_txt; 106 char* loc_txt;
52 u64 instance_ptr; 107 u64 instance_ptr;
108#endif
53 if (chan->entry_type != ENTRY_TYPE_CHAN) { 109 if (chan->entry_type != ENTRY_TYPE_CHAN) {
54 printk(KERN_WARNING "[nvdebug] Attempted to print non-channel in nvdebug_print_channel()!\n"); 110 printk(KERN_WARNING "[nvdebug] Attempted to print non-channel in channel print logic!\n");
55 return -EIO; 111 return -EIO;
56 } 112 }
57 switch (chan->inst_target) { 113#ifdef DETAILED_CHANNEL_INFO
58 case TARGET_VID_MEM: 114 runlist_detail_seq_show_chan(s, g, chan->chid);
59 loc_txt = "VID_MEM"; 115#else
60 break; 116 loc_txt = target_to_text(chan->inst_target);
61 case TARGET_SYS_MEM_COHERENT: 117 if (!loc_txt) {
62 loc_txt = "SYS_MEM_COHERENT"; 118 printk(KERN_WARNING "[nvdebug] Invalid apature in channel print logic!\n");
63 break; 119 return -EIO;
64 case TARGET_SYS_MEM_NONCOHERENT:
65 loc_txt = "SYS_MEM_NONCOHERENT";
66 break;
67 default:
68 printk(KERN_WARNING "[nvdebug] Invalid aperture in runlist channel!\n");
69 return -EIO;
70 } 120 }
71 // Reconstruct pointer to channel instance block 121 // Reconstruct pointer to channel instance block
72 instance_ptr = chan->inst_ptr_hi; 122 instance_ptr = chan->inst_ptr_hi;
@@ -79,6 +129,7 @@ static int runlist_file_seq_show(struct seq_file *s, void *raw_rl_iter) {
79 seq_printf(s, " | %#018llx |\n", instance_ptr); 129 seq_printf(s, " | %#018llx |\n", instance_ptr);
80 seq_printf(s, " | %-20s|\n", loc_txt); 130 seq_printf(s, " | %-20s|\n", loc_txt);
81 seq_printf(s, " +---------------------+\n"); 131 seq_printf(s, " +---------------------+\n");
132#endif
82 } 133 }
83 return 0; 134 return 0;
84} 135}