mmci: U300 "sync with blockend" broken for multi-block?

Linus Walleij linus.ml.walleij at gmail.com
Sun Jan 16 16:11:57 EST 2011


2011/1/14 Russell King - ARM Linux <linux at arm.linux.org.uk>:
> On Fri, Jan 14, 2011 at 09:13:05PM +0100, Linus Walleij wrote:
>> 2011/1/5 Russell King - ARM Linux <linux at arm.linux.org.uk>:
>>
>> > Any chance of pr_debug'ing the complete status register each time you
>> > service an interrupt?  You'll probably need to set the kernel log
>> > buffer fairly large to ensure that you capture everything.
>>
>> I did this test now.
>
> Just to complete the picture, can I see the patch between the version
> which produced this and mainline?

Sure, but I patched on top of the pending DMA-patches, since I
needed to test the workings in DMA mode. Here is that patch, if
you want the entire DMA patch series too I can resend them:

diff --git a/drivers/mmc/host/mmci.c b/drivers/mmc/host/mmci.c
index af0cae9..8ae32d9 100644
--- a/drivers/mmc/host/mmci.c
+++ b/drivers/mmc/host/mmci.c
@@ -81,7 +81,7 @@ static struct variant_data variant_u300 = {
        .fifohalfsize           = 8 * 4,
        .clkreg_enable          = 1 << 13, /* HWFCEN */
        .datalength_bits        = 16,
-       .broken_blockend        = true,
+       .broken_blockend        = false,
        .sdio                   = true,
 };

@@ -414,7 +414,8 @@ static void mmci_start_data(struct mmci_host
*host, struct mmc_data *data)
        void __iomem *base;
        int blksz_bits;

-       dev_dbg(mmc_dev(host->mmc), "blksz %04x blks %04x flags %08x\n",
+       dev_info(mmc_dev(host->mmc), "\n");
+       dev_info(mmc_dev(host->mmc), "START DATA: blksz %04x blks %04x
flags %08x\n",
                data->blksz, data->blocks, data->flags);

        host->data = data;
@@ -480,10 +481,10 @@ static void mmci_start_data(struct mmci_host
*host, struct mmc_data *data)

        writel(datactrl, base + MMCIDATACTRL);
        irqmask0 = readl(base + MMCIMASK0);
-       if (variant->broken_blockend)
-               irqmask0 &= ~MCI_DATABLOCKENDMASK;
-       else
-               irqmask0 |= MCI_DATABLOCKENDMASK;
+       // if (variant->broken_blockend)
+       //      irqmask0 &= ~MCI_DATABLOCKENDMASK;
+       // else
+               irqmask0 |= MCI_DATABLOCKENDMASK;
        irqmask0 &= ~MCI_DATAENDMASK;
        writel(irqmask0, base + MMCIMASK0);
        mmci_set_mask1(host, irqmask1);
@@ -523,6 +524,16 @@ mmci_data_irq(struct mmci_host *host, struct
mmc_data *data,
 {
        struct variant_data *variant = host->variant;

+       if ((status & MCI_DATABLOCKEND) &&
+           (status & MCI_DATAEND)) {
+               dev_info(mmc_dev(host->mmc), "MCI_DATABLOCKEND &&
MCI_DATAEND\n");
+               dev_info(mmc_dev(host->mmc), "xfered according to no
of blockends = 0x%08x, expected: 0x%08x\n", host->data_xfered +
data->blksz, data->blksz * data->blocks);
+       } else if (status & MCI_DATABLOCKEND) {
+               dev_info(mmc_dev(host->mmc), "MCI_DATABLOCKEND\n");
+       } else if (status & MCI_DATAEND) {
+               dev_info(mmc_dev(host->mmc), "MCI_DATAEND\n");
+       }
+
        /* First check for errors */
        if (status &
(MCI_DATACRCFAIL|MCI_DATATIMEOUT|MCI_TXUNDERRUN|MCI_RXOVERRUN)) {
                dev_dbg(mmc_dev(host->mmc), "MCI ERROR IRQ (status
%08x)\n", status);
@@ -589,8 +600,10 @@ mmci_data_irq(struct mmci_host *host, struct
mmc_data *data,
                 */
                if (!variant->broken_blockend && !host->dma_on_current_xfer)
                        host->data_xfered += data->blksz;
-               if (host->data_xfered == data->blksz * data->blocks)
+               if (host->data_xfered == data->blksz * data->blocks) {
                        host->last_blockend = true;
+                       dev_info(mmc_dev(host->mmc), "THIS IS THE LAST
MCI_DATABLOCKEND\n");
+               }
        }

        if (status & MCI_DATAEND)


Yours,
Linus Walleij



More information about the linux-arm-kernel mailing list