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