From bfb4dcf0e78954c0163f3a06a5a088c4d1b437a8 Mon Sep 17 00:00:00 2001 From: Benjamin Hadad IV Date: Thu, 13 Jul 2023 12:13:17 -0400 Subject: This commit is to update the repo for display during a meeting. - Added an Ampere version of the device info data. - Added Ampere versions of auxillary functions. - Modified display functions to accommodate Ampere data. - Made other various small modifications. --- device_info_procfs.c | 140 ++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 127 insertions(+), 13 deletions(-) (limited to 'device_info_procfs.c') 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 = { // Called to start or resume a sequence. Prior to 4.19, *pos is unreliable. // Initializes iterator `idx` state and returns it. Ends sequence on NULL. -static void* device_info_file_seq_start(struct seq_file *s, loff_t *pos) { +static void* device_info_file_seq_start_previous(struct seq_file *s, loff_t *pos) { static int idx; // If start of sequence, reset `idx` if (*pos == 0) @@ -42,9 +42,21 @@ static void* device_info_file_seq_start(struct seq_file *s, loff_t *pos) { return &idx; } +static void* device_info_file_seq_start_ampere(struct seq_file *s, loff_t *pos) { + static int idx; + // If start of sequence, reset `idx` + if (*pos == 0) + idx = 0; + struct nvdebug_state *g = &g_nvdebug_state[seq2gpuidx(s)]; + // Number of possible info entries is fixed, and list is sparse + if (idx >= (nvdebug_readl(g, 0x0224fc) >> 20)) + return NULL; + return &idx; +} + // Steps to next record. Returns new value of `idx`. // Calls show() on non-NULL return -static void* device_info_file_seq_next(struct seq_file *s, void *idx, +static void* device_info_file_seq_next_previous(struct seq_file *s, void *idx, loff_t *pos) { (*pos)++; // Required by seq interface // 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, return idx; } +// Steps to next record. Returns new value of `idx`. +// Calls show() on non-NULL return +static void* device_info_file_seq_next_ampere(struct seq_file *s, void *idx, + loff_t *pos) { + (*pos)++; // Required by seq interface + // Number of possible info entries is fixed, and list is sparse + struct nvdebug_state *g = &g_nvdebug_state[seq2gpuidx(s)]; + if ((*(int*)idx)++ >= (nvdebug_readl(g, 0x0224fc) >> 20)) + return NULL; + return idx; +} +/* +// Steps to next record on Ampere GPUs. Returns new value of `idx`. +static void* device_info_file_seq_next_ampere(struct seq_file *s, void *idx, + loff_t *pos) { + (*pos)++; // Required by seq interface + // Number of possible info entries is fixed, and list is sparse + while(1) { + struct nvdebug_state *g = &g_nvdebug_state[seq2gpuidx(s)]; + if ((*(int*)idx)++ >= (nvdebug_readl(g, 0x0224fc) >> 20)) + return NULL; + ptop_device_info_t curr_info; + curr_info.raw = nvdebug_readl(g, NV_PTOP_DEVICE_INFO_AMPERE(*(int*)idx)); + if(!curr_info.raw && !*info_type) continue; + (*info_type)++; + break; + } + while(1) { + struct nvdebug_state *g = &g_nvdebug_state[seq2gpuidx(s)]; + if ((*(int*)idx)++ >= (nvdebug_readl(g, 0x0224fc) >> 20)) + return NULL; + ptop_device_info_t curr_info; + curr_info.raw = nvdebug_readl(g, NV_PTOP_DEVICE_INFO_AMPERE(*(int*)idx)); + if(curr_info.raw & 0x80000000) continue; + break; + } + return idx; +} +*/ // Print info at index *idx. Returns non-zero on error. -static int device_info_file_seq_show(struct seq_file *s, void *idx) { +static int device_info_file_seq_show_previous(struct seq_file *s, void *idx) { ptop_device_info_t curr_info; struct nvdebug_state *g = &g_nvdebug_state[seq2gpuidx(s)]; - - curr_info.raw = nvdebug_readl(g, NV_PTOP_DEVICE_INFO(*(int*)idx)); + curr_info.raw = nvdebug_readl(g, NV_PTOP_DEVICE_INFO_PREVIOUS(*(int*)idx)); // Check for read errors if (curr_info.raw == -1) return -EIO; @@ -104,24 +154,88 @@ static int device_info_file_seq_show(struct seq_file *s, void *idx) { return 0; } +// Print info at index *idx for Ampere GPUs. Returns non-zero on error. +static int device_info_file_seq_show_ampere(struct seq_file *s, void *idx) { + ptop_device_info_t curr_info; + struct nvdebug_state *g = &g_nvdebug_state[seq2gpuidx(s)]; + curr_info.raw = nvdebug_readl(g, NV_PTOP_DEVICE_INFO_AMPERE(*(int*)idx)); + // Check for read errors + if (curr_info.raw == -1) + return -EIO; + int info_type = -1; + if(curr_info.raw) { + if(*(int*)idx < 1 || !nvdebug_readl(g, NV_PTOP_DEVICE_INFO_AMPERE(*(int*)idx) - 1)) info_type = 0; + if(*(int*)idx < 2 || !nvdebug_readl(g, NV_PTOP_DEVICE_INFO_AMPERE(*(int*)idx) - 2)) info_type = 1; + if(*(int*)idx < 3 || !nvdebug_readl(g, NV_PTOP_DEVICE_INFO_AMPERE(*(int*)idx) - 3)) info_type = 2; + } + // Parse and print the data + switch(info_type) { + case 0: + seq_printf(s, "| instance %d\n", curr_info.inst_id_ampere); + seq_printf(s, "| Fault ID: %3d\n", curr_info.fault_id_ampere); + seq_printf(s, "| Engine Type: %2d (", curr_info.engine_type_ampere); + if (curr_info.engine_type_ampere < ENGINE_TYPES_LEN) + seq_printf(s, "%s)\n", ENGINE_TYPES_NAMES[curr_info.engine_type_ampere]); + else + seq_printf(s, "Unknown Engine, introduced post-Ampere)\n"); + break; + case 1: + seq_printf(s, "| BAR0 Base %#.8x\n", curr_info.pri_base_ampere << 12); + seq_printf(s, "| Reset ID: %2d\n", curr_info.reset_enum_ampere); + break; + case 2: + seq_printf(s, "| Host's Engine ID: %2d\n", curr_info.engine_enum_ampere); + seq_printf(s, "| Runlist ID: %2d\n", curr_info.runlist_enum_ampere); + break; + default: + // Device info records are sparse, so skip unset or unknown ones + return 0; + } + + // Draw a line between each device entry + if (!curr_info.has_next_entry_ampere) { + seq_printf(s, "+---------------------+\n"); + } + return 0; +} + + static void device_info_file_seq_stop(struct seq_file *s, void *idx) { // No cleanup needed } -static const struct seq_operations device_info_file_seq_ops = { - .start = device_info_file_seq_start, - .next = device_info_file_seq_next, +static const struct seq_operations device_info_file_seq_ops_previous = { + .start = device_info_file_seq_start_previous, + .next = device_info_file_seq_next_previous, .stop = device_info_file_seq_stop, - .show = device_info_file_seq_show, + .show = device_info_file_seq_show_previous, +}; + +static const struct seq_operations device_info_file_seq_ops_ampere = { + .start = device_info_file_seq_start_ampere, + .next = device_info_file_seq_next_ampere, + .stop = device_info_file_seq_stop, + .show = device_info_file_seq_show_ampere, }; -static int device_info_file_open(struct inode *inode, struct file *f) { - return seq_open(f, &device_info_file_seq_ops); +static int device_info_file_open_previous(struct inode *inode, struct file *f) { + return seq_open(f, &device_info_file_seq_ops_previous); } -struct file_operations device_info_file_ops = { - .open = device_info_file_open, +static int device_info_file_open_ampere(struct inode *inode, struct file *f) { + return seq_open(f, &device_info_file_seq_ops_ampere); +} + +struct file_operations device_info_file_ops_previous = { + .open = device_info_file_open_previous, .read = seq_read, .llseek = seq_lseek, .release = seq_release, }; + +struct file_operations device_info_file_ops_ampere = { + .open = device_info_file_open_ampere, + .read = seq_read, + .llseek = seq_lseek, + .release = seq_release, +}; -- cgit v1.2.2