aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Makefile1
-rw-r--r--device_info_procfs.c57
-rw-r--r--nvdebug.h4
-rw-r--r--nvdebug_entry.c9
4 files changed, 21 insertions, 50 deletions
diff --git a/Makefile b/Makefile
index 8e32bd0..2dc90c7 100644
--- a/Makefile
+++ b/Makefile
@@ -5,7 +5,6 @@ KBUILD_CFLAGS += -DGIT_HASH=\"$(shell git --git-dir=$(PWD)/.git rev-parse --shor
5 5
6# TODO: Avoid needing to distribute NVIDIA's headers (at least they're MIT...) 6# TODO: Avoid needing to distribute NVIDIA's headers (at least they're MIT...)
7ccflags-y += -I$(PWD)/include 7ccflags-y += -I$(PWD)/include
8ccflags-y += -std=gnu99
9#ccflags-y += -I/playpen/Linux_for_Tegra/source/public/kernel/nvgpu/drivers/gpu/nvgpu/include 8#ccflags-y += -I/playpen/Linux_for_Tegra/source/public/kernel/nvgpu/drivers/gpu/nvgpu/include
10#ccflags-y += -I/playpen/Linux_for_Tegra/source/public/kernel/nvgpu/drivers/gpu/nvgpu 9#ccflags-y += -I/playpen/Linux_for_Tegra/source/public/kernel/nvgpu/drivers/gpu/nvgpu
11#ccflags-y += -I/playpen/Linux_for_Tegra/source/public/kernel/nvgpu/include 10#ccflags-y += -I/playpen/Linux_for_Tegra/source/public/kernel/nvgpu/include
diff --git a/device_info_procfs.c b/device_info_procfs.c
index 5ddf240..efef41a 100644
--- a/device_info_procfs.c
+++ b/device_info_procfs.c
@@ -35,31 +35,24 @@ typedef struct {
35 35
36//// ==v== PTOP_DEVICE_INFO ==v== //// 36//// ==v== PTOP_DEVICE_INFO ==v== ////
37 37
38static void* device_info_seq_start_backend(struct seq_file *s, loff_t *pos, int initial_entry_value, int total_entries) { 38// Called to start or resume a sequence. Prior to 4.19, *pos is unreliable.
39// Initializes iterator `idx` state and returns it. Ends sequence on NULL.
40static void* device_info_file_seq_start(struct seq_file *s, loff_t *pos) {
39 static device_info_iter idx; 41 static device_info_iter idx;
42 struct nvdebug_state *g = &g_nvdebug_state[seq2gpuidx(s)];
43 int is_ampere = g->chip_id == NV_CHIP_ID_AMPERE;
40 // If start of sequence, reset `idx` 44 // If start of sequence, reset `idx`
41 if (*pos == 0) { 45 if (*pos == 0) {
42 idx.index = 0; 46 idx.index = 0;
43 idx.type_of_next_entry = initial_entry_value; 47 idx.type_of_next_entry = is_ampere ? 0 : -1;
44 } 48 }
45 idx.total_entries = total_entries; 49 idx.total_entries = is_ampere ? NV_PTOP_DEVICE_INFO__SIZE_1_PREVIOUS : NV_PTOP_DEVICE_INFO__SIZE_1_AMPERE(g);
46 // Number of possible info entries is fixed, and list is sparse 50 // Number of possible info entries is fixed, and list is sparse
47 if (idx.index >= idx.total_entries) 51 if (idx.index >= idx.total_entries)
48 return NULL; 52 return NULL;
49 return &idx; 53 return &idx;
50} 54}
51 55
52// Called to start or resume a sequence. Prior to 4.19, *pos is unreliable.
53// Initializes iterator `idx` state and returns it. Ends sequence on NULL.
54static void* device_info_file_seq_start_previous(struct seq_file *s, loff_t *pos) {
55 return device_info_seq_start_backend(s, pos, -1, NV_PTOP_DEVICE_INFO__SIZE_1_PREVIOUS);
56}
57
58static void* device_info_file_seq_start_ampere(struct seq_file *s, loff_t *pos) {
59 struct nvdebug_state *g = &g_nvdebug_state[seq2gpuidx(s)];
60 return device_info_seq_start_backend(s, pos, 0, NV_PTOP_DEVICE_INFO__SIZE_1_AMPERE(g));
61}
62
63// Steps to next record. Returns new value of `idx`. 56// Steps to next record. Returns new value of `idx`.
64// Calls show() on non-NULL return 57// Calls show() on non-NULL return
65static void* device_info_file_seq_next(struct seq_file *s, void *idx, 58static void* device_info_file_seq_next(struct seq_file *s, void *idx,
@@ -166,43 +159,25 @@ static int device_info_file_seq_show_ampere(struct seq_file *s, void *idx) {
166 return 0; 159 return 0;
167} 160}
168 161
169
170static void device_info_file_seq_stop(struct seq_file *s, void *idx) { 162static void device_info_file_seq_stop(struct seq_file *s, void *idx) {
171 // No cleanup needed 163 // No cleanup needed
172} 164}
173 165
174static const struct seq_operations device_info_file_seq_ops_previous = { 166static struct seq_operations device_info_file_seq_ops = {
175 .start = device_info_file_seq_start_previous, 167 .start = device_info_file_seq_start,
176 .next = device_info_file_seq_next, 168 .next = device_info_file_seq_next,
177 .stop = device_info_file_seq_stop, 169 .stop = device_info_file_seq_stop
178 .show = device_info_file_seq_show_previous,
179};
180
181static const struct seq_operations device_info_file_seq_ops_ampere = {
182 .start = device_info_file_seq_start_ampere,
183 .next = device_info_file_seq_next,
184 .stop = device_info_file_seq_stop,
185 .show = device_info_file_seq_show_ampere,
186}; 170};
187 171
188static int device_info_file_open_previous(struct inode *inode, struct file *f) { 172static int device_info_file_open(struct inode *inode, struct file *f) {
189 return seq_open(f, &device_info_file_seq_ops_previous); 173 struct seq_operations file_seq_ops = device_info_file_seq_ops;
174 file_seq_ops.show = (g_nvdebug_state[file2parentgpuidx(f)].chip_id == NV_CHIP_ID_AMPERE) ? device_info_file_seq_show_ampere : device_info_file_seq_show_previous;
175 return seq_open(f, &file_seq_ops);
190} 176}
191 177
192static int device_info_file_open_ampere(struct inode *inode, struct file *f) { 178struct file_operations device_info_file_ops = {
193 return seq_open(f, &device_info_file_seq_ops_ampere); 179 .open = device_info_file_open,
194}
195
196struct file_operations device_info_file_ops_previous = {
197 .open = device_info_file_open_previous,
198 .read = seq_read, 180 .read = seq_read,
199 .llseek = seq_lseek, 181 .llseek = seq_lseek,
200 .release = seq_release, 182 .release = seq_release,
201}; 183};
202
203struct file_operations device_info_file_ops_ampere = {
204 .open = device_info_file_open_ampere,
205 .read = seq_read,
206 .llseek = seq_lseek,
207 .release = seq_release,
208};
diff --git a/nvdebug.h b/nvdebug.h
index c45e460..471adf9 100644
--- a/nvdebug.h
+++ b/nvdebug.h
@@ -9,8 +9,6 @@
9#include <linux/version.h> // For KERNEL_VERSION and LINUX_VERSION_CODE 9#include <linux/version.h> // For KERNEL_VERSION and LINUX_VERSION_CODE
10#include <asm/io.h> 10#include <asm/io.h>
11 11
12#define NV_BUILD_FOR_AMPERE
13
14/* Runlist Channel 12/* Runlist Channel
15 A timeslice group (TSG) is composed of channels. Each channel is a FIFO queue 13 A timeslice group (TSG) is composed of channels. Each channel is a FIFO queue
16 of GPU commands. These commands are typically queued from userspace. 14 of GPU commands. These commands are typically queued from userspace.
@@ -382,6 +380,7 @@ typedef union {
382#define NV_CHIP_ID_GV11B 0x15B // Jetson Xavier embedded GPU 380#define NV_CHIP_ID_GV11B 0x15B // Jetson Xavier embedded GPU
383#define NV_CHIP_ID_KEPLER 0x0E0 381#define NV_CHIP_ID_KEPLER 0x0E0
384#define NV_CHIP_ID_VOLTA 0x140 382#define NV_CHIP_ID_VOLTA 0x140
383#define NV_CHIP_ID_AMPERE 0x170
385 384
386inline static const char* ARCH2NAME(uint32_t arch) { 385inline static const char* ARCH2NAME(uint32_t arch) {
387 switch (arch) { 386 switch (arch) {
@@ -565,6 +564,7 @@ static const char* const ENGINE_TYPES_NAMES[ENGINE_TYPES_LEN] = {
565#define NV_PTOP_DEVICE_INFO__SIZE_1_AMPERE(g) (nvdebug_readl(g, 0x0224fc) >> 20) 564#define NV_PTOP_DEVICE_INFO__SIZE_1_AMPERE(g) (nvdebug_readl(g, 0x0224fc) >> 20)
566#define NV_PTOP_DEVICE_INFO__SIZE_1_PREVIOUS 64 565#define NV_PTOP_DEVICE_INFO__SIZE_1_PREVIOUS 64
567#define NV_PTOP_DEVICE_INFO_TYPE_COUNT 3 566#define NV_PTOP_DEVICE_INFO_TYPE_COUNT 3
567#define NV_CHIP_ID_AMPERE 0x170
568typedef union { 568typedef union {
569 struct { 569 struct {
570 uint32_t fault_id:7; 570 uint32_t fault_id:7;
diff --git a/nvdebug_entry.c b/nvdebug_entry.c
index d3d934e..0560ead 100644
--- a/nvdebug_entry.c
+++ b/nvdebug_entry.c
@@ -23,14 +23,12 @@ extern struct file_operations preempt_tsg_file_ops;
23extern struct file_operations disable_channel_file_ops; 23extern struct file_operations disable_channel_file_ops;
24extern struct file_operations enable_channel_file_ops; 24extern struct file_operations enable_channel_file_ops;
25extern struct file_operations switch_to_tsg_file_ops; 25extern struct file_operations switch_to_tsg_file_ops;
26extern struct file_operations device_info_file_ops_previous; 26extern struct file_operations device_info_file_ops;
27extern struct file_operations device_info_file_ops_ampere;
28extern struct file_operations nvdebug_read_reg32_file_ops; 27extern struct file_operations nvdebug_read_reg32_file_ops;
29 28
30// Bus types are global symbols in the kernel 29// Bus types are global symbols in the kernel
31extern struct bus_type platform_bus_type; 30extern struct bus_type platform_bus_type;
32struct nvdebug_state g_nvdebug_state[NVDEBUG_MAX_DEVICES]; 31struct nvdebug_state g_nvdebug_state[NVDEBUG_MAX_DEVICES];
33int g_architectures[NVDEBUG_MAX_DEVICES];
34unsigned int g_nvdebug_devices = 0; 32unsigned int g_nvdebug_devices = 0;
35 33
36// Starting in Kernel 5.6, proc_ops is required instead of file_operations 34// Starting in Kernel 5.6, proc_ops is required instead of file_operations
@@ -125,7 +123,6 @@ int probe_and_cache_device(void) {
125 return -EADDRNOTAVAIL; 123 return -EADDRNOTAVAIL;
126 } 124 }
127 g_nvdebug_state[i].chip_id = ids.chip_id; 125 g_nvdebug_state[i].chip_id = ids.chip_id;
128 g_architectures[i] = ids.architecture;
129 printk(KERN_INFO "[nvdebug] Chip ID %x (architecture %s) detected on PCI bus and initialized.", 126 printk(KERN_INFO "[nvdebug] Chip ID %x (architecture %s) detected on PCI bus and initialized.",
130 ids.chip_id, ARCH2NAME(ids.architecture)); 127 ids.chip_id, ARCH2NAME(ids.architecture));
131 // TEMP 128 // TEMP
@@ -243,7 +240,7 @@ int __init nvdebug_init(void) {
243 if (!(dir = proc_mkdir_data(device_id_str, 0555, NULL, (void*)device_id))) 240 if (!(dir = proc_mkdir_data(device_id_str, 0555, NULL, (void*)device_id)))
244 goto out_nomem; 241 goto out_nomem;
245 // Create files `/proc/gpu#/runlist#`, world readable 242 // Create files `/proc/gpu#/runlist#`, world readable
246 rl_create_err = g_architectures[device_id] == 0x17 ? create_runlist_files_ampere(device_id, dir) : create_runlist_files_previous(device_id, dir); 243 rl_create_err = (g_nvdebug_state[device_id].chip_id == NV_CHIP_ID_AMPERE) ? create_runlist_files_ampere(device_id, dir) : create_runlist_files_previous(device_id, dir);
247 // Create files `/proc/gpu#/gpc#_tpc_mask`, world readable 244 // Create files `/proc/gpu#/gpc#_tpc_mask`, world readable
248 tpc_masks_create_err = create_tpc_mask_files(device_id, dir); 245 tpc_masks_create_err = create_tpc_mask_files(device_id, dir);
249 // Create file `/proc/gpu#/preempt_tsg`, world writable 246 // Create file `/proc/gpu#/preempt_tsg`, world writable
@@ -264,7 +261,7 @@ int __init nvdebug_init(void) {
264 (void*)device_id); 261 (void*)device_id);
265 // Create file `/proc/gpu#/device_info`, world readable 262 // Create file `/proc/gpu#/device_info`, world readable
266 device_info_entry = proc_create_data( 263 device_info_entry = proc_create_data(
267 "device_info", 0444, dir, compat_ops(g_architectures[device_id] == 0x17 ? &device_info_file_ops_previous : &device_info_file_ops_ampere), 264 "device_info", 0444, dir, compat_ops(&device_info_file_ops),
268 (void*)device_id); 265 (void*)device_id);
269 // Create file `/proc/gpu#/num_gpcs`, world readable 266 // Create file `/proc/gpu#/num_gpcs`, world readable
270 num_gpcs_entry = proc_create_data( 267 num_gpcs_entry = proc_create_data(