This is an automated email from the ASF dual-hosted git repository.

xiaoxiang pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/nuttx.git

commit 72bba3b2ee088eb0898860dd823830f7435518f2
Author: Ville Juven <ville.ju...@unikie.com>
AuthorDate: Tue Apr 22 12:25:06 2025 +0300

    mpfs_emmcsd/coremmc.c: Fix interrupt handling in SMP mode
    
    In SMP mode one CPU can be executing the MMC interrupt while another CPU
    disables (e.g. via watchdog timeout). As it is disabled the other CPU
    assumes it's safe to start configuring the device after this.
    
    This causes a leak in the driver's private data as well as a mutual
    exclusion leak on the device itself.
    
    Fix this by aborting any triggered interrupt by checking whether it's
    even enabled.
    
    Signed-off-by: Jukka Laitinen <jukka.laiti...@tii.ae>
---
 arch/risc-v/src/mpfs/mpfs_coremmc.c | 34 +++++++++++++++++++++++++++++++++-
 arch/risc-v/src/mpfs/mpfs_emmcsd.c  | 14 ++++++++++++++
 2 files changed, 47 insertions(+), 1 deletion(-)

diff --git a/arch/risc-v/src/mpfs/mpfs_coremmc.c 
b/arch/risc-v/src/mpfs/mpfs_coremmc.c
index d8d260d080a..b7731f0406c 100644
--- a/arch/risc-v/src/mpfs/mpfs_coremmc.c
+++ b/arch/risc-v/src/mpfs/mpfs_coremmc.c
@@ -654,7 +654,7 @@ static void mpfs_recvfifo(struct mpfs_dev_s *priv)
         }
     }
 
-    mcinfo("Read all\n");
+  mcinfo("Read all\n");
 }
 
 /****************************************************************************
@@ -818,6 +818,22 @@ static int mpfs_coremmc_wrcomplete_interrupt(int irq, void 
*context,
 
   DEBUGASSERT(priv != NULL);
 
+#ifdef CONFIG_SPINLOCK
+  spin_lock(&priv->lock);
+
+  /* Check if the write complete event is enabled */
+
+  if ((priv->waitevents & SDIOWAIT_WRCOMPLETE) == 0)
+    {
+      spin_unlock(&priv->lock);
+      return OK;
+    }
+
+  spin_unlock(&priv->lock);
+#endif
+
+  /* Note: the spin lock must NOT be held when calling mpfs_endwait */
+
   mpfs_endwait(priv, SDIOWAIT_WRCOMPLETE);
 
   return OK;
@@ -846,6 +862,22 @@ static int mpfs_coremmc_interrupt(int irq, void *context, 
void *arg)
 
   DEBUGASSERT(priv != NULL);
 
+#ifdef CONFIG_SPINLOCK
+  spin_lock(&priv->lock);
+
+  /* Check if any of the interrupt sources are even enabled */
+
+  if (priv->xfrmask == 0 && priv->waitmask == 0 && priv->xfr_blkmask == 0)
+    {
+      spin_unlock(&priv->lock);
+      return OK;
+    }
+
+  spin_unlock(&priv->lock);
+#endif
+
+  /* Note: the spin lock must NOT be held when calling mpfs_endtransfer */
+
   status = getreg8(MPFS_COREMMC_ISR);
 
   if (priv->multiblock)
diff --git a/arch/risc-v/src/mpfs/mpfs_emmcsd.c 
b/arch/risc-v/src/mpfs/mpfs_emmcsd.c
index a627fe12ad1..86358cf8542 100644
--- a/arch/risc-v/src/mpfs/mpfs_emmcsd.c
+++ b/arch/risc-v/src/mpfs/mpfs_emmcsd.c
@@ -986,6 +986,20 @@ static int mpfs_emmcsd_interrupt(int irq, void *context, 
void *arg)
 
   DEBUGASSERT(priv != NULL);
 
+#ifdef CONFIG_SPINLOCK
+  spin_lock(&priv->lock);
+
+  /* Check if any of the interrupt sources are even enabled */
+
+  if (priv->xfrmask == 0 && priv->waitmask == 0 && priv->xfr_blkmask == 0)
+    {
+      spin_unlock(&priv->lock);
+      return OK;
+    }
+
+  spin_unlock(&priv->lock);
+#endif
+
   status = getreg32(MPFS_EMMCSD_SRS12);
 
   mcinfo("status: %08" PRIx32 "\n", status);

Reply via email to