1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Copyright (C) 2020-2023 Intel Corporation 4 */ 5 6 #include <drm/drm_debugfs.h> 7 #include <drm/drm_file.h> 8 #include <drm/drm_print.h> 9 10 #include <uapi/drm/ivpu_accel.h> 11 12 #include "ivpu_debugfs.h" 13 #include "ivpu_drv.h" 14 #include "ivpu_fw.h" 15 #include "ivpu_fw_log.h" 16 #include "ivpu_gem.h" 17 #include "ivpu_jsm_msg.h" 18 #include "ivpu_pm.h" 19 20 static int bo_list_show(struct seq_file *s, void *v) 21 { 22 struct drm_info_node *node = (struct drm_info_node *)s->private; 23 struct drm_printer p = drm_seq_file_printer(s); 24 25 ivpu_bo_list(node->minor->dev, &p); 26 27 return 0; 28 } 29 30 static int fw_name_show(struct seq_file *s, void *v) 31 { 32 struct drm_info_node *node = (struct drm_info_node *)s->private; 33 struct ivpu_device *vdev = to_ivpu_device(node->minor->dev); 34 35 seq_printf(s, "%s\n", vdev->fw->name); 36 return 0; 37 } 38 39 static int fw_trace_capability_show(struct seq_file *s, void *v) 40 { 41 struct drm_info_node *node = (struct drm_info_node *)s->private; 42 struct ivpu_device *vdev = to_ivpu_device(node->minor->dev); 43 u64 trace_hw_component_mask; 44 u32 trace_destination_mask; 45 int ret; 46 47 ret = ivpu_jsm_trace_get_capability(vdev, &trace_destination_mask, 48 &trace_hw_component_mask); 49 if (!ret) { 50 seq_printf(s, 51 "trace_destination_mask: %#18x\n" 52 "trace_hw_component_mask: %#18llx\n", 53 trace_destination_mask, trace_hw_component_mask); 54 } 55 return 0; 56 } 57 58 static int fw_trace_config_show(struct seq_file *s, void *v) 59 { 60 struct drm_info_node *node = (struct drm_info_node *)s->private; 61 struct ivpu_device *vdev = to_ivpu_device(node->minor->dev); 62 /** 63 * WA: VPU_JSM_MSG_TRACE_GET_CONFIG command is not working yet, 64 * so we use values from vdev->fw instead of calling ivpu_jsm_trace_get_config() 65 */ 66 u32 trace_level = vdev->fw->trace_level; 67 u32 trace_destination_mask = vdev->fw->trace_destination_mask; 68 u64 trace_hw_component_mask = vdev->fw->trace_hw_component_mask; 69 70 seq_printf(s, 71 "trace_level: %#18x\n" 72 "trace_destination_mask: %#18x\n" 73 "trace_hw_component_mask: %#18llx\n", 74 trace_level, trace_destination_mask, trace_hw_component_mask); 75 76 return 0; 77 } 78 79 static int last_bootmode_show(struct seq_file *s, void *v) 80 { 81 struct drm_info_node *node = (struct drm_info_node *)s->private; 82 struct ivpu_device *vdev = to_ivpu_device(node->minor->dev); 83 84 seq_printf(s, "%s\n", (vdev->pm->is_warmboot) ? "warmboot" : "coldboot"); 85 86 return 0; 87 } 88 89 static int reset_counter_show(struct seq_file *s, void *v) 90 { 91 struct drm_info_node *node = (struct drm_info_node *)s->private; 92 struct ivpu_device *vdev = to_ivpu_device(node->minor->dev); 93 94 seq_printf(s, "%d\n", atomic_read(&vdev->pm->reset_counter)); 95 return 0; 96 } 97 98 static int reset_pending_show(struct seq_file *s, void *v) 99 { 100 struct drm_info_node *node = (struct drm_info_node *)s->private; 101 struct ivpu_device *vdev = to_ivpu_device(node->minor->dev); 102 103 seq_printf(s, "%d\n", atomic_read(&vdev->pm->in_reset)); 104 return 0; 105 } 106 107 static const struct drm_info_list vdev_debugfs_list[] = { 108 {"bo_list", bo_list_show, 0}, 109 {"fw_name", fw_name_show, 0}, 110 {"fw_trace_capability", fw_trace_capability_show, 0}, 111 {"fw_trace_config", fw_trace_config_show, 0}, 112 {"last_bootmode", last_bootmode_show, 0}, 113 {"reset_counter", reset_counter_show, 0}, 114 {"reset_pending", reset_pending_show, 0}, 115 }; 116 117 static int fw_log_show(struct seq_file *s, void *v) 118 { 119 struct ivpu_device *vdev = s->private; 120 struct drm_printer p = drm_seq_file_printer(s); 121 122 ivpu_fw_log_print(vdev, true, &p); 123 return 0; 124 } 125 126 static int fw_log_fops_open(struct inode *inode, struct file *file) 127 { 128 return single_open(file, fw_log_show, inode->i_private); 129 } 130 131 static ssize_t 132 fw_log_fops_write(struct file *file, const char __user *user_buf, size_t size, loff_t *pos) 133 { 134 struct seq_file *s = file->private_data; 135 struct ivpu_device *vdev = s->private; 136 137 if (!size) 138 return -EINVAL; 139 140 ivpu_fw_log_clear(vdev); 141 return size; 142 } 143 144 static const struct file_operations fw_log_fops = { 145 .owner = THIS_MODULE, 146 .open = fw_log_fops_open, 147 .write = fw_log_fops_write, 148 .read = seq_read, 149 .llseek = seq_lseek, 150 .release = single_release, 151 }; 152 153 static ssize_t 154 fw_trace_destination_mask_fops_write(struct file *file, const char __user *user_buf, 155 size_t size, loff_t *pos) 156 { 157 struct ivpu_device *vdev = file->private_data; 158 struct ivpu_fw_info *fw = vdev->fw; 159 u32 trace_destination_mask; 160 int ret; 161 162 ret = kstrtou32_from_user(user_buf, size, 0, &trace_destination_mask); 163 if (ret < 0) 164 return ret; 165 166 fw->trace_destination_mask = trace_destination_mask; 167 168 ivpu_jsm_trace_set_config(vdev, fw->trace_level, trace_destination_mask, 169 fw->trace_hw_component_mask); 170 171 return size; 172 } 173 174 static const struct file_operations fw_trace_destination_mask_fops = { 175 .owner = THIS_MODULE, 176 .open = simple_open, 177 .write = fw_trace_destination_mask_fops_write, 178 }; 179 180 static ssize_t 181 fw_trace_hw_comp_mask_fops_write(struct file *file, const char __user *user_buf, 182 size_t size, loff_t *pos) 183 { 184 struct ivpu_device *vdev = file->private_data; 185 struct ivpu_fw_info *fw = vdev->fw; 186 u64 trace_hw_component_mask; 187 int ret; 188 189 ret = kstrtou64_from_user(user_buf, size, 0, &trace_hw_component_mask); 190 if (ret < 0) 191 return ret; 192 193 fw->trace_hw_component_mask = trace_hw_component_mask; 194 195 ivpu_jsm_trace_set_config(vdev, fw->trace_level, fw->trace_destination_mask, 196 trace_hw_component_mask); 197 198 return size; 199 } 200 201 static const struct file_operations fw_trace_hw_comp_mask_fops = { 202 .owner = THIS_MODULE, 203 .open = simple_open, 204 .write = fw_trace_hw_comp_mask_fops_write, 205 }; 206 207 static ssize_t 208 fw_trace_level_fops_write(struct file *file, const char __user *user_buf, size_t size, loff_t *pos) 209 { 210 struct ivpu_device *vdev = file->private_data; 211 struct ivpu_fw_info *fw = vdev->fw; 212 u32 trace_level; 213 int ret; 214 215 ret = kstrtou32_from_user(user_buf, size, 0, &trace_level); 216 if (ret < 0) 217 return ret; 218 219 fw->trace_level = trace_level; 220 221 ivpu_jsm_trace_set_config(vdev, trace_level, fw->trace_destination_mask, 222 fw->trace_hw_component_mask); 223 224 return size; 225 } 226 227 static const struct file_operations fw_trace_level_fops = { 228 .owner = THIS_MODULE, 229 .open = simple_open, 230 .write = fw_trace_level_fops_write, 231 }; 232 233 static ssize_t 234 ivpu_reset_engine_fn(struct file *file, const char __user *user_buf, size_t size, loff_t *pos) 235 { 236 struct ivpu_device *vdev = file->private_data; 237 238 if (!size) 239 return -EINVAL; 240 241 if (ivpu_jsm_reset_engine(vdev, DRM_IVPU_ENGINE_COMPUTE)) 242 return -ENODEV; 243 if (ivpu_jsm_reset_engine(vdev, DRM_IVPU_ENGINE_COPY)) 244 return -ENODEV; 245 246 return size; 247 } 248 249 static ssize_t 250 ivpu_force_recovery_fn(struct file *file, const char __user *user_buf, size_t size, loff_t *pos) 251 { 252 struct ivpu_device *vdev = file->private_data; 253 254 if (!size) 255 return -EINVAL; 256 257 ivpu_pm_schedule_recovery(vdev); 258 return size; 259 } 260 261 static const struct file_operations ivpu_force_recovery_fops = { 262 .owner = THIS_MODULE, 263 .open = simple_open, 264 .write = ivpu_force_recovery_fn, 265 }; 266 267 static const struct file_operations ivpu_reset_engine_fops = { 268 .owner = THIS_MODULE, 269 .open = simple_open, 270 .write = ivpu_reset_engine_fn, 271 }; 272 273 void ivpu_debugfs_init(struct drm_minor *minor) 274 { 275 struct ivpu_device *vdev = to_ivpu_device(minor->dev); 276 277 drm_debugfs_create_files(vdev_debugfs_list, ARRAY_SIZE(vdev_debugfs_list), 278 minor->debugfs_root, minor); 279 280 debugfs_create_file("force_recovery", 0200, minor->debugfs_root, vdev, 281 &ivpu_force_recovery_fops); 282 283 debugfs_create_file("fw_log", 0644, minor->debugfs_root, vdev, 284 &fw_log_fops); 285 debugfs_create_file("fw_trace_destination_mask", 0200, minor->debugfs_root, vdev, 286 &fw_trace_destination_mask_fops); 287 debugfs_create_file("fw_trace_hw_comp_mask", 0200, minor->debugfs_root, vdev, 288 &fw_trace_hw_comp_mask_fops); 289 debugfs_create_file("fw_trace_level", 0200, minor->debugfs_root, vdev, 290 &fw_trace_level_fops); 291 292 debugfs_create_file("reset_engine", 0200, minor->debugfs_root, vdev, 293 &ivpu_reset_engine_fops); 294 } 295