@@ -270,6 +270,11 @@ static void __sprint_engine_name(char *name, const struct engine_info *info)
info->instance) >= INTEL_ENGINE_CS_MAX_NAME);
}
+u32 intel_class_context_size(struct drm_i915_private *dev_priv, u8 class)
+{
+ return __intel_engine_context_size(dev_priv, class);
+}
+
static int
intel_engine_setup(struct drm_i915_private *dev_priv,
enum intel_engine_id id)
@@ -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,12 +61,35 @@ static void guc_policies_init(struct guc_policies *policies)
policies->is_valid = 1;
}
+static u8 guc_class_to_intel_class(u8 guc_class)
+{
+ switch (guc_class) {
+ default:
+ MISSING_CASE(guc_class);
+ /* fall through */
+ case GUC_RENDER_CLASS:
+ return RENDER_CLASS;
+ case GUC_VIDEO_CLASS:
+ return VIDEO_DECODE_CLASS;
+ case GUC_VIDEOENHANCE_CLASS:
+ return VIDEO_ENHANCEMENT_CLASS;
+ case GUC_BLITTER_CLASS:
+ return COPY_ENGINE_CLASS;
+ }
+}
+
/*
* The first 80 dwords of the register state context, containing the
* execlists and ppgtt registers.
*/
#define LR_HW_CONTEXT_SIZE (80 * sizeof(u32))
+static void
+guc_master_cmd_transport_pool_init(struct guc_master_cmd_transport_pool *pool)
+{
+ memset(pool, 0, sizeof(*pool));
+}
+
/**
* intel_guc_ads_create() - creates GuC ADS
* @guc: intel_guc struct
@@ -76,19 +99,22 @@ 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;
/* 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_gt_system_additional_info add_system_info;
+ struct guc_master_cmd_transport_pool ct_pool;
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 media_fuse;
u32 base;
+ u8 class;
+ int ret;
GEM_BUG_ON(guc->ads_vma);
@@ -98,21 +124,15 @@ 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
@@ -123,27 +143,50 @@ int intel_guc_ads_create(struct intel_guc *guc)
*/
kernel_ctx_vma = to_intel_context(dev_priv->kernel_context,
dev_priv->engine[RCS])->state;
- blob->ads.golden_context_lrca =
+ blob->ads.golden_context_lrca[GUC_RENDER_CLASS] =
intel_guc_ggtt_offset(guc, kernel_ctx_vma) + skipped_offset;
/*
- * 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.
+ * We only care about the golden context for the render class, really
+ * (but skipping the execlist part of the context)
*/
- for_each_engine(engine, dev_priv, id)
- blob->ads.eng_state_size[engine->guc_id] =
- engine->context_size - skipped_size;
+ class = guc_class_to_intel_class(GUC_RENDER_CLASS);
+ blob->ads.eng_state_size[GUC_RENDER_CLASS] =
+ intel_class_context_size(dev_priv, class) - skipped_size;
+
+ /* System info */
+ blob->system_info.slice_enabled = hweight8(INTEL_INFO(dev_priv)->sseu.slice_mask);
+ blob->system_info.rcs_enabled = 1;
+ blob->system_info.bcs_enabled = 1;
+
+ media_fuse = I915_READ(GEN11_GT_VEBOX_VDBOX_DISABLE);
+ blob->system_info.vdbox_enable_mask = ~(media_fuse & GEN11_GT_VDBOX_DISABLE_MASK);
+ blob->system_info.vebox_enable_mask = ~((media_fuse & GEN11_GT_VEBOX_DISABLE_MASK) >>
+ GEN11_GT_VEBOX_DISABLE_SHIFT);
base = intel_guc_ggtt_offset(guc, vma);
+
+ /* Additional info */
+ guc_master_cmd_transport_pool_init(&blob->ct_pool);
+
+ blob->add_system_info.gfx_address_command_transport_pool =
+ base + ptr_offset(blob, ct_pool);
+ blob->add_system_info.command_transport_pool_count = GUC_CT_POOL_SIZE;
+
+ /* 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.gt_system_additional_info = base + ptr_offset(blob, add_system_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)
@@ -45,6 +45,7 @@
#define GUC_BLITTER_CLASS 3
#define GUC_RESERVED_CLASS 4
#define GUC_MAX_ENGINE_CLASSES (GUC_RESERVED_CLASS + 1)
+#define GUC_MAX_INSTANCES_PER_CLASS 4
/* Work queue item header definitions */
#define WQ_STATUS_ACTIVE 1
@@ -447,23 +448,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). */
@@ -476,57 +473,75 @@ 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;
+
+/* Gen11+ 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;
-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];
+struct guc_gt_system_additional_info {
+ u32 reserved0[14];
+ u32 gfx_address_command_transport_pool;
+ u32 command_transport_pool_count;
+ u32 reserved1[95];
} __packed;
-/* GuC Additional Data Struct */
+struct guc_master_cmd_transport_buffer_alloc {
+ struct guc_ct_buffer_desc desc;
+ u32 reserved[7];
+} __packed;
+#define GUC_CT_POOL_SIZE 2
+
+struct guc_master_cmd_transport_pool {
+ struct guc_master_cmd_transport_buffer_alloc pool[GUC_CT_POOL_SIZE];
+} __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 gt_system_additional_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 */
@@ -1183,6 +1183,8 @@ static inline void intel_engine_context_out(struct intel_engine_cs *engine)
ktime_t intel_engine_get_busy_time(struct intel_engine_cs *engine);
+u32 intel_class_context_size(struct drm_i915_private *dev_priv, u8 class);
+
#if IS_ENABLED(CONFIG_DRM_I915_SELFTEST)
static inline bool inject_preempt_hang(struct intel_engine_execlists *execlists)
Definition of the Additional Data Structure (ADS) object and some of its sub-structs has been updated in the GuC firmware. Signed-off-by: Michal Wajdeczko <michal.wajdeczko@intel.com> Cc: Joonas Lahtinen <joonas.lahtinen@linux.intel.com> Cc: Daniele Ceraolo Spurio <daniele.ceraolospurio@intel.com> Cc: Michel Thierry <michel.thierry@intel.com> Cc: Tomasz Lis <tomasz.lis@intel.com> --- drivers/gpu/drm/i915/intel_engine_cs.c | 5 ++ drivers/gpu/drm/i915/intel_guc_ads.c | 91 ++++++++++++++++++++++++--------- drivers/gpu/drm/i915/intel_guc_fwif.h | 89 ++++++++++++++++++-------------- drivers/gpu/drm/i915/intel_ringbuffer.h | 2 + 4 files changed, 126 insertions(+), 61 deletions(-)