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);