Sfoglia il codice sorgente

disp: msm: sde: avoid double clearing of INTR registers

When there is CPU processing delay between first INTR clear and
second INTR clear there is a chance that the second register
write might clear the next frames interrupts which will avoid
triggering the irq callbacks causing software hung. This
patch avoids such a scenario by removing such double clearing
of INTR registers.

Change-Id: I8407991769c69d2d2c691763240671d5f3c0416d
Signed-off-by: Mahadevan <[email protected]>
Mahadevan 1 anno fa
parent
commit
859ee56480
3 ha cambiato i file con 3 aggiunte e 27 eliminazioni
  1. 1 10
      msm/sde/sde_core_irq.c
  2. 2 8
      msm/sde/sde_hw_interrupts.c
  3. 0 9
      msm/sde/sde_hw_interrupts.h

+ 1 - 10
msm/sde/sde_core_irq.c

@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0-only
 /*
- * Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved.
  * Copyright (c) 2015-2021, The Linux Foundation. All rights reserved.
  */
 
@@ -66,15 +66,6 @@ static void sde_core_irq_callback_handler(void *arg, int irq_idx)
 			SDE_EVT32_IRQ(irq_idx, enable_counts, SDE_EVTLOG_ERROR);
 		}
 	}
-
-	/*
-	 * Clear pending interrupt status in HW.
-	 * NOTE: sde_core_irq_callback_handler is protected by top-level
-	 *       spinlock, so it is safe to clear any interrupt status here.
-	 */
-	sde_kms->hw_intr->ops.clear_intr_status_nolock(
-			sde_kms->hw_intr,
-			irq_idx);
 }
 
 int sde_core_irq_idx_lookup(struct sde_kms *sde_kms,

+ 2 - 8
msm/sde/sde_hw_interrupts.c

@@ -478,16 +478,11 @@ static void sde_hw_intr_dispatch_irq(struct sde_hw_intr *intr,
 				 reg_idx)) {
 				/*
 				 * Once a match on irq mask, perform a callback
-				 * to the given cbfunc. cbfunc will take care
-				 * the interrupt status clearing. If cbfunc is
-				 * not provided, then the interrupt clearing
-				 * is here.
+				 * to the given cbfunc. This callback is done
+				 * after clearing the interrupt registers.
 				 */
 				if (cbfunc)
 					cbfunc(arg, irq_idx);
-				else
-					intr->ops.clear_intr_status_nolock(
-							intr, irq_idx);
 
 				/*
 				 * When callback finish, clear the irq_status
@@ -851,7 +846,6 @@ static void __setup_intr_ops(struct sde_hw_intr_ops *ops)
 	ops->disable_all_irqs = sde_hw_intr_disable_irqs;
 	ops->get_interrupt_sources = sde_hw_intr_get_interrupt_sources;
 	ops->clear_interrupt_status = sde_hw_intr_clear_interrupt_status;
-	ops->clear_intr_status_nolock = sde_hw_intr_clear_intr_status_nolock;
 	ops->get_interrupt_status = sde_hw_intr_get_interrupt_status;
 	ops->get_intr_status_nolock = sde_hw_intr_get_intr_status_nolock;
 }

+ 0 - 9
msm/sde/sde_hw_interrupts.h

@@ -182,15 +182,6 @@ struct sde_hw_intr_ops {
 			struct sde_hw_intr *intr,
 			int irq_idx);
 
-	/**
-	 * clear_intr_status_nolock() - clears the HW interrupts without lock
-	 * @intr:	HW interrupt handle
-	 * @irq_idx:	Lookup irq index return from irq_idx_lookup
-	 */
-	void (*clear_intr_status_nolock)(
-			struct sde_hw_intr *intr,
-			int irq_idx);
-
 	/**
 	 * get_interrupt_status - Gets HW interrupt status, and clear if set,
 	 *                        based on given lookup IRQ index.