Merge tag 'dmaengine-fix-6.6' of git://git.kernel.org/pub/scm/linux/kernel/git/vkoul...
[platform/kernel/linux-rpi.git] / drivers / accel / ivpu / ivpu_debugfs.c
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 }