[PATCH 2/3] drm/i915/guc: handle guc messages received with CTB disabled

Daniele Ceraolo Spurio daniele.ceraolospurio at intel.com
Wed Jun 19 00:01:56 UTC 2019


There is a very small chance of triggering a log flush event when
enabling or disabling CT buffers. Events triggered while CT buffers
are disabled are logged in the SCRATCH_15 register using the same bits
used in the CT message payload. Since our communication channel with
guc is turned off, we can save the message and handle it after we turn
it back on.
GuC should be idle and not generate more events in the meantime because
we're not talking to it.

Signed-off-by: Daniele Ceraolo Spurio <daniele.ceraolospurio at intel.com>
Cc: Michal Wajdeczko <michal.wajdeczko at intel.com>
Cc: Chris Wilson <chris at chris-wilson.co.uk>
---
 drivers/gpu/drm/i915/intel_guc.h |  5 ++++
 drivers/gpu/drm/i915/intel_uc.c  | 49 ++++++++++++++++++++++++++++++++
 2 files changed, 54 insertions(+)

diff --git a/drivers/gpu/drm/i915/intel_guc.h b/drivers/gpu/drm/i915/intel_guc.h
index 08c906abdfa2..5d5fcf435618 100644
--- a/drivers/gpu/drm/i915/intel_guc.h
+++ b/drivers/gpu/drm/i915/intel_guc.h
@@ -88,6 +88,9 @@ struct intel_guc {
 		enum forcewake_domains fw_domains;
 	} send_regs;
 
+	/* Store late msg from guc (e.g. log flush) that we handle on resume */
+	u32 mmio_msg;
+
 	/* To serialize the intel_guc_send actions */
 	struct mutex send_mutex;
 
@@ -181,6 +184,8 @@ static inline bool intel_guc_is_loaded(struct intel_guc *guc)
 static inline int intel_guc_sanitize(struct intel_guc *guc)
 {
 	intel_uc_fw_sanitize(&guc->fw);
+	guc->mmio_msg = 0;
+
 	return 0;
 }
 
diff --git a/drivers/gpu/drm/i915/intel_uc.c b/drivers/gpu/drm/i915/intel_uc.c
index 06e7191b7d0f..9dbaded319e2 100644
--- a/drivers/gpu/drm/i915/intel_uc.c
+++ b/drivers/gpu/drm/i915/intel_uc.c
@@ -218,6 +218,37 @@ static void guc_free_load_err_log(struct intel_guc *guc)
 		i915_gem_object_put(guc->load_err_log);
 }
 
+/*
+ * Events triggered while CT buffers are disabled are logged in the SCRATCH_15
+ * register using the same bits used in the CT message payload. Since our
+ * communication channel with guc is turned off at this point, we can save the
+ * message and handle it after we turn it back on.
+ */
+static void guc_get_mmio_msg(struct intel_guc *guc)
+{
+	struct intel_uncore *uncore = &guc_to_i915(guc)->uncore;
+	u32 msg, val;
+
+	spin_lock(&guc->irq_lock);
+	val = intel_uncore_read(uncore, SOFT_SCRATCH(15));
+	msg = val & guc->msg_enabled_mask;
+	intel_uncore_write(uncore, SOFT_SCRATCH(15), val & ~msg);
+	spin_unlock(&guc->irq_lock);
+
+	guc->mmio_msg |= msg;
+}
+
+static void guc_handle_mmio_msg(struct intel_guc *guc)
+{
+	GEM_BUG_ON(guc->handler == intel_guc_to_host_event_handler_nop);
+
+	if (guc->mmio_msg)
+		intel_guc_to_host_process_recv_msg(guc, &guc->mmio_msg, 1);
+
+	guc->mmio_msg = 0;
+}
+
+
 static void guc_reset_interrupts(struct intel_guc *guc)
 {
 	guc->interrupts.reset(guc_to_i915(guc));
@@ -235,6 +266,7 @@ static void guc_disable_interrupts(struct intel_guc *guc)
 
 static int guc_enable_communication(struct intel_guc *guc)
 {
+	struct drm_i915_private *i915 = guc_to_i915(guc);
 	int ret;
 
 	ret = intel_guc_ct_enable(&guc->ct);
@@ -244,8 +276,17 @@ static int guc_enable_communication(struct intel_guc *guc)
 	guc->send = intel_guc_send_ct;
 	guc->handler = intel_guc_to_host_event_handler_ct;
 
+	/* check for mmio messages received before/during the ct enable */
+	guc_get_mmio_msg(guc);
+	guc_handle_mmio_msg(guc);
+
 	guc_enable_interrupts(guc);
 
+	/* check for CT messages received before we enabled interrupts */
+	spin_lock_irq(&i915->irq_lock);
+	intel_guc_to_host_event_handler_ct(guc);
+	spin_unlock_irq(&i915->irq_lock);
+
 	return 0;
 }
 
@@ -265,6 +306,14 @@ static void guc_disable_communication(struct intel_guc *guc)
 	guc->handler = intel_guc_to_host_event_handler_nop;
 
 	intel_guc_ct_disable(&guc->ct);
+
+	/*
+	 * Check for messages received during/after the CT disable. We do not
+	 * expect any messages to have arrived via CT between the interrupt
+	 * disable and the CT disable because GuC should've been idle until we
+	 * triggered the CT disable protocol.
+	 */
+	guc_get_mmio_msg(guc);
 }
 
 int intel_uc_init_misc(struct drm_i915_private *i915)
-- 
2.20.1



More information about the Intel-gfx-trybot mailing list