[PATCH] mmci: calculate remaining bytes at error correctly

Russell King - ARM Linux linux at arm.linux.org.uk
Mon Jan 31 05:27:26 EST 2011


On Mon, Jan 31, 2011 at 11:17:42AM +0100, Linus Walleij wrote:
> 2011/1/30 Russell King - ARM Linux <linux at arm.linux.org.uk>:
> 
> > 8<----
> > Subject: [PATCH 1/2] ARM: mmci: complete the transaction on error
> >
> > When we encounter an error, make sure we complete the transaction
> > otherwise we'll leave the request dangling.
> >
> > Signed-off-by: Russell King <rmk+kernel at arm.linux.org.uk>
> > ---
> >  drivers/mmc/host/mmci.c |    2 +-
> >  1 files changed, 1 insertions(+), 1 deletions(-)
> >
> > diff --git a/drivers/mmc/host/mmci.c b/drivers/mmc/host/mmci.c
> > index b6fd6dc..175a623 100644
> > --- a/drivers/mmc/host/mmci.c
> > +++ b/drivers/mmc/host/mmci.c
> > @@ -319,7 +319,7 @@ mmci_data_irq(struct mmci_host *host, struct mmc_data *data,
> >        if (status & MCI_DATABLOCKEND)
> >                dev_err(mmc_dev(host->mmc), "stray MCI_DATABLOCKEND interrupt\n");
> >
> > -       if (status & MCI_DATAEND) {
> > +       if (status & MCI_DATAEND || data->error) {
> >                mmci_stop_data(host);
> 
> The hardware always sets the MCI_DATAEND bit if there is
> some error, so these flags always appear simultaneously, but
> it doesn't hurt to take some extra precaution, so

The hardware may do, but you won't see that here.  When we setup a
transfer, we do this:

        writel(readl(base + MMCIMASK0) & ~MCI_DATAENDMASK, base + MMCIMASK0);

When we receive an interrupt:

                status = readl(host->base + MMCISTATUS);
                status &= readl(host->base + MMCIMASK0);

                if (status & (MCI_DATACRCFAIL|MCI_DATATIMEOUT|MCI_TXUNDERRUN|
                              MCI_RXOVERRUN|MCI_DATAEND|MCI_DATABLOCKEND) && data)
                        mmci_data_irq(host, data, status);

When we get to the end of a transfer:

        /*
         * 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) {
                mmci_set_mask1(host, 0);
                writel(readl(base + MMCIMASK0) | MCI_DATAENDMASK, base + MMCIMASK0);
        }

So, we'll only see DATAEND when we actually reach the end of a transfer.
If we error out before hand, we won't see it.



More information about the linux-arm-kernel mailing list