diff options
| -rw-r--r-- | Makefile | 1 | ||||
| -rw-r--r-- | device_info_procfs.c | 57 | ||||
| -rw-r--r-- | nvdebug.h | 4 | ||||
| -rw-r--r-- | nvdebug_entry.c | 9 |
4 files changed, 21 insertions, 50 deletions
| @@ -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...) |
| 7 | ccflags-y += -I$(PWD)/include | 7 | ccflags-y += -I$(PWD)/include |
| 8 | ccflags-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 | ||
| 38 | static 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. | ||
| 40 | static 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. | ||
| 54 | static 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 | |||
| 58 | static 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 |
| 65 | static void* device_info_file_seq_next(struct seq_file *s, void *idx, | 58 | static 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 | |||
| 170 | static void device_info_file_seq_stop(struct seq_file *s, void *idx) { | 162 | static void device_info_file_seq_stop(struct seq_file *s, void *idx) { |
| 171 | // No cleanup needed | 163 | // No cleanup needed |
| 172 | } | 164 | } |
| 173 | 165 | ||
| 174 | static const struct seq_operations device_info_file_seq_ops_previous = { | 166 | static 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 | |||
| 181 | static 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 | ||
| 188 | static int device_info_file_open_previous(struct inode *inode, struct file *f) { | 172 | static 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 | ||
| 192 | static int device_info_file_open_ampere(struct inode *inode, struct file *f) { | 178 | struct 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 | |||
| 196 | struct 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 | |||
| 203 | struct 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 | }; | ||
| @@ -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 | ||
| 386 | inline static const char* ARCH2NAME(uint32_t arch) { | 385 | inline 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 | ||
| 568 | typedef union { | 568 | typedef 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; | |||
| 23 | extern struct file_operations disable_channel_file_ops; | 23 | extern struct file_operations disable_channel_file_ops; |
| 24 | extern struct file_operations enable_channel_file_ops; | 24 | extern struct file_operations enable_channel_file_ops; |
| 25 | extern struct file_operations switch_to_tsg_file_ops; | 25 | extern struct file_operations switch_to_tsg_file_ops; |
| 26 | extern struct file_operations device_info_file_ops_previous; | 26 | extern struct file_operations device_info_file_ops; |
| 27 | extern struct file_operations device_info_file_ops_ampere; | ||
| 28 | extern struct file_operations nvdebug_read_reg32_file_ops; | 27 | extern 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 |
| 31 | extern struct bus_type platform_bus_type; | 30 | extern struct bus_type platform_bus_type; |
| 32 | struct nvdebug_state g_nvdebug_state[NVDEBUG_MAX_DEVICES]; | 31 | struct nvdebug_state g_nvdebug_state[NVDEBUG_MAX_DEVICES]; |
| 33 | int g_architectures[NVDEBUG_MAX_DEVICES]; | ||
| 34 | unsigned int g_nvdebug_devices = 0; | 32 | unsigned 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( |
