xref: /linux/drivers/gpu/drm/xe/xe_guc_capture.c (revision b49024d79fb7304f646003fcd8846ef26dea7e92)
1 // SPDX-License-Identifier: MIT
2 /*
3  * Copyright © 2021-2024 Intel Corporation
4  */
5 
6 #include <linux/types.h>
7 
8 #include <drm/drm_managed.h>
9 #include <drm/drm_print.h>
10 
11 #include "abi/guc_actions_abi.h"
12 #include "abi/guc_capture_abi.h"
13 #include "abi/guc_log_abi.h"
14 #include "regs/xe_engine_regs.h"
15 #include "regs/xe_gt_regs.h"
16 
17 #include "xe_bo_types.h"
18 #include "xe_device.h"
19 #include "xe_exec_queue_types.h"
20 #include "xe_gt.h"
21 #include "xe_gt_mcr.h"
22 #include "xe_gt_printk.h"
23 #include "xe_guc.h"
24 #include "xe_guc_capture.h"
25 #include "xe_guc_capture_types.h"
26 #include "xe_guc_ct.h"
27 #include "xe_guc_exec_queue_types.h"
28 #include "xe_guc_log.h"
29 #include "xe_guc_submit_types.h"
30 #include "xe_guc_submit.h"
31 #include "xe_hw_engine_types.h"
32 #include "xe_hw_engine.h"
33 #include "xe_lrc.h"
34 #include "xe_macros.h"
35 #include "xe_map.h"
36 #include "xe_mmio.h"
37 #include "xe_sched_job.h"
38 
39 /*
40  * struct __guc_capture_bufstate
41  *
42  * Book-keeping structure used to track read and write pointers
43  * as we extract error capture data from the GuC-log-buffer's
44  * error-capture region as a stream of dwords.
45  */
46 struct __guc_capture_bufstate {
47 	u32 size;
48 	u32 data_offset;
49 	u32 rd;
50 	u32 wr;
51 };
52 
53 /*
54  * struct __guc_capture_parsed_output - extracted error capture node
55  *
56  * A single unit of extracted error-capture output data grouped together
57  * at an engine-instance level. We keep these nodes in a linked list.
58  * See cachelist and outlist below.
59  */
60 struct __guc_capture_parsed_output {
61 	/*
62 	 * A single set of 3 capture lists: a global-list
63 	 * an engine-class-list and an engine-instance list.
64 	 * outlist in __guc_capture_parsed_output will keep
65 	 * a linked list of these nodes that will eventually
66 	 * be detached from outlist and attached into to
67 	 * xe_codedump in response to a context reset
68 	 */
69 	struct list_head link;
70 	bool is_partial;
71 	u32 eng_class;
72 	u32 eng_inst;
73 	u32 guc_id;
74 	u32 lrca;
75 	u32 type;
76 	bool locked;
77 	enum xe_hw_engine_snapshot_source_id source;
78 	struct gcap_reg_list_info {
79 		u32 vfid;
80 		u32 num_regs;
81 		struct guc_mmio_reg *regs;
82 	} reginfo[GUC_STATE_CAPTURE_TYPE_MAX];
83 #define GCAP_PARSED_REGLIST_INDEX_GLOBAL   BIT(GUC_STATE_CAPTURE_TYPE_GLOBAL)
84 #define GCAP_PARSED_REGLIST_INDEX_ENGCLASS BIT(GUC_STATE_CAPTURE_TYPE_ENGINE_CLASS)
85 };
86 
87 /*
88  * Define all device tables of GuC error capture register lists
89  * NOTE:
90  *     For engine-registers, GuC only needs the register offsets
91  *     from the engine-mmio-base
92  *
93  *     64 bit registers need 2 entries for low 32 bit register and high 32 bit
94  *     register, for example:
95  *       Register           data_type       flags   mask    Register name
96  *     { XXX_REG_LO(0),  REG_64BIT_LOW_DW,    0,      0,      NULL},
97  *     { XXX_REG_HI(0),  REG_64BIT_HI_DW,,    0,      0,      "XXX_REG"},
98  *     1. data_type: Indicate is hi/low 32 bit for a 64 bit register
99  *                   A 64 bit register define requires 2 consecutive entries,
100  *                   with low dword first and hi dword the second.
101  *     2. Register name: null for incompleted define
102  *     3. Incorrect order will trigger XE_WARN.
103  */
104 #define COMMON_XELP_BASE_GLOBAL \
105 	{ FORCEWAKE_GT,			REG_32BIT,	0,	0,	0,	"FORCEWAKE_GT"}
106 
107 #define COMMON_BASE_ENGINE_INSTANCE \
108 	{ RING_HWSTAM(0),		REG_32BIT,	0,	0,	0,	"HWSTAM"}, \
109 	{ RING_HWS_PGA(0),		REG_32BIT,	0,	0,	0,	"RING_HWS_PGA"}, \
110 	{ RING_HEAD(0),			REG_32BIT,	0,	0,	0,	"RING_HEAD"}, \
111 	{ RING_TAIL(0),			REG_32BIT,	0,	0,	0,	"RING_TAIL"}, \
112 	{ RING_CTL(0),			REG_32BIT,	0,	0,	0,	"RING_CTL"}, \
113 	{ RING_MI_MODE(0),		REG_32BIT,	0,	0,	0,	"RING_MI_MODE"}, \
114 	{ GFX_MODE(0),			REG_32BIT,	0,	0,	0,	"GFX_MODE"}, \
115 	{ RING_ESR(0),			REG_32BIT,	0,	0,	0,	"RING_ESR"}, \
116 	{ RING_EMR(0),			REG_32BIT,	0,	0,	0,	"RING_EMR"}, \
117 	{ RING_EIR(0),			REG_32BIT,	0,	0,	0,	"RING_EIR"}, \
118 	{ RING_IMR(0),			REG_32BIT,	0,	0,	0,	"RING_IMR"}, \
119 	{ RING_IPEHR(0),		REG_32BIT,	0,	0,	0,	"IPEHR"}, \
120 	{ RING_INSTDONE(0),		REG_32BIT,	0,	0,	0,	"RING_INSTDONE"}, \
121 	{ INDIRECT_RING_STATE(0),	REG_32BIT,	0,	0,	0,	"INDIRECT_RING_STATE"}, \
122 	{ RING_CURRENT_LRCA(0),		REG_32BIT,	0,	0,	0,	"CURRENT_LRCA"}, \
123 	{ RING_ACTHD(0),		REG_64BIT_LOW_DW, 0,	0,	0,	NULL}, \
124 	{ RING_ACTHD_UDW(0),		REG_64BIT_HI_DW, 0,	0,	0,	"ACTHD"}, \
125 	{ RING_BBADDR(0),		REG_64BIT_LOW_DW, 0,	0,	0,	NULL}, \
126 	{ RING_BBADDR_UDW(0),		REG_64BIT_HI_DW, 0,	0,	0,	"RING_BBADDR"}, \
127 	{ RING_START(0),		REG_64BIT_LOW_DW, 0,	0,	0,	NULL}, \
128 	{ RING_START_UDW(0),		REG_64BIT_HI_DW, 0,	0,	0,	"RING_START"}, \
129 	{ RING_DMA_FADD(0),		REG_64BIT_LOW_DW, 0,	0,	0,	NULL}, \
130 	{ RING_DMA_FADD_UDW(0),		REG_64BIT_HI_DW, 0,	0,	0,	"RING_DMA_FADD"}, \
131 	{ RING_EXECLIST_STATUS_LO(0),	REG_64BIT_LOW_DW, 0,	0,	0,	NULL}, \
132 	{ RING_EXECLIST_STATUS_HI(0),	REG_64BIT_HI_DW, 0,	0,	0,	"RING_EXECLIST_STATUS"}, \
133 	{ RING_EXECLIST_SQ_CONTENTS_LO(0), REG_64BIT_LOW_DW, 0,	0,	0,	NULL}, \
134 	{ RING_EXECLIST_SQ_CONTENTS_HI(0), REG_64BIT_HI_DW, 0,	0,	0,	"RING_EXECLIST_SQ_CONTENTS"}
135 
136 #define COMMON_XELP_RC_CLASS \
137 	{ RCU_MODE,			REG_32BIT,	0,	0,	0,	"RCU_MODE"}
138 
139 #define COMMON_XELP_RC_CLASS_INSTDONE \
140 	{ SC_INSTDONE,			REG_32BIT,	0,	0,	0,	"SC_INSTDONE"}, \
141 	{ SC_INSTDONE_EXTRA,		REG_32BIT,	0,	0,	0,	"SC_INSTDONE_EXTRA"}, \
142 	{ SC_INSTDONE_EXTRA2,		REG_32BIT,	0,	0,	0,	"SC_INSTDONE_EXTRA2"}
143 
144 #define XELP_VEC_CLASS_REGS \
145 	{ SFC_DONE(0),			0,	0,	0,	0,	"SFC_DONE[0]"}, \
146 	{ SFC_DONE(1),			0,	0,	0,	0,	"SFC_DONE[1]"}, \
147 	{ SFC_DONE(2),			0,	0,	0,	0,	"SFC_DONE[2]"}, \
148 	{ SFC_DONE(3),			0,	0,	0,	0,	"SFC_DONE[3]"}
149 
150 #define XE3P_BASE_ENGINE_INSTANCE \
151 	{ RING_CSMQDEBUG(0),		REG_32BIT,	0,	0,	0,	"CSMQDEBUG"}
152 
153 /* XE_LP Global */
154 static const struct __guc_mmio_reg_descr xe_lp_global_regs[] = {
155 	COMMON_XELP_BASE_GLOBAL,
156 };
157 
158 /* Render / Compute Per-Engine-Instance */
159 static const struct __guc_mmio_reg_descr xe_rc_inst_regs[] = {
160 	COMMON_BASE_ENGINE_INSTANCE,
161 };
162 
163 /* Render / Compute Engine-Class */
164 static const struct __guc_mmio_reg_descr xe_rc_class_regs[] = {
165 	COMMON_XELP_RC_CLASS,
166 	COMMON_XELP_RC_CLASS_INSTDONE,
167 };
168 
169 /* Render / Compute Engine-Class for xehpg */
170 static const struct __guc_mmio_reg_descr xe_hpg_rc_class_regs[] = {
171 	COMMON_XELP_RC_CLASS,
172 };
173 
174 /* Media Decode/Encode Per-Engine-Instance */
175 static const struct __guc_mmio_reg_descr xe_vd_inst_regs[] = {
176 	COMMON_BASE_ENGINE_INSTANCE,
177 };
178 
179 /* Video Enhancement Engine-Class */
180 static const struct __guc_mmio_reg_descr xe_vec_class_regs[] = {
181 	XELP_VEC_CLASS_REGS,
182 };
183 
184 /* Video Enhancement Per-Engine-Instance */
185 static const struct __guc_mmio_reg_descr xe_vec_inst_regs[] = {
186 	COMMON_BASE_ENGINE_INSTANCE,
187 };
188 
189 /* Blitter Per-Engine-Instance */
190 static const struct __guc_mmio_reg_descr xe_blt_inst_regs[] = {
191 	COMMON_BASE_ENGINE_INSTANCE,
192 };
193 
194 /* XE_LP - GSC Per-Engine-Instance */
195 static const struct __guc_mmio_reg_descr xe_lp_gsc_inst_regs[] = {
196 	COMMON_BASE_ENGINE_INSTANCE,
197 };
198 
199 /* Render / Compute Per-Engine-Instance */
200 static const struct __guc_mmio_reg_descr xe3p_rc_inst_regs[] = {
201 	COMMON_BASE_ENGINE_INSTANCE,
202 	XE3P_BASE_ENGINE_INSTANCE,
203 };
204 
205 /*
206  * Empty list to prevent warnings about unknown class/instance types
207  * as not all class/instance types have entries on all platforms.
208  */
209 static const struct __guc_mmio_reg_descr empty_regs_list[] = {
210 };
211 
212 #define TO_GCAP_DEF_OWNER(x) (GUC_CAPTURE_LIST_INDEX_##x)
213 #define TO_GCAP_DEF_TYPE(x) (GUC_STATE_CAPTURE_TYPE_##x)
214 #define MAKE_REGLIST(regslist, regsowner, regstype, class) \
215 	{ \
216 		regslist, \
217 		ARRAY_SIZE(regslist), \
218 		TO_GCAP_DEF_OWNER(regsowner), \
219 		TO_GCAP_DEF_TYPE(regstype), \
220 		class \
221 	}
222 
223 /* List of lists for legacy graphic product version < 1255 */
224 static const struct __guc_mmio_reg_descr_group xe_lp_lists[] = {
225 	MAKE_REGLIST(xe_lp_global_regs, PF, GLOBAL, 0),
226 	MAKE_REGLIST(xe_rc_class_regs, PF, ENGINE_CLASS, GUC_CAPTURE_LIST_CLASS_RENDER_COMPUTE),
227 	MAKE_REGLIST(xe_rc_inst_regs, PF, ENGINE_INSTANCE, GUC_CAPTURE_LIST_CLASS_RENDER_COMPUTE),
228 	MAKE_REGLIST(empty_regs_list, PF, ENGINE_CLASS, GUC_CAPTURE_LIST_CLASS_VIDEO),
229 	MAKE_REGLIST(xe_vd_inst_regs, PF, ENGINE_INSTANCE, GUC_CAPTURE_LIST_CLASS_VIDEO),
230 	MAKE_REGLIST(xe_vec_class_regs, PF, ENGINE_CLASS, GUC_CAPTURE_LIST_CLASS_VIDEOENHANCE),
231 	MAKE_REGLIST(xe_vec_inst_regs, PF, ENGINE_INSTANCE, GUC_CAPTURE_LIST_CLASS_VIDEOENHANCE),
232 	MAKE_REGLIST(empty_regs_list, PF, ENGINE_CLASS, GUC_CAPTURE_LIST_CLASS_BLITTER),
233 	MAKE_REGLIST(xe_blt_inst_regs, PF, ENGINE_INSTANCE, GUC_CAPTURE_LIST_CLASS_BLITTER),
234 	MAKE_REGLIST(empty_regs_list, PF, ENGINE_CLASS, GUC_CAPTURE_LIST_CLASS_GSC_OTHER),
235 	MAKE_REGLIST(xe_lp_gsc_inst_regs, PF, ENGINE_INSTANCE, GUC_CAPTURE_LIST_CLASS_GSC_OTHER),
236 	{}
237 };
238 
239  /* List of lists for graphic product version >= 1255 */
240 static const struct __guc_mmio_reg_descr_group xe_hpg_lists[] = {
241 	MAKE_REGLIST(xe_lp_global_regs, PF, GLOBAL, 0),
242 	MAKE_REGLIST(xe_hpg_rc_class_regs, PF, ENGINE_CLASS, GUC_CAPTURE_LIST_CLASS_RENDER_COMPUTE),
243 	MAKE_REGLIST(xe_rc_inst_regs, PF, ENGINE_INSTANCE, GUC_CAPTURE_LIST_CLASS_RENDER_COMPUTE),
244 	MAKE_REGLIST(empty_regs_list, PF, ENGINE_CLASS, GUC_CAPTURE_LIST_CLASS_VIDEO),
245 	MAKE_REGLIST(xe_vd_inst_regs, PF, ENGINE_INSTANCE, GUC_CAPTURE_LIST_CLASS_VIDEO),
246 	MAKE_REGLIST(xe_vec_class_regs, PF, ENGINE_CLASS, GUC_CAPTURE_LIST_CLASS_VIDEOENHANCE),
247 	MAKE_REGLIST(xe_vec_inst_regs, PF, ENGINE_INSTANCE, GUC_CAPTURE_LIST_CLASS_VIDEOENHANCE),
248 	MAKE_REGLIST(empty_regs_list, PF, ENGINE_CLASS, GUC_CAPTURE_LIST_CLASS_BLITTER),
249 	MAKE_REGLIST(xe_blt_inst_regs, PF, ENGINE_INSTANCE, GUC_CAPTURE_LIST_CLASS_BLITTER),
250 	MAKE_REGLIST(empty_regs_list, PF, ENGINE_CLASS, GUC_CAPTURE_LIST_CLASS_GSC_OTHER),
251 	MAKE_REGLIST(xe_lp_gsc_inst_regs, PF, ENGINE_INSTANCE, GUC_CAPTURE_LIST_CLASS_GSC_OTHER),
252 	MAKE_REGLIST(empty_regs_list, PF, ENGINE_CLASS, GUC_CAPTURE_LIST_CLASS_PAGING),
253 	MAKE_REGLIST(xe_blt_inst_regs, PF, ENGINE_INSTANCE, GUC_CAPTURE_LIST_CLASS_PAGING),
254 	{}
255 };
256 
257  /* List of lists for Xe3p and beyond */
258 static const struct __guc_mmio_reg_descr_group xe3p_lists[] = {
259 	MAKE_REGLIST(xe_lp_global_regs, PF, GLOBAL, 0),
260 	MAKE_REGLIST(xe_hpg_rc_class_regs, PF, ENGINE_CLASS, GUC_CAPTURE_LIST_CLASS_RENDER_COMPUTE),
261 	MAKE_REGLIST(xe3p_rc_inst_regs, PF, ENGINE_INSTANCE, GUC_CAPTURE_LIST_CLASS_RENDER_COMPUTE),
262 	MAKE_REGLIST(empty_regs_list, PF, ENGINE_CLASS, GUC_CAPTURE_LIST_CLASS_VIDEO),
263 	MAKE_REGLIST(xe_vd_inst_regs, PF, ENGINE_INSTANCE, GUC_CAPTURE_LIST_CLASS_VIDEO),
264 	MAKE_REGLIST(xe_vec_class_regs, PF, ENGINE_CLASS, GUC_CAPTURE_LIST_CLASS_VIDEOENHANCE),
265 	MAKE_REGLIST(xe_vec_inst_regs, PF, ENGINE_INSTANCE, GUC_CAPTURE_LIST_CLASS_VIDEOENHANCE),
266 	MAKE_REGLIST(empty_regs_list, PF, ENGINE_CLASS, GUC_CAPTURE_LIST_CLASS_BLITTER),
267 	MAKE_REGLIST(xe_blt_inst_regs, PF, ENGINE_INSTANCE, GUC_CAPTURE_LIST_CLASS_BLITTER),
268 	MAKE_REGLIST(empty_regs_list, PF, ENGINE_CLASS, GUC_CAPTURE_LIST_CLASS_GSC_OTHER),
269 	MAKE_REGLIST(xe_lp_gsc_inst_regs, PF, ENGINE_INSTANCE, GUC_CAPTURE_LIST_CLASS_GSC_OTHER),
270 	MAKE_REGLIST(empty_regs_list, PF, ENGINE_CLASS, GUC_CAPTURE_LIST_CLASS_PAGING),
271 	MAKE_REGLIST(xe_blt_inst_regs, PF, ENGINE_INSTANCE, GUC_CAPTURE_LIST_CLASS_PAGING),
272 	{}
273 };
274 static const char * const capture_list_type_names[] = {
275 	"Global",
276 	"Class",
277 	"Instance",
278 };
279 
280 static const char * const capture_engine_class_names[] = {
281 	"Render/Compute",
282 	"Video",
283 	"VideoEnhance",
284 	"Blitter",
285 	"GSC-Other",
286 	"Paging",
287 };
288 
289 struct __guc_capture_ads_cache {
290 	bool is_valid;
291 	void *ptr;
292 	size_t size;
293 	int status;
294 };
295 
296 struct xe_guc_state_capture {
297 	const struct __guc_mmio_reg_descr_group *reglists;
298 	/**
299 	 * NOTE: steered registers have multiple instances depending on the HW configuration
300 	 * (slices or dual-sub-slices) and thus depends on HW fuses discovered
301 	 */
302 	struct __guc_mmio_reg_descr_group *extlists;
303 	struct __guc_capture_ads_cache ads_cache[GUC_CAPTURE_LIST_INDEX_MAX]
304 						[GUC_STATE_CAPTURE_TYPE_MAX]
305 						[GUC_CAPTURE_LIST_CLASS_MAX];
306 	void *ads_null_cache;
307 	struct list_head cachelist;
308 #define PREALLOC_NODES_MAX_COUNT (3 * GUC_MAX_ENGINE_CLASSES * GUC_MAX_INSTANCES_PER_CLASS)
309 #define PREALLOC_NODES_DEFAULT_NUMREGS 64
310 
311 	int max_mmio_per_node;
312 	struct list_head outlist;
313 };
314 
315 static void
316 guc_capture_remove_stale_matches_from_list(struct xe_guc_state_capture *gc,
317 					   struct __guc_capture_parsed_output *node);
318 
319 static const struct __guc_mmio_reg_descr_group *
guc_capture_get_device_reglist(struct xe_device * xe)320 guc_capture_get_device_reglist(struct xe_device *xe)
321 {
322 	if (GRAPHICS_VER(xe) >= 35)
323 		return xe3p_lists;
324 	else if (GRAPHICS_VERx100(xe) >= 1255)
325 		return xe_hpg_lists;
326 	else
327 		return xe_lp_lists;
328 }
329 
330 static const struct __guc_mmio_reg_descr_group *
guc_capture_get_one_list(const struct __guc_mmio_reg_descr_group * reglists,u32 owner,u32 type,enum guc_capture_list_class_type capture_class)331 guc_capture_get_one_list(const struct __guc_mmio_reg_descr_group *reglists,
332 			 u32 owner, u32 type, enum guc_capture_list_class_type capture_class)
333 {
334 	int i;
335 
336 	if (!reglists)
337 		return NULL;
338 
339 	for (i = 0; reglists[i].list; ++i) {
340 		if (reglists[i].owner == owner && reglists[i].type == type &&
341 		    (reglists[i].engine == capture_class ||
342 		     reglists[i].type == GUC_STATE_CAPTURE_TYPE_GLOBAL))
343 			return &reglists[i];
344 	}
345 
346 	return NULL;
347 }
348 
349 const struct __guc_mmio_reg_descr_group *
xe_guc_capture_get_reg_desc_list(struct xe_gt * gt,u32 owner,u32 type,enum guc_capture_list_class_type capture_class,bool is_ext)350 xe_guc_capture_get_reg_desc_list(struct xe_gt *gt, u32 owner, u32 type,
351 				 enum guc_capture_list_class_type capture_class, bool is_ext)
352 {
353 	const struct __guc_mmio_reg_descr_group *reglists;
354 
355 	if (is_ext) {
356 		struct xe_guc *guc = &gt->uc.guc;
357 
358 		reglists = guc->capture->extlists;
359 	} else {
360 		reglists = guc_capture_get_device_reglist(gt_to_xe(gt));
361 	}
362 	return guc_capture_get_one_list(reglists, owner, type, capture_class);
363 }
364 
365 struct __ext_steer_reg {
366 	const char *name;
367 	struct xe_reg_mcr reg;
368 };
369 
370 static const struct __ext_steer_reg xe_extregs[] = {
371 	{"SAMPLER_INSTDONE",		SAMPLER_INSTDONE},
372 	{"ROW_INSTDONE",		ROW_INSTDONE}
373 };
374 
375 static const struct __ext_steer_reg xehpg_extregs[] = {
376 	{"SC_INSTDONE",			XEHPG_SC_INSTDONE},
377 	{"SC_INSTDONE_EXTRA",		XEHPG_SC_INSTDONE_EXTRA},
378 	{"SC_INSTDONE_EXTRA2",		XEHPG_SC_INSTDONE_EXTRA2},
379 	{"INSTDONE_GEOM_SVGUNIT",	XEHPG_INSTDONE_GEOM_SVGUNIT}
380 };
381 
__fill_ext_reg(struct __guc_mmio_reg_descr * ext,const struct __ext_steer_reg * extlist,u32 dss_id,u16 slice_id,u16 subslice_id)382 static void __fill_ext_reg(struct __guc_mmio_reg_descr *ext,
383 			   const struct __ext_steer_reg *extlist,
384 			   u32 dss_id, u16 slice_id, u16 subslice_id)
385 {
386 	if (!ext || !extlist)
387 		return;
388 
389 	ext->reg = XE_REG(extlist->reg.__reg.addr);
390 	ext->flags = FIELD_PREP(GUC_REGSET_STEERING_NEEDED, 1);
391 	ext->flags |= FIELD_PREP(GUC_REGSET_STEERING_GROUP, slice_id);
392 	ext->flags |= FIELD_PREP(GUC_REGSET_STEERING_INSTANCE, subslice_id);
393 	ext->dss_id = dss_id;
394 	ext->regname = extlist->name;
395 }
396 
397 static int
__alloc_ext_regs(struct drm_device * drm,struct __guc_mmio_reg_descr_group * newlist,const struct __guc_mmio_reg_descr_group * rootlist,int num_regs)398 __alloc_ext_regs(struct drm_device *drm, struct __guc_mmio_reg_descr_group *newlist,
399 		 const struct __guc_mmio_reg_descr_group *rootlist, int num_regs)
400 {
401 	struct __guc_mmio_reg_descr *list;
402 
403 	list = drmm_kzalloc(drm, num_regs * sizeof(struct __guc_mmio_reg_descr), GFP_KERNEL);
404 	if (!list)
405 		return -ENOMEM;
406 
407 	newlist->list = list;
408 	newlist->num_regs = num_regs;
409 	newlist->owner = rootlist->owner;
410 	newlist->engine = rootlist->engine;
411 	newlist->type = rootlist->type;
412 
413 	return 0;
414 }
415 
guc_capture_get_steer_reg_num(struct xe_device * xe)416 static int guc_capture_get_steer_reg_num(struct xe_device *xe)
417 {
418 	int num = ARRAY_SIZE(xe_extregs);
419 
420 	if (GRAPHICS_VERx100(xe) >= 1255)
421 		num += ARRAY_SIZE(xehpg_extregs);
422 
423 	return num;
424 }
425 
guc_capture_alloc_steered_lists(struct xe_guc * guc)426 static void guc_capture_alloc_steered_lists(struct xe_guc *guc)
427 {
428 	struct xe_gt *gt = guc_to_gt(guc);
429 	u16 slice, subslice;
430 	int dss, i, total = 0;
431 	const struct __guc_mmio_reg_descr_group *lists = guc->capture->reglists;
432 	const struct __guc_mmio_reg_descr_group *list;
433 	struct __guc_mmio_reg_descr_group *extlists;
434 	struct __guc_mmio_reg_descr *extarray;
435 	bool has_xehpg_extregs = GRAPHICS_VERx100(gt_to_xe(gt)) >= 1255;
436 	struct drm_device *drm = &gt_to_xe(gt)->drm;
437 	bool has_rcs_ccs = false;
438 	struct xe_hw_engine *hwe;
439 	enum xe_hw_engine_id id;
440 
441 	/*
442 	 * If GT has no rcs/ccs, no need to alloc steered list.
443 	 * Currently, only rcs/ccs has steering register, if in the future,
444 	 * other engine types has steering register, this condition check need
445 	 * to be extended
446 	 */
447 	for_each_hw_engine(hwe, gt, id) {
448 		if (xe_hwe_to_guc_capture_class(hwe) ==
449 		    GUC_CAPTURE_LIST_CLASS_RENDER_COMPUTE) {
450 			has_rcs_ccs = true;
451 			break;
452 		}
453 	}
454 
455 	if (!has_rcs_ccs)
456 		return;
457 
458 	/* steered registers currently only exist for the render-class */
459 	list = guc_capture_get_one_list(lists, GUC_CAPTURE_LIST_INDEX_PF,
460 					GUC_STATE_CAPTURE_TYPE_ENGINE_CLASS,
461 					GUC_CAPTURE_LIST_CLASS_RENDER_COMPUTE);
462 	/*
463 	 * Skip if this platform has no engine class registers or if extlists
464 	 * was previously allocated
465 	 */
466 	if (!list || guc->capture->extlists)
467 		return;
468 
469 	{
470 		xe_dss_mask_t all_dss;
471 
472 		total = bitmap_weighted_or(all_dss, gt->fuse_topo.g_dss_mask,
473 					   gt->fuse_topo.c_dss_mask,
474 					   XE_MAX_DSS_FUSE_BITS) *
475 			guc_capture_get_steer_reg_num(guc_to_xe(guc));
476 	}
477 
478 	if (!total)
479 		return;
480 
481 	/* allocate an extra for an end marker */
482 	extlists = drmm_kzalloc(drm, 2 * sizeof(struct __guc_mmio_reg_descr_group), GFP_KERNEL);
483 	if (!extlists)
484 		return;
485 
486 	if (__alloc_ext_regs(drm, &extlists[0], list, total)) {
487 		drmm_kfree(drm, extlists);
488 		return;
489 	}
490 
491 	/* For steering registers, the list is generated at run-time */
492 	extarray = (struct __guc_mmio_reg_descr *)extlists[0].list;
493 	for_each_dss_steering(dss, gt, slice, subslice) {
494 		for (i = 0; i < ARRAY_SIZE(xe_extregs); ++i) {
495 			__fill_ext_reg(extarray, &xe_extregs[i], dss, slice, subslice);
496 			++extarray;
497 		}
498 
499 		if (has_xehpg_extregs)
500 			for (i = 0; i < ARRAY_SIZE(xehpg_extregs); ++i) {
501 				__fill_ext_reg(extarray, &xehpg_extregs[i], dss, slice, subslice);
502 				++extarray;
503 			}
504 	}
505 
506 	extlists[0].num_regs = total;
507 
508 	xe_gt_dbg(guc_to_gt(guc), "capture found %d ext-regs.\n", total);
509 	guc->capture->extlists = extlists;
510 }
511 
512 static int
guc_capture_list_init(struct xe_guc * guc,u32 owner,u32 type,enum guc_capture_list_class_type capture_class,struct guc_mmio_reg * ptr,u16 num_entries)513 guc_capture_list_init(struct xe_guc *guc, u32 owner, u32 type,
514 		      enum guc_capture_list_class_type capture_class, struct guc_mmio_reg *ptr,
515 		      u16 num_entries)
516 {
517 	u32 ptr_idx = 0, list_idx = 0;
518 	const struct __guc_mmio_reg_descr_group *reglists = guc->capture->reglists;
519 	struct __guc_mmio_reg_descr_group *extlists = guc->capture->extlists;
520 	const struct __guc_mmio_reg_descr_group *match;
521 	u32 list_num;
522 
523 	if (!reglists)
524 		return -ENODEV;
525 
526 	match = guc_capture_get_one_list(reglists, owner, type, capture_class);
527 	if (!match)
528 		return -ENODATA;
529 
530 	list_num = match->num_regs;
531 	for (list_idx = 0; ptr_idx < num_entries && list_idx < list_num; ++list_idx, ++ptr_idx) {
532 		ptr[ptr_idx].offset = match->list[list_idx].reg.addr;
533 		ptr[ptr_idx].value = 0xDEADF00D;
534 		ptr[ptr_idx].flags = match->list[list_idx].flags;
535 		ptr[ptr_idx].mask = match->list[list_idx].mask;
536 	}
537 
538 	match = guc_capture_get_one_list(extlists, owner, type, capture_class);
539 	if (match)
540 		for (ptr_idx = list_num, list_idx = 0;
541 		     ptr_idx < num_entries && list_idx < match->num_regs;
542 		     ++ptr_idx, ++list_idx) {
543 			ptr[ptr_idx].offset = match->list[list_idx].reg.addr;
544 			ptr[ptr_idx].value = 0xDEADF00D;
545 			ptr[ptr_idx].flags = match->list[list_idx].flags;
546 			ptr[ptr_idx].mask = match->list[list_idx].mask;
547 		}
548 
549 	if (ptr_idx < num_entries)
550 		xe_gt_dbg(guc_to_gt(guc), "Got short capture reglist init: %d out-of %d.\n",
551 			  ptr_idx, num_entries);
552 
553 	return 0;
554 }
555 
556 static int
guc_cap_list_num_regs(struct xe_guc * guc,u32 owner,u32 type,enum guc_capture_list_class_type capture_class)557 guc_cap_list_num_regs(struct xe_guc *guc, u32 owner, u32 type,
558 		      enum guc_capture_list_class_type capture_class)
559 {
560 	const struct __guc_mmio_reg_descr_group *match;
561 	int num_regs = 0;
562 
563 	match = guc_capture_get_one_list(guc->capture->reglists, owner, type, capture_class);
564 	if (match)
565 		num_regs = match->num_regs;
566 
567 	match = guc_capture_get_one_list(guc->capture->extlists, owner, type, capture_class);
568 	if (match)
569 		num_regs += match->num_regs;
570 	else
571 		/*
572 		 * If a caller wants the full register dump size but we have
573 		 * not yet got the hw-config, which is before max_mmio_per_node
574 		 * is initialized, then provide a worst-case number for
575 		 * extlists based on max dss fuse bits, but only ever for
576 		 * render/compute
577 		 */
578 		if (owner == GUC_CAPTURE_LIST_INDEX_PF &&
579 		    type == GUC_STATE_CAPTURE_TYPE_ENGINE_CLASS &&
580 		    capture_class == GUC_CAPTURE_LIST_CLASS_RENDER_COMPUTE &&
581 		    !guc->capture->max_mmio_per_node)
582 			num_regs += guc_capture_get_steer_reg_num(guc_to_xe(guc)) *
583 				    XE_MAX_DSS_FUSE_BITS;
584 
585 	return num_regs;
586 }
587 
588 static int
guc_capture_getlistsize(struct xe_guc * guc,u32 owner,u32 type,enum guc_capture_list_class_type capture_class,size_t * size,bool is_purpose_est)589 guc_capture_getlistsize(struct xe_guc *guc, u32 owner, u32 type,
590 			enum guc_capture_list_class_type capture_class,
591 			size_t *size, bool is_purpose_est)
592 {
593 	struct xe_guc_state_capture *gc = guc->capture;
594 	struct xe_gt *gt = guc_to_gt(guc);
595 	struct __guc_capture_ads_cache *cache;
596 	int num_regs;
597 
598 	xe_gt_assert(gt, type < GUC_STATE_CAPTURE_TYPE_MAX);
599 	xe_gt_assert(gt, capture_class < GUC_CAPTURE_LIST_CLASS_MAX);
600 
601 	cache = &gc->ads_cache[owner][type][capture_class];
602 	if (!gc->reglists) {
603 		xe_gt_warn(gt, "No capture reglist for this device\n");
604 		return -ENODEV;
605 	}
606 
607 	if (cache->is_valid) {
608 		*size = cache->size;
609 		return cache->status;
610 	}
611 
612 	if (!is_purpose_est && owner == GUC_CAPTURE_LIST_INDEX_PF &&
613 	    !guc_capture_get_one_list(gc->reglists, owner, type, capture_class)) {
614 		if (type == GUC_STATE_CAPTURE_TYPE_GLOBAL)
615 			xe_gt_warn(gt, "Missing capture reglist: global!\n");
616 		else
617 			xe_gt_warn(gt, "Missing capture reglist: %s(%u):%s(%u)!\n",
618 				   capture_list_type_names[type], type,
619 				   capture_engine_class_names[capture_class], capture_class);
620 		return -ENODEV;
621 	}
622 
623 	num_regs = guc_cap_list_num_regs(guc, owner, type, capture_class);
624 	/* intentional empty lists can exist depending on hw config */
625 	if (!num_regs)
626 		return -ENODATA;
627 
628 	if (size)
629 		*size = PAGE_ALIGN((sizeof(struct guc_debug_capture_list)) +
630 				   (num_regs * sizeof(struct guc_mmio_reg)));
631 
632 	return 0;
633 }
634 
635 /**
636  * xe_guc_capture_getlistsize - Get list size for owner/type/class combination
637  * @guc: The GuC object
638  * @owner: PF/VF owner
639  * @type: GuC capture register type
640  * @capture_class: GuC capture engine class id
641  * @size: Point to the size
642  *
643  * This function will get the list for the owner/type/class combination, and
644  * return the page aligned list size.
645  *
646  * Returns: 0 on success or a negative error code on failure.
647  */
648 int
xe_guc_capture_getlistsize(struct xe_guc * guc,u32 owner,u32 type,enum guc_capture_list_class_type capture_class,size_t * size)649 xe_guc_capture_getlistsize(struct xe_guc *guc, u32 owner, u32 type,
650 			   enum guc_capture_list_class_type capture_class, size_t *size)
651 {
652 	return guc_capture_getlistsize(guc, owner, type, capture_class, size, false);
653 }
654 
655 /**
656  * xe_guc_capture_getlist - Get register capture list for owner/type/class
657  * combination
658  * @guc:	The GuC object
659  * @owner:	PF/VF owner
660  * @type:	GuC capture register type
661  * @capture_class:	GuC capture engine class id
662  * @outptr:	Point to cached register capture list
663  *
664  * This function will get the register capture list for the owner/type/class
665  * combination.
666  *
667  * Returns: 0 on success or a negative error code on failure.
668  */
669 int
xe_guc_capture_getlist(struct xe_guc * guc,u32 owner,u32 type,enum guc_capture_list_class_type capture_class,void ** outptr)670 xe_guc_capture_getlist(struct xe_guc *guc, u32 owner, u32 type,
671 		       enum guc_capture_list_class_type capture_class, void **outptr)
672 {
673 	struct xe_guc_state_capture *gc = guc->capture;
674 	struct __guc_capture_ads_cache *cache = &gc->ads_cache[owner][type][capture_class];
675 	struct guc_debug_capture_list *listnode;
676 	int ret, num_regs;
677 	u8 *caplist, *tmp;
678 	size_t size = 0;
679 
680 	if (!gc->reglists)
681 		return -ENODEV;
682 
683 	if (cache->is_valid) {
684 		*outptr = cache->ptr;
685 		return cache->status;
686 	}
687 
688 	ret = xe_guc_capture_getlistsize(guc, owner, type, capture_class, &size);
689 	if (ret) {
690 		cache->is_valid = true;
691 		cache->ptr = NULL;
692 		cache->size = 0;
693 		cache->status = ret;
694 		return ret;
695 	}
696 
697 	caplist = drmm_kzalloc(guc_to_drm(guc), size, GFP_KERNEL);
698 	if (!caplist)
699 		return -ENOMEM;
700 
701 	/* populate capture list header */
702 	tmp = caplist;
703 	num_regs = guc_cap_list_num_regs(guc, owner, type, capture_class);
704 	listnode = (struct guc_debug_capture_list *)tmp;
705 	listnode->header.info = FIELD_PREP(GUC_CAPTURELISTHDR_NUMDESCR, (u32)num_regs);
706 
707 	/* populate list of register descriptor */
708 	tmp += sizeof(struct guc_debug_capture_list);
709 	guc_capture_list_init(guc, owner, type, capture_class,
710 			      (struct guc_mmio_reg *)tmp, num_regs);
711 
712 	/* cache this list */
713 	cache->is_valid = true;
714 	cache->ptr = caplist;
715 	cache->size = size;
716 	cache->status = 0;
717 
718 	*outptr = caplist;
719 
720 	return 0;
721 }
722 
723 /**
724  * xe_guc_capture_getnullheader - Get a null list for register capture
725  * @guc:	The GuC object
726  * @outptr:	Point to cached register capture list
727  * @size:	Point to the size
728  *
729  * This function will alloc for a null list for register capture.
730  *
731  * Returns: 0 on success or a negative error code on failure.
732  */
733 int
xe_guc_capture_getnullheader(struct xe_guc * guc,void ** outptr,size_t * size)734 xe_guc_capture_getnullheader(struct xe_guc *guc, void **outptr, size_t *size)
735 {
736 	struct xe_guc_state_capture *gc = guc->capture;
737 	int tmp = sizeof(u32) * 4;
738 	void *null_header;
739 
740 	if (gc->ads_null_cache) {
741 		*outptr = gc->ads_null_cache;
742 		*size = tmp;
743 		return 0;
744 	}
745 
746 	null_header = drmm_kzalloc(guc_to_drm(guc), tmp, GFP_KERNEL);
747 	if (!null_header)
748 		return -ENOMEM;
749 
750 	gc->ads_null_cache = null_header;
751 	*outptr = null_header;
752 	*size = tmp;
753 
754 	return 0;
755 }
756 
757 /**
758  * xe_guc_capture_ads_input_worst_size - Calculate the worst size for GuC register capture
759  * @guc: point to xe_guc structure
760  *
761  * Calculate the worst size for GuC register capture by including all possible engines classes.
762  *
763  * Returns: Calculated size
764  */
xe_guc_capture_ads_input_worst_size(struct xe_guc * guc)765 size_t xe_guc_capture_ads_input_worst_size(struct xe_guc *guc)
766 {
767 	size_t total_size, class_size, instance_size, global_size;
768 	int i, j;
769 
770 	/*
771 	 * This function calculates the worst case register lists size by
772 	 * including all possible engines classes. It is called during the
773 	 * first of a two-phase GuC (and ADS-population) initialization
774 	 * sequence, that is, during the pre-hwconfig phase before we have
775 	 * the exact engine fusing info.
776 	 */
777 	total_size = PAGE_SIZE;	/* Pad a page in front for empty lists */
778 	for (i = 0; i < GUC_CAPTURE_LIST_INDEX_MAX; i++) {
779 		for (j = 0; j < GUC_CAPTURE_LIST_CLASS_MAX; j++) {
780 			if (!xe_guc_has_paging_engine(guc) &&
781 			    j == GUC_CAPTURE_LIST_CLASS_PAGING)
782 				continue;
783 
784 			if (xe_guc_capture_getlistsize(guc, i,
785 						       GUC_STATE_CAPTURE_TYPE_ENGINE_CLASS,
786 						       j, &class_size) < 0)
787 				class_size = 0;
788 			if (xe_guc_capture_getlistsize(guc, i,
789 						       GUC_STATE_CAPTURE_TYPE_ENGINE_INSTANCE,
790 						       j, &instance_size) < 0)
791 				instance_size = 0;
792 			total_size += class_size + instance_size;
793 		}
794 		if (xe_guc_capture_getlistsize(guc, i,
795 					       GUC_STATE_CAPTURE_TYPE_GLOBAL,
796 					       0, &global_size) < 0)
797 			global_size = 0;
798 		total_size += global_size;
799 	}
800 
801 	return PAGE_ALIGN(total_size);
802 }
803 
guc_capture_output_size_est(struct xe_guc * guc)804 static int guc_capture_output_size_est(struct xe_guc *guc)
805 {
806 	struct xe_gt *gt = guc_to_gt(guc);
807 	struct xe_hw_engine *hwe;
808 	enum xe_hw_engine_id id;
809 
810 	int capture_size = 0;
811 	size_t tmp = 0;
812 
813 	if (!guc->capture)
814 		return -ENODEV;
815 
816 	/*
817 	 * If every single engine-instance suffered a failure in quick succession but
818 	 * were all unrelated, then a burst of multiple error-capture events would dump
819 	 * registers for every one engine instance, one at a time. In this case, GuC
820 	 * would even dump the global-registers repeatedly.
821 	 *
822 	 * For each engine instance, there would be 1 x guc_state_capture_group_t output
823 	 * followed by 3 x guc_state_capture_t lists. The latter is how the register
824 	 * dumps are split across different register types (where the '3' are global vs class
825 	 * vs instance).
826 	 */
827 	for_each_hw_engine(hwe, gt, id) {
828 		enum guc_capture_list_class_type capture_class;
829 
830 		capture_class = xe_hwe_to_guc_capture_class(hwe);
831 		capture_size += sizeof(struct guc_state_capture_group_header_t) +
832 					 (3 * sizeof(struct guc_state_capture_header_t));
833 
834 		if (!guc_capture_getlistsize(guc, 0, GUC_STATE_CAPTURE_TYPE_GLOBAL,
835 					     0, &tmp, true))
836 			capture_size += tmp;
837 		if (!guc_capture_getlistsize(guc, 0, GUC_STATE_CAPTURE_TYPE_ENGINE_CLASS,
838 					     capture_class, &tmp, true))
839 			capture_size += tmp;
840 		if (!guc_capture_getlistsize(guc, 0, GUC_STATE_CAPTURE_TYPE_ENGINE_INSTANCE,
841 					     capture_class, &tmp, true))
842 			capture_size += tmp;
843 	}
844 
845 	return capture_size;
846 }
847 
848 /*
849  * Add on a 3x multiplier to allow for multiple back-to-back captures occurring
850  * before the Xe can read the data out and process it
851  */
852 #define GUC_CAPTURE_OVERBUFFER_MULTIPLIER 3
853 
check_guc_capture_size(struct xe_guc * guc)854 static void check_guc_capture_size(struct xe_guc *guc)
855 {
856 	int capture_size = guc_capture_output_size_est(guc);
857 	int spare_size = capture_size * GUC_CAPTURE_OVERBUFFER_MULTIPLIER;
858 	u32 buffer_size = XE_GUC_LOG_STATE_CAPTURE_BUFFER_SIZE;
859 
860 	/*
861 	 * NOTE: capture_size is much smaller than the capture region
862 	 * allocation (DG2: <80K vs 1MB).
863 	 * Additionally, its based on space needed to fit all engines getting
864 	 * reset at once within the same G2H handler task slot. This is very
865 	 * unlikely. However, if GuC really does run out of space for whatever
866 	 * reason, we will see an separate warning message when processing the
867 	 * G2H event capture-notification, search for:
868 	 * xe_guc_STATE_CAPTURE_EVENT_STATUS_NOSPACE.
869 	 */
870 	if (capture_size < 0)
871 		xe_gt_dbg(guc_to_gt(guc),
872 			  "Failed to calculate error state capture buffer minimum size: %d!\n",
873 			  capture_size);
874 	if (capture_size > buffer_size)
875 		xe_gt_dbg(guc_to_gt(guc), "Error state capture buffer maybe small: %d < %d\n",
876 			  buffer_size, capture_size);
877 	else if (spare_size > buffer_size)
878 		xe_gt_dbg(guc_to_gt(guc),
879 			  "Error state capture buffer lacks spare size: %d < %d (min = %d)\n",
880 			  buffer_size, spare_size, capture_size);
881 }
882 
883 static void
guc_capture_add_node_to_list(struct __guc_capture_parsed_output * node,struct list_head * list)884 guc_capture_add_node_to_list(struct __guc_capture_parsed_output *node,
885 			     struct list_head *list)
886 {
887 	list_add(&node->link, list);
888 }
889 
890 static void
guc_capture_add_node_to_outlist(struct xe_guc_state_capture * gc,struct __guc_capture_parsed_output * node)891 guc_capture_add_node_to_outlist(struct xe_guc_state_capture *gc,
892 				struct __guc_capture_parsed_output *node)
893 {
894 	guc_capture_remove_stale_matches_from_list(gc, node);
895 	guc_capture_add_node_to_list(node, &gc->outlist);
896 }
897 
898 static void
guc_capture_add_node_to_cachelist(struct xe_guc_state_capture * gc,struct __guc_capture_parsed_output * node)899 guc_capture_add_node_to_cachelist(struct xe_guc_state_capture *gc,
900 				  struct __guc_capture_parsed_output *node)
901 {
902 	guc_capture_add_node_to_list(node, &gc->cachelist);
903 }
904 
905 static void
guc_capture_free_outlist_node(struct xe_guc_state_capture * gc,struct __guc_capture_parsed_output * n)906 guc_capture_free_outlist_node(struct xe_guc_state_capture *gc,
907 			      struct __guc_capture_parsed_output *n)
908 {
909 	if (n) {
910 		n->locked = 0;
911 		list_del(&n->link);
912 		/* put node back to cache list */
913 		guc_capture_add_node_to_cachelist(gc, n);
914 	}
915 }
916 
917 static void
guc_capture_remove_stale_matches_from_list(struct xe_guc_state_capture * gc,struct __guc_capture_parsed_output * node)918 guc_capture_remove_stale_matches_from_list(struct xe_guc_state_capture *gc,
919 					   struct __guc_capture_parsed_output *node)
920 {
921 	struct __guc_capture_parsed_output *n, *ntmp;
922 	int guc_id = node->guc_id;
923 
924 	list_for_each_entry_safe(n, ntmp, &gc->outlist, link) {
925 		if (n != node && !n->locked && n->guc_id == guc_id)
926 			guc_capture_free_outlist_node(gc, n);
927 	}
928 }
929 
930 static void
guc_capture_init_node(struct xe_guc * guc,struct __guc_capture_parsed_output * node)931 guc_capture_init_node(struct xe_guc *guc, struct __guc_capture_parsed_output *node)
932 {
933 	struct guc_mmio_reg *tmp[GUC_STATE_CAPTURE_TYPE_MAX];
934 	int i;
935 
936 	for (i = 0; i < GUC_STATE_CAPTURE_TYPE_MAX; ++i) {
937 		tmp[i] = node->reginfo[i].regs;
938 		memset(tmp[i], 0, sizeof(struct guc_mmio_reg) *
939 		       guc->capture->max_mmio_per_node);
940 	}
941 	memset(node, 0, sizeof(*node));
942 	for (i = 0; i < GUC_STATE_CAPTURE_TYPE_MAX; ++i)
943 		node->reginfo[i].regs = tmp[i];
944 
945 	INIT_LIST_HEAD(&node->link);
946 }
947 
948 /**
949  * DOC: Init, G2H-event and reporting flows for GuC-error-capture
950  *
951  * KMD Init time flows:
952  * --------------------
953  *     --> alloc A: GuC input capture regs lists (registered to GuC via ADS).
954  *                  xe_guc_ads acquires the register lists by calling
955  *                  xe_guc_capture_getlistsize and xe_guc_capture_getlist 'n' times,
956  *                  where n = 1 for global-reg-list +
957  *                            num_engine_classes for class-reg-list +
958  *                            num_engine_classes for instance-reg-list
959  *                               (since all instances of the same engine-class type
960  *                                have an identical engine-instance register-list).
961  *                  ADS module also calls separately for PF vs VF.
962  *
963  *     --> alloc B: GuC output capture buf (registered via guc_init_params(log_param))
964  *                  Size = XE_GUC_LOG_STATE_CAPTURE_BUFFER_SIZE (warns if on too-small)
965  *                  Note2: 'x 3' to hold multiple capture groups
966  *
967  * GUC Runtime notify capture:
968  * --------------------------
969  *     --> G2H STATE_CAPTURE_NOTIFICATION
970  *                   L--> xe_guc_capture_process
971  *                           L--> Loop through B (head..tail) and for each engine instance's
972  *                                err-state-captured register-list we find, we alloc 'C':
973  *      --> alloc C: A capture-output-node structure that includes misc capture info along
974  *                   with 3 register list dumps (global, engine-class and engine-instance)
975  *                   This node is created from a pre-allocated list of blank nodes in
976  *                   guc->capture->cachelist and populated with the error-capture
977  *                   data from GuC and then it's added into guc->capture->outlist linked
978  *                   list. This list is used for matchup and printout by xe_devcoredump_read
979  *                   and xe_engine_snapshot_print, (when user invokes the devcoredump sysfs).
980  *
981  * GUC --> notify context reset:
982  * -----------------------------
983  *     --> guc_exec_queue_timedout_job
984  *                   L--> xe_devcoredump
985  *                          L--> devcoredump_snapshot
986  *                               --> xe_hw_engine_snapshot_capture
987  *                               --> xe_engine_manual_capture(For manual capture)
988  *
989  * User Sysfs / Debugfs
990  * --------------------
991  *      --> xe_devcoredump_read->
992  *             L--> xxx_snapshot_print
993  *                    L--> xe_engine_snapshot_print
994  *                         Print register lists values saved at
995  *                         guc->capture->outlist
996  *
997  */
998 
guc_capture_buf_cnt(struct __guc_capture_bufstate * buf)999 static int guc_capture_buf_cnt(struct __guc_capture_bufstate *buf)
1000 {
1001 	if (buf->wr >= buf->rd)
1002 		return (buf->wr - buf->rd);
1003 	return (buf->size - buf->rd) + buf->wr;
1004 }
1005 
guc_capture_buf_cnt_to_end(struct __guc_capture_bufstate * buf)1006 static int guc_capture_buf_cnt_to_end(struct __guc_capture_bufstate *buf)
1007 {
1008 	if (buf->rd > buf->wr)
1009 		return (buf->size - buf->rd);
1010 	return (buf->wr - buf->rd);
1011 }
1012 
1013 /*
1014  * GuC's error-capture output is a ring buffer populated in a byte-stream fashion:
1015  *
1016  * The GuC Log buffer region for error-capture is managed like a ring buffer.
1017  * The GuC firmware dumps error capture logs into this ring in a byte-stream flow.
1018  * Additionally, as per the current and foreseeable future, all packed error-
1019  * capture output structures are dword aligned.
1020  *
1021  * That said, if the GuC firmware is in the midst of writing a structure that is larger
1022  * than one dword but the tail end of the err-capture buffer-region has lesser space left,
1023  * we would need to extract that structure one dword at a time straddled across the end,
1024  * onto the start of the ring.
1025  *
1026  * Below function, guc_capture_log_remove_bytes is a helper for that. All callers of this
1027  * function would typically do a straight-up memcpy from the ring contents and will only
1028  * call this helper if their structure-extraction is straddling across the end of the
1029  * ring. GuC firmware does not add any padding. The reason for the no-padding is to ease
1030  * scalability for future expansion of output data types without requiring a redesign
1031  * of the flow controls.
1032  */
1033 static int
guc_capture_log_remove_bytes(struct xe_guc * guc,struct __guc_capture_bufstate * buf,void * out,int bytes_needed)1034 guc_capture_log_remove_bytes(struct xe_guc *guc, struct __guc_capture_bufstate *buf,
1035 			     void *out, int bytes_needed)
1036 {
1037 #define GUC_CAPTURE_LOG_BUF_COPY_RETRY_MAX	3
1038 
1039 	int fill_size = 0, tries = GUC_CAPTURE_LOG_BUF_COPY_RETRY_MAX;
1040 	int copy_size, avail;
1041 
1042 	xe_assert(guc_to_xe(guc), bytes_needed % sizeof(u32) == 0);
1043 
1044 	if (bytes_needed > guc_capture_buf_cnt(buf))
1045 		return -1;
1046 
1047 	while (bytes_needed > 0 && tries--) {
1048 		int misaligned;
1049 
1050 		avail = guc_capture_buf_cnt_to_end(buf);
1051 		misaligned = avail % sizeof(u32);
1052 		/* wrap if at end */
1053 		if (!avail) {
1054 			/* output stream clipped */
1055 			if (!buf->rd)
1056 				return fill_size;
1057 			buf->rd = 0;
1058 			continue;
1059 		}
1060 
1061 		/* Only copy to u32 aligned data */
1062 		copy_size = avail < bytes_needed ? avail - misaligned : bytes_needed;
1063 		xe_map_memcpy_from(guc_to_xe(guc), out + fill_size, &guc->log.bo->vmap,
1064 				   buf->data_offset + buf->rd, copy_size);
1065 		buf->rd += copy_size;
1066 		fill_size += copy_size;
1067 		bytes_needed -= copy_size;
1068 
1069 		if (misaligned)
1070 			xe_gt_warn(guc_to_gt(guc),
1071 				   "Bytes extraction not dword aligned, clipping.\n");
1072 	}
1073 
1074 	return fill_size;
1075 }
1076 
1077 static int
guc_capture_log_get_group_hdr(struct xe_guc * guc,struct __guc_capture_bufstate * buf,struct guc_state_capture_group_header_t * ghdr)1078 guc_capture_log_get_group_hdr(struct xe_guc *guc, struct __guc_capture_bufstate *buf,
1079 			      struct guc_state_capture_group_header_t *ghdr)
1080 {
1081 	int fullsize = sizeof(struct guc_state_capture_group_header_t);
1082 
1083 	if (guc_capture_log_remove_bytes(guc, buf, ghdr, fullsize) != fullsize)
1084 		return -1;
1085 	return 0;
1086 }
1087 
1088 static int
guc_capture_log_get_data_hdr(struct xe_guc * guc,struct __guc_capture_bufstate * buf,struct guc_state_capture_header_t * hdr)1089 guc_capture_log_get_data_hdr(struct xe_guc *guc, struct __guc_capture_bufstate *buf,
1090 			     struct guc_state_capture_header_t *hdr)
1091 {
1092 	int fullsize = sizeof(struct guc_state_capture_header_t);
1093 
1094 	if (guc_capture_log_remove_bytes(guc, buf, hdr, fullsize) != fullsize)
1095 		return -1;
1096 	return 0;
1097 }
1098 
1099 static int
guc_capture_log_get_register(struct xe_guc * guc,struct __guc_capture_bufstate * buf,struct guc_mmio_reg * reg)1100 guc_capture_log_get_register(struct xe_guc *guc, struct __guc_capture_bufstate *buf,
1101 			     struct guc_mmio_reg *reg)
1102 {
1103 	int fullsize = sizeof(struct guc_mmio_reg);
1104 
1105 	if (guc_capture_log_remove_bytes(guc, buf, reg, fullsize) != fullsize)
1106 		return -1;
1107 	return 0;
1108 }
1109 
1110 static struct __guc_capture_parsed_output *
guc_capture_get_prealloc_node(struct xe_guc * guc)1111 guc_capture_get_prealloc_node(struct xe_guc *guc)
1112 {
1113 	struct __guc_capture_parsed_output *found = NULL;
1114 
1115 	if (!list_empty(&guc->capture->cachelist)) {
1116 		struct __guc_capture_parsed_output *n, *ntmp;
1117 
1118 		/* get first avail node from the cache list */
1119 		list_for_each_entry_safe(n, ntmp, &guc->capture->cachelist, link) {
1120 			found = n;
1121 			break;
1122 		}
1123 	} else {
1124 		struct __guc_capture_parsed_output *n, *ntmp;
1125 
1126 		/*
1127 		 * traverse reversed and steal back the oldest node already
1128 		 * allocated
1129 		 */
1130 		list_for_each_entry_safe_reverse(n, ntmp, &guc->capture->outlist, link) {
1131 			if (!n->locked)
1132 				found = n;
1133 		}
1134 	}
1135 	if (found) {
1136 		list_del(&found->link);
1137 		guc_capture_init_node(guc, found);
1138 	}
1139 
1140 	return found;
1141 }
1142 
1143 static struct __guc_capture_parsed_output *
guc_capture_clone_node(struct xe_guc * guc,struct __guc_capture_parsed_output * original,u32 keep_reglist_mask)1144 guc_capture_clone_node(struct xe_guc *guc, struct __guc_capture_parsed_output *original,
1145 		       u32 keep_reglist_mask)
1146 {
1147 	struct __guc_capture_parsed_output *new;
1148 	int i;
1149 
1150 	new = guc_capture_get_prealloc_node(guc);
1151 	if (!new)
1152 		return NULL;
1153 	if (!original)
1154 		return new;
1155 
1156 	new->is_partial = original->is_partial;
1157 
1158 	/* copy reg-lists that we want to clone */
1159 	for (i = 0; i < GUC_STATE_CAPTURE_TYPE_MAX; ++i) {
1160 		if (keep_reglist_mask & BIT(i)) {
1161 			XE_WARN_ON(original->reginfo[i].num_regs  >
1162 				   guc->capture->max_mmio_per_node);
1163 
1164 			memcpy(new->reginfo[i].regs, original->reginfo[i].regs,
1165 			       original->reginfo[i].num_regs * sizeof(struct guc_mmio_reg));
1166 
1167 			new->reginfo[i].num_regs = original->reginfo[i].num_regs;
1168 			new->reginfo[i].vfid  = original->reginfo[i].vfid;
1169 
1170 			if (i == GUC_STATE_CAPTURE_TYPE_ENGINE_CLASS) {
1171 				new->eng_class = original->eng_class;
1172 			} else if (i == GUC_STATE_CAPTURE_TYPE_ENGINE_INSTANCE) {
1173 				new->eng_inst = original->eng_inst;
1174 				new->guc_id = original->guc_id;
1175 				new->lrca = original->lrca;
1176 			}
1177 		}
1178 	}
1179 
1180 	return new;
1181 }
1182 
1183 static int
guc_capture_extract_reglists(struct xe_guc * guc,struct __guc_capture_bufstate * buf)1184 guc_capture_extract_reglists(struct xe_guc *guc, struct __guc_capture_bufstate *buf)
1185 {
1186 	struct xe_gt *gt = guc_to_gt(guc);
1187 	struct guc_state_capture_group_header_t ghdr = {0};
1188 	struct guc_state_capture_header_t hdr = {0};
1189 	struct __guc_capture_parsed_output *node = NULL;
1190 	struct guc_mmio_reg *regs = NULL;
1191 	int i, numlists, numregs, ret = 0;
1192 	enum guc_state_capture_type datatype;
1193 	struct guc_mmio_reg tmp;
1194 	bool is_partial = false;
1195 
1196 	i = guc_capture_buf_cnt(buf);
1197 	if (!i)
1198 		return -ENODATA;
1199 
1200 	if (i % sizeof(u32)) {
1201 		xe_gt_warn(gt, "Got mis-aligned register capture entries\n");
1202 		ret = -EIO;
1203 		goto bailout;
1204 	}
1205 
1206 	/* first get the capture group header */
1207 	if (guc_capture_log_get_group_hdr(guc, buf, &ghdr)) {
1208 		ret = -EIO;
1209 		goto bailout;
1210 	}
1211 	/*
1212 	 * we would typically expect a layout as below where n would be expected to be
1213 	 * anywhere between 3 to n where n > 3 if we are seeing multiple dependent engine
1214 	 * instances being reset together.
1215 	 * ____________________________________________
1216 	 * | Capture Group                            |
1217 	 * | ________________________________________ |
1218 	 * | | Capture Group Header:                | |
1219 	 * | |  - num_captures = 5                  | |
1220 	 * | |______________________________________| |
1221 	 * | ________________________________________ |
1222 	 * | | Capture1:                            | |
1223 	 * | |  Hdr: GLOBAL, numregs=a              | |
1224 	 * | | ____________________________________ | |
1225 	 * | | | Reglist                          | | |
1226 	 * | | | - reg1, reg2, ... rega           | | |
1227 	 * | | |__________________________________| | |
1228 	 * | |______________________________________| |
1229 	 * | ________________________________________ |
1230 	 * | | Capture2:                            | |
1231 	 * | |  Hdr: CLASS=RENDER/COMPUTE, numregs=b| |
1232 	 * | | ____________________________________ | |
1233 	 * | | | Reglist                          | | |
1234 	 * | | | - reg1, reg2, ... regb           | | |
1235 	 * | | |__________________________________| | |
1236 	 * | |______________________________________| |
1237 	 * | ________________________________________ |
1238 	 * | | Capture3:                            | |
1239 	 * | |  Hdr: INSTANCE=RCS, numregs=c        | |
1240 	 * | | ____________________________________ | |
1241 	 * | | | Reglist                          | | |
1242 	 * | | | - reg1, reg2, ... regc           | | |
1243 	 * | | |__________________________________| | |
1244 	 * | |______________________________________| |
1245 	 * | ________________________________________ |
1246 	 * | | Capture4:                            | |
1247 	 * | |  Hdr: CLASS=RENDER/COMPUTE, numregs=d| |
1248 	 * | | ____________________________________ | |
1249 	 * | | | Reglist                          | | |
1250 	 * | | | - reg1, reg2, ... regd           | | |
1251 	 * | | |__________________________________| | |
1252 	 * | |______________________________________| |
1253 	 * | ________________________________________ |
1254 	 * | | Capture5:                            | |
1255 	 * | |  Hdr: INSTANCE=CCS0, numregs=e       | |
1256 	 * | | ____________________________________ | |
1257 	 * | | | Reglist                          | | |
1258 	 * | | | - reg1, reg2, ... rege           | | |
1259 	 * | | |__________________________________| | |
1260 	 * | |______________________________________| |
1261 	 * |__________________________________________|
1262 	 */
1263 	is_partial = FIELD_GET(GUC_STATE_CAPTURE_GROUP_HEADER_CAPTURE_GROUP_TYPE, ghdr.info);
1264 	numlists = FIELD_GET(GUC_STATE_CAPTURE_GROUP_HEADER_NUM_CAPTURES, ghdr.info);
1265 
1266 	while (numlists--) {
1267 		if (guc_capture_log_get_data_hdr(guc, buf, &hdr)) {
1268 			ret = -EIO;
1269 			break;
1270 		}
1271 
1272 		datatype = FIELD_GET(GUC_STATE_CAPTURE_HEADER_CAPTURE_TYPE, hdr.info);
1273 		if (datatype > GUC_STATE_CAPTURE_TYPE_ENGINE_INSTANCE) {
1274 			/* unknown capture type - skip over to next capture set */
1275 			numregs = FIELD_GET(GUC_STATE_CAPTURE_HEADER_NUM_MMIO_ENTRIES,
1276 					    hdr.num_mmio_entries);
1277 			while (numregs--) {
1278 				if (guc_capture_log_get_register(guc, buf, &tmp)) {
1279 					ret = -EIO;
1280 					break;
1281 				}
1282 			}
1283 			continue;
1284 		} else if (node) {
1285 			/*
1286 			 * Based on the current capture type and what we have so far,
1287 			 * decide if we should add the current node into the internal
1288 			 * linked list for match-up when xe_devcoredump calls later
1289 			 * (and alloc a blank node for the next set of reglists)
1290 			 * or continue with the same node or clone the current node
1291 			 * but only retain the global or class registers (such as the
1292 			 * case of dependent engine resets).
1293 			 */
1294 			if (datatype == GUC_STATE_CAPTURE_TYPE_GLOBAL) {
1295 				guc_capture_add_node_to_outlist(guc->capture, node);
1296 				node = NULL;
1297 			} else if (datatype == GUC_STATE_CAPTURE_TYPE_ENGINE_CLASS &&
1298 				   node->reginfo[GUC_STATE_CAPTURE_TYPE_ENGINE_CLASS].num_regs) {
1299 				/* Add to list, clone node and duplicate global list */
1300 				guc_capture_add_node_to_outlist(guc->capture, node);
1301 				node = guc_capture_clone_node(guc, node,
1302 							      GCAP_PARSED_REGLIST_INDEX_GLOBAL);
1303 			} else if (datatype == GUC_STATE_CAPTURE_TYPE_ENGINE_INSTANCE &&
1304 				   node->reginfo[GUC_STATE_CAPTURE_TYPE_ENGINE_INSTANCE].num_regs) {
1305 				/* Add to list, clone node and duplicate global + class lists */
1306 				guc_capture_add_node_to_outlist(guc->capture, node);
1307 				node = guc_capture_clone_node(guc, node,
1308 							      (GCAP_PARSED_REGLIST_INDEX_GLOBAL |
1309 							      GCAP_PARSED_REGLIST_INDEX_ENGCLASS));
1310 			}
1311 		}
1312 
1313 		if (!node) {
1314 			node = guc_capture_get_prealloc_node(guc);
1315 			if (!node) {
1316 				ret = -ENOMEM;
1317 				break;
1318 			}
1319 			if (datatype != GUC_STATE_CAPTURE_TYPE_GLOBAL)
1320 				xe_gt_dbg(gt, "Register capture missing global dump: %08x!\n",
1321 					  datatype);
1322 		}
1323 		node->is_partial = is_partial;
1324 		node->reginfo[datatype].vfid = FIELD_GET(GUC_STATE_CAPTURE_HEADER_VFID, hdr.owner);
1325 		node->source = XE_ENGINE_CAPTURE_SOURCE_GUC;
1326 		node->type = datatype;
1327 
1328 		switch (datatype) {
1329 		case GUC_STATE_CAPTURE_TYPE_ENGINE_INSTANCE:
1330 			node->eng_class = FIELD_GET(GUC_STATE_CAPTURE_HEADER_ENGINE_CLASS,
1331 						    hdr.info);
1332 			node->eng_inst = FIELD_GET(GUC_STATE_CAPTURE_HEADER_ENGINE_INSTANCE,
1333 						   hdr.info);
1334 			node->lrca = hdr.lrca;
1335 			node->guc_id = hdr.guc_id;
1336 			break;
1337 		case GUC_STATE_CAPTURE_TYPE_ENGINE_CLASS:
1338 			node->eng_class = FIELD_GET(GUC_STATE_CAPTURE_HEADER_ENGINE_CLASS,
1339 						    hdr.info);
1340 			break;
1341 		default:
1342 			break;
1343 		}
1344 
1345 		numregs = FIELD_GET(GUC_STATE_CAPTURE_HEADER_NUM_MMIO_ENTRIES,
1346 				    hdr.num_mmio_entries);
1347 		if (numregs > guc->capture->max_mmio_per_node) {
1348 			xe_gt_dbg(gt, "Register capture list extraction clipped by prealloc!\n");
1349 			numregs = guc->capture->max_mmio_per_node;
1350 		}
1351 		node->reginfo[datatype].num_regs = numregs;
1352 		regs = node->reginfo[datatype].regs;
1353 		i = 0;
1354 		while (numregs--) {
1355 			if (guc_capture_log_get_register(guc, buf, &regs[i++])) {
1356 				ret = -EIO;
1357 				break;
1358 			}
1359 		}
1360 	}
1361 
1362 bailout:
1363 	if (node) {
1364 		/* If we have data, add to linked list for match-up when xe_devcoredump calls */
1365 		for (i = GUC_STATE_CAPTURE_TYPE_GLOBAL; i < GUC_STATE_CAPTURE_TYPE_MAX; ++i) {
1366 			if (node->reginfo[i].regs) {
1367 				guc_capture_add_node_to_outlist(guc->capture, node);
1368 				node = NULL;
1369 				break;
1370 			}
1371 		}
1372 		if (node) /* else return it back to cache list */
1373 			guc_capture_add_node_to_cachelist(guc->capture, node);
1374 	}
1375 	return ret;
1376 }
1377 
__guc_capture_flushlog_complete(struct xe_guc * guc)1378 static int __guc_capture_flushlog_complete(struct xe_guc *guc)
1379 {
1380 	u32 action[] = {
1381 		XE_GUC_ACTION_LOG_BUFFER_FILE_FLUSH_COMPLETE,
1382 		GUC_LOG_TYPE_STATE_CAPTURE
1383 	};
1384 
1385 	return xe_guc_ct_send_g2h_handler(&guc->ct, action, ARRAY_SIZE(action));
1386 }
1387 
__guc_capture_process_output(struct xe_guc * guc)1388 static void __guc_capture_process_output(struct xe_guc *guc)
1389 {
1390 	unsigned int buffer_size, read_offset, write_offset, full_count;
1391 	struct xe_uc *uc = container_of(guc, typeof(*uc), guc);
1392 	struct guc_log_buffer_state log_buf_state_local;
1393 	struct __guc_capture_bufstate buf;
1394 	bool new_overflow;
1395 	int ret, tmp;
1396 	u32 log_buf_state_offset;
1397 	u32 src_data_offset;
1398 
1399 	log_buf_state_offset = sizeof(struct guc_log_buffer_state) * GUC_LOG_TYPE_STATE_CAPTURE;
1400 	src_data_offset = XE_GUC_LOG_STATE_CAPTURE_OFFSET;
1401 
1402 	/*
1403 	 * Make a copy of the state structure, inside GuC log buffer
1404 	 * (which is uncached mapped), on the stack to avoid reading
1405 	 * from it multiple times.
1406 	 */
1407 	xe_map_memcpy_from(guc_to_xe(guc), &log_buf_state_local, &guc->log.bo->vmap,
1408 			   log_buf_state_offset, sizeof(struct guc_log_buffer_state));
1409 
1410 	buffer_size = XE_GUC_LOG_STATE_CAPTURE_BUFFER_SIZE;
1411 	read_offset = log_buf_state_local.read_ptr;
1412 	write_offset = log_buf_state_local.sampled_write_ptr;
1413 	full_count = FIELD_GET(GUC_LOG_BUFFER_STATE_BUFFER_FULL_CNT, log_buf_state_local.flags);
1414 
1415 	/* Bookkeeping stuff */
1416 	tmp = FIELD_GET(GUC_LOG_BUFFER_STATE_FLUSH_TO_FILE, log_buf_state_local.flags);
1417 	guc->log.stats[GUC_LOG_TYPE_STATE_CAPTURE].flush += tmp;
1418 	new_overflow = xe_guc_check_log_buf_overflow(&guc->log, GUC_LOG_TYPE_STATE_CAPTURE,
1419 						     full_count);
1420 
1421 	/* Now copy the actual logs. */
1422 	if (unlikely(new_overflow)) {
1423 		/* copy the whole buffer in case of overflow */
1424 		read_offset = 0;
1425 		write_offset = buffer_size;
1426 	} else if (unlikely((read_offset > buffer_size) ||
1427 			(write_offset > buffer_size))) {
1428 		xe_gt_err(guc_to_gt(guc),
1429 			  "Register capture buffer in invalid state: read = 0x%X, size = 0x%X!\n",
1430 			  read_offset, buffer_size);
1431 		/* copy whole buffer as offsets are unreliable */
1432 		read_offset = 0;
1433 		write_offset = buffer_size;
1434 	}
1435 
1436 	buf.size = buffer_size;
1437 	buf.rd = read_offset;
1438 	buf.wr = write_offset;
1439 	buf.data_offset = src_data_offset;
1440 
1441 	if (!xe_guc_read_stopped(guc)) {
1442 		do {
1443 			ret = guc_capture_extract_reglists(guc, &buf);
1444 			if (ret && ret != -ENODATA)
1445 				xe_gt_dbg(guc_to_gt(guc), "Capture extraction failed:%d\n", ret);
1446 		} while (ret >= 0);
1447 	}
1448 
1449 	/* Update the state of log buffer err-cap state */
1450 	xe_map_wr(guc_to_xe(guc), &guc->log.bo->vmap,
1451 		  log_buf_state_offset + offsetof(struct guc_log_buffer_state, read_ptr), u32,
1452 		  write_offset);
1453 
1454 	/*
1455 	 * Clear the flush_to_file from local first, the local was loaded by above
1456 	 * xe_map_memcpy_from, then write out the "updated local" through
1457 	 * xe_map_wr()
1458 	 */
1459 	log_buf_state_local.flags &= ~GUC_LOG_BUFFER_STATE_FLUSH_TO_FILE;
1460 	xe_map_wr(guc_to_xe(guc), &guc->log.bo->vmap,
1461 		  log_buf_state_offset + offsetof(struct guc_log_buffer_state, flags), u32,
1462 		  log_buf_state_local.flags);
1463 	__guc_capture_flushlog_complete(guc);
1464 }
1465 
1466 /*
1467  * xe_guc_capture_process - Process GuC register captured data
1468  * @guc: The GuC object
1469  *
1470  * When GuC captured data is ready, GuC will send message
1471  * XE_GUC_ACTION_STATE_CAPTURE_NOTIFICATION to host, this function will be
1472  * called to process the data comes with the message.
1473  *
1474  * Returns: None
1475  */
xe_guc_capture_process(struct xe_guc * guc)1476 void xe_guc_capture_process(struct xe_guc *guc)
1477 {
1478 	if (guc->capture)
1479 		__guc_capture_process_output(guc);
1480 }
1481 
1482 static struct __guc_capture_parsed_output *
guc_capture_alloc_one_node(struct xe_guc * guc)1483 guc_capture_alloc_one_node(struct xe_guc *guc)
1484 {
1485 	struct drm_device *drm = guc_to_drm(guc);
1486 	struct __guc_capture_parsed_output *new;
1487 	int i;
1488 
1489 	new = drmm_kzalloc(drm, sizeof(*new), GFP_KERNEL);
1490 	if (!new)
1491 		return NULL;
1492 
1493 	for (i = 0; i < GUC_STATE_CAPTURE_TYPE_MAX; ++i) {
1494 		new->reginfo[i].regs = drmm_kzalloc(drm, guc->capture->max_mmio_per_node *
1495 						    sizeof(struct guc_mmio_reg), GFP_KERNEL);
1496 		if (!new->reginfo[i].regs) {
1497 			while (i)
1498 				drmm_kfree(drm, new->reginfo[--i].regs);
1499 			drmm_kfree(drm, new);
1500 			return NULL;
1501 		}
1502 	}
1503 	guc_capture_init_node(guc, new);
1504 
1505 	return new;
1506 }
1507 
1508 static void
__guc_capture_create_prealloc_nodes(struct xe_guc * guc)1509 __guc_capture_create_prealloc_nodes(struct xe_guc *guc)
1510 {
1511 	struct __guc_capture_parsed_output *node = NULL;
1512 	int i;
1513 
1514 	for (i = 0; i < PREALLOC_NODES_MAX_COUNT; ++i) {
1515 		node = guc_capture_alloc_one_node(guc);
1516 		if (!node) {
1517 			xe_gt_warn(guc_to_gt(guc), "Register capture pre-alloc-cache failure\n");
1518 			/* dont free the priors, use what we got and cleanup at shutdown */
1519 			return;
1520 		}
1521 		guc_capture_add_node_to_cachelist(guc->capture, node);
1522 	}
1523 }
1524 
1525 static int
guc_get_max_reglist_count(struct xe_guc * guc)1526 guc_get_max_reglist_count(struct xe_guc *guc)
1527 {
1528 	int i, j, k, tmp, maxregcount = 0;
1529 
1530 	for (i = 0; i < GUC_CAPTURE_LIST_INDEX_MAX; ++i) {
1531 		for (j = 0; j < GUC_STATE_CAPTURE_TYPE_MAX; ++j) {
1532 			for (k = 0; k < GUC_CAPTURE_LIST_CLASS_MAX; ++k) {
1533 				const struct __guc_mmio_reg_descr_group *match;
1534 
1535 				if (j == GUC_STATE_CAPTURE_TYPE_GLOBAL && k > 0)
1536 					continue;
1537 
1538 				tmp = 0;
1539 				match = guc_capture_get_one_list(guc->capture->reglists, i, j, k);
1540 				if (match)
1541 					tmp = match->num_regs;
1542 
1543 				match = guc_capture_get_one_list(guc->capture->extlists, i, j, k);
1544 				if (match)
1545 					tmp += match->num_regs;
1546 
1547 				if (tmp > maxregcount)
1548 					maxregcount = tmp;
1549 			}
1550 		}
1551 	}
1552 	if (!maxregcount)
1553 		maxregcount = PREALLOC_NODES_DEFAULT_NUMREGS;
1554 
1555 	return maxregcount;
1556 }
1557 
1558 static void
guc_capture_create_prealloc_nodes(struct xe_guc * guc)1559 guc_capture_create_prealloc_nodes(struct xe_guc *guc)
1560 {
1561 	/* skip if we've already done the pre-alloc */
1562 	if (guc->capture->max_mmio_per_node)
1563 		return;
1564 
1565 	guc->capture->max_mmio_per_node = guc_get_max_reglist_count(guc);
1566 	__guc_capture_create_prealloc_nodes(guc);
1567 }
1568 
1569 static void
read_reg_to_node(struct xe_hw_engine * hwe,const struct __guc_mmio_reg_descr_group * list,struct guc_mmio_reg * regs)1570 read_reg_to_node(struct xe_hw_engine *hwe, const struct __guc_mmio_reg_descr_group *list,
1571 		 struct guc_mmio_reg *regs)
1572 {
1573 	int i;
1574 
1575 	if (!list || !list->list || list->num_regs == 0)
1576 		return;
1577 
1578 	if (!regs)
1579 		return;
1580 
1581 	for (i = 0; i < list->num_regs; i++) {
1582 		struct __guc_mmio_reg_descr desc = list->list[i];
1583 		u32 value;
1584 
1585 		if (list->type == GUC_STATE_CAPTURE_TYPE_ENGINE_INSTANCE) {
1586 			value = xe_hw_engine_mmio_read32(hwe, desc.reg);
1587 		} else {
1588 			if (list->type == GUC_STATE_CAPTURE_TYPE_ENGINE_CLASS &&
1589 			    FIELD_GET(GUC_REGSET_STEERING_NEEDED, desc.flags)) {
1590 				int group, instance;
1591 
1592 				group = FIELD_GET(GUC_REGSET_STEERING_GROUP, desc.flags);
1593 				instance = FIELD_GET(GUC_REGSET_STEERING_INSTANCE, desc.flags);
1594 				value = xe_gt_mcr_unicast_read(hwe->gt, XE_REG_MCR(desc.reg.addr),
1595 							       group, instance);
1596 			} else {
1597 				value = xe_mmio_read32(&hwe->gt->mmio, desc.reg);
1598 			}
1599 		}
1600 
1601 		regs[i].value = value;
1602 		regs[i].offset = desc.reg.addr;
1603 		regs[i].flags = desc.flags;
1604 		regs[i].mask = desc.mask;
1605 	}
1606 }
1607 
1608 /**
1609  * xe_engine_manual_capture - Take a manual engine snapshot from engine.
1610  * @hwe: Xe HW Engine.
1611  * @snapshot: The engine snapshot
1612  *
1613  * Take engine snapshot from engine read.
1614  *
1615  * Returns: None
1616  */
1617 void
xe_engine_manual_capture(struct xe_hw_engine * hwe,struct xe_hw_engine_snapshot * snapshot)1618 xe_engine_manual_capture(struct xe_hw_engine *hwe, struct xe_hw_engine_snapshot *snapshot)
1619 {
1620 	struct xe_gt *gt = hwe->gt;
1621 	struct xe_device *xe = gt_to_xe(gt);
1622 	struct xe_guc *guc = &gt->uc.guc;
1623 	struct xe_devcoredump *devcoredump = &xe->devcoredump;
1624 	enum guc_capture_list_class_type capture_class;
1625 	const struct __guc_mmio_reg_descr_group *list;
1626 	struct __guc_capture_parsed_output *new;
1627 	enum guc_state_capture_type type;
1628 	u16 guc_id = 0;
1629 	u32 lrca = 0;
1630 
1631 	if (IS_SRIOV_VF(xe))
1632 		return;
1633 
1634 	new = guc_capture_get_prealloc_node(guc);
1635 	if (!new)
1636 		return;
1637 
1638 	capture_class = xe_hwe_to_guc_capture_class(hwe);
1639 	for (type = GUC_STATE_CAPTURE_TYPE_GLOBAL; type < GUC_STATE_CAPTURE_TYPE_MAX; type++) {
1640 		struct gcap_reg_list_info *reginfo = &new->reginfo[type];
1641 		/*
1642 		 * regsinfo->regs is allocated based on guc->capture->max_mmio_per_node
1643 		 * which is based on the descriptor list driving the population so
1644 		 * should not overflow
1645 		 */
1646 
1647 		/* Get register list for the type/class */
1648 		list = xe_guc_capture_get_reg_desc_list(gt, GUC_CAPTURE_LIST_INDEX_PF, type,
1649 							capture_class, false);
1650 		if (!list) {
1651 			xe_gt_dbg(gt, "Empty GuC capture register descriptor for %s",
1652 				  hwe->name);
1653 			continue;
1654 		}
1655 
1656 		read_reg_to_node(hwe, list, reginfo->regs);
1657 		reginfo->num_regs = list->num_regs;
1658 
1659 		/* Capture steering registers for rcs/ccs */
1660 		if (capture_class == GUC_CAPTURE_LIST_CLASS_RENDER_COMPUTE) {
1661 			list = xe_guc_capture_get_reg_desc_list(gt, GUC_CAPTURE_LIST_INDEX_PF,
1662 								type, capture_class, true);
1663 			if (list) {
1664 				read_reg_to_node(hwe, list, &reginfo->regs[reginfo->num_regs]);
1665 				reginfo->num_regs += list->num_regs;
1666 			}
1667 		}
1668 	}
1669 
1670 	if (devcoredump && devcoredump->captured) {
1671 		struct xe_guc_submit_exec_queue_snapshot *ge = devcoredump->snapshot.ge;
1672 
1673 		if (ge) {
1674 			guc_id = ge->guc.id;
1675 			if (ge->lrc[0])
1676 				lrca = ge->lrc[0]->context_desc;
1677 		}
1678 	}
1679 
1680 	new->eng_class = xe_hwe_to_guc_class(hwe);
1681 	new->eng_inst = hwe->instance;
1682 	new->guc_id = guc_id;
1683 	new->lrca = lrca;
1684 	new->is_partial = 0;
1685 	new->locked = 1;
1686 	new->source = XE_ENGINE_CAPTURE_SOURCE_MANUAL;
1687 
1688 	guc_capture_add_node_to_outlist(guc->capture, new);
1689 	devcoredump->snapshot.matched_node = new;
1690 }
1691 
1692 static struct guc_mmio_reg *
guc_capture_find_reg(struct gcap_reg_list_info * reginfo,u32 addr,u32 flags)1693 guc_capture_find_reg(struct gcap_reg_list_info *reginfo, u32 addr, u32 flags)
1694 {
1695 	int i;
1696 
1697 	if (reginfo && reginfo->num_regs > 0) {
1698 		struct guc_mmio_reg *regs = reginfo->regs;
1699 
1700 		if (regs)
1701 			for (i = 0; i < reginfo->num_regs; i++)
1702 				if (regs[i].offset == addr && regs[i].flags == flags)
1703 					return &regs[i];
1704 	}
1705 
1706 	return NULL;
1707 }
1708 
1709 static void
snapshot_print_by_list_order(struct xe_hw_engine_snapshot * snapshot,struct drm_printer * p,u32 type,const struct __guc_mmio_reg_descr_group * list)1710 snapshot_print_by_list_order(struct xe_hw_engine_snapshot *snapshot, struct drm_printer *p,
1711 			     u32 type, const struct __guc_mmio_reg_descr_group *list)
1712 {
1713 	struct xe_gt *gt = snapshot->hwe->gt;
1714 	struct xe_device *xe = gt_to_xe(gt);
1715 	struct xe_devcoredump *devcoredump = &xe->devcoredump;
1716 	struct xe_devcoredump_snapshot *devcore_snapshot = &devcoredump->snapshot;
1717 	struct gcap_reg_list_info *reginfo = NULL;
1718 	u32 i, last_value = 0;
1719 	bool low32_ready = false;
1720 
1721 	if (!list || !list->list || list->num_regs == 0)
1722 		return;
1723 	XE_WARN_ON(!devcore_snapshot->matched_node);
1724 
1725 	reginfo = &devcore_snapshot->matched_node->reginfo[type];
1726 
1727 	/*
1728 	 * loop through descriptor first and find the register in the node
1729 	 * this is more scalable for developer maintenance as it will ensure
1730 	 * the printout matched the ordering of the static descriptor
1731 	 * table-of-lists
1732 	 */
1733 	for (i = 0; i < list->num_regs; i++) {
1734 		const struct __guc_mmio_reg_descr *reg_desc = &list->list[i];
1735 		struct guc_mmio_reg *reg;
1736 		u32 value;
1737 
1738 		reg = guc_capture_find_reg(reginfo, reg_desc->reg.addr, reg_desc->flags);
1739 		if (!reg)
1740 			continue;
1741 
1742 		value = reg->value;
1743 		switch (reg_desc->data_type) {
1744 		case REG_64BIT_LOW_DW:
1745 			last_value = value;
1746 
1747 			/*
1748 			 * A 64 bit register define requires 2 consecutive
1749 			 * entries in register list, with low dword first
1750 			 * and hi dword the second, like:
1751 			 *  { XXX_REG_LO(0), REG_64BIT_LOW_DW, 0, 0, NULL},
1752 			 *  { XXX_REG_HI(0), REG_64BIT_HI_DW,  0, 0, "XXX_REG"},
1753 			 *
1754 			 * Incorrect order will trigger XE_WARN.
1755 			 *
1756 			 * Possible double low here, for example:
1757 			 *  { XXX_REG_LO(0), REG_64BIT_LOW_DW, 0, 0, NULL},
1758 			 *  { XXX_REG_LO(0), REG_64BIT_LOW_DW, 0, 0, NULL},
1759 			 */
1760 			XE_WARN_ON(low32_ready);
1761 			low32_ready = true;
1762 			/* Low 32 bit dword saved, continue for high 32 bit */
1763 			break;
1764 
1765 		case REG_64BIT_HI_DW: {
1766 			u64 value_qw = ((u64)value << 32) | last_value;
1767 
1768 			/*
1769 			 * Incorrect 64bit register order. Possible missing low.
1770 			 * for example:
1771 			 *  { XXX_REG(0), REG_32BIT, 0, 0, NULL},
1772 			 *  { XXX_REG_HI(0), REG_64BIT_HI_DW, 0, 0, NULL},
1773 			 */
1774 			XE_WARN_ON(!low32_ready);
1775 			low32_ready = false;
1776 
1777 			drm_printf(p, "\t%s: 0x%016llx\n", reg_desc->regname, value_qw);
1778 			break;
1779 		}
1780 
1781 		case REG_32BIT:
1782 			/*
1783 			 * Incorrect 64bit register order. Possible missing high.
1784 			 * for example:
1785 			 *  { XXX_REG_LO(0), REG_64BIT_LOW_DW, 0, 0, NULL},
1786 			 *  { XXX_REG(0), REG_32BIT, 0, 0, "XXX_REG"},
1787 			 */
1788 			XE_WARN_ON(low32_ready);
1789 
1790 			if (FIELD_GET(GUC_REGSET_STEERING_NEEDED, reg_desc->flags))
1791 				drm_printf(p, "\t%s[%u]: 0x%08x\n", reg_desc->regname,
1792 					   reg_desc->dss_id, value);
1793 			else
1794 				drm_printf(p, "\t%s: 0x%08x\n", reg_desc->regname, value);
1795 
1796 			break;
1797 		}
1798 	}
1799 
1800 	/*
1801 	 * Incorrect 64bit register order. Possible missing high.
1802 	 * for example:
1803 	 *  { XXX_REG_LO(0), REG_64BIT_LOW_DW, 0, 0, NULL},
1804 	 *  } // <- Register list end
1805 	 */
1806 	XE_WARN_ON(low32_ready);
1807 }
1808 
1809 /**
1810  * xe_engine_snapshot_print - Print out a given Xe HW Engine snapshot.
1811  * @snapshot: Xe HW Engine snapshot object.
1812  * @p: drm_printer where it will be printed out.
1813  *
1814  * This function prints out a given Xe HW Engine snapshot object.
1815  */
xe_engine_snapshot_print(struct xe_hw_engine_snapshot * snapshot,struct drm_printer * p)1816 void xe_engine_snapshot_print(struct xe_hw_engine_snapshot *snapshot, struct drm_printer *p)
1817 {
1818 	const char *grptype[GUC_STATE_CAPTURE_GROUP_TYPE_MAX] = {
1819 		"full-capture",
1820 		"partial-capture"
1821 	};
1822 	int type;
1823 	const struct __guc_mmio_reg_descr_group *list;
1824 	enum guc_capture_list_class_type capture_class;
1825 
1826 	struct xe_gt *gt;
1827 	struct xe_device *xe;
1828 	struct xe_devcoredump *devcoredump;
1829 	struct xe_devcoredump_snapshot *devcore_snapshot;
1830 
1831 	if (!snapshot)
1832 		return;
1833 
1834 	gt = snapshot->hwe->gt;
1835 	xe = gt_to_xe(gt);
1836 	devcoredump = &xe->devcoredump;
1837 	devcore_snapshot = &devcoredump->snapshot;
1838 
1839 	if (!devcore_snapshot->matched_node)
1840 		return;
1841 
1842 	xe_gt_assert(gt, snapshot->hwe);
1843 
1844 	capture_class = xe_hwe_to_guc_capture_class(snapshot->hwe);
1845 
1846 	drm_printf(p, "%s (physical), logical instance=%d\n",
1847 		   snapshot->name ? snapshot->name : "",
1848 		   snapshot->logical_instance);
1849 	drm_printf(p, "\tCapture_source: %s\n",
1850 		   devcore_snapshot->matched_node->source == XE_ENGINE_CAPTURE_SOURCE_GUC ?
1851 		   "GuC" : "Manual");
1852 	drm_printf(p, "\tCoverage: %s\n", grptype[devcore_snapshot->matched_node->is_partial]);
1853 	drm_printf(p, "\tForcewake: domain 0x%x, ref %d\n",
1854 		   snapshot->forcewake.domain, snapshot->forcewake.ref);
1855 	drm_printf(p, "\tReserved: %s\n",
1856 		   str_yes_no(snapshot->kernel_reserved));
1857 
1858 	for (type = GUC_STATE_CAPTURE_TYPE_GLOBAL; type < GUC_STATE_CAPTURE_TYPE_MAX; type++) {
1859 		list = xe_guc_capture_get_reg_desc_list(gt, GUC_CAPTURE_LIST_INDEX_PF, type,
1860 							capture_class, false);
1861 		snapshot_print_by_list_order(snapshot, p, type, list);
1862 	}
1863 
1864 	if (capture_class == GUC_CAPTURE_LIST_CLASS_RENDER_COMPUTE) {
1865 		list = xe_guc_capture_get_reg_desc_list(gt, GUC_CAPTURE_LIST_INDEX_PF,
1866 							GUC_STATE_CAPTURE_TYPE_ENGINE_CLASS,
1867 							capture_class, true);
1868 		snapshot_print_by_list_order(snapshot, p, GUC_STATE_CAPTURE_TYPE_ENGINE_CLASS,
1869 					     list);
1870 	}
1871 
1872 	drm_puts(p, "\n");
1873 }
1874 
1875 /**
1876  * xe_guc_capture_get_matching_and_lock - Matching GuC capture for the queue.
1877  * @q: The exec queue object
1878  *
1879  * Search within the capture outlist for the queue, could be used for check if
1880  * GuC capture is ready for the queue.
1881  * If found, the locked boolean of the node will be flagged.
1882  *
1883  * Returns: found guc-capture node ptr else NULL
1884  */
1885 struct __guc_capture_parsed_output *
xe_guc_capture_get_matching_and_lock(struct xe_exec_queue * q)1886 xe_guc_capture_get_matching_and_lock(struct xe_exec_queue *q)
1887 {
1888 	struct xe_hw_engine *hwe;
1889 	enum xe_hw_engine_id id;
1890 	struct xe_device *xe;
1891 	u16 guc_class = GUC_LAST_ENGINE_CLASS + 1;
1892 	struct xe_devcoredump_snapshot *ss;
1893 
1894 	if (!q || !q->gt)
1895 		return NULL;
1896 
1897 	xe = gt_to_xe(q->gt);
1898 
1899 	if (xe->wedged.mode == XE_WEDGED_MODE_UPON_ANY_HANG_NO_RESET)
1900 		return NULL;
1901 
1902 	if (!xe_device_uc_enabled(xe))
1903 		return NULL;
1904 
1905 	if (IS_SRIOV_VF(xe))
1906 		return NULL;
1907 
1908 	ss = &xe->devcoredump.snapshot;
1909 	if (ss->matched_node && ss->matched_node->source == XE_ENGINE_CAPTURE_SOURCE_GUC)
1910 		return ss->matched_node;
1911 
1912 	/* Find hwe for the queue */
1913 	for_each_hw_engine(hwe, q->gt, id) {
1914 		if (hwe != q->hwe)
1915 			continue;
1916 		guc_class = xe_hwe_to_guc_class(hwe);
1917 		break;
1918 	}
1919 
1920 	if (guc_class <= GUC_LAST_ENGINE_CLASS) {
1921 		struct __guc_capture_parsed_output *n, *ntmp;
1922 		struct xe_guc *guc =  &q->gt->uc.guc;
1923 		u16 guc_id = q->guc->id;
1924 		u32 lrca = xe_lrc_ggtt_addr(q->lrc[0]);
1925 
1926 		/*
1927 		 * Look for a matching GuC reported error capture node from
1928 		 * the internal output link-list based on engine, guc id and
1929 		 * lrca info.
1930 		 */
1931 		list_for_each_entry_safe(n, ntmp, &guc->capture->outlist, link) {
1932 			if (n->eng_class == guc_class && n->eng_inst == hwe->instance &&
1933 			    n->guc_id == guc_id && n->lrca == lrca &&
1934 			    n->source == XE_ENGINE_CAPTURE_SOURCE_GUC) {
1935 				n->locked = 1;
1936 				return n;
1937 			}
1938 		}
1939 	}
1940 	return NULL;
1941 }
1942 
1943 /**
1944  * xe_engine_snapshot_capture_for_queue - Take snapshot of associated engine
1945  * @q: The exec queue object
1946  *
1947  * Take snapshot of associated HW Engine
1948  *
1949  * Returns: None.
1950  */
1951 void
xe_engine_snapshot_capture_for_queue(struct xe_exec_queue * q)1952 xe_engine_snapshot_capture_for_queue(struct xe_exec_queue *q)
1953 {
1954 	struct xe_device *xe = gt_to_xe(q->gt);
1955 	struct xe_devcoredump *coredump = &xe->devcoredump;
1956 	struct xe_hw_engine *hwe;
1957 	enum xe_hw_engine_id id;
1958 	u32 adj_logical_mask = q->logical_mask;
1959 
1960 	if (IS_SRIOV_VF(xe))
1961 		return;
1962 
1963 	for_each_hw_engine(hwe, q->gt, id) {
1964 		if (hwe->class != q->hwe->class ||
1965 		    !(BIT(hwe->logical_instance) & adj_logical_mask)) {
1966 			coredump->snapshot.hwe[id] = NULL;
1967 			continue;
1968 		}
1969 
1970 		if (!coredump->snapshot.hwe[id]) {
1971 			coredump->snapshot.hwe[id] =
1972 				xe_hw_engine_snapshot_capture(hwe, q);
1973 		} else {
1974 			struct __guc_capture_parsed_output *new;
1975 
1976 			new = xe_guc_capture_get_matching_and_lock(q);
1977 			if (new) {
1978 				struct xe_guc *guc =  &q->gt->uc.guc;
1979 
1980 				/*
1981 				 * If we are in here, it means we found a fresh
1982 				 * GuC-err-capture node for this engine after
1983 				 * previously failing to find a match in the
1984 				 * early part of guc_exec_queue_timedout_job.
1985 				 * Thus we must free the manually captured node
1986 				 */
1987 				guc_capture_free_outlist_node(guc->capture,
1988 							      coredump->snapshot.matched_node);
1989 				coredump->snapshot.matched_node = new;
1990 			}
1991 		}
1992 
1993 		break;
1994 	}
1995 }
1996 
1997 /*
1998  * xe_guc_capture_put_matched_nodes - Cleanup matched nodes
1999  * @guc: The GuC object
2000  *
2001  * Free matched node and all nodes with the equal guc_id from
2002  * GuC captured outlist
2003  */
xe_guc_capture_put_matched_nodes(struct xe_guc * guc)2004 void xe_guc_capture_put_matched_nodes(struct xe_guc *guc)
2005 {
2006 	struct xe_device *xe = guc_to_xe(guc);
2007 	struct xe_devcoredump *devcoredump = &xe->devcoredump;
2008 	struct __guc_capture_parsed_output *n = devcoredump->snapshot.matched_node;
2009 
2010 	if (n) {
2011 		guc_capture_remove_stale_matches_from_list(guc->capture, n);
2012 		guc_capture_free_outlist_node(guc->capture, n);
2013 		devcoredump->snapshot.matched_node = NULL;
2014 	}
2015 }
2016 
2017 /*
2018  * xe_guc_capture_steered_list_init - Init steering register list
2019  * @guc: The GuC object
2020  *
2021  * Init steering register list for GuC register capture, create pre-alloc node
2022  */
xe_guc_capture_steered_list_init(struct xe_guc * guc)2023 void xe_guc_capture_steered_list_init(struct xe_guc *guc)
2024 {
2025 	/*
2026 	 * For certain engine classes, there are slice and subslice
2027 	 * level registers requiring steering. We allocate and populate
2028 	 * these based on hw config and add it as an extension list at
2029 	 * the end of the pre-populated render list.
2030 	 */
2031 	guc_capture_alloc_steered_lists(guc);
2032 	check_guc_capture_size(guc);
2033 	guc_capture_create_prealloc_nodes(guc);
2034 }
2035 
2036 /*
2037  * xe_guc_capture_init - Init for GuC register capture
2038  * @guc: The GuC object
2039  *
2040  * Init for GuC register capture, alloc memory for capture data structure.
2041  *
2042  * Returns: 0 if success.
2043  *	    -ENOMEM if out of memory
2044  */
xe_guc_capture_init(struct xe_guc * guc)2045 int xe_guc_capture_init(struct xe_guc *guc)
2046 {
2047 	guc->capture = drmm_kzalloc(guc_to_drm(guc), sizeof(*guc->capture), GFP_KERNEL);
2048 	if (!guc->capture)
2049 		return -ENOMEM;
2050 
2051 	guc->capture->reglists = guc_capture_get_device_reglist(guc_to_xe(guc));
2052 
2053 	INIT_LIST_HEAD(&guc->capture->outlist);
2054 	INIT_LIST_HEAD(&guc->capture->cachelist);
2055 
2056 	return 0;
2057 }
2058