drm/i915: Add logical engine mapping
authorMatthew Brost <matthew.brost@intel.com>
Thu, 14 Oct 2021 17:19:45 +0000 (10:19 -0700)
committerJohn Harrison <John.C.Harrison@Intel.com>
Fri, 15 Oct 2021 17:37:29 +0000 (10:37 -0700)
Add logical engine mapping. This is required for split-frame, as
workloads need to be placed on engines in a logically contiguous manner.

v2:
 (Daniel Vetter)
  - Add kernel doc for new fields
v3:
 (Tvrtko)
  - Update comment for new logical_mask field
v4:
 (John Harrison)
  - Update comment for new logical_mask field

Signed-off-by: Matthew Brost <matthew.brost@intel.com>
Reviewed-by: John Harrison <John.C.Harrison@Intel.com>
Signed-off-by: John Harrison <John.C.Harrison@Intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20211014172005.27155-6-matthew.brost@intel.com
drivers/gpu/drm/i915/gt/intel_engine_cs.c
drivers/gpu/drm/i915/gt/intel_engine_types.h
drivers/gpu/drm/i915/gt/intel_execlists_submission.c
drivers/gpu/drm/i915/gt/uc/intel_guc_ads.c
drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c

index 2ae57e4656a37e3e2bed29a6e38b1dc47daf0b2a..2eb798ad068b2f64ddbd24fc27bb4db4f34b8a6d 100644 (file)
@@ -290,7 +290,8 @@ static void nop_irq_handler(struct intel_engine_cs *engine, u16 iir)
        GEM_DEBUG_WARN_ON(iir);
 }
 
-static int intel_engine_setup(struct intel_gt *gt, enum intel_engine_id id)
+static int intel_engine_setup(struct intel_gt *gt, enum intel_engine_id id,
+                             u8 logical_instance)
 {
        const struct engine_info *info = &intel_engines[id];
        struct drm_i915_private *i915 = gt->i915;
@@ -335,6 +336,7 @@ static int intel_engine_setup(struct intel_gt *gt, enum intel_engine_id id)
 
        engine->class = info->class;
        engine->instance = info->instance;
+       engine->logical_mask = BIT(logical_instance);
        __sprint_engine_name(engine);
 
        engine->props.heartbeat_interval_ms =
@@ -588,6 +590,37 @@ static intel_engine_mask_t init_engine_mask(struct intel_gt *gt)
        return info->engine_mask;
 }
 
+static void populate_logical_ids(struct intel_gt *gt, u8 *logical_ids,
+                                u8 class, const u8 *map, u8 num_instances)
+{
+       int i, j;
+       u8 current_logical_id = 0;
+
+       for (j = 0; j < num_instances; ++j) {
+               for (i = 0; i < ARRAY_SIZE(intel_engines); ++i) {
+                       if (!HAS_ENGINE(gt, i) ||
+                           intel_engines[i].class != class)
+                               continue;
+
+                       if (intel_engines[i].instance == map[j]) {
+                               logical_ids[intel_engines[i].instance] =
+                                       current_logical_id++;
+                               break;
+                       }
+               }
+       }
+}
+
+static void setup_logical_ids(struct intel_gt *gt, u8 *logical_ids, u8 class)
+{
+       int i;
+       u8 map[MAX_ENGINE_INSTANCE + 1];
+
+       for (i = 0; i < MAX_ENGINE_INSTANCE + 1; ++i)
+               map[i] = i;
+       populate_logical_ids(gt, logical_ids, class, map, ARRAY_SIZE(map));
+}
+
 /**
  * intel_engines_init_mmio() - allocate and prepare the Engine Command Streamers
  * @gt: pointer to struct intel_gt
@@ -599,7 +632,8 @@ int intel_engines_init_mmio(struct intel_gt *gt)
        struct drm_i915_private *i915 = gt->i915;
        const unsigned int engine_mask = init_engine_mask(gt);
        unsigned int mask = 0;
-       unsigned int i;
+       unsigned int i, class;
+       u8 logical_ids[MAX_ENGINE_INSTANCE + 1];
        int err;
 
        drm_WARN_ON(&i915->drm, engine_mask == 0);
@@ -609,15 +643,23 @@ int intel_engines_init_mmio(struct intel_gt *gt)
        if (i915_inject_probe_failure(i915))
                return -ENODEV;
 
-       for (i = 0; i < ARRAY_SIZE(intel_engines); i++) {
-               if (!HAS_ENGINE(gt, i))
-                       continue;
+       for (class = 0; class < MAX_ENGINE_CLASS + 1; ++class) {
+               setup_logical_ids(gt, logical_ids, class);
 
-               err = intel_engine_setup(gt, i);
-               if (err)
-                       goto cleanup;
+               for (i = 0; i < ARRAY_SIZE(intel_engines); ++i) {
+                       u8 instance = intel_engines[i].instance;
+
+                       if (intel_engines[i].class != class ||
+                           !HAS_ENGINE(gt, i))
+                               continue;
 
-               mask |= BIT(i);
+                       err = intel_engine_setup(gt, i,
+                                                logical_ids[instance]);
+                       if (err)
+                               goto cleanup;
+
+                       mask |= BIT(i);
+               }
        }
 
        /*
index 9167ce52487c2dccbbb9fe0582049f618a371862..e0f773585c297481c45a868ca915920cc233e034 100644 (file)
@@ -269,6 +269,13 @@ struct intel_engine_cs {
        unsigned int guc_id;
 
        intel_engine_mask_t mask;
+       /**
+        * @logical_mask: logical mask of engine, reported to user space via
+        * query IOCTL and used to communicate with the GuC in logical space.
+        * The logical instance of a physical engine can change based on product
+        * and fusing.
+        */
+       intel_engine_mask_t logical_mask;
 
        u8 class;
        u8 instance;
index 73a79c2acd3ad2b09895088a5d4c9747440a1fbe..43a74b216efbde757a37cd5744d704aa84cf6168 100644 (file)
@@ -3877,6 +3877,7 @@ execlists_create_virtual(struct intel_engine_cs **siblings, unsigned int count)
 
                ve->siblings[ve->num_siblings++] = sibling;
                ve->base.mask |= sibling->mask;
+               ve->base.logical_mask |= sibling->logical_mask;
 
                /*
                 * All physical engines must be compatible for their emission
index 2c6ea64af7ec79b401c56c639a71150d36ab6322..621c893a009f9e9e11eb25043b36798f6d0e7dca 100644 (file)
@@ -176,7 +176,7 @@ static void guc_mapping_table_init(struct intel_gt *gt,
        for_each_engine(engine, gt, id) {
                u8 guc_class = engine_class_to_guc_class(engine->class);
 
-               system_info->mapping_table[guc_class][engine->instance] =
+               system_info->mapping_table[guc_class][ilog2(engine->logical_mask)] =
                        engine->instance;
        }
 }
index 795cc071d05d161731675c0e0c5f234867fa1154..fd6594bc1b96047d9f1d97ca5d1a6cd447f24b6e 100644 (file)
@@ -1423,23 +1423,6 @@ static int deregister_context(struct intel_context *ce, u32 guc_id)
        return __guc_action_deregister_context(guc, guc_id);
 }
 
-static intel_engine_mask_t adjust_engine_mask(u8 class, intel_engine_mask_t mask)
-{
-       switch (class) {
-       case RENDER_CLASS:
-               return mask >> RCS0;
-       case VIDEO_ENHANCEMENT_CLASS:
-               return mask >> VECS0;
-       case VIDEO_DECODE_CLASS:
-               return mask >> VCS0;
-       case COPY_ENGINE_CLASS:
-               return mask >> BCS0;
-       default:
-               MISSING_CASE(class);
-               return 0;
-       }
-}
-
 static void guc_context_policy_init(struct intel_engine_cs *engine,
                                    struct guc_lrc_desc *desc)
 {
@@ -1481,8 +1464,7 @@ static int guc_lrc_desc_pin(struct intel_context *ce, bool loop)
 
        desc = __get_lrc_desc(guc, desc_idx);
        desc->engine_class = engine_class_to_guc_class(engine->class);
-       desc->engine_submit_mask = adjust_engine_mask(engine->class,
-                                                     engine->mask);
+       desc->engine_submit_mask = engine->logical_mask;
        desc->hw_context_desc = ce->lrc.lrca;
        desc->priority = ce->guc_state.prio;
        desc->context_flags = CONTEXT_REGISTRATION_FLAG_KMD;
@@ -3271,6 +3253,7 @@ guc_create_virtual(struct intel_engine_cs **siblings, unsigned int count)
                }
 
                ve->base.mask |= sibling->mask;
+               ve->base.logical_mask |= sibling->logical_mask;
 
                if (n != 0 && ve->base.class != sibling->class) {
                        DRM_DEBUG("invalid mixing of engine class, sibling %d, already %d\n",