xref: /linux/drivers/gpu/drm/xe/xe_gt_debugfs.c (revision b94605a3889b9084d88f1fe06b043e082bc6b075)
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_topology.h"
19 #include "xe_hw_engine.h"
20 #include "xe_lrc.h"
21 #include "xe_macros.h"
22 #include "xe_pat.h"
23 #include "xe_reg_sr.h"
24 #include "xe_reg_whitelist.h"
25 #include "xe_uc_debugfs.h"
26 #include "xe_wa.h"
27 
28 static struct xe_gt *node_to_gt(struct drm_info_node *node)
29 {
30 	return node->info_ent->data;
31 }
32 
33 static int hw_engines(struct seq_file *m, void *data)
34 {
35 	struct xe_gt *gt = node_to_gt(m->private);
36 	struct xe_device *xe = gt_to_xe(gt);
37 	struct drm_printer p = drm_seq_file_printer(m);
38 	struct xe_hw_engine *hwe;
39 	enum xe_hw_engine_id id;
40 	int err;
41 
42 	xe_device_mem_access_get(xe);
43 	err = xe_force_wake_get(gt_to_fw(gt), XE_FORCEWAKE_ALL);
44 	if (err) {
45 		xe_device_mem_access_put(xe);
46 		return err;
47 	}
48 
49 	for_each_hw_engine(hwe, gt, id)
50 		xe_hw_engine_print(hwe, &p);
51 
52 	err = xe_force_wake_put(gt_to_fw(gt), XE_FORCEWAKE_ALL);
53 	xe_device_mem_access_put(xe);
54 	if (err)
55 		return err;
56 
57 	return 0;
58 }
59 
60 static int force_reset(struct seq_file *m, void *data)
61 {
62 	struct xe_gt *gt = node_to_gt(m->private);
63 
64 	xe_gt_reset_async(gt);
65 
66 	return 0;
67 }
68 
69 static int sa_info(struct seq_file *m, void *data)
70 {
71 	struct xe_tile *tile = gt_to_tile(node_to_gt(m->private));
72 	struct drm_printer p = drm_seq_file_printer(m);
73 
74 	drm_suballoc_dump_debug_info(&tile->mem.kernel_bb_pool->base, &p,
75 				     tile->mem.kernel_bb_pool->gpu_addr);
76 
77 	return 0;
78 }
79 
80 static int topology(struct seq_file *m, void *data)
81 {
82 	struct xe_gt *gt = node_to_gt(m->private);
83 	struct drm_printer p = drm_seq_file_printer(m);
84 
85 	xe_gt_topology_dump(gt, &p);
86 
87 	return 0;
88 }
89 
90 static int steering(struct seq_file *m, void *data)
91 {
92 	struct xe_gt *gt = node_to_gt(m->private);
93 	struct drm_printer p = drm_seq_file_printer(m);
94 
95 	xe_gt_mcr_steering_dump(gt, &p);
96 
97 	return 0;
98 }
99 
100 static int ggtt(struct seq_file *m, void *data)
101 {
102 	struct xe_gt *gt = node_to_gt(m->private);
103 	struct drm_printer p = drm_seq_file_printer(m);
104 
105 	return xe_ggtt_dump(gt_to_tile(gt)->mem.ggtt, &p);
106 }
107 
108 static int register_save_restore(struct seq_file *m, void *data)
109 {
110 	struct xe_gt *gt = node_to_gt(m->private);
111 	struct drm_printer p = drm_seq_file_printer(m);
112 	struct xe_hw_engine *hwe;
113 	enum xe_hw_engine_id id;
114 
115 	xe_reg_sr_dump(&gt->reg_sr, &p);
116 	drm_printf(&p, "\n");
117 
118 	drm_printf(&p, "Engine\n");
119 	for_each_hw_engine(hwe, gt, id)
120 		xe_reg_sr_dump(&hwe->reg_sr, &p);
121 	drm_printf(&p, "\n");
122 
123 	drm_printf(&p, "LRC\n");
124 	for_each_hw_engine(hwe, gt, id)
125 		xe_reg_sr_dump(&hwe->reg_lrc, &p);
126 	drm_printf(&p, "\n");
127 
128 	drm_printf(&p, "Whitelist\n");
129 	for_each_hw_engine(hwe, gt, id)
130 		xe_reg_whitelist_dump(&hwe->reg_whitelist, &p);
131 
132 	return 0;
133 }
134 
135 static int workarounds(struct seq_file *m, void *data)
136 {
137 	struct xe_gt *gt = node_to_gt(m->private);
138 	struct drm_printer p = drm_seq_file_printer(m);
139 
140 	xe_wa_dump(gt, &p);
141 
142 	return 0;
143 }
144 
145 static int pat(struct seq_file *m, void *data)
146 {
147 	struct xe_gt *gt = node_to_gt(m->private);
148 	struct drm_printer p = drm_seq_file_printer(m);
149 
150 	xe_pat_dump(gt, &p);
151 
152 	return 0;
153 }
154 
155 static int rcs_default_lrc(struct seq_file *m, void *data)
156 {
157 	struct drm_printer p = drm_seq_file_printer(m);
158 
159 	xe_lrc_dump_default(&p, node_to_gt(m->private), XE_ENGINE_CLASS_RENDER);
160 	return 0;
161 }
162 
163 static int ccs_default_lrc(struct seq_file *m, void *data)
164 {
165 	struct drm_printer p = drm_seq_file_printer(m);
166 
167 	xe_lrc_dump_default(&p, node_to_gt(m->private), XE_ENGINE_CLASS_COMPUTE);
168 	return 0;
169 }
170 
171 static int bcs_default_lrc(struct seq_file *m, void *data)
172 {
173 	struct drm_printer p = drm_seq_file_printer(m);
174 
175 	xe_lrc_dump_default(&p, node_to_gt(m->private), XE_ENGINE_CLASS_COPY);
176 	return 0;
177 }
178 
179 static int vcs_default_lrc(struct seq_file *m, void *data)
180 {
181 	struct drm_printer p = drm_seq_file_printer(m);
182 
183 	xe_lrc_dump_default(&p, node_to_gt(m->private), XE_ENGINE_CLASS_VIDEO_DECODE);
184 	return 0;
185 }
186 
187 static int vecs_default_lrc(struct seq_file *m, void *data)
188 {
189 	struct drm_printer p = drm_seq_file_printer(m);
190 
191 	xe_lrc_dump_default(&p, node_to_gt(m->private), XE_ENGINE_CLASS_VIDEO_ENHANCE);
192 	return 0;
193 }
194 
195 static const struct drm_info_list debugfs_list[] = {
196 	{"hw_engines", hw_engines, 0},
197 	{"force_reset", force_reset, 0},
198 	{"sa_info", sa_info, 0},
199 	{"topology", topology, 0},
200 	{"steering", steering, 0},
201 	{"ggtt", ggtt, 0},
202 	{"register-save-restore", register_save_restore, 0},
203 	{"workarounds", workarounds, 0},
204 	{"pat", pat, 0},
205 	{"default_lrc_rcs", rcs_default_lrc},
206 	{"default_lrc_ccs", ccs_default_lrc},
207 	{"default_lrc_bcs", bcs_default_lrc},
208 	{"default_lrc_vcs", vcs_default_lrc},
209 	{"default_lrc_vecs", vecs_default_lrc},
210 };
211 
212 void xe_gt_debugfs_register(struct xe_gt *gt)
213 {
214 	struct xe_device *xe = gt_to_xe(gt);
215 	struct drm_minor *minor = gt_to_xe(gt)->drm.primary;
216 	struct dentry *root;
217 	struct drm_info_list *local;
218 	char name[8];
219 	int i;
220 
221 	xe_gt_assert(gt, minor->debugfs_root);
222 
223 	sprintf(name, "gt%d", gt->info.id);
224 	root = debugfs_create_dir(name, minor->debugfs_root);
225 	if (IS_ERR(root)) {
226 		drm_warn(&xe->drm, "Create GT directory failed");
227 		return;
228 	}
229 
230 	/*
231 	 * Allocate local copy as we need to pass in the GT to the debugfs
232 	 * entry and drm_debugfs_create_files just references the drm_info_list
233 	 * passed in (e.g. can't define this on the stack).
234 	 */
235 #define DEBUGFS_SIZE	(ARRAY_SIZE(debugfs_list) * sizeof(struct drm_info_list))
236 	local = drmm_kmalloc(&xe->drm, DEBUGFS_SIZE, GFP_KERNEL);
237 	if (!local)
238 		return;
239 
240 	memcpy(local, debugfs_list, DEBUGFS_SIZE);
241 #undef DEBUGFS_SIZE
242 
243 	for (i = 0; i < ARRAY_SIZE(debugfs_list); ++i)
244 		local[i].data = gt;
245 
246 	drm_debugfs_create_files(local,
247 				 ARRAY_SIZE(debugfs_list),
248 				 root, minor);
249 
250 	xe_uc_debugfs_register(&gt->uc, root);
251 }
252