Commit e3de2be7 authored by Guennadi Liakhovetski's avatar Guennadi Liakhovetski Committed by Chris Ball

mmc: tmio_mmc: fix card eject during IO with DMA

When DMA is in use and the card is ejected during IO, DMA transfers have to
be terminated, otherwise the dmaengine driver fails to operate properly,
when the card is re-inserted.
Signed-off-by: default avatarGuennadi Liakhovetski <g.liakhovetski@gmx.de>
Signed-off-by: default avatarChris Ball <cjb@laptop.org>
parent dd13b4ed
...@@ -20,8 +20,8 @@ ...@@ -20,8 +20,8 @@
#include <linux/mmc/tmio.h> #include <linux/mmc/tmio.h>
#include <linux/mutex.h> #include <linux/mutex.h>
#include <linux/pagemap.h> #include <linux/pagemap.h>
#include <linux/spinlock.h>
#include <linux/scatterlist.h> #include <linux/scatterlist.h>
#include <linux/spinlock.h>
/* Definitions for values the CTRL_SDIO_STATUS register can take. */ /* Definitions for values the CTRL_SDIO_STATUS register can take. */
#define TMIO_SDIO_STAT_IOIRQ 0x0001 #define TMIO_SDIO_STAT_IOIRQ 0x0001
...@@ -120,6 +120,7 @@ void tmio_mmc_start_dma(struct tmio_mmc_host *host, struct mmc_data *data); ...@@ -120,6 +120,7 @@ void tmio_mmc_start_dma(struct tmio_mmc_host *host, struct mmc_data *data);
void tmio_mmc_enable_dma(struct tmio_mmc_host *host, bool enable); void tmio_mmc_enable_dma(struct tmio_mmc_host *host, bool enable);
void tmio_mmc_request_dma(struct tmio_mmc_host *host, struct tmio_mmc_data *pdata); void tmio_mmc_request_dma(struct tmio_mmc_host *host, struct tmio_mmc_data *pdata);
void tmio_mmc_release_dma(struct tmio_mmc_host *host); void tmio_mmc_release_dma(struct tmio_mmc_host *host);
void tmio_mmc_abort_dma(struct tmio_mmc_host *host);
#else #else
static inline void tmio_mmc_start_dma(struct tmio_mmc_host *host, static inline void tmio_mmc_start_dma(struct tmio_mmc_host *host,
struct mmc_data *data) struct mmc_data *data)
...@@ -140,6 +141,10 @@ static inline void tmio_mmc_request_dma(struct tmio_mmc_host *host, ...@@ -140,6 +141,10 @@ static inline void tmio_mmc_request_dma(struct tmio_mmc_host *host,
static inline void tmio_mmc_release_dma(struct tmio_mmc_host *host) static inline void tmio_mmc_release_dma(struct tmio_mmc_host *host)
{ {
} }
static inline void tmio_mmc_abort_dma(struct tmio_mmc_host *host)
{
}
#endif #endif
#ifdef CONFIG_PM #ifdef CONFIG_PM
......
...@@ -34,6 +34,18 @@ void tmio_mmc_enable_dma(struct tmio_mmc_host *host, bool enable) ...@@ -34,6 +34,18 @@ void tmio_mmc_enable_dma(struct tmio_mmc_host *host, bool enable)
#endif #endif
} }
void tmio_mmc_abort_dma(struct tmio_mmc_host *host)
{
tmio_mmc_enable_dma(host, false);
if (host->chan_rx)
dmaengine_terminate_all(host->chan_rx);
if (host->chan_tx)
dmaengine_terminate_all(host->chan_tx);
tmio_mmc_enable_dma(host, true);
}
static void tmio_mmc_start_dma_rx(struct tmio_mmc_host *host) static void tmio_mmc_start_dma_rx(struct tmio_mmc_host *host)
{ {
struct scatterlist *sg = host->sg_ptr, *sg_tmp; struct scatterlist *sg = host->sg_ptr, *sg_tmp;
......
...@@ -41,8 +41,8 @@ ...@@ -41,8 +41,8 @@
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/pm_runtime.h> #include <linux/pm_runtime.h>
#include <linux/scatterlist.h> #include <linux/scatterlist.h>
#include <linux/workqueue.h>
#include <linux/spinlock.h> #include <linux/spinlock.h>
#include <linux/workqueue.h>
#include "tmio_mmc.h" #include "tmio_mmc.h"
...@@ -246,6 +246,7 @@ static void tmio_mmc_reset_work(struct work_struct *work) ...@@ -246,6 +246,7 @@ static void tmio_mmc_reset_work(struct work_struct *work)
/* Ready for new calls */ /* Ready for new calls */
host->mrq = NULL; host->mrq = NULL;
tmio_mmc_abort_dma(host);
mmc_request_done(host->mmc, mrq); mmc_request_done(host->mmc, mrq);
} }
...@@ -272,6 +273,9 @@ static void tmio_mmc_finish_request(struct tmio_mmc_host *host) ...@@ -272,6 +273,9 @@ static void tmio_mmc_finish_request(struct tmio_mmc_host *host)
host->mrq = NULL; host->mrq = NULL;
spin_unlock_irqrestore(&host->lock, flags); spin_unlock_irqrestore(&host->lock, flags);
if (mrq->cmd->error || (mrq->data && mrq->data->error))
tmio_mmc_abort_dma(host);
mmc_request_done(host->mmc, mrq); mmc_request_done(host->mmc, mrq);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment