From 845960fc1b15995fdbd6d61c384567652a150bc4 Mon Sep 17 00:00:00 2001 From: Benjamin Hadad IV Date: Fri, 28 Jul 2023 11:39:28 -0400 Subject: Refactored various systems and debugged minor issues - Added device_info_iter - Merged functions in device_info_procfs.c - Separated device_info data structs by version in nvdebug.h - Fixed issue with device_info runlist ID data --- device_info_procfs.c | 110 ++++++++++++++++++++++----------------------------- 1 file changed, 47 insertions(+), 63 deletions(-) (limited to 'device_info_procfs.c') diff --git a/device_info_procfs.c b/device_info_procfs.c index 3cf4bc9..5ddf240 100644 --- a/device_info_procfs.c +++ b/device_info_procfs.c @@ -27,61 +27,57 @@ struct file_operations nvdebug_read_reg32_file_ops = { .llseek = default_llseek, }; +typedef struct { + int total_entries; + int index; + int type_of_next_entry; +} device_info_iter; + //// ==v== PTOP_DEVICE_INFO ==v== //// +static void* device_info_seq_start_backend(struct seq_file *s, loff_t *pos, int initial_entry_value, int total_entries) { + static device_info_iter idx; + // If start of sequence, reset `idx` + if (*pos == 0) { + idx.index = 0; + idx.type_of_next_entry = initial_entry_value; + } + idx.total_entries = total_entries; + // Number of possible info entries is fixed, and list is sparse + if (idx.index >= idx.total_entries) + return NULL; + return &idx; +} + // 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_previous(struct seq_file *s, loff_t *pos) { - static int idx; - // If start of sequence, reset `idx` - if (*pos == 0) - idx = 0; - // Number of possible info entries is fixed, and list is sparse - if (idx >= NV_PTOP_DEVICE_INFO__SIZE_1_PREVIOUS) - return NULL; - return &idx; + return device_info_seq_start_backend(s, pos, -1, NV_PTOP_DEVICE_INFO__SIZE_1_PREVIOUS); } 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 >= NV_PTOP_DEVICE_INFO__SIZE_1_AMPERE(g)) - return NULL; - return &idx; + struct nvdebug_state *g = &g_nvdebug_state[seq2gpuidx(s)]; + return device_info_seq_start_backend(s, pos, 0, NV_PTOP_DEVICE_INFO__SIZE_1_AMPERE(g)); } // Steps to next record. Returns new value of `idx`. // Calls show() on non-NULL return -static void* device_info_file_seq_next_previous(struct seq_file *s, void *idx, +static void* device_info_file_seq_next(struct seq_file *s, void *idx, loff_t *pos) { + device_info_iter *idx_iter = (device_info_iter*)idx; (*pos)++; // Required by seq interface // Number of possible info entries is fixed, and list is sparse - if ((*(int*)idx)++ >= NV_PTOP_DEVICE_INFO__SIZE_1_PREVIOUS) + if (idx_iter->index++ >= idx_iter->total_entries) 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_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)++ >= NV_PTOP_DEVICE_INFO__SIZE_1_AMPERE(g)) - return NULL; - return idx; -} - // Print info at index *idx. Returns non-zero on error. static int device_info_file_seq_show_previous(struct seq_file *s, void *idx) { - ptop_device_info_t curr_info; + device_info_iter *idx_iter = (device_info_iter*)idx; + ptop_device_info_previous_t curr_info; struct nvdebug_state *g = &g_nvdebug_state[seq2gpuidx(s)]; - curr_info.raw = nvdebug_readl(g, NV_PTOP_DEVICE_INFO_PREVIOUS(*(int*)idx)); + curr_info.raw = nvdebug_readl(g, NV_PTOP_DEVICE_INFO_PREVIOUS(idx_iter->index)); // Check for read errors if (curr_info.raw == -1) return -EIO; @@ -129,54 +125,42 @@ static int device_info_file_seq_show_previous(struct seq_file *s, void *idx) { // 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; + device_info_iter *idx_iter = (device_info_iter*)idx; + ptop_device_info_ampere_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)); + curr_info.raw = nvdebug_readl(g, NV_PTOP_DEVICE_INFO_AMPERE(idx_iter->index)); // Check for read errors if (curr_info.raw == -1) return -EIO; // The info_type field is not available in the Ampere device_info data, so it must be inferred - int info_type = -1; - if(curr_info.raw) { - for(int i = 0; i < NV_PTOP_DEVICE_INFO_TYPE_COUNT; i++) { - if(*(int*)idx == i) { - info_type = i; - break; - } - ptop_device_info_t prev_info; - prev_info.raw = nvdebug_readl(g, NV_PTOP_DEVICE_INFO_AMPERE(*(int*)idx - i - 1)); - if(!prev_info.raw || !prev_info.has_next_entry_ampere) { - info_type = i; - break; - } - } - } + int info_type = curr_info.raw ? idx_iter->type_of_next_entry : -1; // 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]); + seq_printf(s, "| instance %d\n", curr_info.inst_id); + seq_printf(s, "| Fault ID: %3d\n", curr_info.fault_id); + seq_printf(s, "| Engine Type: %2d (", curr_info.engine_type); + if (curr_info.engine_type < ENGINE_TYPES_LEN) + seq_printf(s, "%s)\n", ENGINE_TYPES_NAMES[curr_info.engine_type]); 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); + seq_printf(s, "| BAR0 Base %#.8x\n", curr_info.pri_base << 12); + seq_printf(s, "| Reset ID: %2d\n", curr_info.reset_enum); 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); + seq_printf(s, "| Host's Engine ID: %2d\n", curr_info.engine_enum); + seq_printf(s, "| Runlist ID: %2d\n", curr_info.runlist_enum); break; default: // Device info records are sparse, so skip unset or unknown ones return 0; } - + if(info_type != -1) idx_iter->type_of_next_entry++; // Draw a line between each device entry - if (!curr_info.has_next_entry_ampere) { + if (!curr_info.has_next_entry) { + idx_iter->type_of_next_entry = 0; seq_printf(s, "+---------------------+\n"); } return 0; @@ -189,14 +173,14 @@ static void device_info_file_seq_stop(struct seq_file *s, void *idx) { 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, + .next = device_info_file_seq_next, .stop = device_info_file_seq_stop, .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, + .next = device_info_file_seq_next, .stop = device_info_file_seq_stop, .show = device_info_file_seq_show_ampere, }; -- cgit v1.2.2