[Intel-gfx] [PATCH v9 01/13] drm/i915/guc: Update GuC ADS size for error capture lists

Teres Alexis, Alan Previn alan.previn.teres.alexis at intel.com
Tue Mar 15 16:06:20 UTC 2022


Thanks Matt! :)

On 3/15/2022 8:17 AM, Matthew Brost wrote:
> On Mon, Mar 14, 2022 at 10:09:42AM -0700, Alan Previn wrote:
>> Update GuC ADS size allocation to include space for
>> the lists of error state capture register descriptors.
>>
>> Then, populate GuC ADS with the lists of registers we want
>> GuC to report back to host on engine reset events. This list
>> should include global, engine-class and engine-instance
>> registers for every engine-class type on the current hardware.
>>
>> Ensure we allocate a persistent store for the register lists
>> that are populated into ADS so that we don't need to allocate
>> memory during GT resets when GuC is reloaded and ADS population
>> happens again.
>>
>> NOTE: Start with a sample static table of register lists to
>> layout the framework before adding real registers in subsequent
>> patch. This static register tables are a different format from
>> the ADS populated list.
>>
>> Signed-off-by: Alan Previn <alan.previn.teres.alexis at intel.com>
> Reviewed-by: Matthew Brost <matthew.brost at intel.com>
>
>> ---
>>   drivers/gpu/drm/i915/Makefile                 |   1 +
>>   drivers/gpu/drm/i915/gt/uc/guc_capture_fwif.h |  91 +++++
>>   drivers/gpu/drm/i915/gt/uc/intel_guc.c        |  13 +-
>>   drivers/gpu/drm/i915/gt/uc/intel_guc.h        |   9 +-
>>   drivers/gpu/drm/i915/gt/uc/intel_guc_ads.c    | 125 +++++-
>>   .../gpu/drm/i915/gt/uc/intel_guc_capture.c    | 374 ++++++++++++++++++
>>   .../gpu/drm/i915/gt/uc/intel_guc_capture.h    |  22 ++
>>   drivers/gpu/drm/i915/gt/uc/intel_guc_fwif.h   |   8 +
>>   8 files changed, 626 insertions(+), 17 deletions(-)
>>   create mode 100644 drivers/gpu/drm/i915/gt/uc/guc_capture_fwif.h
>>   create mode 100644 drivers/gpu/drm/i915/gt/uc/intel_guc_capture.c
>>   create mode 100644 drivers/gpu/drm/i915/gt/uc/intel_guc_capture.h
>>
>> diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile
>> index 1a771ee5b1d0..69ada3b90a2c 100644
>> --- a/drivers/gpu/drm/i915/Makefile
>> +++ b/drivers/gpu/drm/i915/Makefile
>> @@ -184,6 +184,7 @@ i915-y += gt/uc/intel_uc.o \
>>   	  gt/uc/intel_uc_fw.o \
>>   	  gt/uc/intel_guc.o \
>>   	  gt/uc/intel_guc_ads.o \
>> +	  gt/uc/intel_guc_capture.o \
>>   	  gt/uc/intel_guc_ct.o \
>>   	  gt/uc/intel_guc_debugfs.o \
>>   	  gt/uc/intel_guc_fw.o \
>> diff --git a/drivers/gpu/drm/i915/gt/uc/guc_capture_fwif.h b/drivers/gpu/drm/i915/gt/uc/guc_capture_fwif.h
>> new file mode 100644
>> index 000000000000..919ed985f09a
>> --- /dev/null
>> +++ b/drivers/gpu/drm/i915/gt/uc/guc_capture_fwif.h
>> @@ -0,0 +1,91 @@
>> +/* SPDX-License-Identifier: MIT */
>> +/*
>> + * Copyright © 2021-2022 Intel Corporation
>> + */
>> +
>> +#ifndef _INTEL_GUC_CAPTURE_FWIF_H
>> +#define _INTEL_GUC_CAPTURE_FWIF_H
>> +
>> +#include <linux/types.h>
>> +#include "intel_guc_fwif.h"
>> +
>> +struct intel_guc;
>> +struct file;
>> +
>> +/**
>> + * struct guc_debug_capture_list_header / struct guc_debug_capture_list
>> + *
>> + * As part of ADS registration, these header structures (followed by
>> + * an array of 'struct guc_mmio_reg' entries) are used to register with
>> + * GuC microkernel the list of registers we want it to dump out prior
>> + * to a engine reset.
>> + */
>> +struct guc_debug_capture_list_header {
>> +	u32 info;
>> +#define GUC_CAPTURELISTHDR_NUMDESCR GENMASK(15, 0)
>> +} __packed;
>> +
>> +struct guc_debug_capture_list {
>> +	struct guc_debug_capture_list_header header;
>> +	struct guc_mmio_reg regs[0];
>> +} __packed;
>> +
>> +/**
>> + * struct __guc_mmio_reg_descr / struct __guc_mmio_reg_descr_group
>> + *
>> + * intel_guc_capture module uses these structures to maintain static
>> + * tables (per unique platform) that consists of lists of registers
>> + * (offsets, names, flags,...) that are used at the ADS regisration
>> + * time as well as during runtime processing and reporting of error-
>> + * capture states generated by GuC just prior to engine reset events.
>> + */
>> +struct __guc_mmio_reg_descr {
>> +	i915_reg_t reg;
>> +	u32 flags;
>> +	u32 mask;
>> +	const char *regname;
>> +};
>> +
>> +struct __guc_mmio_reg_descr_group {
>> +	const struct __guc_mmio_reg_descr *list;
>> +	u32 num_regs;
>> +	u32 owner; /* see enum guc_capture_owner */
>> +	u32 type; /* see enum guc_capture_type */
>> +	u32 engine; /* as per MAX_ENGINE_CLASS */
>> +};
>> +
>> +/**
>> + * struct __guc_capture_ads_cache
>> + *
>> + * A structure to cache register lists that were populated and registered
>> + * with GuC at startup during ADS registration. This allows much quicker
>> + * GuC resets without re-parsing all the tables for the given gt.
>> + */
>> +struct __guc_capture_ads_cache {
>> +	bool is_valid;
>> +	void *ptr;
>> +	size_t size;
>> +	int status;
>> +};
>> +
>> +/**
>> + * struct intel_guc_state_capture
>> + *
>> + * Internal context of the intel_guc_capture module.
>> + */
>> +struct intel_guc_state_capture {
>> +	/**
>> +	 * @reglists: static table of register lists used for error-capture state.
>> +	 */
>> +	const struct __guc_mmio_reg_descr_group *reglists;
>> +
>> +	/**
>> +	 * @ads_cache: cached register lists that is ADS format ready
>> +	 */
>> +	struct __guc_capture_ads_cache ads_cache[GUC_CAPTURE_LIST_INDEX_MAX]
>> +						[GUC_CAPTURE_LIST_TYPE_MAX]
>> +						[GUC_MAX_ENGINE_CLASSES];
>> +	void *ads_null_cache;
>> +};
>> +
>> +#endif /* _INTEL_GUC_CAPTURE_FWIF_H */
>> diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc.c b/drivers/gpu/drm/i915/gt/uc/intel_guc.c
>> index 447a976c9f25..cda7e4bb8bac 100644
>> --- a/drivers/gpu/drm/i915/gt/uc/intel_guc.c
>> +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc.c
>> @@ -9,8 +9,9 @@
>>   #include "gt/intel_gt_pm_irq.h"
>>   #include "gt/intel_gt_regs.h"
>>   #include "intel_guc.h"
>> -#include "intel_guc_slpc.h"
>>   #include "intel_guc_ads.h"
>> +#include "intel_guc_capture.h"
>> +#include "intel_guc_slpc.h"
>>   #include "intel_guc_submission.h"
>>   #include "i915_drv.h"
>>   #include "i915_irq.h"
>> @@ -362,9 +363,14 @@ int intel_guc_init(struct intel_guc *guc)
>>   	if (ret)
>>   		goto err_fw;
>>   
>> -	ret = intel_guc_ads_create(guc);
>> +	ret = intel_guc_capture_init(guc);
>>   	if (ret)
>>   		goto err_log;
>> +
>> +	ret = intel_guc_ads_create(guc);
>> +	if (ret)
>> +		goto err_capture;
>> +
>>   	GEM_BUG_ON(!guc->ads_vma);
>>   
>>   	ret = intel_guc_ct_init(&guc->ct);
>> @@ -403,6 +409,8 @@ int intel_guc_init(struct intel_guc *guc)
>>   	intel_guc_ct_fini(&guc->ct);
>>   err_ads:
>>   	intel_guc_ads_destroy(guc);
>> +err_capture:
>> +	intel_guc_capture_destroy(guc);
>>   err_log:
>>   	intel_guc_log_destroy(&guc->log);
>>   err_fw:
>> @@ -430,6 +438,7 @@ void intel_guc_fini(struct intel_guc *guc)
>>   	intel_guc_ct_fini(&guc->ct);
>>   
>>   	intel_guc_ads_destroy(guc);
>> +	intel_guc_capture_destroy(guc);
>>   	intel_guc_log_destroy(&guc->log);
>>   	intel_uc_fw_fini(&guc->fw);
>>   }
>> diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc.h b/drivers/gpu/drm/i915/gt/uc/intel_guc.h
>> index e439e6c1ac8b..de32367831c6 100644
>> --- a/drivers/gpu/drm/i915/gt/uc/intel_guc.h
>> +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc.h
>> @@ -10,18 +10,19 @@
>>   #include <linux/iosys-map.h>
>>   #include <linux/xarray.h>
>>   
>> -#include "intel_uncore.h"
>> +#include "intel_guc_ct.h"
>>   #include "intel_guc_fw.h"
>>   #include "intel_guc_fwif.h"
>> -#include "intel_guc_ct.h"
>>   #include "intel_guc_log.h"
>>   #include "intel_guc_reg.h"
>>   #include "intel_guc_slpc_types.h"
>>   #include "intel_uc_fw.h"
>> +#include "intel_uncore.h"
>>   #include "i915_utils.h"
>>   #include "i915_vma.h"
>>   
>>   struct __guc_ads_blob;
>> +struct intel_guc_state_capture;
>>   
>>   /**
>>    * struct intel_guc - Top level structure of GuC.
>> @@ -38,6 +39,8 @@ struct intel_guc {
>>   	struct intel_guc_ct ct;
>>   	/** @slpc: sub-structure containing SLPC related data and objects */
>>   	struct intel_guc_slpc slpc;
>> +	/** @capture: the error-state-capture module's data and objects */
>> +	struct intel_guc_state_capture *capture;
>>   
>>   	/** @sched_engine: Global engine used to submit requests to GuC */
>>   	struct i915_sched_engine *sched_engine;
>> @@ -162,6 +165,8 @@ struct intel_guc {
>>   	struct guc_mmio_reg *ads_regset;
>>   	/** @ads_golden_ctxt_size: size of the golden contexts in the ADS */
>>   	u32 ads_golden_ctxt_size;
>> +	/** @ads_capture_size: size of register lists in the ADS used for error capture */
>> +	u32 ads_capture_size;
>>   	/** @ads_engine_usage_size: size of engine usage in the ADS */
>>   	u32 ads_engine_usage_size;
>>   
>> diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_ads.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_ads.c
>> index acc4a3766dc1..4f1edf919971 100644
>> --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_ads.c
>> +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_ads.c
>> @@ -11,6 +11,7 @@
>>   #include "gt/intel_lrc.h"
>>   #include "gt/shmem_utils.h"
>>   #include "intel_guc_ads.h"
>> +#include "intel_guc_capture.h"
>>   #include "intel_guc_fwif.h"
>>   #include "intel_uc.h"
>>   #include "i915_drv.h"
>> @@ -86,8 +87,7 @@ static u32 guc_ads_golden_ctxt_size(struct intel_guc *guc)
>>   
>>   static u32 guc_ads_capture_size(struct intel_guc *guc)
>>   {
>> -	/* FIXME: Allocate a proper capture list */
>> -	return PAGE_ALIGN(PAGE_SIZE);
>> +	return PAGE_ALIGN(guc->ads_capture_size);
>>   }
>>   
>>   static u32 guc_ads_private_data_size(struct intel_guc *guc)
>> @@ -589,24 +589,117 @@ static void guc_init_golden_context(struct intel_guc *guc)
>>   	GEM_BUG_ON(guc->ads_golden_ctxt_size != total_size);
>>   }
>>   
>> -static void guc_capture_list_init(struct intel_guc *guc)
>> +static int
>> +guc_capture_prep_lists(struct intel_guc *guc)
>>   {
>> +	struct intel_gt *gt = guc_to_gt(guc);
>> +	struct drm_i915_private *i915 = guc_to_gt(guc)->i915;
>> +	u32 ads_ggtt, capture_offset, null_ggtt, total_size = 0;
>> +	struct guc_gt_system_info local_info;
>> +	struct iosys_map info_map;
>> +	bool ads_is_mapped;
>> +	size_t size = 0;
>> +	void *ptr;
>>   	int i, j;
>> -	u32 addr_ggtt, offset;
>>   
>> -	offset = guc_ads_capture_offset(guc);
>> -	addr_ggtt = intel_guc_ggtt_offset(guc, guc->ads_vma) + offset;
>> +	ads_is_mapped = !iosys_map_is_null(&guc->ads_map);
>> +	if (ads_is_mapped) {
>> +		capture_offset = guc_ads_capture_offset(guc);
>> +		ads_ggtt = intel_guc_ggtt_offset(guc, guc->ads_vma);
>> +		info_map = IOSYS_MAP_INIT_OFFSET(&guc->ads_map,
>> +						 offsetof(struct __guc_ads_blob, system_info));
>> +	} else {
>> +		memset(&local_info, 0, sizeof(local_info));
>> +		iosys_map_set_vaddr(&info_map, &local_info);
>> +		fill_engine_enable_masks(gt, &info_map);
>> +	}
>>   
>> -	/* FIXME: Populate a proper capture list */
>> +	/* first, set aside the first page for a capture_list with zero descriptors */
>> +	total_size = PAGE_SIZE;
>> +	if (ads_is_mapped) {
>> +		if (!intel_guc_capture_getnullheader(guc, &ptr, &size))
>> +			iosys_map_memcpy_to(&guc->ads_map, capture_offset, ptr, size);
>> +		null_ggtt = ads_ggtt + capture_offset;
>> +		capture_offset += PAGE_SIZE;
>> +	}
>>   
>>   	for (i = 0; i < GUC_CAPTURE_LIST_INDEX_MAX; i++) {
>>   		for (j = 0; j < GUC_MAX_ENGINE_CLASSES; j++) {
>> -			ads_blob_write(guc, ads.capture_instance[i][j], addr_ggtt);
>> -			ads_blob_write(guc, ads.capture_class[i][j], addr_ggtt);
>> -		}
>>   
>> -		ads_blob_write(guc, ads.capture_global[i], addr_ggtt);
>> +			/* null list if we dont have said engine or list */
>> +			if (!info_map_read(&info_map, engine_enabled_masks[j])) {
>> +				if (ads_is_mapped) {
>> +					ads_blob_write(guc, ads.capture_class[i][j], null_ggtt);
>> +					ads_blob_write(guc, ads.capture_instance[i][j], null_ggtt);
>> +				}
>> +				continue;
>> +			}
>> +			if (intel_guc_capture_getlistsize(guc, i,
>> +							  GUC_CAPTURE_LIST_TYPE_ENGINE_CLASS,
>> +							  j, &size)) {
>> +				if (ads_is_mapped)
>> +					ads_blob_write(guc, ads.capture_class[i][j], null_ggtt);
>> +				goto engine_instance_list;
>> +			}
>> +			total_size += size;
>> +			if (ads_is_mapped) {
>> +				if (total_size > guc->ads_capture_size ||
>> +				    intel_guc_capture_getlist(guc, i,
>> +							      GUC_CAPTURE_LIST_TYPE_ENGINE_CLASS,
>> +							      j, &ptr)) {
>> +					ads_blob_write(guc, ads.capture_class[i][j], null_ggtt);
>> +					continue;
>> +				}
>> +				ads_blob_write(guc, ads.capture_class[i][j], ads_ggtt + capture_offset);
>> +				iosys_map_memcpy_to(&guc->ads_map, capture_offset, ptr, size);
>> +				capture_offset += size;
>> +			}
>> +engine_instance_list:
>> +			if (intel_guc_capture_getlistsize(guc, i,
>> +							  GUC_CAPTURE_LIST_TYPE_ENGINE_INSTANCE,
>> +							  j, &size)) {
>> +				if (ads_is_mapped)
>> +					ads_blob_write(guc, ads.capture_instance[i][j], null_ggtt);
>> +				continue;
>> +			}
>> +			total_size += size;
>> +			if (ads_is_mapped) {
>> +				if (total_size > guc->ads_capture_size ||
>> +				    intel_guc_capture_getlist(guc, i,
>> +							      GUC_CAPTURE_LIST_TYPE_ENGINE_INSTANCE,
>> +							      j, &ptr)) {
>> +					ads_blob_write(guc, ads.capture_instance[i][j], null_ggtt);
>> +					continue;
>> +				}
>> +				ads_blob_write(guc, ads.capture_instance[i][j], ads_ggtt + capture_offset);
>> +				iosys_map_memcpy_to(&guc->ads_map, capture_offset, ptr, size);
>> +				capture_offset += size;
>> +			}
>> +		}
>> +		if (intel_guc_capture_getlistsize(guc, i, GUC_CAPTURE_LIST_TYPE_GLOBAL, 0, &size)) {
>> +			if (ads_is_mapped)
>> +				ads_blob_write(guc, ads.capture_global[i], null_ggtt);
>> +			continue;
>> +		}
>> +		total_size += size;
>> +		if (ads_is_mapped) {
>> +			if (total_size > guc->ads_capture_size ||
>> +			    intel_guc_capture_getlist(guc, i, GUC_CAPTURE_LIST_TYPE_GLOBAL, 0,
>> +						      &ptr)) {
>> +				ads_blob_write(guc, ads.capture_global[i], null_ggtt);
>> +				continue;
>> +			}
>> +			ads_blob_write(guc, ads.capture_global[i], ads_ggtt + capture_offset);
>> +			iosys_map_memcpy_to(&guc->ads_map, capture_offset, ptr, size);
>> +			capture_offset += size;
>> +		}
>>   	}
>> +
>> +	if (guc->ads_capture_size && guc->ads_capture_size != PAGE_ALIGN(total_size))
>> +		drm_warn(&i915->drm, "GuC->ADS->Capture alloc size changed from %d to %d\n",
>> +			 guc->ads_capture_size, PAGE_ALIGN(total_size));
>> +
>> +	return PAGE_ALIGN(total_size);
>>   }
>>   
>>   static void __guc_ads_init(struct intel_guc *guc)
>> @@ -644,8 +737,8 @@ static void __guc_ads_init(struct intel_guc *guc)
>>   
>>   	base = intel_guc_ggtt_offset(guc, guc->ads_vma);
>>   
>> -	/* Capture list for hang debug */
>> -	guc_capture_list_init(guc);
>> +	/* Lists for error capture debug */
>> +	guc_capture_prep_lists(guc);
>>   
>>   	/* ADS */
>>   	ads_blob_write(guc, ads.scheduler_policies, base +
>> @@ -693,6 +786,12 @@ int intel_guc_ads_create(struct intel_guc *guc)
>>   		return ret;
>>   	guc->ads_golden_ctxt_size = ret;
>>   
>> +	/* Likewise the capture lists: */
>> +	ret = guc_capture_prep_lists(guc);
>> +	if (ret < 0)
>> +		return ret;
>> +	guc->ads_capture_size = ret;
>> +
>>   	/* Now the total size can be determined: */
>>   	size = guc_ads_blob_size(guc);
>>   
>> diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.c
>> new file mode 100644
>> index 000000000000..b8bbde01e5b1
>> --- /dev/null
>> +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.c
>> @@ -0,0 +1,374 @@
>> +// SPDX-License-Identifier: MIT
>> +/*
>> + * Copyright © 2021-2022 Intel Corporation
>> + */
>> +
>> +#include <linux/types.h>
>> +
>> +#include <drm/drm_print.h>
>> +
>> +#include "gt/intel_engine_regs.h"
>> +#include "gt/intel_gt.h"
>> +#include "gt/intel_gt_regs.h"
>> +#include "guc_capture_fwif.h"
>> +#include "intel_guc_capture.h"
>> +#include "intel_guc_fwif.h"
>> +#include "i915_drv.h"
>> +#include "i915_memcpy.h"
>> +#include "i915_reg.h"
>> +
>> +/*
>> + * 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
>> + */
>> +/* XE_LPD - Global */
>> +static const struct __guc_mmio_reg_descr xe_lpd_global_regs[] = {
>> +	{GEN12_RING_FAULT_REG,     0,      0, "GEN12_RING_FAULT_REG"}
>> +};
>> +
>> +/* XE_LPD - Render / Compute Per-Class */
>> +static const struct __guc_mmio_reg_descr xe_lpd_rc_class_regs[] = {
>> +	{EIR,                      0,      0, "EIR"}
>> +};
>> +
>> +/* XE_LPD - Render / Compute Per-Engine-Instance */
>> +static const struct __guc_mmio_reg_descr xe_lpd_rc_inst_regs[] = {
>> +	{RING_HEAD(0),             0,      0, "RING_HEAD"},
>> +	{RING_TAIL(0),             0,      0, "RING_TAIL"},
>> +};
>> +
>> +/* XE_LPD - Media Decode/Encode Per-Class */
>> +static const struct __guc_mmio_reg_descr xe_lpd_vd_class_regs[] = {
>> +};
>> +
>> +/* XE_LPD - Media Decode/Encode Per-Engine-Instance */
>> +static const struct __guc_mmio_reg_descr xe_lpd_vd_inst_regs[] = {
>> +	{RING_HEAD(0),             0,      0, "RING_HEAD"},
>> +	{RING_TAIL(0),             0,      0, "RING_TAIL"},
>> +};
>> +
>> +/* XE_LPD - Video Enhancement Per-Class */
>> +static const struct __guc_mmio_reg_descr xe_lpd_vec_class_regs[] = {
>> +};
>> +
>> +/* XE_LPD - Video Enhancement Per-Engine-Instance */
>> +static const struct __guc_mmio_reg_descr xe_lpd_vec_inst_regs[] = {
>> +	{RING_HEAD(0),             0,      0, "RING_HEAD"},
>> +	{RING_TAIL(0),             0,      0, "RING_TAIL"},
>> +};
>> +
>> +#define TO_GCAP_DEF_OWNER(x) (GUC_CAPTURE_LIST_INDEX_##x)
>> +#define TO_GCAP_DEF_TYPE(x) (GUC_CAPTURE_LIST_TYPE_##x)
>> +#define MAKE_REGLIST(regslist, regsowner, regstype, class) \
>> +	{ \
>> +		regslist, \
>> +		ARRAY_SIZE(regslist), \
>> +		TO_GCAP_DEF_OWNER(regsowner), \
>> +		TO_GCAP_DEF_TYPE(regstype), \
>> +		class, \
>> +	}
>> +
>> +/* List of lists */
>> +static const struct __guc_mmio_reg_descr_group xe_lpd_lists[] = {
>> +	MAKE_REGLIST(xe_lpd_global_regs, PF, GLOBAL, 0),
>> +	MAKE_REGLIST(xe_lpd_rc_class_regs, PF, ENGINE_CLASS, GUC_RENDER_CLASS),
>> +	MAKE_REGLIST(xe_lpd_rc_inst_regs, PF, ENGINE_INSTANCE, GUC_RENDER_CLASS),
>> +	MAKE_REGLIST(xe_lpd_vd_class_regs, PF, ENGINE_CLASS, GUC_VIDEO_CLASS),
>> +	MAKE_REGLIST(xe_lpd_vd_inst_regs, PF, ENGINE_INSTANCE, GUC_VIDEO_CLASS),
>> +	MAKE_REGLIST(xe_lpd_vec_class_regs, PF, ENGINE_CLASS, GUC_VIDEOENHANCE_CLASS),
>> +	MAKE_REGLIST(xe_lpd_vec_inst_regs, PF, ENGINE_INSTANCE, GUC_VIDEOENHANCE_CLASS),
>> +	{}
>> +};
>> +
>> +static const struct __guc_mmio_reg_descr_group *
>> +guc_capture_get_device_reglist(struct intel_guc *guc)
>> +{
>> +	struct drm_i915_private *i915 = guc_to_gt(guc)->i915;
>> +
>> +	if (IS_TIGERLAKE(i915) || IS_ROCKETLAKE(i915) ||
>> +	    IS_ALDERLAKE_S(i915) || IS_ALDERLAKE_P(i915)) {
>> +		return xe_lpd_lists;
>> +	}
>> +
>> +	return NULL;
>> +}
>> +
>> +static const struct __guc_mmio_reg_descr_group *
>> +guc_capture_get_one_list(const struct __guc_mmio_reg_descr_group *reglists,
>> +			 u32 owner, u32 type, u32 id)
>> +{
>> +	int i;
>> +
>> +	if (!reglists)
>> +		return NULL;
>> +
>> +	for (i = 0; reglists[i].list; ++i) {
>> +		if (reglists[i].owner == owner && reglists[i].type == type &&
>> +		    (reglists[i].engine == id || reglists[i].type == GUC_CAPTURE_LIST_TYPE_GLOBAL))
>> +		return &reglists[i];
>> +	}
>> +
>> +	return NULL;
>> +}
>> +
>> +static const char *
>> +__stringify_owner(u32 owner)
>> +{
>> +	switch (owner) {
>> +	case GUC_CAPTURE_LIST_INDEX_PF:
>> +		return "PF";
>> +	case GUC_CAPTURE_LIST_INDEX_VF:
>> +		return "VF";
>> +	default:
>> +		return "unknown";
>> +	}
>> +
>> +	return "";
>> +}
>> +
>> +static const char *
>> +__stringify_type(u32 type)
>> +{
>> +	switch (type) {
>> +	case GUC_CAPTURE_LIST_TYPE_GLOBAL:
>> +		return "Global";
>> +	case GUC_CAPTURE_LIST_TYPE_ENGINE_CLASS:
>> +		return "Class";
>> +	case GUC_CAPTURE_LIST_TYPE_ENGINE_INSTANCE:
>> +		return "Instance";
>> +	default:
>> +		return "unknown";
>> +	}
>> +
>> +	return "";
>> +}
>> +
>> +static const char *
>> +__stringify_engclass(u32 class)
>> +{
>> +	switch (class) {
>> +	case GUC_RENDER_CLASS:
>> +		return "Render";
>> +	case GUC_VIDEO_CLASS:
>> +		return "Video";
>> +	case GUC_VIDEOENHANCE_CLASS:
>> +		return "VideoEnhance";
>> +	case GUC_BLITTER_CLASS:
>> +		return "Blitter";
>> +	case GUC_COMPUTE_CLASS:
>> +		return "Compute";
>> +	default:
>> +		return "unknown";
>> +	}
>> +
>> +	return "";
>> +}
>> +
>> +static void
>> +guc_capture_warn_with_list_info(struct drm_i915_private *i915, char *msg,
>> +				u32 owner, u32 type, u32 classid)
>> +{
>> +	if (type == GUC_CAPTURE_LIST_TYPE_GLOBAL)
>> +		drm_dbg(&i915->drm, "GuC-capture: %s for %s %s-Registers.\n", msg,
>> +			__stringify_owner(owner), __stringify_type(type));
>> +	else
>> +		drm_dbg(&i915->drm, "GuC-capture: %s for %s %s-Registers on %s-Engine\n", msg,
>> +			__stringify_owner(owner), __stringify_type(type),
>> +			__stringify_engclass(classid));
>> +}
>> +
>> +static int
>> +guc_capture_list_init(struct intel_guc *guc, u32 owner, u32 type, u32 classid,
>> +		      struct guc_mmio_reg *ptr, u16 num_entries)
>> +{
>> +	u32 i = 0;
>> +	struct drm_i915_private *i915 = guc_to_gt(guc)->i915;
>> +	const struct __guc_mmio_reg_descr_group *reglists = guc->capture->reglists;
>> +	const struct __guc_mmio_reg_descr_group *match;
>> +
>> +	if (!reglists)
>> +		return -ENODEV;
>> +
>> +	match = guc_capture_get_one_list(reglists, owner, type, classid);
>> +	if (match) {
>> +		for (i = 0; i < num_entries && i < match->num_regs; ++i) {
>> +			ptr[i].offset = match->list[i].reg.reg;
>> +			ptr[i].value = 0xDEADF00D;
>> +			ptr[i].flags = match->list[i].flags;
>> +			ptr[i].mask = match->list[i].mask;
>> +		}
>> +		return 0;
>> +	}
>> +
>> +	guc_capture_warn_with_list_info(i915, "Missing register list init", owner, type,
>> +					classid);
>> +
>> +	return -ENODATA;
>> +}
>> +
>> +static int
>> +guc_cap_list_num_regs(struct intel_guc_state_capture *gc, u32 owner, u32 type, u32 classid)
>> +{
>> +	const struct __guc_mmio_reg_descr_group *match;
>> +
>> +	match = guc_capture_get_one_list(gc->reglists, owner, type, classid);
>> +	if (!match)
>> +		return 0;
>> +
>> +	return match->num_regs;
>> +}
>> +
>> +int
>> +intel_guc_capture_getlistsize(struct intel_guc *guc, u32 owner, u32 type, u32 classid,
>> +			      size_t *size)
>> +{
>> +	struct drm_i915_private *i915 = guc_to_gt(guc)->i915;
>> +	struct intel_guc_state_capture *gc = guc->capture;
>> +	struct __guc_capture_ads_cache *cache = &gc->ads_cache[owner][type][classid];
>> +	int num_regs;
>> +
>> +	if (!gc->reglists)
>> +		return -ENODEV;
>> +
>> +	if (cache->is_valid) {
>> +		*size = cache->size;
>> +		return cache->status;
>> +	}
>> +
>> +	num_regs = guc_cap_list_num_regs(gc, owner, type, classid);
>> +	if (!num_regs) {
>> +		guc_capture_warn_with_list_info(i915, "Missing register list size",
>> +						owner, type, classid);
>> +		return -ENODATA;
>> +	}
>> +
>> +	*size = PAGE_ALIGN((sizeof(struct guc_debug_capture_list)) +
>> +			   (num_regs * sizeof(struct guc_mmio_reg)));
>> +
>> +	return 0;
>> +}
>> +
>> +int
>> +intel_guc_capture_getlist(struct intel_guc *guc, u32 owner, u32 type, u32 classid,
>> +			  void **outptr)
>> +{
>> +	struct intel_guc_state_capture *gc = guc->capture;
>> +	struct __guc_capture_ads_cache *cache = &gc->ads_cache[owner][type][classid];
>> +	struct drm_i915_private *i915 = guc_to_gt(guc)->i915;
>> +	struct guc_debug_capture_list *listnode;
>> +	int ret, num_regs;
>> +	u8 *caplist, *tmp;
>> +	size_t size = 0;
>> +
>> +	if (!gc->reglists)
>> +		return -ENODEV;
>> +
>> +	if (cache->is_valid) {
>> +		*outptr = cache->ptr;
>> +		return cache->status;
>> +	}
>> +
>> +	ret = intel_guc_capture_getlistsize(guc, owner, type, classid, &size);
>> +	if (ret) {
>> +		cache->is_valid = true;
>> +		cache->ptr = NULL;
>> +		cache->size = 0;
>> +		cache->status = ret;
>> +		return ret;
>> +	}
>> +
>> +	caplist = kzalloc(size, GFP_KERNEL);
>> +	if (!caplist) {
>> +		drm_dbg(&i915->drm, "GuC-capture: failed to alloc cached caplist");
>> +		return -ENOMEM;
>> +	}
>> +
>> +	/* populate capture list header */
>> +	tmp = caplist;
>> +	num_regs = guc_cap_list_num_regs(guc->capture, owner, type, classid);
>> +	listnode = (struct guc_debug_capture_list *)tmp;
>> +	listnode->header.info = FIELD_PREP(GUC_CAPTURELISTHDR_NUMDESCR, (u32)num_regs);
>> +
>> +	/* populate list of register descriptor */
>> +	tmp += sizeof(struct guc_debug_capture_list);
>> +	guc_capture_list_init(guc, owner, type, classid, (struct guc_mmio_reg *)tmp, num_regs);
>> +
>> +	/* cache this list */
>> +	cache->is_valid = true;
>> +	cache->ptr = caplist;
>> +	cache->size = size;
>> +	cache->status = 0;
>> +
>> +	*outptr = caplist;
>> +
>> +	return 0;
>> +}
>> +
>> +int
>> +intel_guc_capture_getnullheader(struct intel_guc *guc,
>> +				void **outptr, size_t *size)
>> +{
>> +	struct intel_guc_state_capture *gc = guc->capture;
>> +	struct drm_i915_private *i915 = guc_to_gt(guc)->i915;
>> +	int tmp = sizeof(u32) * 4;
>> +	void *null_header;
>> +
>> +	if (gc->ads_null_cache) {
>> +		*outptr = gc->ads_null_cache;
>> +		*size = tmp;
>> +		return 0;
>> +	}
>> +
>> +	null_header = kzalloc(tmp, GFP_KERNEL);
>> +	if (!null_header) {
>> +		drm_dbg(&i915->drm, "GuC-capture: failed to alloc cached nulllist");
>> +		return -ENOMEM;
>> +	}
>> +
>> +	gc->ads_null_cache = null_header;
>> +	*outptr = null_header;
>> +	*size = tmp;
>> +
>> +	return 0;
>> +}
>> +
>> +static void
>> +guc_capture_free_ads_cache(struct intel_guc_state_capture *gc)
>> +{
>> +	int i, j, k;
>> +	struct __guc_capture_ads_cache *cache;
>> +
>> +	for (i = 0; i < GUC_CAPTURE_LIST_INDEX_MAX; ++i) {
>> +		for (j = 0; j < GUC_CAPTURE_LIST_TYPE_MAX; ++j) {
>> +			for (k = 0; k < GUC_MAX_ENGINE_CLASSES; ++k) {
>> +				cache = &gc->ads_cache[i][j][k];
>> +				if (cache->is_valid)
>> +					kfree(cache->ptr);
>> +			}
>> +		}
>> +	}
>> +	kfree(gc->ads_null_cache);
>> +}
>> +
>> +void intel_guc_capture_destroy(struct intel_guc *guc)
>> +{
>> +	if (!guc->capture)
>> +		return;
>> +
>> +	guc_capture_free_ads_cache(guc->capture);
>> +
>> +	kfree(guc->capture);
>> +	guc->capture = NULL;
>> +}
>> +
>> +int intel_guc_capture_init(struct intel_guc *guc)
>> +{
>> +	guc->capture = kzalloc(sizeof(*guc->capture), GFP_KERNEL);
>> +	if (!guc->capture)
>> +		return -ENOMEM;
>> +
>> +	guc->capture->reglists = guc_capture_get_device_reglist(guc);
>> +
>> +	return 0;
>> +}
>> diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.h b/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.h
>> new file mode 100644
>> index 000000000000..8de7704e12eb
>> --- /dev/null
>> +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.h
>> @@ -0,0 +1,22 @@
>> +/* SPDX-License-Identifier: MIT */
>> +/*
>> + * Copyright © 2021-2021 Intel Corporation
>> + */
>> +
>> +#ifndef _INTEL_GUC_CAPTURE_H
>> +#define _INTEL_GUC_CAPTURE_H
>> +
>> +#include <linux/types.h>
>> +
>> +struct guc_gt_system_info;
>> +struct intel_guc;
>> +
>> +int intel_guc_capture_getlist(struct intel_guc *guc, u32 owner, u32 type, u32 classid,
>> +			      void **outptr);
>> +int intel_guc_capture_getlistsize(struct intel_guc *guc, u32 owner, u32 type, u32 classid,
>> +				  size_t *size);
>> +int intel_guc_capture_getnullheader(struct intel_guc *guc, void **outptr, size_t *size);
>> +void intel_guc_capture_destroy(struct intel_guc *guc);
>> +int intel_guc_capture_init(struct intel_guc *guc);
>> +
>> +#endif /* _INTEL_GUC_CAPTURE_H */
>> 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 a4a6136b3616..a1fe4231bb58 100644
>> --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_fwif.h
>> +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_fwif.h
>> @@ -311,6 +311,14 @@ enum {
>>   	GUC_CAPTURE_LIST_INDEX_MAX = 2,
>>   };
>>   
>> +/*Register-types of GuC capture register lists */
>> +enum guc_capture_type {
>> +	GUC_CAPTURE_LIST_TYPE_GLOBAL = 0,
>> +	GUC_CAPTURE_LIST_TYPE_ENGINE_CLASS,
>> +	GUC_CAPTURE_LIST_TYPE_ENGINE_INSTANCE,
>> +	GUC_CAPTURE_LIST_TYPE_MAX,
>> +};
>> +
>>   /* GuC Additional Data Struct */
>>   struct guc_ads {
>>   	struct guc_mmio_reg_set reg_state_list[GUC_MAX_ENGINE_CLASSES][GUC_MAX_INSTANCES_PER_CLASS];
>> -- 
>> 2.25.1
>>


More information about the Intel-gfx mailing list