Commit 2dfa8b1e authored by Russell King's avatar Russell King

[MMC] MMCI: Manipulate IRQ masks according to the data FSM state.

Prevent IRQ race conditions between the two handlers and within the
primecell itself.  Unfortunately, the primecell does not always mask
the FIFO empty interrupt we reach the end of a transfer to the card.
Also, we may receive the "data end" interrupt prior to finishing a
transfer from the card, so mask this off until we've read the last
bytes from the FIFO.
parent 8e86fbab
......@@ -62,6 +62,7 @@ mmci_request_end(struct mmci_host *host, struct mmc_request *mrq)
static void mmci_stop_data(struct mmci_host *host)
{
writel(0, host->base + MMCIDATACTRL);
writel(0, host->base + MMCIMASK1);
host->data = NULL;
host->buffer = NULL;
}
......@@ -100,6 +101,7 @@ static void mmci_start_data(struct mmci_host *host, struct mmc_data *data)
}
writel(datactrl, base + MMCIDATACTRL);
writel(readl(base + MMCIMASK0) & ~MCI_DATAENDMASK, base + MMCIMASK0);
writel(irqmask, base + MMCIMASK1);
}
......@@ -216,15 +218,6 @@ static irqreturn_t mmci_pio_irq(int irq, void *dev_id, struct pt_regs *regs)
readsl(base + MMCIFIFO, host->buffer, count >> 2);
host->buffer += count;
host->size -= count;
if (host->size == 0)
host->buffer = NULL;
} else {
static int first = 1;
if (first) {
first = 0;
printk(KERN_ERR "MMCI: sinking excessive data\n");
}
readl(base + MMCIFIFO);
}
}
......@@ -242,20 +235,22 @@ static irqreturn_t mmci_pio_irq(int irq, void *dev_id, struct pt_regs *regs)
host->buffer += count;
host->size -= count;
/*
* If we run out of data, disable the data IRQs;
* this prevents a race where the FIFO becomes
* empty before the chip itself has disabled the
* data path.
*/
if (host->size == 0)
writel(0, base + MMCIMASK1);
}
ret = 1;
} while (status);
/*
* If we run out of data, disable the data IRQs; this
* prevents a race where the FIFO becomes empty before
* the chip itself has disabled the data path, and
* stops us racing with our data end IRQ.
*/
if (host->size == 0) {
writel(0, base + MMCIMASK1);
writel(readl(base + MMCIMASK0) | MCI_DATAENDMASK, base + MMCIMASK0);
}
return IRQ_RETVAL(ret);
}
......
......@@ -106,8 +106,7 @@
#define MCI_IRQENABLE \
(MCI_CMDCRCFAILMASK|MCI_DATACRCFAILMASK|MCI_CMDTIMEOUTMASK| \
MCI_DATATIMEOUTMASK|MCI_TXUNDERRUNMASK|MCI_RXOVERRUNMASK| \
MCI_CMDRESPENDMASK|MCI_CMDSENTMASK|MCI_DATAENDMASK| \
MCI_DATABLOCKENDMASK)
MCI_CMDRESPENDMASK|MCI_CMDSENTMASK|MCI_DATABLOCKENDMASK)
/*
* The size of the FIFO in bytes.
......
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