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_gt_debugfs.h"
7
8#include <linux/debugfs.h>
9
10#include <drm/drm_debugfs.h>
11#include <drm/drm_managed.h>
12
13#include "xe_device.h"
14#include "xe_force_wake.h"
15#include "xe_ggtt.h"
16#include "xe_gt.h"
17#include "xe_gt_mcr.h"
18#include "xe_gt_sriov_pf_debugfs.h"
19#include "xe_gt_sriov_vf_debugfs.h"
20#include "xe_gt_topology.h"
21#include "xe_hw_engine.h"
22#include "xe_lrc.h"
23#include "xe_macros.h"
24#include "xe_mocs.h"
25#include "xe_pat.h"
26#include "xe_pm.h"
27#include "xe_reg_sr.h"
28#include "xe_reg_whitelist.h"
29#include "xe_sriov.h"
30#include "xe_uc_debugfs.h"
31#include "xe_wa.h"
32
33/**
34 * xe_gt_debugfs_simple_show - A show callback for struct drm_info_list
35 * @m: the &seq_file
36 * @data: data used by the drm debugfs helpers
37 *
38 * This callback can be used in struct drm_info_list to describe debugfs
39 * files that are &xe_gt specific.
40 *
41 * It is assumed that those debugfs files will be created on directory entry
42 * which struct dentry d_inode->i_private points to &xe_gt.
43 *
44 * This function assumes that &m->private will be set to the &struct
45 * drm_info_node corresponding to the instance of the info on a given &struct
46 * drm_minor (see struct drm_info_list.show for details).
47 *
48 * This function also assumes that struct drm_info_list.data will point to the
49 * function code that will actually print a file content::
50 *
51 * int (*print)(struct xe_gt *, struct drm_printer *)
52 *
53 * Example::
54 *
55 * int foo(struct xe_gt *gt, struct drm_printer *p)
56 * {
57 * drm_printf(p, "GT%u\n", gt->info.id);
58 * return 0;
59 * }
60 *
61 * static const struct drm_info_list bar[] = {
62 * { name = "foo", .show = xe_gt_debugfs_simple_show, .data = foo },
63 * };
64 *
65 * dir = debugfs_create_dir("gt", parent);
66 * dir->d_inode->i_private = gt;
67 * drm_debugfs_create_files(bar, ARRAY_SIZE(bar), dir, minor);
68 *
69 * Return: 0 on success or a negative error code on failure.
70 */
71int xe_gt_debugfs_simple_show(struct seq_file *m, void *data)
72{
73 struct drm_printer p = drm_seq_file_printer(m);
74 struct drm_info_node *node = m->private;
75 struct dentry *parent = node->dent->d_parent;
76 struct xe_gt *gt = parent->d_inode->i_private;
77 int (*print)(struct xe_gt *, struct drm_printer *) = node->info_ent->data;
78
79 if (WARN_ON(!print))
80 return -EINVAL;
81
82 return print(gt, &p);
83}
84
85static int hw_engines(struct xe_gt *gt, struct drm_printer *p)
86{
87 struct xe_device *xe = gt_to_xe(gt);
88 struct xe_hw_engine *hwe;
89 enum xe_hw_engine_id id;
90 int err;
91
92 xe_pm_runtime_get(xe);
93 err = xe_force_wake_get(gt_to_fw(gt), XE_FORCEWAKE_ALL);
94 if (err) {
95 xe_pm_runtime_put(xe);
96 return err;
97 }
98
99 for_each_hw_engine(hwe, gt, id)
100 xe_hw_engine_print(hwe, p);
101
102 err = xe_force_wake_put(gt_to_fw(gt), XE_FORCEWAKE_ALL);
103 xe_pm_runtime_put(xe);
104 if (err)
105 return err;
106
107 return 0;
108}
109
110static int force_reset(struct xe_gt *gt, struct drm_printer *p)
111{
112 xe_pm_runtime_get(gt_to_xe(gt));
113 xe_gt_reset_async(gt);
114 xe_pm_runtime_put(gt_to_xe(gt));
115
116 return 0;
117}
118
119static int force_reset_sync(struct xe_gt *gt, struct drm_printer *p)
120{
121 xe_pm_runtime_get(gt_to_xe(gt));
122 xe_gt_reset_async(gt);
123 xe_pm_runtime_put(gt_to_xe(gt));
124
125 flush_work(>->reset.worker);
126
127 return 0;
128}
129
130static int sa_info(struct xe_gt *gt, struct drm_printer *p)
131{
132 struct xe_tile *tile = gt_to_tile(gt);
133
134 xe_pm_runtime_get(gt_to_xe(gt));
135 drm_suballoc_dump_debug_info(&tile->mem.kernel_bb_pool->base, p,
136 tile->mem.kernel_bb_pool->gpu_addr);
137 xe_pm_runtime_put(gt_to_xe(gt));
138
139 return 0;
140}
141
142static int topology(struct xe_gt *gt, struct drm_printer *p)
143{
144 xe_pm_runtime_get(gt_to_xe(gt));
145 xe_gt_topology_dump(gt, p);
146 xe_pm_runtime_put(gt_to_xe(gt));
147
148 return 0;
149}
150
151static int steering(struct xe_gt *gt, struct drm_printer *p)
152{
153 xe_pm_runtime_get(gt_to_xe(gt));
154 xe_gt_mcr_steering_dump(gt, p);
155 xe_pm_runtime_put(gt_to_xe(gt));
156
157 return 0;
158}
159
160static int ggtt(struct xe_gt *gt, struct drm_printer *p)
161{
162 int ret;
163
164 xe_pm_runtime_get(gt_to_xe(gt));
165 ret = xe_ggtt_dump(gt_to_tile(gt)->mem.ggtt, p);
166 xe_pm_runtime_put(gt_to_xe(gt));
167
168 return ret;
169}
170
171static int register_save_restore(struct xe_gt *gt, struct drm_printer *p)
172{
173 struct xe_hw_engine *hwe;
174 enum xe_hw_engine_id id;
175
176 xe_pm_runtime_get(gt_to_xe(gt));
177
178 xe_reg_sr_dump(>->reg_sr, p);
179 drm_printf(p, "\n");
180
181 drm_printf(p, "Engine\n");
182 for_each_hw_engine(hwe, gt, id)
183 xe_reg_sr_dump(&hwe->reg_sr, p);
184 drm_printf(p, "\n");
185
186 drm_printf(p, "LRC\n");
187 for_each_hw_engine(hwe, gt, id)
188 xe_reg_sr_dump(&hwe->reg_lrc, p);
189 drm_printf(p, "\n");
190
191 drm_printf(p, "Whitelist\n");
192 for_each_hw_engine(hwe, gt, id)
193 xe_reg_whitelist_dump(&hwe->reg_whitelist, p);
194
195 xe_pm_runtime_put(gt_to_xe(gt));
196
197 return 0;
198}
199
200static int workarounds(struct xe_gt *gt, struct drm_printer *p)
201{
202 xe_pm_runtime_get(gt_to_xe(gt));
203 xe_wa_dump(gt, p);
204 xe_pm_runtime_put(gt_to_xe(gt));
205
206 return 0;
207}
208
209static int pat(struct xe_gt *gt, struct drm_printer *p)
210{
211 xe_pm_runtime_get(gt_to_xe(gt));
212 xe_pat_dump(gt, p);
213 xe_pm_runtime_put(gt_to_xe(gt));
214
215 return 0;
216}
217
218static int mocs(struct xe_gt *gt, struct drm_printer *p)
219{
220 xe_pm_runtime_get(gt_to_xe(gt));
221 xe_mocs_dump(gt, p);
222 xe_pm_runtime_put(gt_to_xe(gt));
223
224 return 0;
225}
226
227static int rcs_default_lrc(struct xe_gt *gt, struct drm_printer *p)
228{
229 xe_pm_runtime_get(gt_to_xe(gt));
230 xe_lrc_dump_default(p, gt, XE_ENGINE_CLASS_RENDER);
231 xe_pm_runtime_put(gt_to_xe(gt));
232
233 return 0;
234}
235
236static int ccs_default_lrc(struct xe_gt *gt, struct drm_printer *p)
237{
238 xe_pm_runtime_get(gt_to_xe(gt));
239 xe_lrc_dump_default(p, gt, XE_ENGINE_CLASS_COMPUTE);
240 xe_pm_runtime_put(gt_to_xe(gt));
241
242 return 0;
243}
244
245static int bcs_default_lrc(struct xe_gt *gt, struct drm_printer *p)
246{
247 xe_pm_runtime_get(gt_to_xe(gt));
248 xe_lrc_dump_default(p, gt, XE_ENGINE_CLASS_COPY);
249 xe_pm_runtime_put(gt_to_xe(gt));
250
251 return 0;
252}
253
254static int vcs_default_lrc(struct xe_gt *gt, struct drm_printer *p)
255{
256 xe_pm_runtime_get(gt_to_xe(gt));
257 xe_lrc_dump_default(p, gt, XE_ENGINE_CLASS_VIDEO_DECODE);
258 xe_pm_runtime_put(gt_to_xe(gt));
259
260 return 0;
261}
262
263static int vecs_default_lrc(struct xe_gt *gt, struct drm_printer *p)
264{
265 xe_pm_runtime_get(gt_to_xe(gt));
266 xe_lrc_dump_default(p, gt, XE_ENGINE_CLASS_VIDEO_ENHANCE);
267 xe_pm_runtime_put(gt_to_xe(gt));
268
269 return 0;
270}
271
272static const struct drm_info_list debugfs_list[] = {
273 {"hw_engines", .show = xe_gt_debugfs_simple_show, .data = hw_engines},
274 {"force_reset", .show = xe_gt_debugfs_simple_show, .data = force_reset},
275 {"force_reset_sync", .show = xe_gt_debugfs_simple_show, .data = force_reset_sync},
276 {"sa_info", .show = xe_gt_debugfs_simple_show, .data = sa_info},
277 {"topology", .show = xe_gt_debugfs_simple_show, .data = topology},
278 {"steering", .show = xe_gt_debugfs_simple_show, .data = steering},
279 {"ggtt", .show = xe_gt_debugfs_simple_show, .data = ggtt},
280 {"register-save-restore", .show = xe_gt_debugfs_simple_show, .data = register_save_restore},
281 {"workarounds", .show = xe_gt_debugfs_simple_show, .data = workarounds},
282 {"pat", .show = xe_gt_debugfs_simple_show, .data = pat},
283 {"mocs", .show = xe_gt_debugfs_simple_show, .data = mocs},
284 {"default_lrc_rcs", .show = xe_gt_debugfs_simple_show, .data = rcs_default_lrc},
285 {"default_lrc_ccs", .show = xe_gt_debugfs_simple_show, .data = ccs_default_lrc},
286 {"default_lrc_bcs", .show = xe_gt_debugfs_simple_show, .data = bcs_default_lrc},
287 {"default_lrc_vcs", .show = xe_gt_debugfs_simple_show, .data = vcs_default_lrc},
288 {"default_lrc_vecs", .show = xe_gt_debugfs_simple_show, .data = vecs_default_lrc},
289};
290
291void xe_gt_debugfs_register(struct xe_gt *gt)
292{
293 struct xe_device *xe = gt_to_xe(gt);
294 struct drm_minor *minor = gt_to_xe(gt)->drm.primary;
295 struct dentry *root;
296 char name[8];
297
298 xe_gt_assert(gt, minor->debugfs_root);
299
300 snprintf(name, sizeof(name), "gt%d", gt->info.id);
301 root = debugfs_create_dir(name, minor->debugfs_root);
302 if (IS_ERR(root)) {
303 drm_warn(&xe->drm, "Create GT directory failed");
304 return;
305 }
306
307 /*
308 * Store the xe_gt pointer as private data of the gt/ directory node
309 * so other GT specific attributes under that directory may refer to
310 * it by looking at its parent node private data.
311 */
312 root->d_inode->i_private = gt;
313
314 drm_debugfs_create_files(debugfs_list,
315 ARRAY_SIZE(debugfs_list),
316 root, minor);
317
318 xe_uc_debugfs_register(>->uc, root);
319
320 if (IS_SRIOV_PF(xe))
321 xe_gt_sriov_pf_debugfs_register(gt, root);
322 else if (IS_SRIOV_VF(xe))
323 xe_gt_sriov_vf_debugfs_register(gt, root);
324}