Format of the ENGINE_RESET H2G message has been updated. Additionally,
the firmware will send a G2H ENGINE_RESET_COMPLETE message (with the
engine's guc_class in data[2]) to confirm that the reset has been
completed (but this will be handled in a other patch).

Requires GuC fw v25.161+.

Credits-to: Michel Thierry <[email protected]>
Signed-off-by: Michal Wajdeczko <[email protected]>
Cc: Michel Thierry <[email protected]>
Cc: Daniele Ceraolo Spurio <[email protected]>
Cc: Vinay Belgaumkar <[email protected]>
Cc: Michal Winiarski <[email protected]>
Cc: Tomasz Lis <[email protected]>
---
 drivers/gpu/drm/i915/intel_guc.c | 73 ++++++++++++++++++++++++++++++++++------
 drivers/gpu/drm/i915/intel_guc.h |  6 ++++
 2 files changed, 69 insertions(+), 10 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_guc.c b/drivers/gpu/drm/i915/intel_guc.c
index a9c2f7b..64f1dca 100644
--- a/drivers/gpu/drm/i915/intel_guc.c
+++ b/drivers/gpu/drm/i915/intel_guc.c
@@ -576,27 +576,80 @@ int intel_guc_suspend(struct intel_guc *guc)
        return intel_guc_send(guc, data, ARRAY_SIZE(data));
 }
 
+static inline void
+guc_set_class_under_reset(struct intel_guc *guc, unsigned int guc_class)
+{
+       GEM_BUG_ON(guc_class >= GUC_MAX_ENGINE_CLASSES);
+       bitmap32_set_bit(&guc->engine_class_under_reset, guc_class);
+}
+
+static inline void
+guc_clear_class_under_reset(struct intel_guc *guc, unsigned int guc_class)
+{
+       GEM_BUG_ON(guc_class >= GUC_MAX_ENGINE_CLASSES);
+       bitmap32_clear_bit(&guc->engine_class_under_reset, guc_class);
+}
+
+static inline bool
+guc_is_class_under_reset(struct intel_guc *guc, unsigned int guc_class)
+{
+       return bitmap32_test_bit(&guc->engine_class_under_reset, guc_class);
+}
+
+static int __guc_action_reset_engine(struct intel_guc *guc,
+                                    u32 guc_class,
+                                    u32 stage_id)
+{
+       u32 action[] = {
+               INTEL_GUC_ACTION_REQUEST_ENGINE_RESET,
+               guc_class,
+               stage_id,
+       };
+
+       return intel_guc_send(guc, action, ARRAY_SIZE(action));
+}
+
+#define GUC_ENGINE_RESET_COMPLETE_WAIT_MS 100
+
 /**
  * intel_guc_reset_engine() - ask GuC to reset an engine
  * @guc:       intel_guc structure
  * @engine:    engine to be reset
+ *
+ * Ask GuC to reset an engine. The firmware will send a separate
+ * ENGINE_RESET_COMPLETE message (with the engine's guc_class)
+ * to confirm that the reset has been completed.
  */
 int intel_guc_reset_engine(struct intel_guc *guc,
                           struct intel_engine_cs *engine)
 {
-       u32 data[7];
+       struct intel_guc_client *client = guc->execbuf_client;
+       u32 guc_class = engine->guc_class;
+       int ret;
 
-       GEM_BUG_ON(!guc->execbuf_client);
+       GEM_BUG_ON(guc_is_class_under_reset(guc, guc_class));
+       guc_set_class_under_reset(guc, guc_class);
 
-       data[0] = INTEL_GUC_ACTION_REQUEST_ENGINE_RESET;
-       data[1] = engine->guc_id;
-       data[2] = 0;
-       data[3] = 0;
-       data[4] = 0;
-       data[5] = guc->execbuf_client->stage_id;
-       data[6] = intel_guc_ggtt_offset(guc, guc->shared_data);
+       ret = __guc_action_reset_engine(guc, guc_class, client->stage_id);
+       if (ret)
+               goto out;
 
-       return intel_guc_send(guc, data, ARRAY_SIZE(data));
+       if ((wait_for(!guc_is_class_under_reset(guc, guc_class),
+                     GUC_ENGINE_RESET_COMPLETE_WAIT_MS))) {
+               DRM_ERROR("reset_complete timed out, engine class %d\n",
+                         engine->guc_class);
+               ret = -ETIMEDOUT;
+       }
+
+out:
+       /*
+        * Clear flag on any failure, we fall back to full reset in
+        * case of timeout/error.
+        */
+       if (ret)
+               guc_clear_class_under_reset(guc, guc_class);
+
+       return ret;
 }
 
 /**
diff --git a/drivers/gpu/drm/i915/intel_guc.h b/drivers/gpu/drm/i915/intel_guc.h
index ad42faf..8688edc 100644
--- a/drivers/gpu/drm/i915/intel_guc.h
+++ b/drivers/gpu/drm/i915/intel_guc.h
@@ -74,6 +74,12 @@ struct intel_guc {
        /* Cyclic counter mod pagesize  */
        u32 db_cacheline;
 
+       /*
+        * Track outstanding request-engine-reset h2g commands,
+        * accessed by set/clear/is_engine_class_under_reset
+        */
+       u32 engine_class_under_reset;
+
        /* GuC's FW specific registers used in MMIO send */
        struct {
                u32 base;
-- 
1.9.1

_______________________________________________
Intel-gfx mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

Reply via email to