aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--device_info_procfs.c140
-rw-r--r--nvdebug.h37
-rw-r--r--nvdebug_entry.c41
3 files changed, 179 insertions, 39 deletions
diff --git a/device_info_procfs.c b/device_info_procfs.c
index 1fc0586..b1e58b1 100644
--- a/device_info_procfs.c
+++ b/device_info_procfs.c
@@ -31,7 +31,7 @@ struct file_operations nvdebug_read_reg32_file_ops = {
31 31
32// Called to start or resume a sequence. Prior to 4.19, *pos is unreliable. 32// Called to start or resume a sequence. Prior to 4.19, *pos is unreliable.
33// Initializes iterator `idx` state and returns it. Ends sequence on NULL. 33// Initializes iterator `idx` state and returns it. Ends sequence on NULL.
34static void* device_info_file_seq_start(struct seq_file *s, loff_t *pos) { 34static void* device_info_file_seq_start_previous(struct seq_file *s, loff_t *pos) {
35 static int idx; 35 static int idx;
36 // If start of sequence, reset `idx` 36 // If start of sequence, reset `idx`
37 if (*pos == 0) 37 if (*pos == 0)
@@ -42,9 +42,21 @@ static void* device_info_file_seq_start(struct seq_file *s, loff_t *pos) {
42 return &idx; 42 return &idx;
43} 43}
44 44
45static void* device_info_file_seq_start_ampere(struct seq_file *s, loff_t *pos) {
46 static int idx;
47 // If start of sequence, reset `idx`
48 if (*pos == 0)
49 idx = 0;
50 struct nvdebug_state *g = &g_nvdebug_state[seq2gpuidx(s)];
51 // Number of possible info entries is fixed, and list is sparse
52 if (idx >= (nvdebug_readl(g, 0x0224fc) >> 20))
53 return NULL;
54 return &idx;
55}
56
45// Steps to next record. Returns new value of `idx`. 57// Steps to next record. Returns new value of `idx`.
46// Calls show() on non-NULL return 58// Calls show() on non-NULL return
47static void* device_info_file_seq_next(struct seq_file *s, void *idx, 59static void* device_info_file_seq_next_previous(struct seq_file *s, void *idx,
48 loff_t *pos) { 60 loff_t *pos) {
49 (*pos)++; // Required by seq interface 61 (*pos)++; // Required by seq interface
50 // Number of possible info entries is fixed, and list is sparse 62 // Number of possible info entries is fixed, and list is sparse
@@ -53,12 +65,50 @@ static void* device_info_file_seq_next(struct seq_file *s, void *idx,
53 return idx; 65 return idx;
54} 66}
55 67
68// Steps to next record. Returns new value of `idx`.
69// Calls show() on non-NULL return
70static void* device_info_file_seq_next_ampere(struct seq_file *s, void *idx,
71 loff_t *pos) {
72 (*pos)++; // Required by seq interface
73 // Number of possible info entries is fixed, and list is sparse
74 struct nvdebug_state *g = &g_nvdebug_state[seq2gpuidx(s)];
75 if ((*(int*)idx)++ >= (nvdebug_readl(g, 0x0224fc) >> 20))
76 return NULL;
77 return idx;
78}
79/*
80// Steps to next record on Ampere GPUs. Returns new value of `idx`.
81static void* device_info_file_seq_next_ampere(struct seq_file *s, void *idx,
82 loff_t *pos) {
83 (*pos)++; // Required by seq interface
84 // Number of possible info entries is fixed, and list is sparse
85 while(1) {
86 struct nvdebug_state *g = &g_nvdebug_state[seq2gpuidx(s)];
87 if ((*(int*)idx)++ >= (nvdebug_readl(g, 0x0224fc) >> 20))
88 return NULL;
89 ptop_device_info_t curr_info;
90 curr_info.raw = nvdebug_readl(g, NV_PTOP_DEVICE_INFO_AMPERE(*(int*)idx));
91 if(!curr_info.raw && !*info_type) continue;
92 (*info_type)++;
93 break;
94 }
95 while(1) {
96 struct nvdebug_state *g = &g_nvdebug_state[seq2gpuidx(s)];
97 if ((*(int*)idx)++ >= (nvdebug_readl(g, 0x0224fc) >> 20))
98 return NULL;
99 ptop_device_info_t curr_info;
100 curr_info.raw = nvdebug_readl(g, NV_PTOP_DEVICE_INFO_AMPERE(*(int*)idx));
101 if(curr_info.raw & 0x80000000) continue;
102 break;
103 }
104 return idx;
105}
106*/
56// Print info at index *idx. Returns non-zero on error. 107// Print info at index *idx. Returns non-zero on error.
57static int device_info_file_seq_show(struct seq_file *s, void *idx) { 108static int device_info_file_seq_show_previous(struct seq_file *s, void *idx) {
58 ptop_device_info_t curr_info; 109 ptop_device_info_t curr_info;
59 struct nvdebug_state *g = &g_nvdebug_state[seq2gpuidx(s)]; 110 struct nvdebug_state *g = &g_nvdebug_state[seq2gpuidx(s)];
60 111 curr_info.raw = nvdebug_readl(g, NV_PTOP_DEVICE_INFO_PREVIOUS(*(int*)idx));
61 curr_info.raw = nvdebug_readl(g, NV_PTOP_DEVICE_INFO(*(int*)idx));
62 // Check for read errors 112 // Check for read errors
63 if (curr_info.raw == -1) 113 if (curr_info.raw == -1)
64 return -EIO; 114 return -EIO;
@@ -104,24 +154,88 @@ static int device_info_file_seq_show(struct seq_file *s, void *idx) {
104 return 0; 154 return 0;
105} 155}
106 156
157// Print info at index *idx for Ampere GPUs. Returns non-zero on error.
158static int device_info_file_seq_show_ampere(struct seq_file *s, void *idx) {
159 ptop_device_info_t curr_info;
160 struct nvdebug_state *g = &g_nvdebug_state[seq2gpuidx(s)];
161 curr_info.raw = nvdebug_readl(g, NV_PTOP_DEVICE_INFO_AMPERE(*(int*)idx));
162 // Check for read errors
163 if (curr_info.raw == -1)
164 return -EIO;
165 int info_type = -1;
166 if(curr_info.raw) {
167 if(*(int*)idx < 1 || !nvdebug_readl(g, NV_PTOP_DEVICE_INFO_AMPERE(*(int*)idx) - 1)) info_type = 0;
168 if(*(int*)idx < 2 || !nvdebug_readl(g, NV_PTOP_DEVICE_INFO_AMPERE(*(int*)idx) - 2)) info_type = 1;
169 if(*(int*)idx < 3 || !nvdebug_readl(g, NV_PTOP_DEVICE_INFO_AMPERE(*(int*)idx) - 3)) info_type = 2;
170 }
171 // Parse and print the data
172 switch(info_type) {
173 case 0:
174 seq_printf(s, "| instance %d\n", curr_info.inst_id_ampere);
175 seq_printf(s, "| Fault ID: %3d\n", curr_info.fault_id_ampere);
176 seq_printf(s, "| Engine Type: %2d (", curr_info.engine_type_ampere);
177 if (curr_info.engine_type_ampere < ENGINE_TYPES_LEN)
178 seq_printf(s, "%s)\n", ENGINE_TYPES_NAMES[curr_info.engine_type_ampere]);
179 else
180 seq_printf(s, "Unknown Engine, introduced post-Ampere)\n");
181 break;
182 case 1:
183 seq_printf(s, "| BAR0 Base %#.8x\n", curr_info.pri_base_ampere << 12);
184 seq_printf(s, "| Reset ID: %2d\n", curr_info.reset_enum_ampere);
185 break;
186 case 2:
187 seq_printf(s, "| Host's Engine ID: %2d\n", curr_info.engine_enum_ampere);
188 seq_printf(s, "| Runlist ID: %2d\n", curr_info.runlist_enum_ampere);
189 break;
190 default:
191 // Device info records are sparse, so skip unset or unknown ones
192 return 0;
193 }
194
195 // Draw a line between each device entry
196 if (!curr_info.has_next_entry_ampere) {
197 seq_printf(s, "+---------------------+\n");
198 }
199 return 0;
200}
201
202
107static void device_info_file_seq_stop(struct seq_file *s, void *idx) { 203static void device_info_file_seq_stop(struct seq_file *s, void *idx) {
108 // No cleanup needed 204 // No cleanup needed
109} 205}
110 206
111static const struct seq_operations device_info_file_seq_ops = { 207static const struct seq_operations device_info_file_seq_ops_previous = {
112 .start = device_info_file_seq_start, 208 .start = device_info_file_seq_start_previous,
113 .next = device_info_file_seq_next, 209 .next = device_info_file_seq_next_previous,
114 .stop = device_info_file_seq_stop, 210 .stop = device_info_file_seq_stop,
115 .show = device_info_file_seq_show, 211 .show = device_info_file_seq_show_previous,
212};
213
214static const struct seq_operations device_info_file_seq_ops_ampere = {
215 .start = device_info_file_seq_start_ampere,
216 .next = device_info_file_seq_next_ampere,
217 .stop = device_info_file_seq_stop,
218 .show = device_info_file_seq_show_ampere,
116}; 219};
117 220
118static int device_info_file_open(struct inode *inode, struct file *f) { 221static int device_info_file_open_previous(struct inode *inode, struct file *f) {
119 return seq_open(f, &device_info_file_seq_ops); 222 return seq_open(f, &device_info_file_seq_ops_previous);
120} 223}
121 224
122struct file_operations device_info_file_ops = { 225static int device_info_file_open_ampere(struct inode *inode, struct file *f) {
123 .open = device_info_file_open, 226 return seq_open(f, &device_info_file_seq_ops_ampere);
227}
228
229struct file_operations device_info_file_ops_previous = {
230 .open = device_info_file_open_previous,
124 .read = seq_read, 231 .read = seq_read,
125 .llseek = seq_lseek, 232 .llseek = seq_lseek,
126 .release = seq_release, 233 .release = seq_release,
127}; 234};
235
236struct file_operations device_info_file_ops_ampere = {
237 .open = device_info_file_open_ampere,
238 .read = seq_read,
239 .llseek = seq_lseek,
240 .release = seq_release,
241};
diff --git a/nvdebug.h b/nvdebug.h
index f6e057e..3ccdcfe 100644
--- a/nvdebug.h
+++ b/nvdebug.h
@@ -554,34 +554,30 @@ static const char* const ENGINE_TYPES_NAMES[ENGINE_TYPES_LEN] = {
554 See dev_top.ref.txt of NVIDIA's open-gpu-doc for more info. 554 See dev_top.ref.txt of NVIDIA's open-gpu-doc for more info.
555*/ 555*/
556 556
557#ifdef NV_BUILD_FOR_AMPERE 557#define NV_PTOP_DEVICE_INFO_AMPERE(i) (0x00022800+(i)*4)
558#define NV_PTOP_DEVICE_INFO(i) (0x00022800+(i)*4) 558#define NV_PTOP_DEVICE_INFO_PREVIOUS(i) (0x00022700+(i)*4)
559#define NV_PTOP_DEVICE_INFO__SIZE_1 64 559#define NV_PTOP_DEVICE_INFO__SIZE_1 64
560typedef union { 560typedef union {
561 struct { 561 struct {
562 uint32_t fault_id:7; 562 uint32_t fault_id_ampere:7;
563 uint32_t padding0:9; 563 uint32_t padding0_ampere:9;
564 uint32_t inst_id:4; 564 uint32_t inst_id_ampere:4;
565 uint32_t padding1:4; 565 uint32_t padding1_ampere:4;
566 enum ENGINE_TYPES engine_type:7; 566 enum ENGINE_TYPES engine_type_ampere:7;
567 bool has_next_entry:1; 567 bool has_next_entry_ampere:1;