diff mbox

[04/15] drm/i915/guc: Keep GuC interrupts enabled when using GuC

Message ID 20180227125230.13000-4-michal.winiarski@intel.com (mailing list archive)
State New, archived
Headers show

Commit Message

Michał Winiarski Feb. 27, 2018, 12:52 p.m. UTC
The GuC log contains a separate space used for crash dump.
We even get a separate notification for it. While we're not handling
crash differently yet, it makes sense to decouple the two right now to
simplify the following patches.

Signed-off-by: Michał Winiarski <michal.winiarski@intel.com>
Cc: Chris Wilson <chris@chris-wilson.co.uk>
Cc: Daniele Ceraolo Spurio <daniele.ceraolospurio@intel.com>
Cc: Sagar Arun Kamble <sagar.a.kamble@intel.com>
Cc: Michal Wajdeczko <michal.wajdeczko@intel.com>
---
 drivers/gpu/drm/i915/intel_guc.c     | 28 +++++++++++-----------------
 drivers/gpu/drm/i915/intel_guc.h     |  2 ++
 drivers/gpu/drm/i915/intel_guc_log.c | 29 ++++++++++++++++++-----------
 drivers/gpu/drm/i915/intel_uc.c      | 14 +++++---------
 4 files changed, 36 insertions(+), 37 deletions(-)

Comments

sagar.a.kamble@intel.com March 5, 2018, 9:27 a.m. UTC | #1
On 2/27/2018 6:22 PM, Michał Winiarski wrote:
> The GuC log contains a separate space used for crash dump.
> We even get a separate notification for it. While we're not handling
> crash differently yet, it makes sense to decouple the two right now to
> simplify the following patches.
>
> Signed-off-by: Michał Winiarski <michal.winiarski@intel.com>
> Cc: Chris Wilson <chris@chris-wilson.co.uk>
> Cc: Daniele Ceraolo Spurio <daniele.ceraolospurio@intel.com>
> Cc: Sagar Arun Kamble <sagar.a.kamble@intel.com>
> Cc: Michal Wajdeczko <michal.wajdeczko@intel.com>
Reviewed-by: Sagar Arun Kamble <sagar.a.kamble@intel.com>
> ---
>   drivers/gpu/drm/i915/intel_guc.c     | 28 +++++++++++-----------------
>   drivers/gpu/drm/i915/intel_guc.h     |  2 ++
>   drivers/gpu/drm/i915/intel_guc_log.c | 29 ++++++++++++++++++-----------
>   drivers/gpu/drm/i915/intel_uc.c      | 14 +++++---------
>   4 files changed, 36 insertions(+), 37 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/intel_guc.c b/drivers/gpu/drm/i915/intel_guc.c
> index f622dd6009b6..41f2c3b3c482 100644
> --- a/drivers/gpu/drm/i915/intel_guc.c
> +++ b/drivers/gpu/drm/i915/intel_guc.c
> @@ -67,6 +67,7 @@ void intel_guc_init_early(struct intel_guc *guc)
>   	intel_guc_log_init_early(guc);
>   
>   	mutex_init(&guc->send_mutex);
> +	spin_lock_init(&guc->irq_lock);
>   	guc->send = intel_guc_send_nop;
>   	guc->notify = gen8_guc_raise_irq;
>   }
> @@ -367,7 +368,7 @@ int intel_guc_send_mmio(struct intel_guc *guc, const u32 *action, u32 len)
>   void intel_guc_notification_handler(struct intel_guc *guc)
>   {
>   	struct drm_i915_private *dev_priv = guc_to_i915(guc);
> -	u32 msg, flush;
> +	u32 msg, val;
>   
>   	/*
>   	 * Sample the log buffer flush related bits & clear them out now
> @@ -380,24 +381,18 @@ void intel_guc_notification_handler(struct intel_guc *guc)
>   	 * could happen that GuC sets the bit for 2nd interrupt but Host
>   	 * clears out the bit on handling the 1st interrupt.
>   	 */
> -
> -	msg = I915_READ(SOFT_SCRATCH(15));
> -	flush = msg & (INTEL_GUC_RECV_MSG_CRASH_DUMP_POSTED |
> -		       INTEL_GUC_RECV_MSG_FLUSH_LOG_BUFFER);
> -	if (flush) {
> -		/* Clear the message bits that are handled */
> -		I915_WRITE(SOFT_SCRATCH(15), msg & ~flush);
> -
> -		/* Handle flush interrupt in bottom half */
> +	spin_lock(&guc->irq_lock);
> +	val = I915_READ(SOFT_SCRATCH(15));
> +	msg = val & guc->msg_enabled_mask;
> +	I915_WRITE(SOFT_SCRATCH(15), val & ~msg);
> +	spin_unlock(&guc->irq_lock);
> +
> +	if (msg & (INTEL_GUC_RECV_MSG_FLUSH_LOG_BUFFER |
> +		   INTEL_GUC_RECV_MSG_CRASH_DUMP_POSTED)) {
>   		queue_work(guc->log.runtime.flush_wq,
>   			   &guc->log.runtime.flush_work);
>   
>   		guc->log.flush_interrupt_count++;
> -	} else {
> -		/*
> -		 * Not clearing of unhandled event bits won't result in
> -		 * re-triggering of the interrupt.
> -		 */
>   	}
>   }
>   
> @@ -495,8 +490,7 @@ int intel_guc_resume(struct drm_i915_private *dev_priv)
>   	if (guc->fw.load_status != INTEL_UC_FIRMWARE_SUCCESS)
>   		return 0;
>   
> -	if (i915_modparams.guc_log_level)
> -		gen9_enable_guc_interrupts(dev_priv);
> +	gen9_enable_guc_interrupts(dev_priv);
>   
>   	data[0] = INTEL_GUC_ACTION_EXIT_S_STATE;
>   	data[1] = GUC_POWER_D0;
> diff --git a/drivers/gpu/drm/i915/intel_guc.h b/drivers/gpu/drm/i915/intel_guc.h
> index 5b905bae181d..d629bc5d5c0f 100644
> --- a/drivers/gpu/drm/i915/intel_guc.h
> +++ b/drivers/gpu/drm/i915/intel_guc.h
> @@ -53,7 +53,9 @@ struct intel_guc {
>   	struct drm_i915_gem_object *load_err_log;
>   
>   	/* intel_guc_recv interrupt related state */
> +	spinlock_t irq_lock;
>   	bool interrupts_enabled;
> +	unsigned int msg_enabled_mask;
>   
>   	struct i915_vma *ads_vma;
>   	struct i915_vma *stage_desc_pool;
> diff --git a/drivers/gpu/drm/i915/intel_guc_log.c b/drivers/gpu/drm/i915/intel_guc_log.c
> index f1cab43d334e..09be7340652b 100644
> --- a/drivers/gpu/drm/i915/intel_guc_log.c
> +++ b/drivers/gpu/drm/i915/intel_guc_log.c
> @@ -590,6 +590,22 @@ int intel_guc_log_create(struct intel_guc *guc)
>   	return ret;
>   }
>   
> +static void guc_log_flush_irq_enable(struct intel_guc *guc)
> +{
> +	spin_lock_irq(&guc->irq_lock);
> +	guc->msg_enabled_mask |= INTEL_GUC_RECV_MSG_FLUSH_LOG_BUFFER |
> +				 INTEL_GUC_RECV_MSG_CRASH_DUMP_POSTED;
> +	spin_unlock_irq(&guc->irq_lock);
> +}
> +
> +static void guc_log_flush_irq_disable(struct intel_guc *guc)
> +{
> +	spin_lock_irq(&guc->irq_lock);
> +	guc->msg_enabled_mask &= ~(INTEL_GUC_RECV_MSG_FLUSH_LOG_BUFFER |
> +				   INTEL_GUC_RECV_MSG_CRASH_DUMP_POSTED);
> +	spin_unlock_irq(&guc->irq_lock);
> +}
> +
>   void intel_guc_log_destroy(struct intel_guc *guc)
>   {
>   	guc_log_runtime_destroy(guc);
> @@ -687,12 +703,7 @@ int intel_guc_log_register(struct intel_guc *guc)
>   	if (ret)
>   		goto err_runtime;
>   
> -	/* GuC logging is currently the only user of Guc2Host interrupts */
> -	mutex_lock(&dev_priv->drm.struct_mutex);
> -	intel_runtime_pm_get(dev_priv);
> -	gen9_enable_guc_interrupts(dev_priv);
> -	intel_runtime_pm_put(dev_priv);
> -	mutex_unlock(&dev_priv->drm.struct_mutex);
> +	guc_log_flush_irq_enable(guc);
>   
>   	return 0;
>   
> @@ -717,13 +728,9 @@ void intel_guc_log_unregister(struct intel_guc *guc)
>   	 * buffer state and then collect the left over logs.
>   	 */
>   	guc_flush_logs(guc);
> +	guc_log_flush_irq_disable(guc);
>   
>   	mutex_lock(&dev_priv->drm.struct_mutex);
> -	/* GuC logging is currently the only user of Guc2Host interrupts */
> -	intel_runtime_pm_get(dev_priv);
> -	gen9_disable_guc_interrupts(dev_priv);
> -	intel_runtime_pm_put(dev_priv);
> -
>   	guc_log_runtime_destroy(guc);
>   	mutex_unlock(&dev_priv->drm.struct_mutex);
>   
> diff --git a/drivers/gpu/drm/i915/intel_uc.c b/drivers/gpu/drm/i915/intel_uc.c
> index 3f41ef525e26..e9aba3c35264 100644
> --- a/drivers/gpu/drm/i915/intel_uc.c
> +++ b/drivers/gpu/drm/i915/intel_uc.c
> @@ -239,6 +239,8 @@ static int guc_enable_communication(struct intel_guc *guc)
>   {
>   	struct drm_i915_private *dev_priv = guc_to_i915(guc);
>   
> +	gen9_enable_guc_interrupts(dev_priv);
> +
>   	if (HAS_GUC_CT(dev_priv))
>   		return intel_guc_enable_ct(guc);
>   
> @@ -253,6 +255,8 @@ static void guc_disable_communication(struct intel_guc *guc)
>   	if (HAS_GUC_CT(dev_priv))
>   		intel_guc_disable_ct(guc);
>   
> +	gen9_disable_guc_interrupts(dev_priv);
> +
>   	guc->send = intel_guc_send_nop;
>   }
>   
> @@ -391,12 +395,9 @@ int intel_uc_init_hw(struct drm_i915_private *dev_priv)
>   	}
>   
>   	if (USES_GUC_SUBMISSION(dev_priv)) {
> -		if (i915_modparams.guc_log_level)
> -			gen9_enable_guc_interrupts(dev_priv);
> -
>   		ret = intel_guc_submission_enable(guc);
>   		if (ret)
> -			goto err_interrupts;
> +			goto err_communication;
>   	}
>   
>   	dev_info(dev_priv->drm.dev, "GuC firmware version %u.%u\n",
> @@ -411,8 +412,6 @@ int intel_uc_init_hw(struct drm_i915_private *dev_priv)
>   	/*
>   	 * We've failed to load the firmware :(
>   	 */
> -err_interrupts:
> -	gen9_disable_guc_interrupts(dev_priv);
>   err_communication:
>   	guc_disable_communication(guc);
>   err_log_capture:
> @@ -442,7 +441,4 @@ void intel_uc_fini_hw(struct drm_i915_private *dev_priv)
>   		intel_guc_submission_disable(guc);
>   
>   	guc_disable_communication(guc);
> -
> -	if (USES_GUC_SUBMISSION(dev_priv))
> -		gen9_disable_guc_interrupts(dev_priv);
>   }
diff mbox

Patch

diff --git a/drivers/gpu/drm/i915/intel_guc.c b/drivers/gpu/drm/i915/intel_guc.c
index f622dd6009b6..41f2c3b3c482 100644
--- a/drivers/gpu/drm/i915/intel_guc.c
+++ b/drivers/gpu/drm/i915/intel_guc.c
@@ -67,6 +67,7 @@  void intel_guc_init_early(struct intel_guc *guc)
 	intel_guc_log_init_early(guc);
 
 	mutex_init(&guc->send_mutex);
+	spin_lock_init(&guc->irq_lock);
 	guc->send = intel_guc_send_nop;
 	guc->notify = gen8_guc_raise_irq;
 }
@@ -367,7 +368,7 @@  int intel_guc_send_mmio(struct intel_guc *guc, const u32 *action, u32 len)
 void intel_guc_notification_handler(struct intel_guc *guc)
 {
 	struct drm_i915_private *dev_priv = guc_to_i915(guc);
-	u32 msg, flush;
+	u32 msg, val;
 
 	/*
 	 * Sample the log buffer flush related bits & clear them out now
@@ -380,24 +381,18 @@  void intel_guc_notification_handler(struct intel_guc *guc)
 	 * could happen that GuC sets the bit for 2nd interrupt but Host
 	 * clears out the bit on handling the 1st interrupt.
 	 */
-
-	msg = I915_READ(SOFT_SCRATCH(15));
-	flush = msg & (INTEL_GUC_RECV_MSG_CRASH_DUMP_POSTED |
-		       INTEL_GUC_RECV_MSG_FLUSH_LOG_BUFFER);
-	if (flush) {
-		/* Clear the message bits that are handled */
-		I915_WRITE(SOFT_SCRATCH(15), msg & ~flush);
-
-		/* Handle flush interrupt in bottom half */
+	spin_lock(&guc->irq_lock);
+	val = I915_READ(SOFT_SCRATCH(15));
+	msg = val & guc->msg_enabled_mask;
+	I915_WRITE(SOFT_SCRATCH(15), val & ~msg);
+	spin_unlock(&guc->irq_lock);
+
+	if (msg & (INTEL_GUC_RECV_MSG_FLUSH_LOG_BUFFER |
+		   INTEL_GUC_RECV_MSG_CRASH_DUMP_POSTED)) {
 		queue_work(guc->log.runtime.flush_wq,
 			   &guc->log.runtime.flush_work);
 
 		guc->log.flush_interrupt_count++;
-	} else {
-		/*
-		 * Not clearing of unhandled event bits won't result in
-		 * re-triggering of the interrupt.
-		 */
 	}
 }
 
@@ -495,8 +490,7 @@  int intel_guc_resume(struct drm_i915_private *dev_priv)
 	if (guc->fw.load_status != INTEL_UC_FIRMWARE_SUCCESS)
 		return 0;
 
-	if (i915_modparams.guc_log_level)
-		gen9_enable_guc_interrupts(dev_priv);
+	gen9_enable_guc_interrupts(dev_priv);
 
 	data[0] = INTEL_GUC_ACTION_EXIT_S_STATE;
 	data[1] = GUC_POWER_D0;
diff --git a/drivers/gpu/drm/i915/intel_guc.h b/drivers/gpu/drm/i915/intel_guc.h
index 5b905bae181d..d629bc5d5c0f 100644
--- a/drivers/gpu/drm/i915/intel_guc.h
+++ b/drivers/gpu/drm/i915/intel_guc.h
@@ -53,7 +53,9 @@  struct intel_guc {
 	struct drm_i915_gem_object *load_err_log;
 
 	/* intel_guc_recv interrupt related state */
+	spinlock_t irq_lock;
 	bool interrupts_enabled;
+	unsigned int msg_enabled_mask;
 
 	struct i915_vma *ads_vma;
 	struct i915_vma *stage_desc_pool;
diff --git a/drivers/gpu/drm/i915/intel_guc_log.c b/drivers/gpu/drm/i915/intel_guc_log.c
index f1cab43d334e..09be7340652b 100644
--- a/drivers/gpu/drm/i915/intel_guc_log.c
+++ b/drivers/gpu/drm/i915/intel_guc_log.c
@@ -590,6 +590,22 @@  int intel_guc_log_create(struct intel_guc *guc)
 	return ret;
 }
 
+static void guc_log_flush_irq_enable(struct intel_guc *guc)
+{
+	spin_lock_irq(&guc->irq_lock);
+	guc->msg_enabled_mask |= INTEL_GUC_RECV_MSG_FLUSH_LOG_BUFFER |
+				 INTEL_GUC_RECV_MSG_CRASH_DUMP_POSTED;
+	spin_unlock_irq(&guc->irq_lock);
+}
+
+static void guc_log_flush_irq_disable(struct intel_guc *guc)
+{
+	spin_lock_irq(&guc->irq_lock);
+	guc->msg_enabled_mask &= ~(INTEL_GUC_RECV_MSG_FLUSH_LOG_BUFFER |
+				   INTEL_GUC_RECV_MSG_CRASH_DUMP_POSTED);
+	spin_unlock_irq(&guc->irq_lock);
+}
+
 void intel_guc_log_destroy(struct intel_guc *guc)
 {
 	guc_log_runtime_destroy(guc);
@@ -687,12 +703,7 @@  int intel_guc_log_register(struct intel_guc *guc)
 	if (ret)
 		goto err_runtime;
 
-	/* GuC logging is currently the only user of Guc2Host interrupts */
-	mutex_lock(&dev_priv->drm.struct_mutex);
-	intel_runtime_pm_get(dev_priv);
-	gen9_enable_guc_interrupts(dev_priv);
-	intel_runtime_pm_put(dev_priv);
-	mutex_unlock(&dev_priv->drm.struct_mutex);
+	guc_log_flush_irq_enable(guc);
 
 	return 0;
 
@@ -717,13 +728,9 @@  void intel_guc_log_unregister(struct intel_guc *guc)
 	 * buffer state and then collect the left over logs.
 	 */
 	guc_flush_logs(guc);
+	guc_log_flush_irq_disable(guc);
 
 	mutex_lock(&dev_priv->drm.struct_mutex);
-	/* GuC logging is currently the only user of Guc2Host interrupts */
-	intel_runtime_pm_get(dev_priv);
-	gen9_disable_guc_interrupts(dev_priv);
-	intel_runtime_pm_put(dev_priv);
-
 	guc_log_runtime_destroy(guc);
 	mutex_unlock(&dev_priv->drm.struct_mutex);
 
diff --git a/drivers/gpu/drm/i915/intel_uc.c b/drivers/gpu/drm/i915/intel_uc.c
index 3f41ef525e26..e9aba3c35264 100644
--- a/drivers/gpu/drm/i915/intel_uc.c
+++ b/drivers/gpu/drm/i915/intel_uc.c
@@ -239,6 +239,8 @@  static int guc_enable_communication(struct intel_guc *guc)
 {
 	struct drm_i915_private *dev_priv = guc_to_i915(guc);
 
+	gen9_enable_guc_interrupts(dev_priv);
+
 	if (HAS_GUC_CT(dev_priv))
 		return intel_guc_enable_ct(guc);
 
@@ -253,6 +255,8 @@  static void guc_disable_communication(struct intel_guc *guc)
 	if (HAS_GUC_CT(dev_priv))
 		intel_guc_disable_ct(guc);
 
+	gen9_disable_guc_interrupts(dev_priv);
+
 	guc->send = intel_guc_send_nop;
 }
 
@@ -391,12 +395,9 @@  int intel_uc_init_hw(struct drm_i915_private *dev_priv)
 	}
 
 	if (USES_GUC_SUBMISSION(dev_priv)) {
-		if (i915_modparams.guc_log_level)
-			gen9_enable_guc_interrupts(dev_priv);
-
 		ret = intel_guc_submission_enable(guc);
 		if (ret)
-			goto err_interrupts;
+			goto err_communication;
 	}
 
 	dev_info(dev_priv->drm.dev, "GuC firmware version %u.%u\n",
@@ -411,8 +412,6 @@  int intel_uc_init_hw(struct drm_i915_private *dev_priv)
 	/*
 	 * We've failed to load the firmware :(
 	 */
-err_interrupts:
-	gen9_disable_guc_interrupts(dev_priv);
 err_communication:
 	guc_disable_communication(guc);
 err_log_capture:
@@ -442,7 +441,4 @@  void intel_uc_fini_hw(struct drm_i915_private *dev_priv)
 		intel_guc_submission_disable(guc);
 
 	guc_disable_communication(guc);
-
-	if (USES_GUC_SUBMISSION(dev_priv))
-		gen9_disable_guc_interrupts(dev_priv);
 }