[Intel-gfx] [PATCH v3 08/19] drm/i915/guc: Update GuC ADS object definition
Daniele Ceraolo Spurio
daniele.ceraolospurio at intel.com
Wed Apr 17 17:37:19 UTC 2019
On 4/16/19 10:39 PM, Michal Wajdeczko wrote:
> New GuC firmwares use updated definitions for the Additional Data
> Structures (ADS).
>
> v2: add note about Gen9 definition mismatch (Daniele)
> rename __intel_engine_context_size (Daniele)
>
> Signed-off-by: Michal Wajdeczko <michal.wajdeczko at intel.com>
> Signed-off-by: Daniele Ceraolo Spurio <daniele.ceraolospurio at intel.com>
> Signed-off-by: Fernando Pacheco <fernando.pacheco at intel.com>
> Cc: Joonas Lahtinen <joonas.lahtinen at linux.intel.com>
> Cc: John Spotswood <john.a.spotswood at intel.com>
> Cc: Tomasz Lis <tomasz.lis at intel.com>
Reviewed-by: Daniele Ceraolo Spurio <daniele.ceraolospurio at intel.com>
> ---
> drivers/gpu/drm/i915/intel_engine_cs.c | 9 ++-
> drivers/gpu/drm/i915/intel_guc_ads.c | 95 +++++++++++++++----------
> drivers/gpu/drm/i915/intel_guc_fwif.h | 94 ++++++++++++++----------
> drivers/gpu/drm/i915/intel_ringbuffer.h | 2 +
> 4 files changed, 122 insertions(+), 78 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/intel_engine_cs.c b/drivers/gpu/drm/i915/intel_engine_cs.c
> index eea9bec04f1b..5255e3ef81d4 100644
> --- a/drivers/gpu/drm/i915/intel_engine_cs.c
> +++ b/drivers/gpu/drm/i915/intel_engine_cs.c
> @@ -165,7 +165,7 @@ static const struct engine_info intel_engines[] = {
> };
>
> /**
> - * ___intel_engine_context_size() - return the size of the context for an engine
> + * intel_engine_context_size() - return the size of the context for an engine
> * @dev_priv: i915 device private
> * @class: engine class
> *
> @@ -178,8 +178,7 @@ static const struct engine_info intel_engines[] = {
> * in LRC mode, but does not include the "shared data page" used with
> * GuC submission. The caller should account for this if using the GuC.
> */
> -static u32
> -__intel_engine_context_size(struct drm_i915_private *dev_priv, u8 class)
> +u32 intel_engine_context_size(struct drm_i915_private *dev_priv, u8 class)
> {
> u32 cxt_size;
>
> @@ -314,8 +313,8 @@ intel_engine_setup(struct drm_i915_private *dev_priv,
>
> engine->uabi_class = intel_engine_classes[info->class].uabi_class;
>
> - engine->context_size = __intel_engine_context_size(dev_priv,
> - engine->class);
> + engine->context_size = intel_engine_context_size(dev_priv,
> + engine->class);
> if (WARN_ON(engine->context_size > BIT(20)))
> engine->context_size = 0;
> if (engine->context_size)
> diff --git a/drivers/gpu/drm/i915/intel_guc_ads.c b/drivers/gpu/drm/i915/intel_guc_ads.c
> index bec62f34b15a..1aa1ec0ff4a1 100644
> --- a/drivers/gpu/drm/i915/intel_guc_ads.c
> +++ b/drivers/gpu/drm/i915/intel_guc_ads.c
> @@ -51,7 +51,7 @@ static void guc_policies_init(struct guc_policies *policies)
> policies->max_num_work_items = POLICY_MAX_NUM_WI;
>
> for (p = 0; p < GUC_CLIENT_PRIORITY_NUM; p++) {
> - for (i = GUC_RENDER_ENGINE; i < GUC_MAX_ENGINES_NUM; i++) {
> + for (i = 0; i < GUC_MAX_ENGINE_CLASSES; i++) {
> policy = &policies->policy[p][i];
>
> guc_policy_init(policy);
> @@ -61,6 +61,11 @@ static void guc_policies_init(struct guc_policies *policies)
> policies->is_valid = 1;
> }
>
> +static void guc_ct_pool_entries_init(struct guc_ct_pool_entry *pool, u32 num)
> +{
> + memset(pool, 0, num * sizeof(*pool));
> +}
> +
> /*
> * The first 80 dwords of the register state context, containing the
> * execlists and ppgtt registers.
> @@ -75,20 +80,21 @@ static void guc_policies_init(struct guc_policies *policies)
> int intel_guc_ads_create(struct intel_guc *guc)
> {
> struct drm_i915_private *dev_priv = guc_to_i915(guc);
> - struct i915_vma *vma, *kernel_ctx_vma;
> - struct page *page;
> + struct i915_vma *vma;
> /* The ads obj includes the struct itself and buffers passed to GuC */
> struct {
> struct guc_ads ads;
> struct guc_policies policies;
> struct guc_mmio_reg_state reg_state;
> + struct guc_gt_system_info system_info;
> + struct guc_clients_info clients_info;
> + struct guc_ct_pool_entry ct_pool[GUC_CT_POOL_SIZE];
> u8 reg_state_buffer[GUC_S3_SAVE_SPACE_PAGES * PAGE_SIZE];
> } __packed *blob;
> - struct intel_engine_cs *engine;
> - enum intel_engine_id id;
> - const u32 skipped_offset = LRC_HEADER_PAGES * PAGE_SIZE;
> const u32 skipped_size = LRC_PPHWSP_SZ * PAGE_SIZE + LR_HW_CONTEXT_SIZE;
> u32 base;
> + u8 engine_class;
> + int ret;
>
> GEM_BUG_ON(guc->ads_vma);
>
> @@ -98,51 +104,68 @@ int intel_guc_ads_create(struct intel_guc *guc)
>
> guc->ads_vma = vma;
>
> - page = i915_vma_first_page(vma);
> - blob = kmap(page);
> + blob = i915_gem_object_pin_map(guc->ads_vma->obj, I915_MAP_WB);
> + if (IS_ERR(blob)) {
> + ret = PTR_ERR(blob);
> + goto err_vma;
> + }
>
> /* GuC scheduling policies */
> guc_policies_init(&blob->policies);
>
> - /* MMIO reg state */
> - for_each_engine(engine, dev_priv, id) {
> - blob->reg_state.white_list[engine->guc_id].mmio_start =
> - engine->mmio_base + GUC_MMIO_WHITE_LIST_START;
> -
> - /* Nothing to be saved or restored for now. */
> - blob->reg_state.white_list[engine->guc_id].count = 0;
> - }
> -
> /*
> - * The GuC requires a "Golden Context" when it reinitialises
> - * engines after a reset. Here we use the Render ring default
> - * context, which must already exist and be pinned in the GGTT,
> - * so its address won't change after we've told the GuC where
> - * to find it. Note that we have to skip our header (1 page),
> - * because our GuC shared data is there.
> + * GuC expects a per-engine-class context image and size
> + * (minus hwsp and ring context). The context image will be
> + * used to reinitialize engines after a reset. It must exist
> + * and be pinned in the GGTT, so that the address won't change after
> + * we have told GuC where to find it. The context size will be used
> + * to validate that the LRC base + size fall within allowed GGTT.
> */
> - kernel_ctx_vma = dev_priv->engine[RCS0]->kernel_context->state;
> - blob->ads.golden_context_lrca =
> - intel_guc_ggtt_offset(guc, kernel_ctx_vma) + skipped_offset;
> + for (engine_class = 0; engine_class <= MAX_ENGINE_CLASS; ++engine_class) {
> + if (engine_class == OTHER_CLASS)
> + continue;
> + /*
> + * TODO: Set context pointer to default state to allow
> + * GuC to re-init guilty contexts after internal reset.
> + */
> + blob->ads.golden_context_lrca[engine_class] = 0;
> + blob->ads.eng_state_size[engine_class] =
> + intel_engine_context_size(dev_priv, engine_class) -
> + skipped_size;
> + }
>
> - /*
> - * The GuC expects us to exclude the portion of the context image that
> - * it skips from the size it is to read. It starts reading from after
> - * the execlist context (so skipping the first page [PPHWSP] and 80
> - * dwords). Weird guc is weird.
> - */
> - for_each_engine(engine, dev_priv, id)
> - blob->ads.eng_state_size[engine->guc_id] =
> - engine->context_size - skipped_size;
> + /* System info */
> + blob->system_info.slice_enabled = hweight8(RUNTIME_INFO(dev_priv)->sseu.slice_mask);
> + blob->system_info.rcs_enabled = 1;
> + blob->system_info.bcs_enabled = 1;
> +
> + blob->system_info.vdbox_enable_mask = VDBOX_MASK(dev_priv);
> + blob->system_info.vebox_enable_mask = VEBOX_MASK(dev_priv);
> + blob->system_info.vdbox_sfc_support_mask = RUNTIME_INFO(dev_priv)->vdbox_sfc_access;
>
> base = intel_guc_ggtt_offset(guc, vma);
> +
> + /* Clients info */
> + guc_ct_pool_entries_init(blob->ct_pool, ARRAY_SIZE(blob->ct_pool));
> +
> + blob->clients_info.clients_num = 1;
> + blob->clients_info.ct_pool_addr = base + ptr_offset(blob, ct_pool);
> + blob->clients_info.ct_pool_count = ARRAY_SIZE(blob->ct_pool);
> +
> + /* ADS */
> blob->ads.scheduler_policies = base + ptr_offset(blob, policies);
> blob->ads.reg_state_buffer = base + ptr_offset(blob, reg_state_buffer);
> blob->ads.reg_state_addr = base + ptr_offset(blob, reg_state);
> + blob->ads.gt_system_info = base + ptr_offset(blob, system_info);
> + blob->ads.clients_info = base + ptr_offset(blob, clients_info);
>
> - kunmap(page);
> + i915_gem_object_unpin_map(guc->ads_vma->obj);
>
> return 0;
> +
> +err_vma:
> + i915_vma_unpin_and_release(&guc->ads_vma, 0);
> + return ret;
> }
>
> void intel_guc_ads_destroy(struct intel_guc *guc)
> diff --git a/drivers/gpu/drm/i915/intel_guc_fwif.h b/drivers/gpu/drm/i915/intel_guc_fwif.h
> index 9b4436acba17..fa745a58d38d 100644
> --- a/drivers/gpu/drm/i915/intel_guc_fwif.h
> +++ b/drivers/gpu/drm/i915/intel_guc_fwif.h
> @@ -39,6 +39,14 @@
> #define GUC_VIDEO_ENGINE2 4
> #define GUC_MAX_ENGINES_NUM (GUC_VIDEO_ENGINE2 + 1)
>
> +/*
> + * XXX: Beware that Gen9 firmware 32.x uses wrong definition for
> + * GUC_MAX_INSTANCES_PER_CLASS (1) but this is harmless for us now
> + * as we are not enabling GuC submission mode where this will be used
> + */
> +#define GUC_MAX_ENGINE_CLASSES 5
> +#define GUC_MAX_INSTANCES_PER_CLASS 4
> +
> #define GUC_DOORBELL_INVALID 256
>
> #define GUC_DB_SIZE (PAGE_SIZE)
> @@ -386,23 +394,19 @@ struct guc_ct_buffer_desc {
> struct guc_policy {
> /* Time for one workload to execute. (in micro seconds) */
> u32 execution_quantum;
> - u32 reserved1;
> -
> /* Time to wait for a preemption request to completed before issuing a
> * reset. (in micro seconds). */
> u32 preemption_time;
> -
> /* How much time to allow to run after the first fault is observed.
> * Then preempt afterwards. (in micro seconds) */
> u32 fault_time;
> -
> u32 policy_flags;
> - u32 reserved[2];
> + u32 reserved[8];
> } __packed;
>
> struct guc_policies {
> - struct guc_policy policy[GUC_CLIENT_PRIORITY_NUM][GUC_MAX_ENGINES_NUM];
> -
> + struct guc_policy policy[GUC_CLIENT_PRIORITY_NUM][GUC_MAX_ENGINE_CLASSES];
> + u32 submission_queue_depth[GUC_MAX_ENGINE_CLASSES];
> /* In micro seconds. How much time to allow before DPC processing is
> * called back via interrupt (to prevent DPC queue drain starving).
> * Typically 1000s of micro seconds (example only, not granularity). */
> @@ -415,57 +419,73 @@ struct guc_policies {
> * idle. */
> u32 max_num_work_items;
>
> - u32 reserved[19];
> + u32 reserved[4];
> } __packed;
>
> /* GuC MMIO reg state struct */
>
> -#define GUC_REGSET_FLAGS_NONE 0x0
> -#define GUC_REGSET_POWERCYCLE 0x1
> -#define GUC_REGSET_MASKED 0x2
> -#define GUC_REGSET_ENGINERESET 0x4
> -#define GUC_REGSET_SAVE_DEFAULT_VALUE 0x8
> -#define GUC_REGSET_SAVE_CURRENT_VALUE 0x10
>
> -#define GUC_REGSET_MAX_REGISTERS 25
> -#define GUC_MMIO_WHITE_LIST_START 0x24d0
> -#define GUC_MMIO_WHITE_LIST_MAX 12
> +#define GUC_REGSET_MAX_REGISTERS 64
> #define GUC_S3_SAVE_SPACE_PAGES 10
>
> -struct guc_mmio_regset {
> - struct __packed {
> - u32 offset;
> - u32 value;
> - u32 flags;
> - } registers[GUC_REGSET_MAX_REGISTERS];
> +struct guc_mmio_reg {
> + u32 offset;
> + u32 value;
> + u32 flags;
> +#define GUC_REGSET_MASKED (1 << 0)
> +} __packed;
>
> +struct guc_mmio_regset {
> + struct guc_mmio_reg registers[GUC_REGSET_MAX_REGISTERS];
> u32 values_valid;
> u32 number_of_registers;
> } __packed;
>
> -/* MMIO registers that are set as non privileged */
> -struct mmio_white_list {
> - u32 mmio_start;
> - u32 offsets[GUC_MMIO_WHITE_LIST_MAX];
> - u32 count;
> +/* GuC register sets */
> +struct guc_mmio_reg_state {
> + struct guc_mmio_regset engine_reg[GUC_MAX_ENGINE_CLASSES][GUC_MAX_INSTANCES_PER_CLASS];
> + u32 reserved[98];
> } __packed;
>
> -struct guc_mmio_reg_state {
> - struct guc_mmio_regset global_reg;
> - struct guc_mmio_regset engine_reg[GUC_MAX_ENGINES_NUM];
> - struct mmio_white_list white_list[GUC_MAX_ENGINES_NUM];
> +/* HW info */
> +struct guc_gt_system_info {
> + u32 slice_enabled;
> + u32 rcs_enabled;
> + u32 reserved0;
> + u32 bcs_enabled;
> + u32 vdbox_enable_mask;
> + u32 vdbox_sfc_support_mask;
> + u32 vebox_enable_mask;
> + u32 reserved[9];
> } __packed;
>
> -/* GuC Additional Data Struct */
> +/* Clients info */
> +struct guc_ct_pool_entry {
> + struct guc_ct_buffer_desc desc;
> + u32 reserved[7];
> +} __packed;
>
> +#define GUC_CT_POOL_SIZE 2
> +
> +struct guc_clients_info {
> + u32 clients_num;
> + u32 reserved0[13];
> + u32 ct_pool_addr;
> + u32 ct_pool_count;
> + u32 reserved[4];
> +} __packed;
> +
> +/* GuC Additional Data Struct */
> struct guc_ads {
> u32 reg_state_addr;
> u32 reg_state_buffer;
> - u32 golden_context_lrca;
> u32 scheduler_policies;
> - u32 reserved0[3];
> - u32 eng_state_size[GUC_MAX_ENGINES_NUM];
> - u32 reserved2[4];
> + u32 gt_system_info;
> + u32 clients_info;
> + u32 control_data;
> + u32 golden_context_lrca[GUC_MAX_ENGINE_CLASSES];
> + u32 eng_state_size[GUC_MAX_ENGINE_CLASSES];
> + u32 reserved[16];
> } __packed;
>
> /* GuC logging structures */
> diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.h b/drivers/gpu/drm/i915/intel_ringbuffer.h
> index 72c7c337ace9..0107a39f3ec2 100644
> --- a/drivers/gpu/drm/i915/intel_ringbuffer.h
> +++ b/drivers/gpu/drm/i915/intel_ringbuffer.h
> @@ -547,6 +547,8 @@ ktime_t intel_engine_get_busy_time(struct intel_engine_cs *engine);
> struct i915_request *
> intel_engine_find_active_request(struct intel_engine_cs *engine);
>
> +u32 intel_engine_context_size(struct drm_i915_private *i915, u8 class);
> +
> #if IS_ENABLED(CONFIG_DRM_I915_SELFTEST)
>
> static inline bool inject_preempt_hang(struct intel_engine_execlists *execlists)
>
More information about the Intel-gfx
mailing list