[Intel-gfx] [RFC 3/7] drm/i915/guc: Populate XE_LP register lists for GuC error state capture.
Michal Wajdeczko
michal.wajdeczko at intel.com
Tue Nov 23 21:55:58 UTC 2021
On 23.11.2021 00:03, Alan Previn wrote:
> Add device specific tables and register lists to cover different engines
> class types for GuC error state capture.
>
> Also, add runtime allocation and freeing of extended register lists
> for registers that need steering identifiers that depend on
> the detected HW config.
>
> Signed-off-by: Alan Previn <alan.previn.teres.alexis at intel.com>
> ---
> .../gpu/drm/i915/gt/uc/intel_guc_capture.c | 260 +++++++++++++-----
> .../gpu/drm/i915/gt/uc/intel_guc_capture.h | 2 +
> drivers/gpu/drm/i915/gt/uc/intel_guc_fwif.h | 2 +
> 3 files changed, 197 insertions(+), 67 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.c
> index c741c77b7fc8..eec1d193ac26 100644
> --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.c
> +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.c
> @@ -9,120 +9,245 @@
> #include "i915_drv.h"
> #include "i915_memcpy.h"
> #include "gt/intel_gt.h"
> +#include "gt/intel_lrc_reg.h"
>
> #include "intel_guc_fwif.h"
> #include "intel_guc_capture.h"
>
> -/* Define all device tables of GuC error capture register lists */
> +/*
> + * Define all device tables of GuC error capture register lists
> + * NOTE: For engine-registers, GuC only needs the register offsets
> + * from the engine-mmio-base
> + */
> +#define COMMON_GEN12BASE_GLOBAL() \
> + {GEN12_FAULT_TLB_DATA0, 0, 0, "GEN12_FAULT_TLB_DATA0"}, \
> + {GEN12_FAULT_TLB_DATA1, 0, 0, "GEN12_FAULT_TLB_DATA1"}, \
> + {FORCEWAKE_MT, 0, 0, "FORCEWAKE_MT"}, \
> + {DERRMR, 0, 0, "DERRMR"}, \
> + {GEN12_AUX_ERR_DBG, 0, 0, "GEN12_AUX_ERR_DBG"}, \
> + {GEN12_GAM_DONE, 0, 0, "GEN12_GAM_DONE"}, \
> + {GEN11_GUC_SG_INTR_ENABLE, 0, 0, "GEN11_GUC_SG_INTR_ENABLE"}, \
> + {GEN11_CRYPTO_RSVD_INTR_ENABLE, 0, 0, "GEN11_CRYPTO_RSVD_INTR_ENABLE"}, \
> + {GEN11_GUNIT_CSME_INTR_ENABLE, 0, 0, "GEN11_GUNIT_CSME_INTR_ENABLE"}, \
> + {GEN12_RING_FAULT_REG, 0, 0, "GEN12_RING_FAULT_REG"}
> +
> +#define COMMON_GEN12BASE_ENGINE_INSTANCE() \
> + {RING_PSMI_CTL(0), 0, 0, "RING_PSMI_CTL"}, \
> + {RING_ESR(0), 0, 0, "RING_ESR"}, \
> + {RING_ESR(0), 0, 0, "RING_ESR"}, \
> + {RING_DMA_FADD(0), 0, 0, "RING_DMA_FADD_LOW32"}, \
> + {RING_DMA_FADD_UDW(0), 0, 0, "RING_DMA_FADD_UP32"}, \
> + {RING_IPEIR(0), 0, 0, "RING_IPEIR"}, \
> + {RING_IPEHR(0), 0, 0, "RING_IPEHR"}, \
> + {RING_INSTPS(0), 0, 0, "RING_INSTPS"}, \
> + {RING_BBADDR(0), 0, 0, "RING_BBADDR_LOW32"}, \
> + {RING_BBADDR_UDW(0), 0, 0, "RING_BBADDR_UP32"}, \
> + {RING_BBSTATE(0), 0, 0, "RING_BBSTATE"}, \
> + {CCID(0), 0, 0, "CCID"}, \
> + {RING_ACTHD(0), 0, 0, "RING_ACTHD_LOW32"}, \
> + {RING_ACTHD_UDW(0), 0, 0, "RING_ACTHD_UP32"}, \
> + {RING_INSTPM(0), 0, 0, "RING_INSTPM"}, \
> + {RING_NOPID(0), 0, 0, "RING_NOPID"}, \
> + {RING_START(0), 0, 0, "RING_START"}, \
> + {RING_HEAD(0), 0, 0, "RING_HEAD"}, \
> + {RING_TAIL(0), 0, 0, "RING_TAIL"}, \
> + {RING_CTL(0), 0, 0, "RING_CTL"}, \
> + {RING_MI_MODE(0), 0, 0, "RING_MI_MODE"}, \
> + {RING_CONTEXT_CONTROL(0), 0, 0, "RING_CONTEXT_CONTROL"}, \
> + {RING_INSTDONE(0), 0, 0, "RING_INSTDONE"}, \
> + {RING_HWS_PGA(0), 0, 0, "RING_HWS_PGA"}, \
> + {RING_MODE_GEN7(0), 0, 0, "RING_MODE_GEN7"}, \
> + {GEN8_RING_PDP_LDW(0, 0), 0, 0, "GEN8_RING_PDP0_LDW"}, \
> + {GEN8_RING_PDP_UDW(0, 0), 0, 0, "GEN8_RING_PDP0_UDW"}, \
> + {GEN8_RING_PDP_LDW(0, 1), 0, 0, "GEN8_RING_PDP1_LDW"}, \
> + {GEN8_RING_PDP_UDW(0, 1), 0, 0, "GEN8_RING_PDP1_UDW"}, \
> + {GEN8_RING_PDP_LDW(0, 2), 0, 0, "GEN8_RING_PDP2_LDW"}, \
> + {GEN8_RING_PDP_UDW(0, 2), 0, 0, "GEN8_RING_PDP2_UDW"}, \
> + {GEN8_RING_PDP_LDW(0, 3), 0, 0, "GEN8_RING_PDP3_LDW"}, \
> + {GEN8_RING_PDP_UDW(0, 3), 0, 0, "GEN8_RING_PDP3_UDW"}
> +
> +#define COMMON_GEN12BASE_HAS_EU() \
> + {EIR, 0, 0, "EIR"}
> +
> +#define COMMON_GEN12BASE_RENDER() \
> + {GEN7_SC_INSTDONE, 0, 0, "GEN7_SC_INSTDONE"}, \
> + {GEN12_SC_INSTDONE_EXTRA, 0, 0, "GEN12_SC_INSTDONE_EXTRA"}, \
> + {GEN12_SC_INSTDONE_EXTRA2, 0, 0, "GEN12_SC_INSTDONE_EXTRA2"}
> +
> +#define COMMON_GEN12BASE_VEC() \
> + {GEN11_VCS_VECS_INTR_ENABLE, 0, 0, "GEN11_VCS_VECS_INTR_ENABLE"}, \
> + {GEN12_SFC_DONE(0), 0, 0, "GEN12_SFC_DONE0"}, \
> + {GEN12_SFC_DONE(1), 0, 0, "GEN12_SFC_DONE1"}, \
> + {GEN12_SFC_DONE(2), 0, 0, "GEN12_SFC_DONE2"}, \
> + {GEN12_SFC_DONE(3), 0, 0, "GEN12_SFC_DONE3"}
>
> /********************************* Gen12 LP *********************************/
> /************** GLOBAL *************/
> struct __guc_mmio_reg_descr gen12lp_global_regs[] = {
> - {SWF_ILK(0), 0, 0, "SWF_ILK0"},
we should avoid adding/removing code in same series
> - /* Add additional register list */
> + COMMON_GEN12BASE_GLOBAL(),
> + {GEN7_ROW_INSTDONE, 0, 0, "GEN7_ROW_INSTDONE"},
> };
>
> /********** RENDER/COMPUTE *********/
> /* Per-Class */
> struct __guc_mmio_reg_descr gen12lp_rc_class_regs[] = {
> - {SWF_ILK(0), 0, 0, "SWF_ILK0"},
> - /* Add additional register list */
> + COMMON_GEN12BASE_HAS_EU(),
> + COMMON_GEN12BASE_RENDER(),
> + {GEN11_RENDER_COPY_INTR_ENABLE, 0, 0, "GEN11_RENDER_COPY_INTR_ENABLE"},
> };
>
> /* Per-Engine-Instance */
> struct __guc_mmio_reg_descr gen12lp_rc_inst_regs[] = {
> - {SWF_ILK(0), 0, 0, "SWF_ILK0"},
> - /* Add additional register list */
> + COMMON_GEN12BASE_ENGINE_INSTANCE(),
> };
>
> /************* MEDIA-VD ************/
> /* Per-Class */
> struct __guc_mmio_reg_descr gen12lp_vd_class_regs[] = {
> - {SWF_ILK(0), 0, 0, "SWF_ILK0"},
> - /* Add additional register list */
> };
>
> /* Per-Engine-Instance */
> struct __guc_mmio_reg_descr gen12lp_vd_inst_regs[] = {
> - {SWF_ILK(0), 0, 0, "SWF_ILK0"},
> - /* Add additional register list */
> + COMMON_GEN12BASE_ENGINE_INSTANCE(),
> };
>
> /************* MEDIA-VEC ***********/
> /* Per-Class */
> struct __guc_mmio_reg_descr gen12lp_vec_class_regs[] = {
> - {SWF_ILK(0), 0, 0, "SWF_ILK0"},
> - /* Add additional register list */
> + COMMON_GEN12BASE_VEC(),
> };
>
> /* Per-Engine-Instance */
> struct __guc_mmio_reg_descr gen12lp_vec_inst_regs[] = {
> - {SWF_ILK(0), 0, 0, "SWF_ILK0"},
> - /* Add additional register list */
> + COMMON_GEN12BASE_ENGINE_INSTANCE(),
> +};
> +
> +/************* BLITTER ***********/
> +/* Per-Class */
> +struct __guc_mmio_reg_descr gen12lp_blt_class_regs[] = {
> +};
> +
> +/* Per-Engine-Instance */
> +struct __guc_mmio_reg_descr gen12lp_blt_inst_regs[] = {
> + COMMON_GEN12BASE_ENGINE_INSTANCE(),
> };
>
> +#define TO_GCAP_DEF(x) (GUC_CAPTURE_LIST_##x)
> +#define MAKE_GCAP_REGLIST_DESCR(regslist, regsowner, regstype, class) \
> + { \
> + .list = (regslist), \
> + .num_regs = (sizeof(regslist) / sizeof(struct __guc_mmio_reg_descr)), \
> + .owner = TO_GCAP_DEF(regsowner), \
> + .type = TO_GCAP_DEF(regstype), \
> + .engine = class, \
> + .num_ext = 0, \
> + .ext = NULL, \
> + }
> +
> +
> /********** List of lists **********/
> -struct __guc_mmio_reg_descr_group gen12lp_lists[] = {
> - {
> - .list = gen12lp_global_regs,
> - .num_regs = (sizeof(gen12lp_global_regs) / sizeof(struct __guc_mmio_reg_descr)),
> - .owner = GUC_CAPTURE_LIST_INDEX_PF,
> - .type = GUC_CAPTURE_LIST_TYPE_GLOBAL,
> - .engine = 0
> - },
> - {
> - .list = gen12lp_rc_class_regs,
> - .num_regs = (sizeof(gen12lp_rc_class_regs) / sizeof(struct __guc_mmio_reg_descr)),
> - .owner = GUC_CAPTURE_LIST_INDEX_PF,
> - .type = GUC_CAPTURE_LIST_TYPE_ENGINE_CLASS,
> - .engine = RENDER_CLASS
> - },
> - {
> - .list = gen12lp_rc_inst_regs,
> - .num_regs = (sizeof(gen12lp_rc_inst_regs) / sizeof(struct __guc_mmio_reg_descr)),
> - .owner = GUC_CAPTURE_LIST_INDEX_PF,
> - .type = GUC_CAPTURE_LIST_TYPE_ENGINE_INSTANCE,
> - .engine = RENDER_CLASS
> - },
> - {
> - .list = gen12lp_vd_class_regs,
> - .num_regs = (sizeof(gen12lp_vd_class_regs) / sizeof(struct __guc_mmio_reg_descr)),
> - .owner = GUC_CAPTURE_LIST_INDEX_PF,
> - .type = GUC_CAPTURE_LIST_TYPE_ENGINE_CLASS,
> - .engine = VIDEO_DECODE_CLASS
> - },
> - {
> - .list = gen12lp_vd_inst_regs,
> - .num_regs = (sizeof(gen12lp_vd_inst_regs) / sizeof(struct __guc_mmio_reg_descr)),
> - .owner = GUC_CAPTURE_LIST_INDEX_PF,
> - .type = GUC_CAPTURE_LIST_TYPE_ENGINE_INSTANCE,
> - .engine = VIDEO_DECODE_CLASS
> - },
> - {
> - .list = gen12lp_vec_class_regs,
> - .num_regs = (sizeof(gen12lp_vec_class_regs) / sizeof(struct __guc_mmio_reg_descr)),
> - .owner = GUC_CAPTURE_LIST_INDEX_PF,
> - .type = GUC_CAPTURE_LIST_TYPE_ENGINE_CLASS,
> - .engine = VIDEO_ENHANCEMENT_CLASS
> - },
> - {
> - .list = gen12lp_vec_inst_regs,
> - .num_regs = (sizeof(gen12lp_vec_inst_regs) / sizeof(struct __guc_mmio_reg_descr)),
> - .owner = GUC_CAPTURE_LIST_INDEX_PF,
> - .type = GUC_CAPTURE_LIST_TYPE_ENGINE_INSTANCE,
> - .engine = VIDEO_ENHANCEMENT_CLASS
> - },
> +struct __guc_mmio_reg_descr_group xe_lpd_lists[] = {
> + MAKE_GCAP_REGLIST_DESCR(gen12lp_global_regs, INDEX_PF, TYPE_GLOBAL, 0),
> + MAKE_GCAP_REGLIST_DESCR(gen12lp_rc_class_regs, INDEX_PF, TYPE_ENGINE_CLASS, GUC_RENDER_CLASS),
> + MAKE_GCAP_REGLIST_DESCR(gen12lp_rc_inst_regs, INDEX_PF, TYPE_ENGINE_INSTANCE, GUC_RENDER_CLASS),
> + MAKE_GCAP_REGLIST_DESCR(gen12lp_vd_class_regs, INDEX_PF, TYPE_ENGINE_CLASS, GUC_VIDEO_CLASS),
> + MAKE_GCAP_REGLIST_DESCR(gen12lp_vd_inst_regs, INDEX_PF, TYPE_ENGINE_INSTANCE, GUC_VIDEO_CLASS),
> + MAKE_GCAP_REGLIST_DESCR(gen12lp_vec_class_regs, INDEX_PF, TYPE_ENGINE_CLASS, GUC_VIDEOENHANCE_CLASS),
> + MAKE_GCAP_REGLIST_DESCR(gen12lp_vec_inst_regs, INDEX_PF, TYPE_ENGINE_INSTANCE, GUC_VIDEOENHANCE_CLASS),
> + MAKE_GCAP_REGLIST_DESCR(gen12lp_blt_class_regs, INDEX_PF, TYPE_ENGINE_CLASS, GUC_BLITTER_CLASS),
> + MAKE_GCAP_REGLIST_DESCR(gen12lp_blt_inst_regs, INDEX_PF, TYPE_ENGINE_INSTANCE, GUC_BLITTER_CLASS),
if you knew that you want to use macros, why not start with them in
previous patch ?
> {NULL, 0, 0, 0, 0}
> };
>
> -/************ FIXME: Populate tables for other devices in subsequent patch ************/
> +/************* Populate additional registers / device tables *************/
> +
> +static inline struct __guc_mmio_reg_descr **
> +guc_capture_get_ext_list_ptr(struct __guc_mmio_reg_descr_group * lists, u32 owner, u32 type, u32 class)
> +{
> + while(lists->list){
please run checkpatch.pl
> + if (lists->owner == owner && lists->type == type && lists->engine == class)
> + break;
> + ++lists;
> + }
> + if (!lists->list)
> + return NULL;
> +
> + return &(lists->ext);
> +}
> +
> +void guc_capture_clear_ext_regs(struct __guc_mmio_reg_descr_group * lists)
> +{
> + while(lists->list){
> + if (lists->ext) {
> + kfree(lists->ext);
> + lists->ext = NULL;
> + }
> + ++lists;
> + }
> + return;
> +}
> +
> +static void
> +xelpd_alloc_steered_ext_list(struct drm_i915_private *i915,
> + struct __guc_mmio_reg_descr_group * lists)
> +{
> + struct intel_gt *gt = &i915->gt;
> + struct sseu_dev_info *sseu;
> + int slice, subslice, i, num_tot_regs = 0;
> + struct __guc_mmio_reg_descr **ext;
> + static char * const strings[] = {
> + [0] = "GEN7_SAMPLER_INSTDONE",
> + [1] = "GEN7_ROW_INSTDONE",
> + };
> +
> + /* In XE_LP we only care about render-class steering registers during error-capture */
> + ext = guc_capture_get_ext_list_ptr(lists, GUC_CAPTURE_LIST_INDEX_PF,
> + GUC_CAPTURE_LIST_TYPE_ENGINE_CLASS, GUC_RENDER_CLASS);
> + if (!ext)
> + return;
> + if (*ext)
> + return; /* already populated */
> +
> + sseu = >->info.sseu;
> + for_each_instdone_slice_subslice(i915, sseu, slice, subslice) {
> + num_tot_regs += 2; /* two registers of interest for now */
> + }
> + if (!num_tot_regs)
> + return;
> +
> + *ext = kzalloc(2 * num_tot_regs * sizeof(struct __guc_mmio_reg_descr), GFP_KERNEL);
kcalloc ?
> + if (!*ext) {
> + drm_warn(&i915->drm, "GuC-capture: Fail to allocate for extended registers\n");
> + return;
> + }
> +
> + for_each_instdone_slice_subslice(i915, sseu, slice, subslice) {
> + for (i = 0; i < 2; i++) {
> + if (i == 0)
> + (*ext)->reg = GEN7_SAMPLER_INSTDONE;
> + else
> + (*ext)->reg = GEN7_ROW_INSTDONE;
> + (*ext)->flags = FIELD_PREP(GUC_REGSET_STEERING_GROUP, slice);
> + (*ext)->flags |= FIELD_PREP(GUC_REGSET_STEERING_INSTANCE, subslice);
> + (*ext)->regname = strings[i];
> + (*ext)++;
> + }
> + }
> +}
>
> static struct __guc_mmio_reg_descr_group *
> guc_capture_get_device_reglist(struct drm_i915_private *dev_priv)
> {
> if (IS_TIGERLAKE(dev_priv) || IS_ROCKETLAKE(dev_priv) ||
> IS_ALDERLAKE_S(dev_priv) || IS_ALDERLAKE_P(dev_priv)) {
> - return gen12lp_lists;
patch2: gen12lp_lists
patch3: xe_lpd_lists
please be consistent across series
> + /*
> + * For certain engine classes, there are slice and subslice
> + * level registers requiring steering. We allocate and populate
> + * these at init time based on hw config add it as an extension
> + * list at the end of the pre-populated render list.
> + */
> + xelpd_alloc_steered_ext_list(dev_priv, xe_lpd_lists);
> + return xe_lpd_lists;
> }
>
> return NULL;
> @@ -221,6 +346,7 @@ int intel_guc_capture_list_init(struct intel_guc *guc, u32 owner, u32 type, u32
>
> void intel_guc_capture_destroy(struct intel_guc *guc)
> {
> + guc_capture_clear_ext_regs(guc->capture.reglists);
> }
maybe whole function shall be introduced in this patch ?
-Michal
>
> int intel_guc_capture_init(struct intel_guc *guc)
> diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.h b/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.h
> index 352940b8bc87..df420f0f49b3 100644
> --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.h
> +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.h
> @@ -25,6 +25,8 @@ struct __guc_mmio_reg_descr_group {
> u32 owner; /* see enum guc_capture_owner */
> u32 type; /* see enum guc_capture_type */
> u32 engine; /* as per MAX_ENGINE_CLASS */
> + int num_ext;
> + struct __guc_mmio_reg_descr * ext;
> };
>
> struct intel_guc_state_capture {
> diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_fwif.h b/drivers/gpu/drm/i915/gt/uc/intel_guc_fwif.h
> index 1a1d2271c7e9..c26cfefd916c 100644
> --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_fwif.h
> +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_fwif.h
> @@ -267,6 +267,8 @@ struct guc_mmio_reg {
> u32 value;
> u32 flags;
> #define GUC_REGSET_MASKED (1 << 0)
> +#define GUC_REGSET_STEERING_GROUP GENMASK(15, 12)
> +#define GUC_REGSET_STEERING_INSTANCE GENMASK(23, 20)
> u32 mask;
> } __packed;
>
>
More information about the Intel-gfx
mailing list