ARM: mx3: Fix a race condition in mxcmmc
Subsystems (2)
PATCH 1/1 ARM: mx3: Fix a race condition in mxcmmc
This fixes a race condition regarding interrupt bits in the SDHC controller driver code.
In case of PIO-transfer it does not clear SDHC-status bit#11/12 in the INT-handler anymore. INT-handler might be called during an ongoing PIO-data-transfer (with some other INT-flag set) and PIO-transfer depends on these bits being set to detect the end of the data-transfer. This also means that at the end of PIO- transfer that PIO-software has to clear these bits itself.
However in case of DMA-transfer these bits have to be cleared in the INT-handler, because they are used to generate INTs then.
Works solid, no more problems here, can transfer big files.
Signed-off-by Volker Ernst <[email protected]>
Acked-by Daniel Mack <[email protected]>
Cc Andy Green <[email protected]>
--- drivers/mmc/host/mxcmmc.c | 13 ++++++++++++- 1 files changed, 12 insertions(+), 1 deletions(-)
drivers/mmc/host/mxcmmc.c +12 -1
@@ -489,6 +489,9 @@ static void mxcmci_datawork(struct work_struct *work) struct mxcmci_host *host = container_of(work, struct mxcmci_host, datawork);int datastat =mxcmci_transfer_data (host); + +writel (STATUS_READ_OP_DONE |STATUS_WRITE_OP_DONE , + host->base +MMC_REG_STATUS );mxcmci_finish_data (host, datastat);if (host->req->stop) {
@@ -553,7 +556,8 @@ static irqreturn_t mxcmci_irq(int irq, void *devid)u32 stat; stat =readl (host->base +MMC_REG_STATUS ); -writel (stat & ~STATUS_SDIO_INT_ACTIVE , host->base +MMC_REG_STATUS ); +writel (stat & ~(STATUS_SDIO_INT_ACTIVE |STATUS_DATA_TRANS_DONE | +STATUS_WRITE_OP_DONE ), host->base +MMC_REG_STATUS );dev_dbg (mmc_dev (host->mmc),"%s: 0x%08x\n" , __func__, stat);
@@ -561,6 +565,13 @@ static irqreturn_t mxcmci_irq(int irq, void *devid) sdio_irq = (stat &STATUS_SDIO_INT_ACTIVE ) && host->use_sdio;spin_unlock_irqrestore (&host->lock, flags); +#ifdef HAS_DMA +if (mxcmci_use_dma (host) && + (stat & (STATUS_READ_OP_DONE |STATUS_WRITE_OP_DONE ))) +writel (STATUS_READ_OP_DONE |STATUS_WRITE_OP_DONE , + host->base +MMC_REG_STATUS ); +#endif +if (sdio_irq) {writel (STATUS_SDIO_INT_ACTIVE , host->base +MMC_REG_STATUS );mmc_signal_sdio_irq (host->mmc);
Signature · 1 line
1.7.0.3