[PATCH v3] drm/i915/guc: Add synchronization on interrupt enable flag

Dong, Zhanjun zhanjun.dong at intel.com
Mon Aug 25 21:33:57 UTC 2025


The skip on disabled case for tasklet add in v2, effected part:
diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c 
b/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c
index 380a11c92d63..f0ee3f1235d4 100644
--- a/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c
+++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c
@@ -1326,6 +1326,9 @@  static void ct_try_receive_message(struct 
intel_guc_ct *ct)
  {
  	int ret;

+	if (!atomic_read(&ct_to_guc(ct)->interrupts.enabled))
+		return;
+
  	if (GEM_WARN_ON(!ct->enabled))
  		return;

This part was dropped, caller intel_guc_to_host_event_handler already 
did that check.

Regards,
Zhanjun Dong

On 2025-08-25 5:19 p.m., Zhanjun Dong wrote:
> Boolean flag access from interrupt context might have synchronous issueis
> on multiple processor platform, flags modified by one core might be read
> as an old value by another core. This issue on interrupt enable flag might
> causes interrupt misses or leakage.
> Change the interrupts.enable type to atomic to ensure memory
> synchronization.
> 
> Fixes: a187f13d51fa0 ("drm/i915/guc: handle interrupts from media GuC")
> Closes: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/14834
> Signed-off-by: Zhanjun Dong <zhanjun.dong at intel.com>
> Cc: Andi Shyti <andi.shyti at kernel.org>
> Cc: Daniele Ceraolo Spurio <daniele.ceraolospurio at intel.com>
> 
> ---
> Change history:
> v3: Drop skip on disabled case for tasklet
>      Drop memory barrier
> v2: Add skip on disabled case for tasklet
>      Add memory barrier after flag changed
>      Add Closes tag and typo fix
> ---
>   drivers/gpu/drm/i915/gt/intel_gt_irq.c |  2 +-
>   drivers/gpu/drm/i915/gt/uc/intel_guc.c | 11 +++++++----
>   drivers/gpu/drm/i915/gt/uc/intel_guc.h |  4 ++--
>   drivers/gpu/drm/i915/gt/uc/intel_uc.c  |  5 +++--
>   4 files changed, 13 insertions(+), 9 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/gt/intel_gt_irq.c b/drivers/gpu/drm/i915/gt/intel_gt_irq.c
> index 75e802e10be2..21804eec8320 100644
> --- a/drivers/gpu/drm/i915/gt/intel_gt_irq.c
> +++ b/drivers/gpu/drm/i915/gt/intel_gt_irq.c
> @@ -20,7 +20,7 @@
>   
>   static void guc_irq_handler(struct intel_guc *guc, u16 iir)
>   {
> -	if (unlikely(!guc->interrupts.enabled))
> +	if (unlikely(!atomic_read(&guc->interrupts.enabled)))
>   		return;
>   
>   	if (iir & GUC_INTR_GUC2HOST)
> diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc.c b/drivers/gpu/drm/i915/gt/uc/intel_guc.c
> index f360f020d8f1..1b8d3bbfa16d 100644
> --- a/drivers/gpu/drm/i915/gt/uc/intel_guc.c
> +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc.c
> @@ -100,8 +100,8 @@ static void gen9_enable_guc_interrupts(struct intel_guc *guc)
>   			 gt->pm_guc_events);
>   	gen6_gt_pm_enable_irq(gt, gt->pm_guc_events);
>   	spin_unlock_irq(gt->irq_lock);
> +	atomic_set(&guc->interrupts.enabled, true);
>   
> -	guc->interrupts.enabled = true;
>   }
>   
>   static void gen9_disable_guc_interrupts(struct intel_guc *guc)
> @@ -109,7 +109,8 @@ static void gen9_disable_guc_interrupts(struct intel_guc *guc)
>   	struct intel_gt *gt = guc_to_gt(guc);
>   
>   	assert_rpm_wakelock_held(&gt->i915->runtime_pm);
> -	guc->interrupts.enabled = false;
> +	atomic_set(&guc->interrupts.enabled, false);
> +
>   
>   	spin_lock_irq(gt->irq_lock);
>   
> @@ -146,14 +147,16 @@ static void gen11_enable_guc_interrupts(struct intel_guc *guc)
>   	__gen11_reset_guc_interrupts(gt);
>   	spin_unlock_irq(gt->irq_lock);
>   
> -	guc->interrupts.enabled = true;
> +	atomic_set(&guc->interrupts.enabled, true);
> +
>   }
>   
>   static void gen11_disable_guc_interrupts(struct intel_guc *guc)
>   {
>   	struct intel_gt *gt = guc_to_gt(guc);
>   
> -	guc->interrupts.enabled = false;
> +	atomic_set(&guc->interrupts.enabled, false);
> +
>   	intel_synchronize_irq(gt->i915);
>   
>   	gen11_reset_guc_interrupts(guc);
> diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc.h b/drivers/gpu/drm/i915/gt/uc/intel_guc.h
> index 053780f562c1..40242bbb166e 100644
> --- a/drivers/gpu/drm/i915/gt/uc/intel_guc.h
> +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc.h
> @@ -93,7 +93,7 @@ struct intel_guc {
>   
>   	/** @interrupts: pointers to GuC interrupt-managing functions. */
>   	struct {
> -		bool enabled;
> +		atomic_t enabled;
>   		void (*reset)(struct intel_guc *guc);
>   		void (*enable)(struct intel_guc *guc);
>   		void (*disable)(struct intel_guc *guc);
> @@ -393,7 +393,7 @@ static inline int intel_guc_send_busy_loop(struct intel_guc *guc,
>   /* Only call this from the interrupt handler code */
>   static inline void intel_guc_to_host_event_handler(struct intel_guc *guc)
>   {
> -	if (guc->interrupts.enabled)
> +	if (atomic_read(&guc->interrupts.enabled))
>   		intel_guc_ct_event_handler(&guc->ct);
>   }
>   
> diff --git a/drivers/gpu/drm/i915/gt/uc/intel_uc.c b/drivers/gpu/drm/i915/gt/uc/intel_uc.c
> index 4a3493e8d433..9d01c3c3d504 100644
> --- a/drivers/gpu/drm/i915/gt/uc/intel_uc.c
> +++ b/drivers/gpu/drm/i915/gt/uc/intel_uc.c
> @@ -659,7 +659,8 @@ void intel_uc_runtime_suspend(struct intel_uc *uc)
>   	struct intel_guc *guc = &uc->guc;
>   
>   	if (!intel_guc_is_ready(guc)) {
> -		guc->interrupts.enabled = false;
> +		atomic_set(&guc->interrupts.enabled, false);
> +
>   		return;
>   	}
>   
> @@ -687,7 +688,7 @@ void intel_uc_suspend(struct intel_uc *uc)
>   	wake_up_all_tlb_invalidate(guc);
>   
>   	if (!intel_guc_is_ready(guc)) {
> -		guc->interrupts.enabled = false;
> +		atomic_set(&guc->interrupts.enabled, false);
>   		return;
>   	}
>   



More information about the Intel-gfx mailing list