Skip to content

Commit b170d69

Browse files
zhanjunmattrope
authored andcommitted
drm/xe/guc: Add XE_LP steered register lists
Add the ability for runtime allocation and freeing of steered register list extentions that depend on the detected HW config fuses. Signed-off-by: Zhanjun Dong <[email protected]> Reviewed-by: Alan Previn <[email protected]> Signed-off-by: Matt Roper <[email protected]> Link: https://patchwork.freedesktop.org/patch/msgid/[email protected]
1 parent 9c8c7a7 commit b170d69

File tree

3 files changed

+206
-13
lines changed

3 files changed

+206
-13
lines changed

drivers/gpu/drm/xe/xe_guc_ads.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -599,6 +599,12 @@ static int guc_capture_prep_lists(struct xe_guc_ads *ads)
599599
void *ptr;
600600
int i, j;
601601

602+
/*
603+
* GuC Capture's steered reg-list needs to be allocated and initialized
604+
* after the GuC-hwconfig is available which guaranteed from here.
605+
*/
606+
xe_guc_capture_steered_list_init(ads_to_guc(ads));
607+
602608
capture_offset = guc_ads_capture_offset(ads);
603609
ads_ggtt = xe_bo_ggtt_addr(ads->bo);
604610
info_map = IOSYS_MAP_INIT_OFFSET(ads_to_map(ads),

drivers/gpu/drm/xe/xe_guc_capture.c

Lines changed: 199 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -211,6 +211,11 @@ struct __guc_capture_ads_cache {
211211

212212
struct xe_guc_state_capture {
213213
const struct __guc_mmio_reg_descr_group *reglists;
214+
/**
215+
* NOTE: steered registers have multiple instances depending on the HW configuration
216+
* (slices or dual-sub-slices) and thus depends on HW fuses discovered
217+
*/
218+
struct __guc_mmio_reg_descr_group *extlists;
214219
struct __guc_capture_ads_cache ads_cache[GUC_CAPTURE_LIST_INDEX_MAX]
215220
[GUC_STATE_CAPTURE_TYPE_MAX]
216221
[GUC_CAPTURE_LIST_CLASS_MAX];
@@ -245,14 +250,156 @@ guc_capture_get_one_list(const struct __guc_mmio_reg_descr_group *reglists,
245250
return NULL;
246251
}
247252

253+
struct __ext_steer_reg {
254+
const char *name;
255+
struct xe_reg_mcr reg;
256+
};
257+
258+
static const struct __ext_steer_reg xe_extregs[] = {
259+
{"SAMPLER_INSTDONE", SAMPLER_INSTDONE},
260+
{"ROW_INSTDONE", ROW_INSTDONE}
261+
};
262+
263+
static const struct __ext_steer_reg xehpg_extregs[] = {
264+
{"SC_INSTDONE", XEHPG_SC_INSTDONE},
265+
{"SC_INSTDONE_EXTRA", XEHPG_SC_INSTDONE_EXTRA},
266+
{"SC_INSTDONE_EXTRA2", XEHPG_SC_INSTDONE_EXTRA2},
267+
{"INSTDONE_GEOM_SVGUNIT", XEHPG_INSTDONE_GEOM_SVGUNIT}
268+
};
269+
270+
static void __fill_ext_reg(struct __guc_mmio_reg_descr *ext,
271+
const struct __ext_steer_reg *extlist,
272+
int slice_id, int subslice_id)
273+
{
274+
if (!ext || !extlist)
275+
return;
276+
277+
ext->reg = XE_REG(extlist->reg.__reg.addr);
278+
ext->flags = FIELD_PREP(GUC_REGSET_STEERING_NEEDED, 1);
279+
ext->flags = FIELD_PREP(GUC_REGSET_STEERING_GROUP, slice_id);
280+
ext->flags |= FIELD_PREP(GUC_REGSET_STEERING_INSTANCE, subslice_id);
281+
ext->regname = extlist->name;
282+
}
283+
284+
static int
285+
__alloc_ext_regs(struct drm_device *drm, struct __guc_mmio_reg_descr_group *newlist,
286+
const struct __guc_mmio_reg_descr_group *rootlist, int num_regs)
287+
{
288+
struct __guc_mmio_reg_descr *list;
289+
290+
list = drmm_kzalloc(drm, num_regs * sizeof(struct __guc_mmio_reg_descr), GFP_KERNEL);
291+
if (!list)
292+
return -ENOMEM;
293+
294+
newlist->list = list;
295+
newlist->num_regs = num_regs;
296+
newlist->owner = rootlist->owner;
297+
newlist->engine = rootlist->engine;
298+
newlist->type = rootlist->type;
299+
300+
return 0;
301+
}
302+
303+
static int guc_capture_get_steer_reg_num(struct xe_device *xe)
304+
{
305+
int num = ARRAY_SIZE(xe_extregs);
306+
307+
if (GRAPHICS_VERx100(xe) >= 1255)
308+
num += ARRAY_SIZE(xehpg_extregs);
309+
310+
return num;
311+
}
312+
313+
static void guc_capture_alloc_steered_lists(struct xe_guc *guc)
314+
{
315+
struct xe_gt *gt = guc_to_gt(guc);
316+
u16 slice, subslice;
317+
int iter, i, total = 0;
318+
const struct __guc_mmio_reg_descr_group *lists = guc->capture->reglists;
319+
const struct __guc_mmio_reg_descr_group *list;
320+
struct __guc_mmio_reg_descr_group *extlists;
321+
struct __guc_mmio_reg_descr *extarray;
322+
bool has_xehpg_extregs = GRAPHICS_VERx100(gt_to_xe(gt)) >= 1255;
323+
struct drm_device *drm = &gt_to_xe(gt)->drm;
324+
bool has_rcs_ccs = false;
325+
struct xe_hw_engine *hwe;
326+
enum xe_hw_engine_id id;
327+
328+
/*
329+
* If GT has no rcs/ccs, no need to alloc steered list.
330+
* Currently, only rcs/ccs has steering register, if in the future,
331+
* other engine types has steering register, this condition check need
332+
* to be extended
333+
*/
334+
for_each_hw_engine(hwe, gt, id) {
335+
if (xe_engine_class_to_guc_capture_class(hwe->class) ==
336+
GUC_CAPTURE_LIST_CLASS_RENDER_COMPUTE) {
337+
has_rcs_ccs = true;
338+
break;
339+
}
340+
}
341+
342+
if (!has_rcs_ccs)
343+
return;
344+
345+
/* steered registers currently only exist for the render-class */
346+
list = guc_capture_get_one_list(lists, GUC_CAPTURE_LIST_INDEX_PF,
347+
GUC_STATE_CAPTURE_TYPE_ENGINE_CLASS,
348+
GUC_CAPTURE_LIST_CLASS_RENDER_COMPUTE);
349+
/*
350+
* Skip if this platform has no engine class registers or if extlists
351+
* was previously allocated
352+
*/
353+
if (!list || guc->capture->extlists)
354+
return;
355+
356+
total = bitmap_weight(gt->fuse_topo.g_dss_mask, sizeof(gt->fuse_topo.g_dss_mask) * 8) *
357+
guc_capture_get_steer_reg_num(guc_to_xe(guc));
358+
359+
if (!total)
360+
return;
361+
362+
/* allocate an extra for an end marker */
363+
extlists = drmm_kzalloc(drm, 2 * sizeof(struct __guc_mmio_reg_descr_group), GFP_KERNEL);
364+
if (!extlists)
365+
return;
366+
367+
if (__alloc_ext_regs(drm, &extlists[0], list, total)) {
368+
drmm_kfree(drm, extlists);
369+
return;
370+
}
371+
372+
/* For steering registers, the list is generated at run-time */
373+
extarray = (struct __guc_mmio_reg_descr *)extlists[0].list;
374+
for_each_dss_steering(iter, gt, slice, subslice) {
375+
for (i = 0; i < ARRAY_SIZE(xe_extregs); ++i) {
376+
__fill_ext_reg(extarray, &xe_extregs[i], slice, subslice);
377+
++extarray;
378+
}
379+
380+
if (has_xehpg_extregs)
381+
for (i = 0; i < ARRAY_SIZE(xehpg_extregs); ++i) {
382+
__fill_ext_reg(extarray, &xehpg_extregs[i], slice, subslice);
383+
++extarray;
384+
}
385+
}
386+
387+
extlists[0].num_regs = total;
388+
389+
xe_gt_dbg(guc_to_gt(guc), "capture found %d ext-regs.\n", total);
390+
guc->capture->extlists = extlists;
391+
}
392+
248393
static int
249394
guc_capture_list_init(struct xe_guc *guc, u32 owner, u32 type,
250395
enum guc_capture_list_class_type capture_class, struct guc_mmio_reg *ptr,
251396
u16 num_entries)
252397
{
253-
u32 i = 0;
398+
u32 ptr_idx = 0, list_idx = 0;
254399
const struct __guc_mmio_reg_descr_group *reglists = guc->capture->reglists;
400+
struct __guc_mmio_reg_descr_group *extlists = guc->capture->extlists;
255401
const struct __guc_mmio_reg_descr_group *match;
402+
u32 list_num;
256403

257404
if (!reglists)
258405
return -ENODEV;
@@ -261,16 +408,28 @@ guc_capture_list_init(struct xe_guc *guc, u32 owner, u32 type,
261408
if (!match)
262409
return -ENODATA;
263410

264-
for (i = 0; i < num_entries && i < match->num_regs; ++i) {
265-
ptr[i].offset = match->list[i].reg.addr;
266-
ptr[i].value = 0xDEADF00D;
267-
ptr[i].flags = match->list[i].flags;
268-
ptr[i].mask = match->list[i].mask;
411+
list_num = match->num_regs;
412+
for (list_idx = 0; ptr_idx < num_entries && list_idx < list_num; ++list_idx, ++ptr_idx) {
413+
ptr[ptr_idx].offset = match->list[list_idx].reg.addr;
414+
ptr[ptr_idx].value = 0xDEADF00D;
415+
ptr[ptr_idx].flags = match->list[list_idx].flags;
416+
ptr[ptr_idx].mask = match->list[list_idx].mask;
269417
}
270418

271-
if (i < num_entries)
272-
xe_gt_dbg(guc_to_gt(guc), "Got short capture reglist init: %d out %d.\n", i,
273-
num_entries);
419+
match = guc_capture_get_one_list(extlists, owner, type, capture_class);
420+
if (match)
421+
for (ptr_idx = list_num, list_idx = 0;
422+
ptr_idx < num_entries && list_idx < match->num_regs;
423+
++ptr_idx, ++list_idx) {
424+
ptr[ptr_idx].offset = match->list[list_idx].reg.addr;
425+
ptr[ptr_idx].value = 0xDEADF00D;
426+
ptr[ptr_idx].flags = match->list[list_idx].flags;
427+
ptr[ptr_idx].mask = match->list[list_idx].mask;
428+
}
429+
430+
if (ptr_idx < num_entries)
431+
xe_gt_dbg(guc_to_gt(guc), "Got short capture reglist init: %d out-of %d.\n",
432+
ptr_idx, num_entries);
274433

275434
return 0;
276435
}
@@ -280,12 +439,22 @@ guc_cap_list_num_regs(struct xe_guc *guc, u32 owner, u32 type,
280439
enum guc_capture_list_class_type capture_class)
281440
{
282441
const struct __guc_mmio_reg_descr_group *match;
442+
int num_regs = 0;
283443

284444
match = guc_capture_get_one_list(guc->capture->reglists, owner, type, capture_class);
285-
if (!match)
286-
return 0;
445+
if (match)
446+
num_regs = match->num_regs;
447+
448+
match = guc_capture_get_one_list(guc->capture->extlists, owner, type, capture_class);
449+
if (match)
450+
num_regs += match->num_regs;
451+
else
452+
/* Estimate steering register size for rcs/ccs */
453+
if (capture_class == GUC_CAPTURE_LIST_CLASS_RENDER_COMPUTE)
454+
num_regs += guc_capture_get_steer_reg_num(guc_to_xe(guc)) *
455+
XE_MAX_DSS_FUSE_BITS;
287456

288-
return match->num_regs;
457+
return num_regs;
289458
}
290459

291460
static int
@@ -500,14 +669,31 @@ size_t xe_guc_capture_ads_input_worst_size(struct xe_guc *guc)
500669
return PAGE_ALIGN(total_size);
501670
}
502671

672+
/*
673+
* xe_guc_capture_steered_list_init - Init steering register list
674+
* @guc: The GuC object
675+
*
676+
* Init steering register list for GuC register capture
677+
*/
678+
void xe_guc_capture_steered_list_init(struct xe_guc *guc)
679+
{
680+
/*
681+
* For certain engine classes, there are slice and subslice
682+
* level registers requiring steering. We allocate and populate
683+
* these based on hw config and add it as an extension list at
684+
* the end of the pre-populated render list.
685+
*/
686+
guc_capture_alloc_steered_lists(guc);
687+
}
688+
503689
/**
504690
* xe_guc_capture_init - Init for GuC register capture
505691
* @guc: The GuC object
506692
*
507693
* Init for GuC register capture, alloc memory for capture data structure.
508694
*
509695
* Returns: 0 if success.
510-
-ENOMEM if out of memory
696+
* -ENOMEM if out of memory
511697
*/
512698
int xe_guc_capture_init(struct xe_guc *guc)
513699
{

drivers/gpu/drm/xe/xe_guc_capture.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ int xe_guc_capture_getlistsize(struct xe_guc *guc, u32 owner, u32 type,
4343
enum guc_capture_list_class_type capture_class, size_t *size);
4444
int xe_guc_capture_getnullheader(struct xe_guc *guc, void **outptr, size_t *size);
4545
size_t xe_guc_capture_ads_input_worst_size(struct xe_guc *guc);
46+
void xe_guc_capture_steered_list_init(struct xe_guc *guc);
4647
int xe_guc_capture_init(struct xe_guc *guc);
4748

4849
#endif

0 commit comments

Comments
 (0)