Linux kernel mirror (for testing)
git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel
os
linux
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
31DECLARE_FAULT_ATTR(gt_reset_failure);
32
33static struct xe_device *node_to_xe(struct drm_info_node *node)
34{
35 return to_xe_device(node->minor->dev);
36}
37
38static 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
76static 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
85static const struct drm_info_list debugfs_list[] = {
86 {"info", info, 0},
87 { .name = "sriov_info", .show = sriov_info, },
88};
89
90static 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
108err_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
122static 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
135static const struct file_operations forcewake_all_fops = {
136 .owner = THIS_MODULE,
137 .open = forcewake_open,
138 .release = forcewake_release,
139};
140
141static 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
153static 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
188static const struct file_operations wedged_mode_fops = {
189 .owner = THIS_MODULE,
190 .read = wedged_mode_show,
191 .write = wedged_mode_set,
192};
193
194void 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}