From d7a76d63d3964ccbaf2d8d8898fc1fd0394e8a88 Mon Sep 17 00:00:00 2001 From: Gregory Nutt Date: Fri, 18 Oct 2013 08:24:18 -0600 Subject: Enhanced the mmcdd_sdio driver to perform DMA preflight operations and fail DMA read/write requests that fail preflighting. From Mike Smith --- nuttx/ChangeLog | 4 +- nuttx/drivers/mmcsd/mmcsd_sdio.c | 96 +++++++++++++++++++++++++++++++++++++--- 2 files changed, 93 insertions(+), 7 deletions(-) diff --git a/nuttx/ChangeLog b/nuttx/ChangeLog index 99708875b..5781d36fd 100644 --- a/nuttx/ChangeLog +++ b/nuttx/ChangeLog @@ -5803,4 +5803,6 @@ additional conditions that will cause DMA to fail or lose data (2013-10-18). * include/nuttx/sdio.h: Add a preflight method to the SDIO interface. From Mike Smith (2013-10-18). - + * drivers/mmcsd/mmscd_sdio.c: Enhanced the mmcdd_sdio driver to perform + DMA preflight operations and fail DMA read/write requests that fail + preflighting. From Mike Smith (2013-10-18). diff --git a/nuttx/drivers/mmcsd/mmcsd_sdio.c b/nuttx/drivers/mmcsd/mmcsd_sdio.c index 2332261fc..b0968cdd7 100644 --- a/nuttx/drivers/mmcsd/mmcsd_sdio.c +++ b/nuttx/drivers/mmcsd/mmcsd_sdio.c @@ -1285,6 +1285,22 @@ static ssize_t mmcsd_readsingle(FAR struct mmcsd_state_s *priv, return -EPERM; } +#if defined(CONFIG_SDIO_DMA) && defined(CONFIG_SDIO_PREFLIGHT) + /* If we think we are going to perform a DMA transfer, make sure that we + * will be able to before we commit the card to the operation. + */ + + if (priv->dma) + { + ret = SDIO_DMAPREFLIGHT(priv->dev, buffer, priv->blocksize); + + if (ret != OK) + { + return ret; + } + } +#endif + /* Verify that the card is ready for the transfer. The card may still be * busy from the preceding write transfer. It would be simpler to check * for write busy at the end of each write, rather than at the beginning of @@ -1327,10 +1343,16 @@ static ssize_t mmcsd_readsingle(FAR struct mmcsd_state_s *priv, SDIO_BLOCKSETUP(priv->dev, priv->blocksize, 1); SDIO_WAITENABLE(priv->dev, SDIOWAIT_TRANSFERDONE|SDIOWAIT_TIMEOUT|SDIOWAIT_ERROR); + #ifdef CONFIG_SDIO_DMA if (priv->dma) { - SDIO_DMARECVSETUP(priv->dev, buffer, priv->blocksize); + ret = SDIO_DMARECVSETUP(priv->dev, buffer, priv->blocksize); + if (ret != OK) + { + fvdbg("SDIO_DMARECVSETUP: error %d\n", ret); + return ret; + } } else #endif @@ -1395,6 +1417,22 @@ static ssize_t mmcsd_readmultiple(FAR struct mmcsd_state_s *priv, return -EPERM; } +#if defined(CONFIG_SDIO_DMA) && defined(CONFIG_SDIO_PREFLIGHT) + /* If we think we are going to perform a DMA transfer, make sure that we + * will be able to before we commit the card to the operation. + */ + + if (priv->dma) + { + ret = SDIO_DMAPREFLIGHT(priv->dev, buffer, priv->blocksize); + + if (ret != OK) + { + return ret; + } + } +#endif + /* Verify that the card is ready for the transfer. The card may still be * busy from the preceding write transfer. It would be simpler to check * for write busy at the end of each write, rather than at the beginning of @@ -1440,7 +1478,12 @@ static ssize_t mmcsd_readmultiple(FAR struct mmcsd_state_s *priv, #ifdef CONFIG_SDIO_DMA if (priv->dma) { - SDIO_DMARECVSETUP(priv->dev, buffer, nbytes); + ret = SDIO_DMARECVSETUP(priv->dev, buffer, nbytes); + if (ret != OK) + { + fvdbg("SDIO_DMARECVSETUP: error %d\n", ret); + return ret; + } } else #endif @@ -1576,6 +1619,22 @@ static ssize_t mmcsd_writesingle(FAR struct mmcsd_state_s *priv, return -EPERM; } +#if defined(CONFIG_SDIO_DMA) && defined(CONFIG_SDIO_PREFLIGHT) + /* If we think we are going to perform a DMA transfer, make sure that we + * will be able to before we commit the card to the operation. + */ + + if (priv->dma) + { + ret = SDIO_DMAPREFLIGHT(priv->dev, buffer, priv->blocksize); + + if (ret != OK) + { + return ret; + } + } +#endif + /* Verify that the card is ready for the transfer. The card may still be * busy from the preceding write transfer. It would be simpler to check * for write busy at the end of each write, rather than at the beginning of @@ -1631,7 +1690,12 @@ static ssize_t mmcsd_writesingle(FAR struct mmcsd_state_s *priv, #ifdef CONFIG_SDIO_DMA if (priv->dma) { - SDIO_DMASENDSETUP(priv->dev, buffer, priv->blocksize); + ret = SDIO_DMASENDSETUP(priv->dev, buffer, priv->blocksize); + if (ret != OK) + { + fvdbg("SDIO_DMASENDSETUP: error %d\n", ret); + return ret; + } } else #endif @@ -1690,6 +1754,22 @@ static ssize_t mmcsd_writemultiple(FAR struct mmcsd_state_s *priv, return -EPERM; } +#if defined(CONFIG_SDIO_DMA) && defined(CONFIG_SDIO_PREFLIGHT) + /* If we think we are going to perform a DMA transfer, make sure that we + * will be able to before we commit the card to the operation. + */ + + if (priv->dma) + { + ret = SDIO_DMAPREFLIGHT(priv->dev, buffer, priv->blocksize); + + if (ret != OK) + { + return ret; + } + } +#endif + /* Verify that the card is ready for the transfer. The card may still be * busy from the preceding write transfer. It would be simpler to check * for write busy at the end of each write, rather than at the beginning of @@ -1777,7 +1857,12 @@ static ssize_t mmcsd_writemultiple(FAR struct mmcsd_state_s *priv, #ifdef CONFIG_SDIO_DMA if (priv->dma) { - SDIO_DMASENDSETUP(priv->dev, buffer, nbytes); + ret = SDIO_DMASENDSETUP(priv->dev, buffer, nbytes); + if (ret != OK) + { + fvdbg("SDIO_DMASENDSETUP: error %d\n", ret); + return ret; + } } else #endif @@ -3180,9 +3265,8 @@ int mmcsd_slotinitialize(int minor, FAR struct sdio_dev_s *dev) } } - /* Initialize buffering */ - #if defined(CONFIG_FS_WRITEBUFFER) || defined(CONFIG_FS_READAHEAD) + /* Initialize buffering */ ret = rwb_initialize(&priv->rwbuffer); if (ret < 0) -- cgit v1.2.3