1 // SPDX-License-Identifier: MIT
2 /*
3 * Copyright © 2022 Intel Corporation
4 */
5
6 #include "xe_debugfs.h"
7
8 #include <linux/debugfs.h>
9 #include <linux/fault-inject.h>
10 #include <linux/string_helpers.h>
11
12 #include <drm/drm_debugfs.h>
13
14 #include "xe_bo.h"
15 #include "xe_device.h"
16 #include "xe_force_wake.h"
17 #include "xe_gt_debugfs.h"
18 #include "xe_gt_printk.h"
19 #include "xe_guc_ads.h"
20 #include "xe_pm.h"
21 #include "xe_pxp_debugfs.h"
22 #include "xe_sriov.h"
23 #include "xe_step.h"
24
25 #ifdef CONFIG_DRM_XE_DEBUG
26 #include "xe_bo_evict.h"
27 #include "xe_migrate.h"
28 #include "xe_vm.h"
29 #endif
30
31 DECLARE_FAULT_ATTR(gt_reset_failure);
32
node_to_xe(struct drm_info_node * node)33 static struct xe_device *node_to_xe(struct drm_info_node *node)
34 {
35 return to_xe_device(node->minor->dev);
36 }
37
info(struct seq_file * m,void * data)38 static int info(struct seq_file *m, void *data)
39 {
40 struct xe_device *xe = node_to_xe(m->private);
41 struct drm_printer p = drm_seq_file_printer(m);
42 struct xe_gt *gt;
43 u8 id;
44
45 xe_pm_runtime_get(xe);
46
47 drm_printf(&p, "graphics_verx100 %d\n", xe->info.graphics_verx100);
48 drm_printf(&p, "media_verx100 %d\n", xe->info.media_verx100);
49 drm_printf(&p, "stepping G:%s M:%s B:%s\n",
50 xe_step_name(xe->info.step.graphics),
51 xe_step_name(xe->info.step.media),
52 xe_step_name(xe->info.step.basedie));
53 drm_printf(&p, "is_dgfx %s\n", str_yes_no(xe->info.is_dgfx));
54 drm_printf(&p, "platform %d\n", xe->info.platform);
55 drm_printf(&p, "subplatform %d\n",
56 xe->info.subplatform > XE_SUBPLATFORM_NONE ? xe->info.subplatform : 0);
57 drm_printf(&p, "devid 0x%x\n", xe->info.devid);
58 drm_printf(&p, "revid %d\n", xe->info.revid);
59 drm_printf(&p, "tile_count %d\n", xe->info.tile_count);
60 drm_printf(&p, "vm_max_level %d\n", xe->info.vm_max_level);
61 drm_printf(&p, "force_execlist %s\n", str_yes_no(xe->info.force_execlist));
62 drm_printf(&p, "has_flat_ccs %s\n", str_yes_no(xe->info.has_flat_ccs));
63 drm_printf(&p, "has_usm %s\n", str_yes_no(xe->info.has_usm));
64 drm_printf(&p, "skip_guc_pc %s\n", str_yes_no(xe->info.skip_guc_pc));
65 for_each_gt(gt, xe, id) {
66 drm_printf(&p, "gt%d force wake %d\n", id,
67 xe_force_wake_ref(gt_to_fw(gt), XE_FW_GT));
68 drm_printf(&p, "gt%d engine_mask 0x%llx\n", id,
69 gt->info.engine_mask);
70 }
71
72 xe_pm_runtime_put(xe);
73 return 0;
74 }
75
sriov_info(struct seq_file * m,void * data)76 static int sriov_info(struct seq_file *m, void *data)
77 {
78 struct xe_device *xe = node_to_xe(m->private);
79 struct drm_printer p = drm_seq_file_printer(m);
80
81 xe_sriov_print_info(xe, &p);
82 return 0;
83 }
84
85 static const struct drm_info_list debugfs_list[] = {
86 {"info", info, 0},
87 { .name = "sriov_info", .show = sriov_info, },
88 };
89
forcewake_open(struct inode * inode,struct file * file)90 static int forcewake_open(struct inode *inode, struct file *file)
91 {
92 struct xe_device *xe = inode->i_private;
93 struct xe_gt *gt;
94 u8 id, last_gt;
95 unsigned int fw_ref;
96
97 xe_pm_runtime_get(xe);
98 for_each_gt(gt, xe, id) {
99 last_gt = id;
100
101 fw_ref = xe_force_wake_get(gt_to_fw(gt), XE_FORCEWAKE_ALL);
102 if (!xe_force_wake_ref_has_domain(fw_ref, XE_FORCEWAKE_ALL))
103 goto err_fw_get;
104 }
105
106 return 0;
107
108 err_fw_get:
109 for_each_gt(gt, xe, id) {
110 if (id < last_gt)
111 xe_force_wake_put(gt_to_fw(gt), XE_FORCEWAKE_ALL);
112 else if (id == last_gt)
113 xe_force_wake_put(gt_to_fw(gt), fw_ref);
114 else
115 break;
116 }
117
118 xe_pm_runtime_put(xe);
119 return -ETIMEDOUT;
120 }
121
forcewake_release(struct inode * inode,struct file * file)122 static int forcewake_release(struct inode *inode, struct file *file)
123 {
124 struct xe_device *xe = inode->i_private;
125 struct xe_gt *gt;
126 u8 id;
127
128 for_each_gt(gt, xe, id)
129 xe_force_wake_put(gt_to_fw(gt), XE_FORCEWAKE_ALL);
130 xe_pm_runtime_put(xe);
131
132 return 0;
133 }
134
135 static const struct file_operations forcewake_all_fops = {
136 .owner = THIS_MODULE,
137 .open = forcewake_open,
138 .release = forcewake_release,
139 };
140
wedged_mode_show(struct file * f,char __user * ubuf,size_t size,loff_t * pos)141 static ssize_t wedged_mode_show(struct file *f, char __user *ubuf,
142 size_t size, loff_t *pos)
143 {
144 struct xe_device *xe = file_inode(f)->i_private;
145 char buf[32];
146 int len = 0;
147
148 len = scnprintf(buf, sizeof(buf), "%d\n", xe->wedged.mode);
149
150 return simple_read_from_buffer(ubuf, size, pos, buf, len);
151 }
152
wedged_mode_set(struct file * f,const char __user * ubuf,size_t size,loff_t * pos)153 static ssize_t wedged_mode_set(struct file *f, const char __user *ubuf,
154 size_t size, loff_t *pos)
155 {
156 struct xe_device *xe = file_inode(f)->i_private;
157 struct xe_gt *gt;
158 u32 wedged_mode;
159 ssize_t ret;
160 u8 id;
161
162 ret = kstrtouint_from_user(ubuf, size, 0, &wedged_mode);
163 if (ret)
164 return ret;
165
166 if (wedged_mode > 2)
167 return -EINVAL;
168
169 if (xe->wedged.mode == wedged_mode)
170 return size;
171
172 xe->wedged.mode = wedged_mode;
173
174 xe_pm_runtime_get(xe);
175 for_each_gt(gt, xe, id) {
176 ret = xe_guc_ads_scheduler_policy_toggle_reset(>->uc.guc.ads);
177 if (ret) {
178 xe_gt_err(gt, "Failed to update GuC ADS scheduler policy. GuC may still cause engine reset even with wedged_mode=2\n");
179 xe_pm_runtime_put(xe);
180 return -EIO;
181 }
182 }
183 xe_pm_runtime_put(xe);
184
185 return size;
186 }
187
188 static const struct file_operations wedged_mode_fops = {
189 .owner = THIS_MODULE,
190 .read = wedged_mode_show,
191 .write = wedged_mode_set,
192 };
193
xe_debugfs_register(struct xe_device * xe)194 void xe_debugfs_register(struct xe_device *xe)
195 {
196 struct ttm_device *bdev = &xe->ttm;
197 struct drm_minor *minor = xe->drm.primary;
198 struct dentry *root = minor->debugfs_root;
199 struct ttm_resource_manager *man;
200 struct xe_gt *gt;
201 u32 mem_type;
202 u8 id;
203
204 drm_debugfs_create_files(debugfs_list,
205 ARRAY_SIZE(debugfs_list),
206 root, minor);
207
208 debugfs_create_file("forcewake_all", 0400, root, xe,
209 &forcewake_all_fops);
210
211 debugfs_create_file("wedged_mode", 0600, root, xe,
212 &wedged_mode_fops);
213
214 for (mem_type = XE_PL_VRAM0; mem_type <= XE_PL_VRAM1; ++mem_type) {
215 man = ttm_manager_type(bdev, mem_type);
216
217 if (man) {
218 char name[16];
219
220 snprintf(name, sizeof(name), "vram%d_mm", mem_type - XE_PL_VRAM0);
221 ttm_resource_manager_create_debugfs(man, root, name);
222 }
223 }
224
225 man = ttm_manager_type(bdev, XE_PL_TT);
226 ttm_resource_manager_create_debugfs(man, root, "gtt_mm");
227
228 man = ttm_manager_type(bdev, XE_PL_STOLEN);
229 if (man)
230 ttm_resource_manager_create_debugfs(man, root, "stolen_mm");
231
232 for_each_gt(gt, xe, id)
233 xe_gt_debugfs_register(gt);
234
235 xe_pxp_debugfs_register(xe->pxp);
236
237 fault_create_debugfs_attr("fail_gt_reset", root, >_reset_failure);
238 }
239