drm/i915/guc: Add error-capture init warnings when needed
[platform/kernel/linux-starfive.git] / drivers / gpu / drm / i915 / gt / uc / intel_guc_capture.c
1 // SPDX-License-Identifier: MIT
2 /*
3  * Copyright © 2021-2022 Intel Corporation
4  */
5
6 #include <linux/types.h>
7
8 #include <drm/drm_print.h>
9
10 #include "gt/intel_engine_regs.h"
11 #include "gt/intel_gt.h"
12 #include "gt/intel_gt_mcr.h"
13 #include "gt/intel_gt_regs.h"
14 #include "gt/intel_lrc.h"
15 #include "guc_capture_fwif.h"
16 #include "intel_guc_capture.h"
17 #include "intel_guc_fwif.h"
18 #include "i915_drv.h"
19 #include "i915_gpu_error.h"
20 #include "i915_irq.h"
21 #include "i915_memcpy.h"
22 #include "i915_reg.h"
23
24 /*
25  * Define all device tables of GuC error capture register lists
26  * NOTE: For engine-registers, GuC only needs the register offsets
27  *       from the engine-mmio-base
28  */
29 #define COMMON_BASE_GLOBAL \
30         { FORCEWAKE_MT,             0,      0, "FORCEWAKE" }
31
32 #define COMMON_GEN9BASE_GLOBAL \
33         { GEN8_FAULT_TLB_DATA0,     0,      0, "GEN8_FAULT_TLB_DATA0" }, \
34         { GEN8_FAULT_TLB_DATA1,     0,      0, "GEN8_FAULT_TLB_DATA1" }, \
35         { ERROR_GEN6,               0,      0, "ERROR_GEN6" }, \
36         { DONE_REG,                 0,      0, "DONE_REG" }, \
37         { HSW_GTT_CACHE_EN,         0,      0, "HSW_GTT_CACHE_EN" }
38
39 #define COMMON_GEN12BASE_GLOBAL \
40         { GEN12_FAULT_TLB_DATA0,    0,      0, "GEN12_FAULT_TLB_DATA0" }, \
41         { GEN12_FAULT_TLB_DATA1,    0,      0, "GEN12_FAULT_TLB_DATA1" }, \
42         { GEN12_AUX_ERR_DBG,        0,      0, "AUX_ERR_DBG" }, \
43         { GEN12_GAM_DONE,           0,      0, "GAM_DONE" }, \
44         { GEN12_RING_FAULT_REG,     0,      0, "FAULT_REG" }
45
46 #define COMMON_BASE_ENGINE_INSTANCE \
47         { RING_PSMI_CTL(0),         0,      0, "RC PSMI" }, \
48         { RING_ESR(0),              0,      0, "ESR" }, \
49         { RING_DMA_FADD(0),         0,      0, "RING_DMA_FADD_LDW" }, \
50         { RING_DMA_FADD_UDW(0),     0,      0, "RING_DMA_FADD_UDW" }, \
51         { RING_IPEIR(0),            0,      0, "IPEIR" }, \
52         { RING_IPEHR(0),            0,      0, "IPEHR" }, \
53         { RING_INSTPS(0),           0,      0, "INSTPS" }, \
54         { RING_BBADDR(0),           0,      0, "RING_BBADDR_LOW32" }, \
55         { RING_BBADDR_UDW(0),       0,      0, "RING_BBADDR_UP32" }, \
56         { RING_BBSTATE(0),          0,      0, "BB_STATE" }, \
57         { CCID(0),                  0,      0, "CCID" }, \
58         { RING_ACTHD(0),            0,      0, "ACTHD_LDW" }, \
59         { RING_ACTHD_UDW(0),        0,      0, "ACTHD_UDW" }, \
60         { RING_INSTPM(0),           0,      0, "INSTPM" }, \
61         { RING_INSTDONE(0),         0,      0, "INSTDONE" }, \
62         { RING_NOPID(0),            0,      0, "RING_NOPID" }, \
63         { RING_START(0),            0,      0, "START" }, \
64         { RING_HEAD(0),             0,      0, "HEAD" }, \
65         { RING_TAIL(0),             0,      0, "TAIL" }, \
66         { RING_CTL(0),              0,      0, "CTL" }, \
67         { RING_MI_MODE(0),          0,      0, "MODE" }, \
68         { RING_CONTEXT_CONTROL(0),  0,      0, "RING_CONTEXT_CONTROL" }, \
69         { RING_HWS_PGA(0),          0,      0, "HWS" }, \
70         { RING_MODE_GEN7(0),        0,      0, "GFX_MODE" }, \
71         { GEN8_RING_PDP_LDW(0, 0),  0,      0, "PDP0_LDW" }, \
72         { GEN8_RING_PDP_UDW(0, 0),  0,      0, "PDP0_UDW" }, \
73         { GEN8_RING_PDP_LDW(0, 1),  0,      0, "PDP1_LDW" }, \
74         { GEN8_RING_PDP_UDW(0, 1),  0,      0, "PDP1_UDW" }, \
75         { GEN8_RING_PDP_LDW(0, 2),  0,      0, "PDP2_LDW" }, \
76         { GEN8_RING_PDP_UDW(0, 2),  0,      0, "PDP2_UDW" }, \
77         { GEN8_RING_PDP_LDW(0, 3),  0,      0, "PDP3_LDW" }, \
78         { GEN8_RING_PDP_UDW(0, 3),  0,      0, "PDP3_UDW" }
79
80 #define COMMON_BASE_HAS_EU \
81         { EIR,                      0,      0, "EIR" }
82
83 #define COMMON_BASE_RENDER \
84         { GEN7_SC_INSTDONE,         0,      0, "GEN7_SC_INSTDONE" }
85
86 #define COMMON_GEN12BASE_RENDER \
87         { GEN12_SC_INSTDONE_EXTRA,  0,      0, "GEN12_SC_INSTDONE_EXTRA" }, \
88         { GEN12_SC_INSTDONE_EXTRA2, 0,      0, "GEN12_SC_INSTDONE_EXTRA2" }
89
90 #define COMMON_GEN12BASE_VEC \
91         { GEN12_SFC_DONE(0),        0,      0, "SFC_DONE[0]" }, \
92         { GEN12_SFC_DONE(1),        0,      0, "SFC_DONE[1]" }, \
93         { GEN12_SFC_DONE(2),        0,      0, "SFC_DONE[2]" }, \
94         { GEN12_SFC_DONE(3),        0,      0, "SFC_DONE[3]" }
95
96 /* XE_LPD - Global */
97 static const struct __guc_mmio_reg_descr xe_lpd_global_regs[] = {
98         COMMON_BASE_GLOBAL,
99         COMMON_GEN9BASE_GLOBAL,
100         COMMON_GEN12BASE_GLOBAL,
101 };
102
103 /* XE_LPD - Render / Compute Per-Class */
104 static const struct __guc_mmio_reg_descr xe_lpd_rc_class_regs[] = {
105         COMMON_BASE_HAS_EU,
106         COMMON_BASE_RENDER,
107         COMMON_GEN12BASE_RENDER,
108 };
109
110 /* GEN9/XE_LPD - Render / Compute Per-Engine-Instance */
111 static const struct __guc_mmio_reg_descr xe_lpd_rc_inst_regs[] = {
112         COMMON_BASE_ENGINE_INSTANCE,
113 };
114
115 /* GEN9/XE_LPD - Media Decode/Encode Per-Engine-Instance */
116 static const struct __guc_mmio_reg_descr xe_lpd_vd_inst_regs[] = {
117         COMMON_BASE_ENGINE_INSTANCE,
118 };
119
120 /* XE_LPD - Video Enhancement Per-Class */
121 static const struct __guc_mmio_reg_descr xe_lpd_vec_class_regs[] = {
122         COMMON_GEN12BASE_VEC,
123 };
124
125 /* GEN9/XE_LPD - Video Enhancement Per-Engine-Instance */
126 static const struct __guc_mmio_reg_descr xe_lpd_vec_inst_regs[] = {
127         COMMON_BASE_ENGINE_INSTANCE,
128 };
129
130 /* GEN9/XE_LPD - Blitter Per-Engine-Instance */
131 static const struct __guc_mmio_reg_descr xe_lpd_blt_inst_regs[] = {
132         COMMON_BASE_ENGINE_INSTANCE,
133 };
134
135 /* GEN9 - Global */
136 static const struct __guc_mmio_reg_descr default_global_regs[] = {
137         COMMON_BASE_GLOBAL,
138         COMMON_GEN9BASE_GLOBAL,
139 };
140
141 static const struct __guc_mmio_reg_descr default_rc_class_regs[] = {
142         COMMON_BASE_HAS_EU,
143         COMMON_BASE_RENDER,
144 };
145
146 /*
147  * Empty lists:
148  * GEN9/XE_LPD - Blitter Per-Class
149  * GEN9/XE_LPD - Media Decode/Encode Per-Class
150  * GEN9 - VEC Class
151  */
152 static const struct __guc_mmio_reg_descr empty_regs_list[] = {
153 };
154
155 #define TO_GCAP_DEF_OWNER(x) (GUC_CAPTURE_LIST_INDEX_##x)
156 #define TO_GCAP_DEF_TYPE(x) (GUC_CAPTURE_LIST_TYPE_##x)
157 #define MAKE_REGLIST(regslist, regsowner, regstype, class) \
158         { \
159                 regslist, \
160                 ARRAY_SIZE(regslist), \
161                 TO_GCAP_DEF_OWNER(regsowner), \
162                 TO_GCAP_DEF_TYPE(regstype), \
163                 class, \
164                 NULL, \
165         }
166
167 /* List of lists */
168 static struct __guc_mmio_reg_descr_group default_lists[] = {
169         MAKE_REGLIST(default_global_regs, PF, GLOBAL, 0),
170         MAKE_REGLIST(default_rc_class_regs, PF, ENGINE_CLASS, GUC_RENDER_CLASS),
171         MAKE_REGLIST(xe_lpd_rc_inst_regs, PF, ENGINE_INSTANCE, GUC_RENDER_CLASS),
172         MAKE_REGLIST(empty_regs_list, PF, ENGINE_CLASS, GUC_VIDEO_CLASS),
173         MAKE_REGLIST(xe_lpd_vd_inst_regs, PF, ENGINE_INSTANCE, GUC_VIDEO_CLASS),
174         MAKE_REGLIST(empty_regs_list, PF, ENGINE_CLASS, GUC_VIDEOENHANCE_CLASS),
175         MAKE_REGLIST(xe_lpd_vec_inst_regs, PF, ENGINE_INSTANCE, GUC_VIDEOENHANCE_CLASS),
176         MAKE_REGLIST(empty_regs_list, PF, ENGINE_CLASS, GUC_BLITTER_CLASS),
177         MAKE_REGLIST(xe_lpd_blt_inst_regs, PF, ENGINE_INSTANCE, GUC_BLITTER_CLASS),
178         {}
179 };
180
181 static const struct __guc_mmio_reg_descr_group xe_lpd_lists[] = {
182         MAKE_REGLIST(xe_lpd_global_regs, PF, GLOBAL, 0),
183         MAKE_REGLIST(xe_lpd_rc_class_regs, PF, ENGINE_CLASS, GUC_RENDER_CLASS),
184         MAKE_REGLIST(xe_lpd_rc_inst_regs, PF, ENGINE_INSTANCE, GUC_RENDER_CLASS),
185         MAKE_REGLIST(empty_regs_list, PF, ENGINE_CLASS, GUC_VIDEO_CLASS),
186         MAKE_REGLIST(xe_lpd_vd_inst_regs, PF, ENGINE_INSTANCE, GUC_VIDEO_CLASS),
187         MAKE_REGLIST(xe_lpd_vec_class_regs, PF, ENGINE_CLASS, GUC_VIDEOENHANCE_CLASS),
188         MAKE_REGLIST(xe_lpd_vec_inst_regs, PF, ENGINE_INSTANCE, GUC_VIDEOENHANCE_CLASS),
189         MAKE_REGLIST(empty_regs_list, PF, ENGINE_CLASS, GUC_BLITTER_CLASS),
190         MAKE_REGLIST(xe_lpd_blt_inst_regs, PF, ENGINE_INSTANCE, GUC_BLITTER_CLASS),
191         {}
192 };
193
194 static const struct __guc_mmio_reg_descr_group *
195 guc_capture_get_one_list(const struct __guc_mmio_reg_descr_group *reglists,
196                          u32 owner, u32 type, u32 id)
197 {
198         int i;
199
200         if (!reglists)
201                 return NULL;
202
203         for (i = 0; reglists[i].list; ++i) {
204                 if (reglists[i].owner == owner && reglists[i].type == type &&
205                     (reglists[i].engine == id || reglists[i].type == GUC_CAPTURE_LIST_TYPE_GLOBAL))
206                         return &reglists[i];
207         }
208
209         return NULL;
210 }
211
212 static struct __guc_mmio_reg_descr_group *
213 guc_capture_get_one_ext_list(struct __guc_mmio_reg_descr_group *reglists,
214                              u32 owner, u32 type, u32 id)
215 {
216         int i;
217
218         if (!reglists)
219                 return NULL;
220
221         for (i = 0; reglists[i].extlist; ++i) {
222                 if (reglists[i].owner == owner && reglists[i].type == type &&
223                     (reglists[i].engine == id || reglists[i].type == GUC_CAPTURE_LIST_TYPE_GLOBAL))
224                         return &reglists[i];
225         }
226
227         return NULL;
228 }
229
230 static void guc_capture_free_extlists(struct __guc_mmio_reg_descr_group *reglists)
231 {
232         int i = 0;
233
234         if (!reglists)
235                 return;
236
237         while (reglists[i].extlist)
238                 kfree(reglists[i++].extlist);
239 }
240
241 struct __ext_steer_reg {
242         const char *name;
243         i915_reg_t reg;
244 };
245
246 static const struct __ext_steer_reg xe_extregs[] = {
247         {"GEN7_SAMPLER_INSTDONE", GEN7_SAMPLER_INSTDONE},
248         {"GEN7_ROW_INSTDONE", GEN7_ROW_INSTDONE}
249 };
250
251 static void __fill_ext_reg(struct __guc_mmio_reg_descr *ext,
252                            const struct __ext_steer_reg *extlist,
253                            int slice_id, int subslice_id)
254 {
255         ext->reg = extlist->reg;
256         ext->flags = FIELD_PREP(GUC_REGSET_STEERING_GROUP, slice_id);
257         ext->flags |= FIELD_PREP(GUC_REGSET_STEERING_INSTANCE, subslice_id);
258         ext->regname = extlist->name;
259 }
260
261 static int
262 __alloc_ext_regs(struct __guc_mmio_reg_descr_group *newlist,
263                  const struct __guc_mmio_reg_descr_group *rootlist, int num_regs)
264 {
265         struct __guc_mmio_reg_descr *list;
266
267         list = kcalloc(num_regs, sizeof(struct __guc_mmio_reg_descr), GFP_KERNEL);
268         if (!list)
269                 return -ENOMEM;
270
271         newlist->extlist = list;
272         newlist->num_regs = num_regs;
273         newlist->owner = rootlist->owner;
274         newlist->engine = rootlist->engine;
275         newlist->type = rootlist->type;
276
277         return 0;
278 }
279
280 static void
281 guc_capture_alloc_steered_lists_xe_lpd(struct intel_guc *guc,
282                                        const struct __guc_mmio_reg_descr_group *lists)
283 {
284         struct intel_gt *gt = guc_to_gt(guc);
285         int slice, subslice, iter, i, num_steer_regs, num_tot_regs = 0;
286         const struct __guc_mmio_reg_descr_group *list;
287         struct __guc_mmio_reg_descr_group *extlists;
288         struct __guc_mmio_reg_descr *extarray;
289         struct sseu_dev_info *sseu;
290
291         /* In XE_LPD we only have steered registers for the render-class */
292         list = guc_capture_get_one_list(lists, GUC_CAPTURE_LIST_INDEX_PF,
293                                         GUC_CAPTURE_LIST_TYPE_ENGINE_CLASS, GUC_RENDER_CLASS);
294         /* skip if extlists was previously allocated */
295         if (!list || guc->capture->extlists)
296                 return;
297
298         num_steer_regs = ARRAY_SIZE(xe_extregs);
299
300         sseu = &gt->info.sseu;
301         for_each_ss_steering(iter, gt, slice, subslice)
302                 num_tot_regs += num_steer_regs;
303
304         if (!num_tot_regs)
305                 return;
306
307         /* allocate an extra for an end marker */
308         extlists = kcalloc(2, sizeof(struct __guc_mmio_reg_descr_group), GFP_KERNEL);
309         if (!extlists)
310                 return;
311
312         if (__alloc_ext_regs(&extlists[0], list, num_tot_regs)) {
313                 kfree(extlists);
314                 return;
315         }
316
317         extarray = extlists[0].extlist;
318         for_each_ss_steering(iter, gt, slice, subslice) {
319                 for (i = 0; i < num_steer_regs; ++i) {
320                         __fill_ext_reg(extarray, &xe_extregs[i], slice, subslice);
321                         ++extarray;
322                 }
323         }
324
325         guc->capture->extlists = extlists;
326 }
327
328 static const struct __ext_steer_reg xehpg_extregs[] = {
329         {"XEHPG_INSTDONE_GEOM_SVG", XEHPG_INSTDONE_GEOM_SVG}
330 };
331
332 static bool __has_xehpg_extregs(u32 ipver)
333 {
334         return (ipver >= IP_VER(12, 55));
335 }
336
337 static void
338 guc_capture_alloc_steered_lists_xe_hpg(struct intel_guc *guc,
339                                        const struct __guc_mmio_reg_descr_group *lists,
340                                        u32 ipver)
341 {
342         struct intel_gt *gt = guc_to_gt(guc);
343         struct drm_i915_private *i915 = guc_to_gt(guc)->i915;
344         struct sseu_dev_info *sseu;
345         int slice, subslice, i, iter, num_steer_regs, num_tot_regs = 0;
346         const struct __guc_mmio_reg_descr_group *list;
347         struct __guc_mmio_reg_descr_group *extlists;
348         struct __guc_mmio_reg_descr *extarray;
349
350         /* In XE_LP / HPG we only have render-class steering registers during error-capture */
351         list = guc_capture_get_one_list(lists, GUC_CAPTURE_LIST_INDEX_PF,
352                                         GUC_CAPTURE_LIST_TYPE_ENGINE_CLASS, GUC_RENDER_CLASS);
353         /* skip if extlists was previously allocated */
354         if (!list || guc->capture->extlists)
355                 return;
356
357         num_steer_regs = ARRAY_SIZE(xe_extregs);
358         if (__has_xehpg_extregs(ipver))
359                 num_steer_regs += ARRAY_SIZE(xehpg_extregs);
360
361         sseu = &gt->info.sseu;
362         for_each_ss_steering(iter, gt, slice, subslice)
363                 num_tot_regs += num_steer_regs;
364
365         if (!num_tot_regs)
366                 return;
367
368         /* allocate an extra for an end marker */
369         extlists = kcalloc(2, sizeof(struct __guc_mmio_reg_descr_group), GFP_KERNEL);
370         if (!extlists)
371                 return;
372
373         if (__alloc_ext_regs(&extlists[0], list, num_tot_regs)) {
374                 kfree(extlists);
375                 return;
376         }
377
378         extarray = extlists[0].extlist;
379         for_each_ss_steering(iter, gt, slice, subslice) {
380                 for (i = 0; i < ARRAY_SIZE(xe_extregs); ++i) {
381                         __fill_ext_reg(extarray, &xe_extregs[i], slice, subslice);
382                         ++extarray;
383                 }
384                 if (__has_xehpg_extregs(ipver)) {
385                         for (i = 0; i < ARRAY_SIZE(xehpg_extregs); ++i) {
386                                 __fill_ext_reg(extarray, &xehpg_extregs[i], slice, subslice);
387                                 ++extarray;
388                         }
389                 }
390         }
391
392         drm_dbg(&i915->drm, "GuC-capture found %d-ext-regs.\n", num_tot_regs);
393         guc->capture->extlists = extlists;
394 }
395
396 static const struct __guc_mmio_reg_descr_group *
397 guc_capture_get_device_reglist(struct intel_guc *guc)
398 {
399         struct drm_i915_private *i915 = guc_to_gt(guc)->i915;
400
401         if (GRAPHICS_VER(i915) > 11) {
402                 /*
403                  * For certain engine classes, there are slice and subslice
404                  * level registers requiring steering. We allocate and populate
405                  * these at init time based on hw config add it as an extension
406                  * list at the end of the pre-populated render list.
407                  */
408                 if (IS_DG2(i915))
409                         guc_capture_alloc_steered_lists_xe_hpg(guc, xe_lpd_lists, IP_VER(12, 55));
410                 else if (IS_XEHPSDV(i915))
411                         guc_capture_alloc_steered_lists_xe_hpg(guc, xe_lpd_lists, IP_VER(12, 50));
412                 else
413                         guc_capture_alloc_steered_lists_xe_lpd(guc, xe_lpd_lists);
414
415                 return xe_lpd_lists;
416         }
417
418         /* if GuC submission is enabled on a non-POR platform, just use a common baseline */
419         return default_lists;
420 }
421
422 static const char *
423 __stringify_type(u32 type)
424 {
425         switch (type) {
426         case GUC_CAPTURE_LIST_TYPE_GLOBAL:
427                 return "Global";
428         case GUC_CAPTURE_LIST_TYPE_ENGINE_CLASS:
429                 return "Class";
430         case GUC_CAPTURE_LIST_TYPE_ENGINE_INSTANCE:
431                 return "Instance";
432         default:
433                 break;
434         }
435
436         return "unknown";
437 }
438
439 static const char *
440 __stringify_engclass(u32 class)
441 {
442         switch (class) {
443         case GUC_RENDER_CLASS:
444                 return "Render";
445         case GUC_VIDEO_CLASS:
446                 return "Video";
447         case GUC_VIDEOENHANCE_CLASS:
448                 return "VideoEnhance";
449         case GUC_BLITTER_CLASS:
450                 return "Blitter";
451         case GUC_COMPUTE_CLASS:
452                 return "Compute";
453         default:
454                 break;
455         }
456
457         return "unknown";
458 }
459
460 static int
461 guc_capture_list_init(struct intel_guc *guc, u32 owner, u32 type, u32 classid,
462                       struct guc_mmio_reg *ptr, u16 num_entries)
463 {
464         u32 i = 0, j = 0;
465         struct drm_i915_private *i915 = guc_to_gt(guc)->i915;
466         const struct __guc_mmio_reg_descr_group *reglists = guc->capture->reglists;
467         struct __guc_mmio_reg_descr_group *extlists = guc->capture->extlists;
468         const struct __guc_mmio_reg_descr_group *match;
469         struct __guc_mmio_reg_descr_group *matchext;
470
471         if (!reglists)
472                 return -ENODEV;
473
474         match = guc_capture_get_one_list(reglists, owner, type, classid);
475         if (!match)
476                 return -ENODATA;
477
478         for (i = 0; i < num_entries && i < match->num_regs; ++i) {
479                 ptr[i].offset = match->list[i].reg.reg;
480                 ptr[i].value = 0xDEADF00D;
481                 ptr[i].flags = match->list[i].flags;
482                 ptr[i].mask = match->list[i].mask;
483         }
484
485         matchext = guc_capture_get_one_ext_list(extlists, owner, type, classid);
486         if (matchext) {
487                 for (i = match->num_regs, j = 0; i < num_entries &&
488                      i < (match->num_regs + matchext->num_regs) &&
489                         j < matchext->num_regs; ++i, ++j) {
490                         ptr[i].offset = matchext->extlist[j].reg.reg;
491                         ptr[i].value = 0xDEADF00D;
492                         ptr[i].flags = matchext->extlist[j].flags;
493                         ptr[i].mask = matchext->extlist[j].mask;
494                 }
495         }
496         if (i < num_entries)
497                 drm_dbg(&i915->drm, "GuC-capture: Init reglist short %d out %d.\n",
498                         (int)i, (int)num_entries);
499
500         return 0;
501 }
502
503 static int
504 guc_cap_list_num_regs(struct intel_guc_state_capture *gc, u32 owner, u32 type, u32 classid)
505 {
506         const struct __guc_mmio_reg_descr_group *match;
507         struct __guc_mmio_reg_descr_group *matchext;
508         int num_regs;
509
510         match = guc_capture_get_one_list(gc->reglists, owner, type, classid);
511         if (!match)
512                 return 0;
513
514         num_regs = match->num_regs;
515
516         matchext = guc_capture_get_one_ext_list(gc->extlists, owner, type, classid);
517         if (matchext)
518                 num_regs += matchext->num_regs;
519
520         return num_regs;
521 }
522
523 static int
524 guc_capture_getlistsize(struct intel_guc *guc, u32 owner, u32 type, u32 classid,
525                         size_t *size, bool is_purpose_est)
526 {
527         struct intel_guc_state_capture *gc = guc->capture;
528         struct drm_i915_private *i915 = guc_to_gt(guc)->i915;
529         struct __guc_capture_ads_cache *cache = &gc->ads_cache[owner][type][classid];
530         int num_regs;
531
532         if (!gc->reglists) {
533                 drm_warn(&i915->drm, "GuC-capture: No reglist on this device\n");
534                 return -ENODEV;
535         }
536
537         if (cache->is_valid) {
538                 *size = cache->size;
539                 return cache->status;
540         }
541
542         if (!is_purpose_est && owner == GUC_CAPTURE_LIST_INDEX_PF &&
543             !guc_capture_get_one_list(gc->reglists, owner, type, classid)) {
544                 if (type == GUC_CAPTURE_LIST_TYPE_GLOBAL)
545                         drm_warn(&i915->drm, "Missing GuC-Err-Cap reglist Global!\n");
546                 else
547                         drm_warn(&i915->drm, "Missing GuC-Err-Cap reglist %s(%u):%s(%u)!\n",
548                                  __stringify_type(type), type,
549                                  __stringify_engclass(classid), classid);
550                 return -ENODATA;
551         }
552
553         num_regs = guc_cap_list_num_regs(gc, owner, type, classid);
554         /* intentional empty lists can exist depending on hw config */
555         if (!num_regs)
556                 return -ENODATA;
557
558         *size = PAGE_ALIGN((sizeof(struct guc_debug_capture_list)) +
559                            (num_regs * sizeof(struct guc_mmio_reg)));
560
561         return 0;
562 }
563
564 int
565 intel_guc_capture_getlistsize(struct intel_guc *guc, u32 owner, u32 type, u32 classid,
566                               size_t *size)
567 {
568         return guc_capture_getlistsize(guc, owner, type, classid, size, false);
569 }
570
571 static void guc_capture_create_prealloc_nodes(struct intel_guc *guc);
572
573 int
574 intel_guc_capture_getlist(struct intel_guc *guc, u32 owner, u32 type, u32 classid,
575                           void **outptr)
576 {
577         struct intel_guc_state_capture *gc = guc->capture;
578         struct __guc_capture_ads_cache *cache = &gc->ads_cache[owner][type][classid];
579         struct drm_i915_private *i915 = guc_to_gt(guc)->i915;
580         struct guc_debug_capture_list *listnode;
581         int ret, num_regs;
582         u8 *caplist, *tmp;
583         size_t size = 0;
584
585         if (!gc->reglists)
586                 return -ENODEV;
587
588         if (cache->is_valid) {
589                 *outptr = cache->ptr;
590                 return cache->status;
591         }
592
593         /*
594          * ADS population of input registers is a good
595          * time to pre-allocate cachelist output nodes
596          */
597         guc_capture_create_prealloc_nodes(guc);
598
599         ret = intel_guc_capture_getlistsize(guc, owner, type, classid, &size);
600         if (ret) {
601                 cache->is_valid = true;
602                 cache->ptr = NULL;
603                 cache->size = 0;
604                 cache->status = ret;
605                 return ret;
606         }
607
608         caplist = kzalloc(size, GFP_KERNEL);
609         if (!caplist) {
610                 drm_dbg(&i915->drm, "GuC-capture: failed to alloc cached caplist");
611                 return -ENOMEM;
612         }
613
614         /* populate capture list header */
615         tmp = caplist;
616         num_regs = guc_cap_list_num_regs(guc->capture, owner, type, classid);
617         listnode = (struct guc_debug_capture_list *)tmp;
618         listnode->header.info = FIELD_PREP(GUC_CAPTURELISTHDR_NUMDESCR, (u32)num_regs);
619
620         /* populate list of register descriptor */
621         tmp += sizeof(struct guc_debug_capture_list);
622         guc_capture_list_init(guc, owner, type, classid, (struct guc_mmio_reg *)tmp, num_regs);
623
624         /* cache this list */
625         cache->is_valid = true;
626         cache->ptr = caplist;
627         cache->size = size;
628         cache->status = 0;
629
630         *outptr = caplist;
631
632         return 0;
633 }
634
635 int
636 intel_guc_capture_getnullheader(struct intel_guc *guc,
637                                 void **outptr, size_t *size)
638 {
639         struct intel_guc_state_capture *gc = guc->capture;
640         struct drm_i915_private *i915 = guc_to_gt(guc)->i915;
641         int tmp = sizeof(u32) * 4;
642         void *null_header;
643
644         if (gc->ads_null_cache) {
645                 *outptr = gc->ads_null_cache;
646                 *size = tmp;
647                 return 0;
648         }
649
650         null_header = kzalloc(tmp, GFP_KERNEL);
651         if (!null_header) {
652                 drm_dbg(&i915->drm, "GuC-capture: failed to alloc cached nulllist");
653                 return -ENOMEM;
654         }
655
656         gc->ads_null_cache = null_header;
657         *outptr = null_header;
658         *size = tmp;
659
660         return 0;
661 }
662
663 static int
664 guc_capture_output_min_size_est(struct intel_guc *guc)
665 {
666         struct intel_gt *gt = guc_to_gt(guc);
667         struct intel_engine_cs *engine;
668         enum intel_engine_id id;
669         int worst_min_size = 0, num_regs = 0;
670         size_t tmp = 0;
671
672         if (!guc->capture)
673                 return -ENODEV;
674
675         /*
676          * If every single engine-instance suffered a failure in quick succession but
677          * were all unrelated, then a burst of multiple error-capture events would dump
678          * registers for every one engine instance, one at a time. In this case, GuC
679          * would even dump the global-registers repeatedly.
680          *
681          * For each engine instance, there would be 1 x guc_state_capture_group_t output
682          * followed by 3 x guc_state_capture_t lists. The latter is how the register
683          * dumps are split across different register types (where the '3' are global vs class
684          * vs instance).
685          */
686         for_each_engine(engine, gt, id) {
687                 worst_min_size += sizeof(struct guc_state_capture_group_header_t) +
688                                          (3 * sizeof(struct guc_state_capture_header_t));
689
690                 if (!guc_capture_getlistsize(guc, 0, GUC_CAPTURE_LIST_TYPE_GLOBAL, 0, &tmp, true))
691                         num_regs += tmp;
692
693                 if (!guc_capture_getlistsize(guc, 0, GUC_CAPTURE_LIST_TYPE_ENGINE_CLASS,
694                                              engine->class, &tmp, true)) {
695                         num_regs += tmp;
696                 }
697                 if (!guc_capture_getlistsize(guc, 0, GUC_CAPTURE_LIST_TYPE_ENGINE_INSTANCE,
698                                              engine->class, &tmp, true)) {
699                         num_regs += tmp;
700                 }
701         }
702
703         worst_min_size += (num_regs * sizeof(struct guc_mmio_reg));
704
705         return worst_min_size;
706 }
707
708 /*
709  * Add on a 3x multiplier to allow for multiple back-to-back captures occurring
710  * before the i915 can read the data out and process it
711  */
712 #define GUC_CAPTURE_OVERBUFFER_MULTIPLIER 3
713
714 static void check_guc_capture_size(struct intel_guc *guc)
715 {
716         struct drm_i915_private *i915 = guc_to_gt(guc)->i915;
717         int min_size = guc_capture_output_min_size_est(guc);
718         int spare_size = min_size * GUC_CAPTURE_OVERBUFFER_MULTIPLIER;
719         u32 buffer_size = intel_guc_log_section_size_capture(&guc->log);
720
721         if (min_size < 0)
722                 drm_warn(&i915->drm, "Failed to calculate GuC error state capture buffer minimum size: %d!\n",
723                          min_size);
724         else if (min_size > buffer_size)
725                 drm_warn(&i915->drm, "GuC error state capture buffer is too small: %d < %d\n",
726                          buffer_size, min_size);
727         else if (spare_size > buffer_size)
728                 drm_notice(&i915->drm, "GuC error state capture buffer maybe too small: %d < %d (min = %d)\n",
729                            buffer_size, spare_size, min_size);
730 }
731
732 /*
733  * KMD Init time flows:
734  * --------------------
735  *     --> alloc A: GuC input capture regs lists (registered to GuC via ADS).
736  *                  intel_guc_ads acquires the register lists by calling
737  *                  intel_guc_capture_list_size and intel_guc_capture_list_get 'n' times,
738  *                  where n = 1 for global-reg-list +
739  *                            num_engine_classes for class-reg-list +
740  *                            num_engine_classes for instance-reg-list
741  *                               (since all instances of the same engine-class type
742  *                                have an identical engine-instance register-list).
743  *                  ADS module also calls separately for PF vs VF.
744  *
745  *     --> alloc B: GuC output capture buf (registered via guc_init_params(log_param))
746  *                  Size = #define CAPTURE_BUFFER_SIZE (warns if on too-small)
747  *                  Note2: 'x 3' to hold multiple capture groups
748  *
749  * GUC Runtime notify capture:
750  * --------------------------
751  *     --> G2H STATE_CAPTURE_NOTIFICATION
752  *                   L--> intel_guc_capture_process
753  *                           L--> Loop through B (head..tail) and for each engine instance's
754  *                                err-state-captured register-list we find, we alloc 'C':
755  *      --> alloc C: A capture-output-node structure that includes misc capture info along
756  *                   with 3 register list dumps (global, engine-class and engine-instance)
757  *                   This node is created from a pre-allocated list of blank nodes in
758  *                   guc->capture->cachelist and populated with the error-capture
759  *                   data from GuC and then it's added into guc->capture->outlist linked
760  *                   list. This list is used for matchup and printout by i915_gpu_coredump
761  *                   and err_print_gt, (when user invokes the error capture sysfs).
762  *
763  * GUC --> notify context reset:
764  * -----------------------------
765  *     --> G2H CONTEXT RESET
766  *                   L--> guc_handle_context_reset --> i915_capture_error_state
767  *                          L--> i915_gpu_coredump(..IS_GUC_CAPTURE) --> gt_record_engines
768  *                               --> capture_engine(..IS_GUC_CAPTURE)
769  *                               L--> intel_guc_capture_get_matching_node is where
770  *                                    detach C from internal linked list and add it into
771  *                                    intel_engine_coredump struct (if the context and
772  *                                    engine of the event notification matches a node
773  *                                    in the link list).
774  *
775  * User Sysfs / Debugfs
776  * --------------------
777  *      --> i915_gpu_coredump_copy_to_buffer->
778  *                   L--> err_print_to_sgl --> err_print_gt
779  *                        L--> error_print_guc_captures
780  *                             L--> intel_guc_capture_print_node prints the
781  *                                  register lists values of the attached node
782  *                                  on the error-engine-dump being reported.
783  *                   L--> i915_reset_error_state ... -->__i915_gpu_coredump_free
784  *                        L--> ... cleanup_gt -->
785  *                             L--> intel_guc_capture_free_node returns the
786  *                                  capture-output-node back to the internal
787  *                                  cachelist for reuse.
788  *
789  */
790
791 static int guc_capture_buf_cnt(struct __guc_capture_bufstate *buf)
792 {
793         if (buf->wr >= buf->rd)
794                 return (buf->wr - buf->rd);
795         return (buf->size - buf->rd) + buf->wr;
796 }
797
798 static int guc_capture_buf_cnt_to_end(struct __guc_capture_bufstate *buf)
799 {
800         if (buf->rd > buf->wr)
801                 return (buf->size - buf->rd);
802         return (buf->wr - buf->rd);
803 }
804
805 /*
806  * GuC's error-capture output is a ring buffer populated in a byte-stream fashion:
807  *
808  * The GuC Log buffer region for error-capture is managed like a ring buffer.
809  * The GuC firmware dumps error capture logs into this ring in a byte-stream flow.
810  * Additionally, as per the current and foreseeable future, all packed error-
811  * capture output structures are dword aligned.
812  *
813  * That said, if the GuC firmware is in the midst of writing a structure that is larger
814  * than one dword but the tail end of the err-capture buffer-region has lesser space left,
815  * we would need to extract that structure one dword at a time straddled across the end,
816  * onto the start of the ring.
817  *
818  * Below function, guc_capture_log_remove_dw is a helper for that. All callers of this
819  * function would typically do a straight-up memcpy from the ring contents and will only
820  * call this helper if their structure-extraction is straddling across the end of the
821  * ring. GuC firmware does not add any padding. The reason for the no-padding is to ease
822  * scalability for future expansion of output data types without requiring a redesign
823  * of the flow controls.
824  */
825 static int
826 guc_capture_log_remove_dw(struct intel_guc *guc, struct __guc_capture_bufstate *buf,
827                           u32 *dw)
828 {
829         struct drm_i915_private *i915 = guc_to_gt(guc)->i915;
830         int tries = 2;
831         int avail = 0;
832         u32 *src_data;
833
834         if (!guc_capture_buf_cnt(buf))
835                 return 0;
836
837         while (tries--) {
838                 avail = guc_capture_buf_cnt_to_end(buf);
839                 if (avail >= sizeof(u32)) {
840                         src_data = (u32 *)(buf->data + buf->rd);
841                         *dw = *src_data;
842                         buf->rd += 4;
843                         return 4;
844                 }
845                 if (avail)
846                         drm_dbg(&i915->drm, "GuC-Cap-Logs not dword aligned, skipping.\n");
847                 buf->rd = 0;
848         }
849
850         return 0;
851 }
852
853 static bool
854 guc_capture_data_extracted(struct __guc_capture_bufstate *b,
855                            int size, void *dest)
856 {
857         if (guc_capture_buf_cnt_to_end(b) >= size) {
858                 memcpy(dest, (b->data + b->rd), size);
859                 b->rd += size;
860                 return true;
861         }
862         return false;
863 }
864
865 static int
866 guc_capture_log_get_group_hdr(struct intel_guc *guc, struct __guc_capture_bufstate *buf,
867                               struct guc_state_capture_group_header_t *ghdr)
868 {
869         int read = 0;
870         int fullsize = sizeof(struct guc_state_capture_group_header_t);
871
872         if (fullsize > guc_capture_buf_cnt(buf))
873                 return -1;
874
875         if (guc_capture_data_extracted(buf, fullsize, (void *)ghdr))
876                 return 0;
877
878         read += guc_capture_log_remove_dw(guc, buf, &ghdr->owner);
879         read += guc_capture_log_remove_dw(guc, buf, &ghdr->info);
880         if (read != fullsize)
881                 return -1;
882
883         return 0;
884 }
885
886 static int
887 guc_capture_log_get_data_hdr(struct intel_guc *guc, struct __guc_capture_bufstate *buf,
888                              struct guc_state_capture_header_t *hdr)
889 {
890         int read = 0;
891         int fullsize = sizeof(struct guc_state_capture_header_t);
892
893         if (fullsize > guc_capture_buf_cnt(buf))
894                 return -1;
895
896         if (guc_capture_data_extracted(buf, fullsize, (void *)hdr))
897                 return 0;
898
899         read += guc_capture_log_remove_dw(guc, buf, &hdr->owner);
900         read += guc_capture_log_remove_dw(guc, buf, &hdr->info);
901         read += guc_capture_log_remove_dw(guc, buf, &hdr->lrca);
902         read += guc_capture_log_remove_dw(guc, buf, &hdr->guc_id);
903         read += guc_capture_log_remove_dw(guc, buf, &hdr->num_mmios);
904         if (read != fullsize)
905                 return -1;
906
907         return 0;
908 }
909
910 static int
911 guc_capture_log_get_register(struct intel_guc *guc, struct __guc_capture_bufstate *buf,
912                              struct guc_mmio_reg *reg)
913 {
914         int read = 0;
915         int fullsize = sizeof(struct guc_mmio_reg);
916
917         if (fullsize > guc_capture_buf_cnt(buf))
918                 return -1;
919
920         if (guc_capture_data_extracted(buf, fullsize, (void *)reg))
921                 return 0;
922
923         read += guc_capture_log_remove_dw(guc, buf, &reg->offset);
924         read += guc_capture_log_remove_dw(guc, buf, &reg->value);
925         read += guc_capture_log_remove_dw(guc, buf, &reg->flags);
926         read += guc_capture_log_remove_dw(guc, buf, &reg->mask);
927         if (read != fullsize)
928                 return -1;
929
930         return 0;
931 }
932
933 static void
934 guc_capture_delete_one_node(struct intel_guc *guc, struct __guc_capture_parsed_output *node)
935 {
936         int i;
937
938         for (i = 0; i < GUC_CAPTURE_LIST_TYPE_MAX; ++i)
939                 kfree(node->reginfo[i].regs);
940         list_del(&node->link);
941         kfree(node);
942 }
943
944 static void
945 guc_capture_delete_prealloc_nodes(struct intel_guc *guc)
946 {
947         struct __guc_capture_parsed_output *n, *ntmp;
948
949         /*
950          * NOTE: At the end of driver operation, we must assume that we
951          * have prealloc nodes in both the cachelist as well as outlist
952          * if unclaimed error capture events occurred prior to shutdown.
953          */
954         list_for_each_entry_safe(n, ntmp, &guc->capture->outlist, link)
955                 guc_capture_delete_one_node(guc, n);
956
957         list_for_each_entry_safe(n, ntmp, &guc->capture->cachelist, link)
958                 guc_capture_delete_one_node(guc, n);
959 }
960
961 static void
962 guc_capture_add_node_to_list(struct __guc_capture_parsed_output *node,
963                              struct list_head *list)
964 {
965         list_add_tail(&node->link, list);
966 }
967
968 static void
969 guc_capture_add_node_to_outlist(struct intel_guc_state_capture *gc,
970                                 struct __guc_capture_parsed_output *node)
971 {
972         guc_capture_add_node_to_list(node, &gc->outlist);
973 }
974
975 static void
976 guc_capture_add_node_to_cachelist(struct intel_guc_state_capture *gc,
977                                   struct __guc_capture_parsed_output *node)
978 {
979         guc_capture_add_node_to_list(node, &gc->cachelist);
980 }
981
982 static void
983 guc_capture_init_node(struct intel_guc *guc, struct __guc_capture_parsed_output *node)
984 {
985         struct guc_mmio_reg *tmp[GUC_CAPTURE_LIST_TYPE_MAX];
986         int i;
987
988         for (i = 0; i < GUC_CAPTURE_LIST_TYPE_MAX; ++i) {
989                 tmp[i] = node->reginfo[i].regs;
990                 memset(tmp[i], 0, sizeof(struct guc_mmio_reg) *
991                        guc->capture->max_mmio_per_node);
992         }
993         memset(node, 0, sizeof(*node));
994         for (i = 0; i < GUC_CAPTURE_LIST_TYPE_MAX; ++i)
995                 node->reginfo[i].regs = tmp[i];
996
997         INIT_LIST_HEAD(&node->link);
998 }
999
1000 static struct __guc_capture_parsed_output *
1001 guc_capture_get_prealloc_node(struct intel_guc *guc)
1002 {
1003         struct __guc_capture_parsed_output *found = NULL;
1004
1005         if (!list_empty(&guc->capture->cachelist)) {
1006                 struct __guc_capture_parsed_output *n, *ntmp;
1007
1008                 /* get first avail node from the cache list */
1009                 list_for_each_entry_safe(n, ntmp, &guc->capture->cachelist, link) {
1010                         found = n;
1011                         list_del(&n->link);
1012                         break;
1013                 }
1014         } else {
1015                 struct __guc_capture_parsed_output *n, *ntmp;
1016
1017                 /* traverse down and steal back the oldest node already allocated */
1018                 list_for_each_entry_safe(n, ntmp, &guc->capture->outlist, link) {
1019                         found = n;
1020                 }
1021                 if (found)
1022                         list_del(&found->link);
1023         }
1024         if (found)
1025                 guc_capture_init_node(guc, found);
1026
1027         return found;
1028 }
1029
1030 static struct __guc_capture_parsed_output *
1031 guc_capture_alloc_one_node(struct intel_guc *guc)
1032 {
1033         struct __guc_capture_parsed_output *new;
1034         int i;
1035
1036         new = kzalloc(sizeof(*new), GFP_KERNEL);
1037         if (!new)
1038                 return NULL;
1039
1040         for (i = 0; i < GUC_CAPTURE_LIST_TYPE_MAX; ++i) {
1041                 new->reginfo[i].regs = kcalloc(guc->capture->max_mmio_per_node,
1042                                                sizeof(struct guc_mmio_reg), GFP_KERNEL);
1043                 if (!new->reginfo[i].regs) {
1044                         while (i)
1045                                 kfree(new->reginfo[--i].regs);
1046                         kfree(new);
1047                         return NULL;
1048                 }
1049         }
1050         guc_capture_init_node(guc, new);
1051
1052         return new;
1053 }
1054
1055 static struct __guc_capture_parsed_output *
1056 guc_capture_clone_node(struct intel_guc *guc, struct __guc_capture_parsed_output *original,
1057                        u32 keep_reglist_mask)
1058 {
1059         struct __guc_capture_parsed_output *new;
1060         int i;
1061
1062         new = guc_capture_get_prealloc_node(guc);
1063         if (!new)
1064                 return NULL;
1065         if (!original)
1066                 return new;
1067
1068         new->is_partial = original->is_partial;
1069
1070         /* copy reg-lists that we want to clone */
1071         for (i = 0; i < GUC_CAPTURE_LIST_TYPE_MAX; ++i) {
1072                 if (keep_reglist_mask & BIT(i)) {
1073                         GEM_BUG_ON(original->reginfo[i].num_regs  >
1074                                    guc->capture->max_mmio_per_node);
1075
1076                         memcpy(new->reginfo[i].regs, original->reginfo[i].regs,
1077                                original->reginfo[i].num_regs * sizeof(struct guc_mmio_reg));
1078
1079                         new->reginfo[i].num_regs = original->reginfo[i].num_regs;
1080                         new->reginfo[i].vfid  = original->reginfo[i].vfid;
1081
1082                         if (i == GUC_CAPTURE_LIST_TYPE_ENGINE_CLASS) {
1083                                 new->eng_class = original->eng_class;
1084                         } else if (i == GUC_CAPTURE_LIST_TYPE_ENGINE_INSTANCE) {
1085                                 new->eng_inst = original->eng_inst;
1086                                 new->guc_id = original->guc_id;
1087                                 new->lrca = original->lrca;
1088                         }
1089                 }
1090         }
1091
1092         return new;
1093 }
1094
1095 static void
1096 __guc_capture_create_prealloc_nodes(struct intel_guc *guc)
1097 {
1098         struct __guc_capture_parsed_output *node = NULL;
1099         struct drm_i915_private *i915 = guc_to_gt(guc)->i915;
1100         int i;
1101
1102         for (i = 0; i < PREALLOC_NODES_MAX_COUNT; ++i) {
1103                 node = guc_capture_alloc_one_node(guc);
1104                 if (!node) {
1105                         drm_warn(&i915->drm, "GuC Capture pre-alloc-cache failure\n");
1106                         /* dont free the priors, use what we got and cleanup at shutdown */
1107                         return;
1108                 }
1109                 guc_capture_add_node_to_cachelist(guc->capture, node);
1110         }
1111 }
1112
1113 static int
1114 guc_get_max_reglist_count(struct intel_guc *guc)
1115 {
1116         int i, j, k, tmp, maxregcount = 0;
1117
1118         for (i = 0; i < GUC_CAPTURE_LIST_INDEX_MAX; ++i) {
1119                 for (j = 0; j < GUC_CAPTURE_LIST_TYPE_MAX; ++j) {
1120                         for (k = 0; k < GUC_MAX_ENGINE_CLASSES; ++k) {
1121                                 if (j == GUC_CAPTURE_LIST_TYPE_GLOBAL && k > 0)
1122                                         continue;
1123
1124                                 tmp = guc_cap_list_num_regs(guc->capture, i, j, k);
1125                                 if (tmp > maxregcount)
1126                                         maxregcount = tmp;
1127                         }
1128                 }
1129         }
1130         if (!maxregcount)
1131                 maxregcount = PREALLOC_NODES_DEFAULT_NUMREGS;
1132
1133         return maxregcount;
1134 }
1135
1136 static void
1137 guc_capture_create_prealloc_nodes(struct intel_guc *guc)
1138 {
1139         /* skip if we've already done the pre-alloc */
1140         if (guc->capture->max_mmio_per_node)
1141                 return;
1142
1143         guc->capture->max_mmio_per_node = guc_get_max_reglist_count(guc);
1144         __guc_capture_create_prealloc_nodes(guc);
1145 }
1146
1147 static int
1148 guc_capture_extract_reglists(struct intel_guc *guc, struct __guc_capture_bufstate *buf)
1149 {
1150         struct drm_i915_private *i915 = guc_to_gt(guc)->i915;
1151         struct guc_state_capture_group_header_t ghdr = {0};
1152         struct guc_state_capture_header_t hdr = {0};
1153         struct __guc_capture_parsed_output *node = NULL;
1154         struct guc_mmio_reg *regs = NULL;
1155         int i, numlists, numregs, ret = 0;
1156         enum guc_capture_type datatype;
1157         struct guc_mmio_reg tmp;
1158         bool is_partial = false;
1159
1160         i = guc_capture_buf_cnt(buf);
1161         if (!i)
1162                 return -ENODATA;
1163         if (i % sizeof(u32)) {
1164                 drm_warn(&i915->drm, "GuC Capture new entries unaligned\n");
1165                 ret = -EIO;
1166                 goto bailout;
1167         }
1168
1169         /* first get the capture group header */
1170         if (guc_capture_log_get_group_hdr(guc, buf, &ghdr)) {
1171                 ret = -EIO;
1172                 goto bailout;
1173         }
1174         /*
1175          * we would typically expect a layout as below where n would be expected to be
1176          * anywhere between 3 to n where n > 3 if we are seeing multiple dependent engine
1177          * instances being reset together.
1178          * ____________________________________________
1179          * | Capture Group                            |
1180          * | ________________________________________ |
1181          * | | Capture Group Header:                | |
1182          * | |  - num_captures = 5                  | |
1183          * | |______________________________________| |
1184          * | ________________________________________ |
1185          * | | Capture1:                            | |
1186          * | |  Hdr: GLOBAL, numregs=a              | |
1187          * | | ____________________________________ | |
1188          * | | | Reglist                          | | |
1189          * | | | - reg1, reg2, ... rega           | | |
1190          * | | |__________________________________| | |
1191          * | |______________________________________| |
1192          * | ________________________________________ |
1193          * | | Capture2:                            | |
1194          * | |  Hdr: CLASS=RENDER/COMPUTE, numregs=b| |
1195          * | | ____________________________________ | |
1196          * | | | Reglist                          | | |
1197          * | | | - reg1, reg2, ... regb           | | |
1198          * | | |__________________________________| | |
1199          * | |______________________________________| |
1200          * | ________________________________________ |
1201          * | | Capture3:                            | |
1202          * | |  Hdr: INSTANCE=RCS, numregs=c        | |
1203          * | | ____________________________________ | |
1204          * | | | Reglist                          | | |
1205          * | | | - reg1, reg2, ... regc           | | |
1206          * | | |__________________________________| | |
1207          * | |______________________________________| |
1208          * | ________________________________________ |
1209          * | | Capture4:                            | |
1210          * | |  Hdr: CLASS=RENDER/COMPUTE, numregs=d| |
1211          * | | ____________________________________ | |
1212          * | | | Reglist                          | | |
1213          * | | | - reg1, reg2, ... regd           | | |
1214          * | | |__________________________________| | |
1215          * | |______________________________________| |
1216          * | ________________________________________ |
1217          * | | Capture5:                            | |
1218          * | |  Hdr: INSTANCE=CCS0, numregs=e       | |
1219          * | | ____________________________________ | |
1220          * | | | Reglist                          | | |
1221          * | | | - reg1, reg2, ... rege           | | |
1222          * | | |__________________________________| | |
1223          * | |______________________________________| |
1224          * |__________________________________________|
1225          */
1226         is_partial = FIELD_GET(CAP_GRP_HDR_CAPTURE_TYPE, ghdr.info);
1227         numlists = FIELD_GET(CAP_GRP_HDR_NUM_CAPTURES, ghdr.info);
1228
1229         while (numlists--) {
1230                 if (guc_capture_log_get_data_hdr(guc, buf, &hdr)) {
1231                         ret = -EIO;
1232                         break;
1233                 }
1234
1235                 datatype = FIELD_GET(CAP_HDR_CAPTURE_TYPE, hdr.info);
1236                 if (datatype > GUC_CAPTURE_LIST_TYPE_ENGINE_INSTANCE) {
1237                         /* unknown capture type - skip over to next capture set */
1238                         numregs = FIELD_GET(CAP_HDR_NUM_MMIOS, hdr.num_mmios);
1239                         while (numregs--) {
1240                                 if (guc_capture_log_get_register(guc, buf, &tmp)) {
1241                                         ret = -EIO;
1242                                         break;
1243                                 }
1244                         }
1245                         continue;
1246                 } else if (node) {
1247                         /*
1248                          * Based on the current capture type and what we have so far,
1249                          * decide if we should add the current node into the internal
1250                          * linked list for match-up when i915_gpu_coredump calls later
1251                          * (and alloc a blank node for the next set of reglists)
1252                          * or continue with the same node or clone the current node
1253                          * but only retain the global or class registers (such as the
1254                          * case of dependent engine resets).
1255                          */
1256                         if (datatype == GUC_CAPTURE_LIST_TYPE_GLOBAL) {
1257                                 guc_capture_add_node_to_outlist(guc->capture, node);
1258                                 node = NULL;
1259                         } else if (datatype == GUC_CAPTURE_LIST_TYPE_ENGINE_CLASS &&
1260                                    node->reginfo[GUC_CAPTURE_LIST_TYPE_ENGINE_CLASS].num_regs) {
1261                                 /* Add to list, clone node and duplicate global list */
1262                                 guc_capture_add_node_to_outlist(guc->capture, node);
1263                                 node = guc_capture_clone_node(guc, node,
1264                                                               GCAP_PARSED_REGLIST_INDEX_GLOBAL);
1265                         } else if (datatype == GUC_CAPTURE_LIST_TYPE_ENGINE_INSTANCE &&
1266                                    node->reginfo[GUC_CAPTURE_LIST_TYPE_ENGINE_INSTANCE].num_regs) {
1267                                 /* Add to list, clone node and duplicate global + class lists */
1268                                 guc_capture_add_node_to_outlist(guc->capture, node);
1269                                 node = guc_capture_clone_node(guc, node,
1270                                                               (GCAP_PARSED_REGLIST_INDEX_GLOBAL |
1271                                                               GCAP_PARSED_REGLIST_INDEX_ENGCLASS));
1272                         }
1273                 }
1274
1275                 if (!node) {
1276                         node = guc_capture_get_prealloc_node(guc);
1277                         if (!node) {
1278                                 ret = -ENOMEM;
1279                                 break;
1280                         }
1281                         if (datatype != GUC_CAPTURE_LIST_TYPE_GLOBAL)
1282                                 drm_dbg(&i915->drm, "GuC Capture missing global dump: %08x!\n",
1283                                         datatype);
1284                 }
1285                 node->is_partial = is_partial;
1286                 node->reginfo[datatype].vfid = FIELD_GET(CAP_HDR_CAPTURE_VFID, hdr.owner);
1287                 switch (datatype) {
1288                 case GUC_CAPTURE_LIST_TYPE_ENGINE_INSTANCE:
1289                         node->eng_class = FIELD_GET(CAP_HDR_ENGINE_CLASS, hdr.info);
1290                         node->eng_inst = FIELD_GET(CAP_HDR_ENGINE_INSTANCE, hdr.info);
1291                         node->lrca = hdr.lrca;
1292                         node->guc_id = hdr.guc_id;
1293                         break;
1294                 case GUC_CAPTURE_LIST_TYPE_ENGINE_CLASS:
1295                         node->eng_class = FIELD_GET(CAP_HDR_ENGINE_CLASS, hdr.info);
1296                         break;
1297                 default:
1298                         break;
1299                 }
1300
1301                 numregs = FIELD_GET(CAP_HDR_NUM_MMIOS, hdr.num_mmios);
1302                 if (numregs > guc->capture->max_mmio_per_node) {
1303                         drm_dbg(&i915->drm, "GuC Capture list extraction clipped by prealloc!\n");
1304                         numregs = guc->capture->max_mmio_per_node;
1305                 }
1306                 node->reginfo[datatype].num_regs = numregs;
1307                 regs = node->reginfo[datatype].regs;
1308                 i = 0;
1309                 while (numregs--) {
1310                         if (guc_capture_log_get_register(guc, buf, &regs[i++])) {
1311                                 ret = -EIO;
1312                                 break;
1313                         }
1314                 }
1315         }
1316
1317 bailout:
1318         if (node) {
1319                 /* If we have data, add to linked list for match-up when i915_gpu_coredump calls */
1320                 for (i = GUC_CAPTURE_LIST_TYPE_GLOBAL; i < GUC_CAPTURE_LIST_TYPE_MAX; ++i) {
1321                         if (node->reginfo[i].regs) {
1322                                 guc_capture_add_node_to_outlist(guc->capture, node);
1323                                 node = NULL;
1324                                 break;
1325                         }
1326                 }
1327                 if (node) /* else return it back to cache list */
1328                         guc_capture_add_node_to_cachelist(guc->capture, node);
1329         }
1330         return ret;
1331 }
1332
1333 static int __guc_capture_flushlog_complete(struct intel_guc *guc)
1334 {
1335         u32 action[] = {
1336                 INTEL_GUC_ACTION_LOG_BUFFER_FILE_FLUSH_COMPLETE,
1337                 GUC_CAPTURE_LOG_BUFFER
1338         };
1339
1340         return intel_guc_send_nb(guc, action, ARRAY_SIZE(action), 0);
1341
1342 }
1343
1344 static void __guc_capture_process_output(struct intel_guc *guc)
1345 {
1346         unsigned int buffer_size, read_offset, write_offset, full_count;
1347         struct intel_uc *uc = container_of(guc, typeof(*uc), guc);
1348         struct drm_i915_private *i915 = guc_to_gt(guc)->i915;
1349         struct guc_log_buffer_state log_buf_state_local;
1350         struct guc_log_buffer_state *log_buf_state;
1351         struct __guc_capture_bufstate buf;
1352         void *src_data = NULL;
1353         bool new_overflow;
1354         int ret;
1355
1356         log_buf_state = guc->log.buf_addr +
1357                         (sizeof(struct guc_log_buffer_state) * GUC_CAPTURE_LOG_BUFFER);
1358         src_data = guc->log.buf_addr +
1359                    intel_guc_get_log_buffer_offset(&guc->log, GUC_CAPTURE_LOG_BUFFER);
1360
1361         /*
1362          * Make a copy of the state structure, inside GuC log buffer
1363          * (which is uncached mapped), on the stack to avoid reading
1364          * from it multiple times.
1365          */
1366         memcpy(&log_buf_state_local, log_buf_state, sizeof(struct guc_log_buffer_state));
1367         buffer_size = intel_guc_get_log_buffer_size(&guc->log, GUC_CAPTURE_LOG_BUFFER);
1368         read_offset = log_buf_state_local.read_ptr;
1369         write_offset = log_buf_state_local.sampled_write_ptr;
1370         full_count = log_buf_state_local.buffer_full_cnt;
1371
1372         /* Bookkeeping stuff */
1373         guc->log.stats[GUC_CAPTURE_LOG_BUFFER].flush += log_buf_state_local.flush_to_file;
1374         new_overflow = intel_guc_check_log_buf_overflow(&guc->log, GUC_CAPTURE_LOG_BUFFER,
1375                                                         full_count);
1376
1377         /* Now copy the actual logs. */
1378         if (unlikely(new_overflow)) {
1379                 /* copy the whole buffer in case of overflow */
1380                 read_offset = 0;
1381                 write_offset = buffer_size;
1382         } else if (unlikely((read_offset > buffer_size) ||
1383                         (write_offset > buffer_size))) {
1384                 drm_err(&i915->drm, "invalid GuC log capture buffer state!\n");
1385                 /* copy whole buffer as offsets are unreliable */
1386                 read_offset = 0;
1387                 write_offset = buffer_size;
1388         }
1389
1390         buf.size = buffer_size;
1391         buf.rd = read_offset;
1392         buf.wr = write_offset;
1393         buf.data = src_data;
1394
1395         if (!uc->reset_in_progress) {
1396                 do {
1397                         ret = guc_capture_extract_reglists(guc, &buf);
1398                 } while (ret >= 0);
1399         }
1400
1401         /* Update the state of log buffer err-cap state */
1402         log_buf_state->read_ptr = write_offset;
1403         log_buf_state->flush_to_file = 0;
1404         __guc_capture_flushlog_complete(guc);
1405 }
1406
1407 #if IS_ENABLED(CONFIG_DRM_I915_CAPTURE_ERROR)
1408
1409 static const char *
1410 guc_capture_reg_to_str(const struct intel_guc *guc, u32 owner, u32 type,
1411                        u32 class, u32 id, u32 offset, u32 *is_ext)
1412 {
1413         const struct __guc_mmio_reg_descr_group *reglists = guc->capture->reglists;
1414         struct __guc_mmio_reg_descr_group *extlists = guc->capture->extlists;
1415         const struct __guc_mmio_reg_descr_group *match;
1416         struct __guc_mmio_reg_descr_group *matchext;
1417         int j;
1418
1419         *is_ext = 0;
1420         if (!reglists)
1421                 return NULL;
1422
1423         match = guc_capture_get_one_list(reglists, owner, type, id);
1424         if (!match)
1425                 return NULL;
1426
1427         for (j = 0; j < match->num_regs; ++j) {
1428                 if (offset == match->list[j].reg.reg)
1429                         return match->list[j].regname;
1430         }
1431         if (extlists) {
1432                 matchext = guc_capture_get_one_ext_list(extlists, owner, type, id);
1433                 if (!matchext)
1434                         return NULL;
1435                 for (j = 0; j < matchext->num_regs; ++j) {
1436                         if (offset == matchext->extlist[j].reg.reg) {
1437                                 *is_ext = 1;
1438                                 return matchext->extlist[j].regname;
1439                         }
1440                 }
1441         }
1442
1443         return NULL;
1444 }
1445
1446 #define GCAP_PRINT_INTEL_ENG_INFO(ebuf, eng) \
1447         do { \
1448                 i915_error_printf(ebuf, "    i915-Eng-Name: %s command stream\n", \
1449                                   (eng)->name); \
1450                 i915_error_printf(ebuf, "    i915-Eng-Inst-Class: 0x%02x\n", (eng)->class); \
1451                 i915_error_printf(ebuf, "    i915-Eng-Inst-Id: 0x%02x\n", (eng)->instance); \
1452                 i915_error_printf(ebuf, "    i915-Eng-LogicalMask: 0x%08x\n", \
1453                                   (eng)->logical_mask); \
1454         } while (0)
1455
1456 #define GCAP_PRINT_GUC_INST_INFO(ebuf, node) \
1457         do { \
1458                 i915_error_printf(ebuf, "    GuC-Engine-Inst-Id: 0x%08x\n", \
1459                                   (node)->eng_inst); \
1460                 i915_error_printf(ebuf, "    GuC-Context-Id: 0x%08x\n", (node)->guc_id); \
1461                 i915_error_printf(ebuf, "    LRCA: 0x%08x\n", (node)->lrca); \
1462         } while (0)
1463
1464 int intel_guc_capture_print_engine_node(struct drm_i915_error_state_buf *ebuf,
1465                                         const struct intel_engine_coredump *ee)
1466 {
1467         const char *grptype[GUC_STATE_CAPTURE_GROUP_TYPE_MAX] = {
1468                 "full-capture",
1469                 "partial-capture"
1470         };
1471         const char *datatype[GUC_CAPTURE_LIST_TYPE_MAX] = {
1472                 "Global",
1473                 "Engine-Class",
1474                 "Engine-Instance"
1475         };
1476         struct intel_guc_state_capture *cap;
1477         struct __guc_capture_parsed_output *node;
1478         struct intel_engine_cs *eng;
1479         struct guc_mmio_reg *regs;
1480         struct intel_guc *guc;
1481         const char *str;
1482         int numregs, i, j;
1483         u32 is_ext;
1484
1485         if (!ebuf || !ee)
1486                 return -EINVAL;
1487         cap = ee->capture;
1488         if (!cap || !ee->engine)
1489                 return -ENODEV;
1490
1491         guc = &ee->engine->gt->uc.guc;
1492
1493         i915_error_printf(ebuf, "global --- GuC Error Capture on %s command stream:\n",
1494                           ee->engine->name);
1495
1496         node = ee->guc_capture_node;
1497         if (!node) {
1498                 i915_error_printf(ebuf, "  No matching ee-node\n");
1499                 return 0;
1500         }
1501
1502         i915_error_printf(ebuf, "Coverage:  %s\n", grptype[node->is_partial]);
1503
1504         for (i = GUC_CAPTURE_LIST_TYPE_GLOBAL; i < GUC_CAPTURE_LIST_TYPE_MAX; ++i) {
1505                 i915_error_printf(ebuf, "  RegListType: %s\n",
1506                                   datatype[i % GUC_CAPTURE_LIST_TYPE_MAX]);
1507                 i915_error_printf(ebuf, "    Owner-Id: %d\n", node->reginfo[i].vfid);
1508
1509                 switch (i) {
1510                 case GUC_CAPTURE_LIST_TYPE_GLOBAL:
1511                 default:
1512                         break;
1513                 case GUC_CAPTURE_LIST_TYPE_ENGINE_CLASS:
1514                         i915_error_printf(ebuf, "    GuC-Eng-Class: %d\n", node->eng_class);
1515                         i915_error_printf(ebuf, "    i915-Eng-Class: %d\n",
1516                                           guc_class_to_engine_class(node->eng_class));
1517                         break;
1518                 case GUC_CAPTURE_LIST_TYPE_ENGINE_INSTANCE:
1519                         eng = intel_guc_lookup_engine(guc, node->eng_class, node->eng_inst);
1520                         if (eng)
1521                                 GCAP_PRINT_INTEL_ENG_INFO(ebuf, eng);
1522                         else
1523                                 i915_error_printf(ebuf, "    i915-Eng-Lookup Fail!\n");
1524                         GCAP_PRINT_GUC_INST_INFO(ebuf, node);
1525                         break;
1526                 }
1527
1528                 numregs = node->reginfo[i].num_regs;
1529                 i915_error_printf(ebuf, "    NumRegs: %d\n", numregs);
1530                 j = 0;
1531                 while (numregs--) {
1532                         regs = node->reginfo[i].regs;
1533                         str = guc_capture_reg_to_str(guc, GUC_CAPTURE_LIST_INDEX_PF, i,
1534                                                      node->eng_class, 0, regs[j].offset, &is_ext);
1535                         if (!str)
1536                                 i915_error_printf(ebuf, "      REG-0x%08x", regs[j].offset);
1537                         else
1538                                 i915_error_printf(ebuf, "      %s", str);
1539                         if (is_ext)
1540                                 i915_error_printf(ebuf, "[%ld][%ld]",
1541                                         FIELD_GET(GUC_REGSET_STEERING_GROUP, regs[j].flags),
1542                                         FIELD_GET(GUC_REGSET_STEERING_INSTANCE, regs[j].flags));
1543                         i915_error_printf(ebuf, ":  0x%08x\n", regs[j].value);
1544                         ++j;
1545                 }
1546         }
1547         return 0;
1548 }
1549
1550 #endif //CONFIG_DRM_I915_CAPTURE_ERROR
1551
1552 void intel_guc_capture_free_node(struct intel_engine_coredump *ee)
1553 {
1554         if (!ee || !ee->guc_capture_node)
1555                 return;
1556
1557         guc_capture_add_node_to_cachelist(ee->capture, ee->guc_capture_node);
1558         ee->capture = NULL;
1559         ee->guc_capture_node = NULL;
1560 }
1561
1562 void intel_guc_capture_get_matching_node(struct intel_gt *gt,
1563                                          struct intel_engine_coredump *ee,
1564                                          struct intel_context *ce)
1565 {
1566         struct __guc_capture_parsed_output *n, *ntmp;
1567         struct drm_i915_private *i915;
1568         struct intel_guc *guc;
1569
1570         if (!gt || !ee || !ce)
1571                 return;
1572
1573         i915 = gt->i915;
1574         guc = &gt->uc.guc;
1575         if (!guc->capture)
1576                 return;
1577
1578         GEM_BUG_ON(ee->guc_capture_node);
1579         /*
1580          * Look for a matching GuC reported error capture node from
1581          * the internal output link-list based on lrca, guc-id and engine
1582          * identification.
1583          */
1584         list_for_each_entry_safe(n, ntmp, &guc->capture->outlist, link) {
1585                 if (n->eng_inst == GUC_ID_TO_ENGINE_INSTANCE(ee->engine->guc_id) &&
1586                     n->eng_class == GUC_ID_TO_ENGINE_CLASS(ee->engine->guc_id) &&
1587                     n->guc_id && n->guc_id == ce->guc_id.id &&
1588                     (n->lrca & CTX_GTT_ADDRESS_MASK) && (n->lrca & CTX_GTT_ADDRESS_MASK) ==
1589                     (ce->lrc.lrca & CTX_GTT_ADDRESS_MASK)) {
1590                         list_del(&n->link);
1591                         ee->guc_capture_node = n;
1592                         ee->capture = guc->capture;
1593                         return;
1594                 }
1595         }
1596         drm_dbg(&i915->drm, "GuC capture can't match ee to node\n");
1597 }
1598
1599 void intel_guc_capture_process(struct intel_guc *guc)
1600 {
1601         if (guc->capture)
1602                 __guc_capture_process_output(guc);
1603 }
1604
1605 static void
1606 guc_capture_free_ads_cache(struct intel_guc_state_capture *gc)
1607 {
1608         int i, j, k;
1609         struct __guc_capture_ads_cache *cache;
1610
1611         for (i = 0; i < GUC_CAPTURE_LIST_INDEX_MAX; ++i) {
1612                 for (j = 0; j < GUC_CAPTURE_LIST_TYPE_MAX; ++j) {
1613                         for (k = 0; k < GUC_MAX_ENGINE_CLASSES; ++k) {
1614                                 cache = &gc->ads_cache[i][j][k];
1615                                 if (cache->is_valid)
1616                                         kfree(cache->ptr);
1617                         }
1618                 }
1619         }
1620         kfree(gc->ads_null_cache);
1621 }
1622
1623 void intel_guc_capture_destroy(struct intel_guc *guc)
1624 {
1625         if (!guc->capture)
1626                 return;
1627
1628         guc_capture_free_ads_cache(guc->capture);
1629
1630         guc_capture_delete_prealloc_nodes(guc);
1631
1632         guc_capture_free_extlists(guc->capture->extlists);
1633         kfree(guc->capture->extlists);
1634
1635         kfree(guc->capture);
1636         guc->capture = NULL;
1637 }
1638
1639 int intel_guc_capture_init(struct intel_guc *guc)
1640 {
1641         guc->capture = kzalloc(sizeof(*guc->capture), GFP_KERNEL);
1642         if (!guc->capture)
1643                 return -ENOMEM;
1644
1645         guc->capture->reglists = guc_capture_get_device_reglist(guc);
1646
1647         INIT_LIST_HEAD(&guc->capture->outlist);
1648         INIT_LIST_HEAD(&guc->capture->cachelist);
1649
1650         check_guc_capture_size(guc);
1651
1652         return 0;
1653 }