aboutsummaryrefslogtreecommitdiffstats
path: root/nvdebug_entry.c
diff options
context:
space:
mode:
Diffstat (limited to 'nvdebug_entry.c')
-rw-r--r--nvdebug_entry.c41
1 files changed, 36 insertions, 5 deletions
diff --git a/nvdebug_entry.c b/nvdebug_entry.c
index 8e8266c..d82c648 100644
--- a/nvdebug_entry.c
+++ b/nvdebug_entry.c
@@ -23,12 +23,14 @@ 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; 26extern struct file_operations device_info_file_ops_previous;
27extern struct file_operations device_info_file_ops_ampere;
27extern struct file_operations nvdebug_read_reg32_file_ops; 28extern struct file_operations nvdebug_read_reg32_file_ops;
28 29
29// Bus types are global symbols in the kernel 30// Bus types are global symbols in the kernel
30extern struct bus_type platform_bus_type; 31extern struct bus_type platform_bus_type;
31struct nvdebug_state g_nvdebug_state[NVDEBUG_MAX_DEVICES]; 32struct nvdebug_state g_nvdebug_state[NVDEBUG_MAX_DEVICES];
33int g_architectures[NVDEBUG_MAX_DEVICES];
32unsigned int g_nvdebug_devices = 0; 34unsigned int g_nvdebug_devices = 0;
33 35
34// Starting in Kernel 5.6, proc_ops is required instead of file_operations 36// Starting in Kernel 5.6, proc_ops is required instead of file_operations
@@ -123,6 +125,7 @@ int probe_and_cache_device(void) {
123 return -EADDRNOTAVAIL; 125 return -EADDRNOTAVAIL;
124 } 126 }
125 g_nvdebug_state[i].chip_id = ids.chip_id; 127 g_nvdebug_state[i].chip_id = ids.chip_id;
128 g_architectures[i] = ids.architecture;
126 printk(KERN_INFO "[nvdebug] Chip ID %x (architecture %s) detected on PCI bus and initialized.", 129 printk(KERN_INFO "[nvdebug] Chip ID %x (architecture %s) detected on PCI bus and initialized.",
127 ids.chip_id, ARCH2NAME(ids.architecture)); 130 ids.chip_id, ARCH2NAME(ids.architecture));
128 // TEMP 131 // TEMP
@@ -138,7 +141,7 @@ int probe_and_cache_device(void) {
138} 141}
139 142
140// Create files `/proc/gpu#/runlist#`, world readable 143// Create files `/proc/gpu#/runlist#`, world readable
141int create_runlist_files(int device_id, struct proc_dir_entry *dir) { 144int create_runlist_files_previous(int device_id, struct proc_dir_entry *dir) {
142 ptop_device_info_t info; 145 ptop_device_info_t info;
143 struct proc_dir_entry *rl_entry; 146 struct proc_dir_entry *rl_entry;
144 int i, rl_id; 147 int i, rl_id;
@@ -148,7 +151,7 @@ int create_runlist_files(int device_id, struct proc_dir_entry *dir) {
148 // registers. Runlists are always numbered sequentially, so we just have 151 // registers. Runlists are always numbered sequentially, so we just have
149 // to find the highest-valued one and add 1 to get the number of runlists. 152 // to find the highest-valued one and add 1 to get the number of runlists.
150 for (i = 0; i < NV_PTOP_DEVICE_INFO__SIZE_1; i++) { 153 for (i = 0; i < NV_PTOP_DEVICE_INFO__SIZE_1; i++) {
151 info.raw = nvdebug_readl(&g_nvdebug_state[device_id], NV_PTOP_DEVICE_INFO(i)); 154 info.raw = nvdebug_readl(&g_nvdebug_state[device_id], NV_PTOP_DEVICE_INFO_PREVIOUS(i));
152 if (info.info_type != INFO_TYPE_ENUM || !info.runlist_is_valid) 155 if (info.info_type != INFO_TYPE_ENUM || !info.runlist_is_valid)
153 continue; 156 continue;
154 if (info.runlist_enum > max_rl_id) 157 if (info.runlist_enum > max_rl_id)
@@ -167,6 +170,34 @@ int create_runlist_files(int device_id, struct proc_dir_entry *dir) {
167 return 0; 170 return 0;
168} 171}
169 172
173// Create files `/proc/gpu#/runlist#`, world readable
174int create_runlist_files_ampere(int device_id, struct proc_dir_entry *dir) {
175 ptop_device_info_t info;
176 struct proc_dir_entry *rl_entry;
177 int i, rl_id;
178 char runlist_name[12];
179 int max_rl_id = 0; // Always at least one runlist
180 // Figure out how many runlists there are by checking the device info
181 // registers. Runlists are always numbered sequentially, so we just have
182 // to find the highest-valued one and add 1 to get the number of runlists.
183 for (i = 0; i < (nvdebug_readl(&g_nvdebug_state[device_id], 0x0224fc) >> 20); i++) {
184 info.raw = nvdebug_readl(&g_nvdebug_state[device_id], NV_PTOP_DEVICE_INFO_AMPERE(i));
185 if (info.runlist_enum_ampere > max_rl_id)
186 max_rl_id = info.runlist_enum;
187 }
188 // Create files to read each runlist. The read handling code looks at the
189 // PDE_DATA associated with the file to determine what the runlist ID is.
190 for (rl_id = 0; rl_id <= max_rl_id; rl_id++) {
191 snprintf(runlist_name, 12, "runlist%d", rl_id);
192 rl_entry = proc_create_data(
193 runlist_name, 0444, dir, compat_ops(&runlist_file_ops),
194 (void*)(uintptr_t)rl_id);
195 if (!rl_entry)
196 return -ENOMEM;
197 }
198 return 0;
199}
200
170// Create files /proc/gpu# 201// Create files /proc/gpu#
171// TODO: Don't run this on unsupported GPUs 202// TODO: Don't run this on unsupported GPUs
172int create_tpc_mask_files(int device_id, struct proc_dir_entry *dir) { 203int create_tpc_mask_files(int device_id, struct proc_dir_entry *dir) {
@@ -212,7 +243,7 @@ int __init nvdebug_init(void) {
212 if (!(dir = proc_mkdir_data(device_id_str, 0555, NULL, (void*)device_id))) 243 if (!(dir = proc_mkdir_data(device_id_str, 0555, NULL, (void*)device_id)))
213 goto out_nomem; 244 goto out_nomem;
214 // Create files `/proc/gpu#/runlist#`, world readable 245 // Create files `/proc/gpu#/runlist#`, world readable
215 rl_create_err = create_runlist_files(device_id, dir); 246 rl_create_err = g_architectures[device_id] == 0x17 ? create_runlist_files_ampere(device_id, dir) : create_runlist_files_previous(device_id, dir);
216 // Create files `/proc/gpu#/gpc#_tpc_mask`, world readable 247 // Create files `/proc/gpu#/gpc#_tpc_mask`, world readable
217 tpc_masks_create_err = create_tpc_mask_files(device_id, dir); 248 tpc_masks_create_err = create_tpc_mask_files(device_id, dir);
218 // Create file `/proc/gpu#/preempt_tsg`, world writable 249 // Create file `/proc/gpu#/preempt_tsg`, world writable
@@ -233,7 +264,7 @@ int __init nvdebug_init(void) {
233 (void*)device_id); 264 (void*)device_id);
234 // Create file `/proc/gpu#/device_info`, world readable 265 // Create file `/proc/gpu#/device_info`, world readable
235 device_info_entry = proc_create_data( 266 device_info_entry = proc_create_data(
236 "device_info", 0444, dir, compat_ops(&device_info_file_ops), 267 "device_info", 0444, dir, compat_ops(g_architectures[device_id] == 0x17 ? &device_info_file_ops_previous : &device_info_file_ops_ampere),
237 (void*)device_id); 268 (void*)device_id);
238 // Create file `/proc/gpu#/num_gpcs`, world readable 269 // Create file `/proc/gpu#/num_gpcs`, world readable
239 num_gpcs_entry = proc_create_data( 270 num_gpcs_entry = proc_create_data(