From 1501d284c33d073dbdac5767de1cb859ae27726d Mon Sep 17 00:00:00 2001 From: Gregory Nutt Date: Sat, 4 Apr 2020 10:38:16 -0600 Subject: [PATCH] Check return from nxsem_wait_uninterruptible() Resolution of Issue 619 will require multiple steps, this part of the first step in that resolution: Every call to nxsem_wait_uninterruptible() must handle the return value from nxsem_wait_uninterruptible properly. This commit is for all SDIO card drivers under arch/. --- arch/arm/src/cxd56xx/cxd56_sdhci.c | 84 ++++++++++++++++----- arch/arm/src/imxrt/imxrt_usdhc.c | 21 ++++-- arch/arm/src/kinetis/kinetis_sdhc.c | 21 ++++-- arch/arm/src/lpc17xx_40xx/lpc17_40_sdcard.c | 9 ++- arch/arm/src/lpc43xx/lpc43_sdmmc.c | 22 ++++-- arch/arm/src/lpc54xx/lpc54_sdmmc.c | 22 ++++-- arch/arm/src/sam34/sam_hsmci.c | 23 ++++-- arch/arm/src/sama5/sam_hsmci.c | 23 ++++-- arch/arm/src/samv7/sam_hsmci.c | 23 ++++-- arch/arm/src/samv7/sam_twihs.c | 23 +----- arch/arm/src/stm32/stm32_sdio.c | 28 ++++--- arch/arm/src/stm32f7/stm32_sdmmc.c | 28 ++++--- arch/arm/src/stm32h7/stm32_sdmmc.c | 28 ++++--- arch/arm/src/stm32l4/stm32l4_sdmmc.c | 28 ++++--- 14 files changed, 268 insertions(+), 115 deletions(-) diff --git a/arch/arm/src/cxd56xx/cxd56_sdhci.c b/arch/arm/src/cxd56xx/cxd56_sdhci.c index 0af13e0aa0..0028d8a4d8 100644 --- a/arch/arm/src/cxd56xx/cxd56_sdhci.c +++ b/arch/arm/src/cxd56xx/cxd56_sdhci.c @@ -359,7 +359,7 @@ struct cxd56_sdhcregs_s /* Low-level helpers ********************************************************/ -static void cxd56_takesem(struct cxd56_sdiodev_s *priv); +static int cxd56_takesem(struct cxd56_sdiodev_s *priv); #define cxd56_givesem(priv) (nxsem_post(&(priv)->waitsem)) static void cxd56_configwaitints(struct cxd56_sdiodev_s *priv, uint32_t waitints, sdio_eventset_t waitevents, @@ -566,13 +566,14 @@ static FAR uint32_t cxd56_sdhci_adma_dscr[CXD56_SDIO_MAX_LEN_ADMA_DSCR * 2]; * dev - Instance of the SDIO device driver state structure. * * Returned Value: - * None + * Normally OK, but may return -ECANCELED in the rare event that the task + * has been canceled. * ****************************************************************************/ -static void cxd56_takesem(struct cxd56_sdiodev_s *priv) +static int cxd56_takesem(struct cxd56_sdiodev_s *priv) { - nxsem_wait_uninterruptible(&priv->waitsem); + return nxsem_wait_uninterruptible(&priv->waitsem); } /**************************************************************************** @@ -2664,7 +2665,17 @@ static sdio_eventset_t cxd56_sdio_eventwait(FAR struct sdio_dev_s *dev, * there will be no wait. */ - cxd56_takesem(priv); + ret = cxd56_takesem(priv); + if (ret < 0) + { + /* Task canceled. Cancel the wdog (assuming it was started) and + * return an SDIO error. + */ + + wd_cancel(priv->waitwdog); + return SDIOWAIT_ERROR; + } + wkupevent = priv->wkupevent; /* Check if the event has occurred @@ -3233,9 +3244,9 @@ static void cxd56_sdio_callback(void *arg) } #ifdef CONFIG_CXD56_SDIO_ENABLE_MULTIFUNCTION -static void cxd56_sdio_takesem(FAR struct cxd56_sdiodev_s *priv) +static int cxd56_sdio_takesem(FAR struct cxd56_sdiodev_s *priv) { - nxsem_wait_uninterruptible(&priv->sc.sem); + return nxsem_wait_uninterruptible(&priv->sc.sem); } /**************************************************************************** @@ -3732,7 +3743,11 @@ static int cxd56_sdio_register_irq(FAR struct sdio_dev_s *dev, int func_num, return -EBUSY; } - cxd56_sdio_takesem(priv); + ret = cxd56_sdio_takesem(priv); + if (ret < 0) + { + return ret; + } /* enable irq in device side */ @@ -3849,7 +3864,12 @@ static int cxd56_sdio_function_disable(FAR struct sdio_dev_s *dev, sf0 = priv->sc.fn[0]; mcinfo("I/O func's num:%d\n", sf->number); - cxd56_sdio_takesem(priv); + ret = cxd56_sdio_takesem(priv); + if (ret < 0) + { + return ret; + } + ret = cxd56_sdio_readb_internal(sf0, SDIO_CCCR_IOEN, &rv); if (ret) { @@ -3865,6 +3885,7 @@ static int cxd56_sdio_function_disable(FAR struct sdio_dev_s *dev, nxsem_post(&priv->sc.sem); return 0; + FUNC_DIS_ERR: mcerr("ERROR: Io fail ret %u\n", ret); nxsem_post(&priv->sc.sem); @@ -3901,7 +3922,12 @@ static int cxd56_sdio_function_enable(FAR struct sdio_dev_s *dev, return 0; } - cxd56_sdio_takesem(priv); + ret = cxd56_sdio_takesem(priv); + if (ret < 0) + { + return ret; + } + ret = cxd56_sdio_readb_internal(sf0, SDIO_CCCR_IOEN, &rv); if (ret) { @@ -3962,9 +3988,13 @@ static int cxd56_sdio_readb(FAR struct sdio_dev_s *dev, int func_num, struct cxd56_sdiodev_s *priv = (struct cxd56_sdiodev_s *)dev; int ret; - cxd56_sdio_takesem(priv); - ret = cxd56_sdio_readb_internal(priv->sc.fn[func_num], addr, rdata); - nxsem_post(&priv->sc.sem); + ret = cxd56_sdio_takesem(priv); + if (ret >= 0) + { + ret = cxd56_sdio_readb_internal(priv->sc.fn[func_num], addr, rdata); + nxsem_post(&priv->sc.sem); + } + return ret; } @@ -3991,9 +4021,14 @@ static int cxd56_sdio_writeb(FAR struct sdio_dev_s *dev, int func_num, struct cxd56_sdiodev_s *priv = (struct cxd56_sdiodev_s *)dev; int ret; - cxd56_sdio_takesem(priv); - ret = cxd56_sdio_writeb_internal(priv->sc.fn[func_num], addr, data, rdata); - nxsem_post(&priv->sc.sem); + ret = cxd56_sdio_takesem(priv); + if (ret >= 0) + { + ret = cxd56_sdio_writeb_internal(priv->sc.fn[func_num], addr, data, + data); + nxsem_post(&priv->sc.sem); + } + return ret; } @@ -4014,7 +4049,8 @@ static int cxd56_sdio_writeb(FAR struct sdio_dev_s *dev, int func_num, ****************************************************************************/ static int cxd56_sdio_write(FAR struct sdio_dev_s *dev, int func_num, - uint32_t addr, FAR uint8_t * data, uint32_t size) + uint32_t addr, FAR uint8_t * data, + uint32_t size) { uint32_t remainder = size; int ret; @@ -4028,7 +4064,12 @@ static int cxd56_sdio_write(FAR struct sdio_dev_s *dev, int func_num, /* Do the bulk of the transfer using block mode (if supported). */ - cxd56_sdio_takesem(priv); + ret = cxd56_sdio_takesem(priv); + if (ret < 0) + { + return ret; + } + if (size >= SDIO_BLOCK_SIZE) { while (remainder >= SDIO_BLOCK_SIZE) @@ -4165,7 +4206,12 @@ static int cxd56_sdio_read(FAR struct sdio_dev_s *dev, int func_num, /* Do the bulk of the transfer using block mode (if supported). */ - cxd56_sdio_takesem(priv); + ret = cxd56_sdio_takesem(priv); + if (ret < 0) + { + return ret; + } + if (size >= SDIO_BLOCK_SIZE) { while (remainder >= SDIO_BLOCK_SIZE) diff --git a/arch/arm/src/imxrt/imxrt_usdhc.c b/arch/arm/src/imxrt/imxrt_usdhc.c index e582455c83..40b4b6e626 100644 --- a/arch/arm/src/imxrt/imxrt_usdhc.c +++ b/arch/arm/src/imxrt/imxrt_usdhc.c @@ -254,7 +254,7 @@ struct imxrt_sdhcregs_s /* Low-level helpers ********************************************************/ -static void imxrt_takesem(struct imxrt_dev_s *priv); +static int imxrt_takesem(struct imxrt_dev_s *priv); #define imxrt_givesem(priv) (nxsem_post(&priv->waitsem)) static void imxrt_configwaitints(struct imxrt_dev_s *priv, uint32_t waitints, sdio_eventset_t waitevents, sdio_eventset_t wkupevents); @@ -514,13 +514,14 @@ static struct imxrt_sdhcregs_s g_sampleregs[DEBUG_NSAMPLES]; * dev - Instance of the SDIO device driver state structure. * * Returned Value: - * None + * Normally OK, but may return -ECANCELED in the rare event that the task + * has been canceled. * ****************************************************************************/ -static void imxrt_takesem(struct imxrt_dev_s *priv) +static int imxrt_takesem(struct imxrt_dev_s *priv) { - nxsem_wait_uninterruptible(&priv->waitsem); + return nxsem_wait_uninterruptible(&priv->waitsem); } /**************************************************************************** @@ -2724,7 +2725,17 @@ static sdio_eventset_t imxrt_eventwait(FAR struct sdio_dev_s *dev, * incremented and there will be no wait. */ - imxrt_takesem(priv); + ret = imxrt_takesem(priv); + if (ret < 0) + { + /* Task canceled. Cancel the wdog (assuming it was started) and + * return an SDIO error. + */ + + wd_cancel(priv->waitwdog); + return SDIOWAIT_ERROR; + } + wkupevent = priv->wkupevent; /* Check if the event has occurred. When the event has occurred, then diff --git a/arch/arm/src/kinetis/kinetis_sdhc.c b/arch/arm/src/kinetis/kinetis_sdhc.c index a360cb1394..e3fb7c18eb 100644 --- a/arch/arm/src/kinetis/kinetis_sdhc.c +++ b/arch/arm/src/kinetis/kinetis_sdhc.c @@ -229,7 +229,7 @@ struct kinetis_sdhcregs_s /* Low-level helpers ********************************************************/ -static void kinetis_takesem(struct kinetis_dev_s *priv); +static int kinetis_takesem(struct kinetis_dev_s *priv); #define kinetis_givesem(priv) (nxsem_post(&priv->waitsem)) static void kinetis_configwaitints(struct kinetis_dev_s *priv, uint32_t waitints, sdio_eventset_t waitevents, @@ -423,13 +423,14 @@ static struct kinetis_sdhcregs_s g_sampleregs[DEBUG_NSAMPLES]; * dev - Instance of the SDIO device driver state structure. * * Returned Value: - * None + * Normally OK, but may return -ECANCELED in the rare event that the task + * has been canceled. * ****************************************************************************/ -static void kinetis_takesem(struct kinetis_dev_s *priv) +static int kinetis_takesem(struct kinetis_dev_s *priv) { - nxsem_wait_uninterruptible(&priv->waitsem); + return nxsem_wait_uninterruptible(&priv->waitsem); } /**************************************************************************** @@ -2520,7 +2521,17 @@ static sdio_eventset_t kinetis_eventwait(FAR struct sdio_dev_s *dev, * incremented and there will be no wait. */ - kinetis_takesem(priv); + ret = kinetis_takesem(priv); + if (ret < 0) + { + /* Task canceled. Cancel the wdog (assuming it was started) and + * return an SDIO error. + */ + + wd_cancel(priv->waitwdog); + return SDIOWAIT_ERROR; + } + wkupevent = priv->wkupevent; /* Check if the event has occurred. When the event has occurred, then diff --git a/arch/arm/src/lpc17xx_40xx/lpc17_40_sdcard.c b/arch/arm/src/lpc17xx_40xx/lpc17_40_sdcard.c index 36b381af15..e3d5f08439 100644 --- a/arch/arm/src/lpc17xx_40xx/lpc17_40_sdcard.c +++ b/arch/arm/src/lpc17xx_40xx/lpc17_40_sdcard.c @@ -488,7 +488,8 @@ static struct lpc17_40_sampleregs_s g_sampleregs[DEBUG_NSAMPLES]; * dev - Instance of the SD card device driver state structure. * * Returned Value: - * None + * Normally OK, but may return -ECANCELED in the rare event that the task + * has been canceled. * ****************************************************************************/ @@ -2363,10 +2364,12 @@ static sdio_eventset_t lpc17_40_eventwait(FAR struct sdio_dev_s *dev, ret = lpc17_40_takesem(priv); if (ret < 0) { + /* Task canceled. Cancel the wdog (assuming it was started) and + * return an SDIO error. + */ + wd_cancel(priv->waitwdog); - leave_critical_section(flags); - return SDIOWAIT_ERROR; } diff --git a/arch/arm/src/lpc43xx/lpc43_sdmmc.c b/arch/arm/src/lpc43xx/lpc43_sdmmc.c index a41106a885..b5e93ae5029 100644 --- a/arch/arm/src/lpc43xx/lpc43_sdmmc.c +++ b/arch/arm/src/lpc43xx/lpc43_sdmmc.c @@ -271,7 +271,7 @@ static void lpc43_putreg(uint32_t val, uint32_t addr); /* Low-level helpers ********************************************************/ -static void lpc43_takesem(struct lpc43_dev_s *priv); +static int lpc43_takesem(struct lpc43_dev_s *priv); #define lpc43_givesem(priv) (nxsem_post(&priv->waitsem)) static inline void lpc43_setclock(uint32_t clkdiv); static inline void lpc43_sdcard_clock(bool enable); @@ -525,13 +525,14 @@ static void lpc43_putreg(uint32_t val, uint32_t addr) * dev - Instance of the SD card device driver state structure. * * Returned Value: - * None + * Normally OK, but may return -ECANCELED in the rare event that the task + * has been canceled. * ****************************************************************************/ -static void lpc43_takesem(struct lpc43_dev_s *priv) +static int lpc43_takesem(struct lpc43_dev_s *priv) { - nxsem_wait_uninterruptible(&priv->waitsem); + return nxsem_wait_uninterruptible(&priv->waitsem); } /**************************************************************************** @@ -2329,7 +2330,18 @@ static sdio_eventset_t lpc43_eventwait(FAR struct sdio_dev_s *dev, * incremented and there will be no wait. */ - lpc43_takesem(priv); + ret = lpc43_takesem(priv); + if (ret < 0) + { + /* Task canceled. Cancel the wdog -- assuming it was started and + * return an SDIO error. + */ + + wd_cancel(priv->waitwdog); + leave_critical_section(flags); + return SDIOWAIT_ERROR; + } + wkupevent = priv->wkupevent; /* Check if the event has occurred. When the event has occurred, then diff --git a/arch/arm/src/lpc54xx/lpc54_sdmmc.c b/arch/arm/src/lpc54xx/lpc54_sdmmc.c index be8c0d2a8a..c9878a3f24 100644 --- a/arch/arm/src/lpc54xx/lpc54_sdmmc.c +++ b/arch/arm/src/lpc54xx/lpc54_sdmmc.c @@ -275,7 +275,7 @@ static void lpc54_putreg(uint32_t val, uint32_t addr); /* Low-level helpers ********************************************************/ -static void lpc54_takesem(struct lpc54_dev_s *priv); +static int lpc54_takesem(struct lpc54_dev_s *priv); #define lpc54_givesem(priv) (nxsem_post(&priv->waitsem)) static inline void lpc54_setclock(uint32_t clkdiv); static inline void lpc54_sdcard_clock(bool enable); @@ -529,13 +529,14 @@ static void lpc54_putreg(uint32_t val, uint32_t addr) * dev - Instance of the SD card device driver state structure. * * Returned Value: - * None + * Normally OK, but may return -ECANCELED in the rare event that the task + * has been canceled. * ****************************************************************************/ -static void lpc54_takesem(struct lpc54_dev_s *priv) +static int lpc54_takesem(struct lpc54_dev_s *priv) { - nxsem_wait_uninterruptible(&priv->waitsem); + return nxsem_wait_uninterruptible(&priv->waitsem); } /**************************************************************************** @@ -2329,7 +2330,18 @@ static sdio_eventset_t lpc54_eventwait(FAR struct sdio_dev_s *dev, * incremented and there will be no wait. */ - lpc54_takesem(priv); + ret = lpc54_takesem(priv); + if (ret < 0) + { + /* Task canceled. Cancel the wdog (assuming it was started) and + * return an SDIO error. + */ + + wd_cancel(priv->waitwdog); + leave_critical_section(flags); + return SDIOWAIT_ERROR; + } + wkupevent = priv->wkupevent; /* Check if the event has occurred. When the event has occurred, then diff --git a/arch/arm/src/sam34/sam_hsmci.c b/arch/arm/src/sam34/sam_hsmci.c index 5324a45ec1..851fb81143 100644 --- a/arch/arm/src/sam34/sam_hsmci.c +++ b/arch/arm/src/sam34/sam_hsmci.c @@ -394,7 +394,7 @@ struct sam_xfrregs_s /* Low-level helpers ********************************************************/ -static void sam_takesem(struct sam_dev_s *priv); +static int sam_takesem(struct sam_dev_s *priv); #define sam_givesem(priv) (nxsem_post(&priv->waitsem)) static void sam_configwaitints(struct sam_dev_s *priv, uint32_t waitmask, @@ -575,13 +575,14 @@ static bool g_cmdinitialized; * dev - Instance of the SDIO device driver state structure. * * Returned Value: - * None + * Normally OK, but may return -ECANCELED in the rare event that the task + * has been canceled. * ****************************************************************************/ -static void sam_takesem(struct sam_dev_s *priv) +static int sam_takesem(struct sam_dev_s *priv) { - nxsem_wait_uninterruptible(&priv->waitsem); + return nxsem_wait_uninterruptible(&priv->waitsem); } /**************************************************************************** @@ -2342,7 +2343,19 @@ static sdio_eventset_t sam_eventwait(FAR struct sdio_dev_s *dev, * incremented and there will be no wait. */ - sam_takesem(priv); + ret = sam_takesem(priv); + if (ret < 0) + { + /* Task canceled. Cancel the wdog (assuming it was started), + * disable all event, and return an SDIO error. + */ + + wd_cancel(priv->waitwdog); + sam_disablexfrints(priv); + sam_disablewaitints(priv, SDIOWAIT_ERROR); + return SDIOWAIT_ERROR; + } + wkupevent = priv->wkupevent; /* Check if the event has occurred. When the event has occurred, then diff --git a/arch/arm/src/sama5/sam_hsmci.c b/arch/arm/src/sama5/sam_hsmci.c index a226b18ddc..bb4c80729b 100644 --- a/arch/arm/src/sama5/sam_hsmci.c +++ b/arch/arm/src/sama5/sam_hsmci.c @@ -458,7 +458,7 @@ struct sam_dev_s /* Low-level helpers ********************************************************/ -static void sam_takesem(struct sam_dev_s *priv); +static int sam_takesem(struct sam_dev_s *priv); #define sam_givesem(priv) (nxsem_post(&priv->waitsem)) #ifdef CONFIG_SAMA5_HSMCI_REGDEBUG @@ -668,13 +668,14 @@ static struct sam_dev_s g_hsmci2; * dev - Instance of the SDIO device driver state structure. * * Returned Value: - * None + * Normally OK, but may return -ECANCELED in the rare event that the task + * has been canceled. * ****************************************************************************/ -static void sam_takesem(struct sam_dev_s *priv) +static int sam_takesem(struct sam_dev_s *priv) { - nxsem_wait_uninterruptible(&priv->waitsem); + return nxsem_wait_uninterruptible(&priv->waitsem); } /**************************************************************************** @@ -2763,7 +2764,19 @@ static sdio_eventset_t sam_eventwait(FAR struct sdio_dev_s *dev, * incremented and there will be no wait. */ - sam_takesem(priv); + ret = sam_takesem(priv); + if (ret < 0) + { + /* Task canceled. Cancel the wdog (assuming it was started), + * disable all event, and return an SDIO error. + */ + + wd_cancel(priv->waitwdog); + sam_disablexfrints(priv); + sam_disablewaitints(priv, SDIOWAIT_ERROR); + return SDIOWAIT_ERROR; + } + wkupevent = priv->wkupevent; /* Check if the event has occurred. When the event has occurred, then diff --git a/arch/arm/src/samv7/sam_hsmci.c b/arch/arm/src/samv7/sam_hsmci.c index ece88b472f..82e79051b9 100644 --- a/arch/arm/src/samv7/sam_hsmci.c +++ b/arch/arm/src/samv7/sam_hsmci.c @@ -393,7 +393,7 @@ struct sam_dev_s /* Low-level helpers ********************************************************/ -static void sam_takesem(struct sam_dev_s *priv); +static int sam_takesem(struct sam_dev_s *priv); #define sam_givesem(priv) (nxsem_post(&priv->waitsem)) #ifdef CONFIG_SAMV7_HSMCI_REGDEBUG @@ -600,13 +600,14 @@ static struct sam_dev_s g_hsmci1; * dev - Instance of the SDIO device driver state structure. * * Returned Value: - * None + * Normally OK, but may return -ECANCELED in the rare event that the task + * has been canceled. * ****************************************************************************/ -static void sam_takesem(struct sam_dev_s *priv) +static int sam_takesem(struct sam_dev_s *priv) { - nxsem_wait_uninterruptible(&priv->waitsem); + return nxsem_wait_uninterruptible(&priv->waitsem); } /**************************************************************************** @@ -2811,7 +2812,19 @@ static sdio_eventset_t sam_eventwait(FAR struct sdio_dev_s *dev, * incremented and there will be no wait. */ - sam_takesem(priv); + ret = sam_takesem(priv); + if (ret < 0) + { + /* Task canceled. Cancel the wdog (assuming it was started), + * disable all event, and return an SDIO error. + */ + + wd_cancel(priv->waitwdog); + sam_disablexfrints(priv); + sam_disablewaitints(priv, SDIOWAIT_ERROR); + return SDIOWAIT_ERROR; + } + wkupevent = priv->wkupevent; /* Check if the event has occurred. When the event has occurred, then diff --git a/arch/arm/src/samv7/sam_twihs.c b/arch/arm/src/samv7/sam_twihs.c index 9d75440111..0d778e6272 100644 --- a/arch/arm/src/samv7/sam_twihs.c +++ b/arch/arm/src/samv7/sam_twihs.c @@ -181,7 +181,6 @@ struct twi_dev_s /* Low-level helper functions */ static int twi_takesem(sem_t *sem); -static int twi_takesem_uninterruptible(sem_t *sem); #define twi_givesem(sem) (nxsem_post(sem)) #ifdef CONFIG_SAMV7_TWIHSHS_REGDEBUG @@ -321,26 +320,6 @@ static int twi_takesem(sem_t *sem) return nxsem_wait(sem); } -/**************************************************************************** - * Name: twi_takesem_uninterruptible - * - * Description: - * Take the wait semaphore (handling false alarm wake-ups due to the - * receipt of signals). - * - * Input Parameters: - * dev - Instance of the SDIO device driver state structure. - * - * Returned Value: - * None - * - ****************************************************************************/ - -static int twi_takesem_uninterruptible(sem_t *sem) -{ - return nxsem_wait_uninterruptible(sem); -} - /**************************************************************************** * Name: twi_checkreg * @@ -1156,7 +1135,7 @@ static int twi_reset(FAR struct i2c_master_s *dev) /* Get exclusive access to the TWIHS device */ - ret = twi_takesem_uninterruptible(&priv->exclsem); + ret = twi_takesem(&priv->exclsem); if (ret >= 0) { /* Do the reset-procedure */ diff --git a/arch/arm/src/stm32/stm32_sdio.c b/arch/arm/src/stm32/stm32_sdio.c index ec1f001712..1cf001b55e 100644 --- a/arch/arm/src/stm32/stm32_sdio.c +++ b/arch/arm/src/stm32/stm32_sdio.c @@ -379,7 +379,7 @@ struct stm32_sampleregs_s /* Low-level helpers ********************************************************/ -static void stm32_takesem(struct stm32_dev_s *priv); +static int stm32_takesem(struct stm32_dev_s *priv); #define stm32_givesem(priv) (nxsem_post(&priv->waitsem)) static inline void stm32_setclkcr(uint32_t clkcr); static void stm32_configwaitints(struct stm32_dev_s *priv, uint32_t waitmask, @@ -573,13 +573,14 @@ static struct stm32_sampleregs_s g_sampleregs[DEBUG_NSAMPLES]; * dev - Instance of the SDIO device driver state structure. * * Returned Value: - * None + * Normally OK, but may return -ECANCELED in the rare event that the task + * has been canceled. * ****************************************************************************/ -static void stm32_takesem(struct stm32_dev_s *priv) +static int stm32_takesem(struct stm32_dev_s *priv) { - nxsem_wait_uninterruptible(&priv->waitsem); + return nxsem_wait_uninterruptible(&priv->waitsem); } /**************************************************************************** @@ -2512,7 +2513,7 @@ static sdio_eventset_t stm32_eventwait(FAR struct sdio_dev_s *dev, if (priv->waitevents == 0 && priv->wkupevent == 0) { wkupevent = SDIOWAIT_ERROR; - goto erroutdisable; + goto errout_with_waitints; } #else @@ -2576,7 +2577,18 @@ static sdio_eventset_t stm32_eventwait(FAR struct sdio_dev_s *dev, * incremented and there will be no wait. */ - stm32_takesem(priv); + ret = stm32_takesem(priv); + if (ret < 0) + { + /* Task canceled. Cancel the wdog (assuming it was started) and + * return an SDIO error. + */ + + wd_cancel(priv->waitwdog); + wkupevent = SDIOWAIT_ERROR; + goto errout_with_waitints; + } + wkupevent = priv->wkupevent; /* Check if the event has occurred. When the event has occurred, then @@ -2594,9 +2606,7 @@ static sdio_eventset_t stm32_eventwait(FAR struct sdio_dev_s *dev, /* Disable event-related interrupts */ -#if defined(CONFIG_MMCSD_SDIOWAIT_WRCOMPLETE) -erroutdisable: -#endif +errout_with_waitints: stm32_configwaitints(priv, 0, 0, 0); #ifdef CONFIG_STM32_SDIO_DMA diff --git a/arch/arm/src/stm32f7/stm32_sdmmc.c b/arch/arm/src/stm32f7/stm32_sdmmc.c index e2a1458dd8..34870f7b00 100644 --- a/arch/arm/src/stm32f7/stm32_sdmmc.c +++ b/arch/arm/src/stm32f7/stm32_sdmmc.c @@ -471,7 +471,7 @@ struct stm32_sampleregs_s static inline void sdmmc_putreg32(struct stm32_dev_s *priv, uint32_t value, int offset); static inline uint32_t sdmmc_getreg32(struct stm32_dev_s *priv, int offset); -static void stm32_takesem(struct stm32_dev_s *priv); +static int stm32_takesem(struct stm32_dev_s *priv); #define stm32_givesem(priv) (nxsem_post(&priv->waitsem)) static inline void stm32_setclkcr(struct stm32_dev_s *priv, uint32_t clkcr); static void stm32_configwaitints(struct stm32_dev_s *priv, uint32_t waitmask, @@ -786,13 +786,14 @@ static inline void sdmmc_modifyreg32(struct stm32_dev_s *priv, int offset, * priv - Instance of the SDMMC private state structure. * * Returned Value: - * None + * Normally OK, but may return -ECANCELED in the rare event that the task + * has been canceled. * ****************************************************************************/ -static void stm32_takesem(struct stm32_dev_s *priv) +static int stm32_takesem(struct stm32_dev_s *priv) { - nxsem_wait_uninterruptible(&priv->waitsem); + return nxsem_wait_uninterruptible(&priv->waitsem); } /**************************************************************************** @@ -2794,7 +2795,7 @@ static sdio_eventset_t stm32_eventwait(FAR struct sdio_dev_s *dev, if (priv->waitevents == 0 && priv->wkupevent == 0) { wkupevent = SDIOWAIT_ERROR; - goto erroutdisable; + goto errout_with_waitints; } #else @@ -2858,7 +2859,18 @@ static sdio_eventset_t stm32_eventwait(FAR struct sdio_dev_s *dev, * incremented and there will be no wait. */ - stm32_takesem(priv); + ret = stm32_takesem(priv); + if (ret < 0) + { + /* Task canceled. Cancel the wdog (assuming it was started) and + * return an SDIO error. + */ + + wd_cancel(priv->waitwdog); + wkupevent = SDIOWAIT_ERROR; + goto errout_with_waitints; + } + wkupevent = priv->wkupevent; /* Check if the event has occurred. When the event has occurred, then @@ -2876,9 +2888,7 @@ static sdio_eventset_t stm32_eventwait(FAR struct sdio_dev_s *dev, /* Disable event-related interrupts */ -#if defined(CONFIG_MMCSD_SDIOWAIT_WRCOMPLETE) -erroutdisable: -#endif +errout_with_waitints: stm32_configwaitints(priv, 0, 0, 0); #ifdef CONFIG_STM32F7_SDMMC_DMA diff --git a/arch/arm/src/stm32h7/stm32_sdmmc.c b/arch/arm/src/stm32h7/stm32_sdmmc.c index f5c329cd7c..f6927716f0 100644 --- a/arch/arm/src/stm32h7/stm32_sdmmc.c +++ b/arch/arm/src/stm32h7/stm32_sdmmc.c @@ -392,7 +392,7 @@ struct stm32_sampleregs_s static inline void sdmmc_putreg32(struct stm32_dev_s *priv, uint32_t value, int offset); static inline uint32_t sdmmc_getreg32(struct stm32_dev_s *priv, int offset); -static void stm32_takesem(struct stm32_dev_s *priv); +static int stm32_takesem(struct stm32_dev_s *priv); #define stm32_givesem(priv) (nxsem_post(&priv->waitsem)) static inline void stm32_setclkcr(struct stm32_dev_s *priv, uint32_t clkcr); static void stm32_configwaitints(struct stm32_dev_s *priv, uint32_t waitmask, @@ -679,13 +679,14 @@ static inline void sdmmc_modifyreg32(struct stm32_dev_s *priv, int offset, * priv - Instance of the SDMMC private state structure. * * Returned Value: - * None + * Normally OK, but may return -ECANCELED in the rare event that the task + * has been canceled. * ****************************************************************************/ -static void stm32_takesem(struct stm32_dev_s *priv) +static int stm32_takesem(struct stm32_dev_s *priv) { - nxsem_wait_uninterruptible(&priv->waitsem); + return nxsem_wait_uninterruptible(&priv->waitsem); } /**************************************************************************** @@ -2698,7 +2699,7 @@ static sdio_eventset_t stm32_eventwait(FAR struct sdio_dev_s *dev, if (priv->waitevents == 0 && priv->wkupevent == 0) { wkupevent = SDIOWAIT_ERROR; - goto erroutdisable; + goto errout_with_waitints; } #else @@ -2762,7 +2763,18 @@ static sdio_eventset_t stm32_eventwait(FAR struct sdio_dev_s *dev, * incremented and there will be no wait. */ - stm32_takesem(priv); + ret = stm32_takesem(priv); + if (ret < 0) + { + /* Task canceled. Cancel the wdog (assuming it was started) and + * return an SDIO error. + */ + + wd_cancel(priv->waitwdog); + wkupevent = SDIOWAIT_ERROR; + goto errout_with_waitints; + } + wkupevent = priv->wkupevent; /* Check if the event has occurred. When the event has occurred, then @@ -2780,9 +2792,7 @@ static sdio_eventset_t stm32_eventwait(FAR struct sdio_dev_s *dev, /* Disable event-related interrupts */ -#if defined(CONFIG_MMCSD_SDIOWAIT_WRCOMPLETE) -erroutdisable: -#endif +errout_with_waitints: stm32_configwaitints(priv, 0, 0, 0); diff --git a/arch/arm/src/stm32l4/stm32l4_sdmmc.c b/arch/arm/src/stm32l4/stm32l4_sdmmc.c index 5d75f93827..a4ef5c48e1 100644 --- a/arch/arm/src/stm32l4/stm32l4_sdmmc.c +++ b/arch/arm/src/stm32l4/stm32l4_sdmmc.c @@ -408,7 +408,7 @@ struct stm32_sampleregs_s static inline void sdmmc_putreg32(struct stm32_dev_s *priv, uint32_t value, int offset); static inline uint32_t sdmmc_getreg32(struct stm32_dev_s *priv, int offset); -static void stm32_takesem(struct stm32_dev_s *priv); +static int stm32_takesem(struct stm32_dev_s *priv); #define stm32_givesem(priv) (nxsem_post(&priv->waitsem)) static inline void stm32_setclkcr(struct stm32_dev_s *priv, uint32_t clkcr); static void stm32_configwaitints(struct stm32_dev_s *priv, uint32_t waitmask, @@ -703,13 +703,14 @@ static inline void sdmmc_modifyreg32(struct stm32_dev_s *priv, int offset, * priv - Instance of the SDMMC private state structure. * * Returned Value: - * None + * Normally OK, but may return -ECANCELED in the rare event that the task + * has been canceled. * ****************************************************************************/ -static void stm32_takesem(struct stm32_dev_s *priv) +static int stm32_takesem(struct stm32_dev_s *priv) { - nxsem_wait_uninterruptible(&priv->waitsem); + return nxsem_wait_uninterruptible(&priv->waitsem); } /**************************************************************************** @@ -2600,7 +2601,7 @@ static sdio_eventset_t stm32_eventwait(FAR struct sdio_dev_s *dev, if (priv->waitevents == 0 && priv->wkupevent == 0) { wkupevent = SDIOWAIT_ERROR; - goto erroutdisable; + goto errout_with_waitints; } #else @@ -2664,7 +2665,18 @@ static sdio_eventset_t stm32_eventwait(FAR struct sdio_dev_s *dev, * incremented and there will be no wait. */ - stm32_takesem(priv); + ret = stm32_takesem(priv); + if (ret < 0) + { + /* Task canceled. Cancel the wdog (assuming it was started) and + * return an SDIO error. + */ + + wd_cancel(priv->waitwdog); + wkupevent = SDIOWAIT_ERROR; + goto errout_with_waitints; + } + wkupevent = priv->wkupevent; /* Check if the event has occurred. When the event has occurred, then @@ -2682,9 +2694,7 @@ static sdio_eventset_t stm32_eventwait(FAR struct sdio_dev_s *dev, /* Disable event-related interrupts */ -#if defined(CONFIG_MMCSD_SDIOWAIT_WRCOMPLETE) -erroutdisable: -#endif +errout_with_waitints: stm32_configwaitints(priv, 0, 0, 0); #ifdef CONFIG_STM32L4_SDMMC_DMA