Skip to content

Commit

Permalink
mmc: tmio_mmc: fix card eject during IO with DMA
Browse files Browse the repository at this point in the history
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: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
Signed-off-by: Chris Ball <cjb@laptop.org>
  • Loading branch information
Guennadi Liakhovetski authored and Chris Ball committed Feb 14, 2012
1 parent dd13b4e commit e3de2be
Show file tree
Hide file tree
Showing 3 changed files with 23 additions and 2 deletions.
7 changes: 6 additions & 1 deletion drivers/mmc/host/tmio_mmc.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@
#include <linux/mmc/tmio.h>
#include <linux/mutex.h>
#include <linux/pagemap.h>
#include <linux/spinlock.h>
#include <linux/scatterlist.h>
#include <linux/spinlock.h>

/* Definitions for values the CTRL_SDIO_STATUS register can take. */
#define TMIO_SDIO_STAT_IOIRQ 0x0001
Expand Down Expand Up @@ -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_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_abort_dma(struct tmio_mmc_host *host);
#else
static inline void tmio_mmc_start_dma(struct tmio_mmc_host *host,
struct mmc_data *data)
Expand All @@ -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_abort_dma(struct tmio_mmc_host *host)
{
}
#endif

#ifdef CONFIG_PM
Expand Down
12 changes: 12 additions & 0 deletions drivers/mmc/host/tmio_mmc_dma.c
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,18 @@ void tmio_mmc_enable_dma(struct tmio_mmc_host *host, bool enable)
#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)
{
struct scatterlist *sg = host->sg_ptr, *sg_tmp;
Expand Down
6 changes: 5 additions & 1 deletion drivers/mmc/host/tmio_mmc_pio.c
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,8 @@
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
#include <linux/scatterlist.h>
#include <linux/workqueue.h>
#include <linux/spinlock.h>
#include <linux/workqueue.h>

#include "tmio_mmc.h"

Expand Down Expand Up @@ -246,6 +246,7 @@ static void tmio_mmc_reset_work(struct work_struct *work)
/* Ready for new calls */
host->mrq = NULL;

tmio_mmc_abort_dma(host);
mmc_request_done(host->mmc, mrq);
}

Expand All @@ -272,6 +273,9 @@ static void tmio_mmc_finish_request(struct tmio_mmc_host *host)
host->mrq = NULL;
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);
}

Expand Down

0 comments on commit e3de2be

Please sign in to comment.