lkml.org 
[lkml]   [2008]   [Dec]   [2]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    Date
    From
    Subject[patch 6/8] SDHCI: Check DMA for overruns at end of transfer
    At the end of a transfer, check that the DMA engine in the
    SDHCI controller actually did what it was meant to and didn't
    overrun the end of the buffer.

    This seems to be triggered by a timeout during an CMD25 (multiple block
    write) to a card. The mmc_block module then issues a command to find out
    how much data was moved and this seems to end up triggering this DMA
    check. The result is the card's queue generates an OOPS as the stack has
    been trampled on due to the extra data transfered.

    Signed-off-by: Ben Dooks <ben-linux@fluff.org>

    Index: linux.git/drivers/mmc/host/sdhci.c
    ===================================================================
    --- linux.git.orig/drivers/mmc/host/sdhci.c 2008-10-29 16:59:38.000000000 +0000
    +++ linux.git/drivers/mmc/host/sdhci.c 2008-10-29 16:59:41.000000000 +0000
    @@ -736,6 +736,23 @@ static void sdhci_set_transfer_mode(stru
    writew(mode, host->ioaddr + SDHCI_TRANSFER_MODE);
    }

    +static void shdci_check_dma_overrun(struct sdhci_host *host, struct mmc_data *data)
    +{
    + u32 dma_pos = readl(host->ioaddr + SDHCI_DMA_ADDRESS);
    + u32 dma_start = sg_dma_address(data->sg);
    + u32 dma_end = dma_start + data->sg->length;
    +
    + /* Test whether we ended up moving more data than
    + * was originally requested. */
    +
    + if (dma_pos <= dma_end)
    + return;
    +
    + printk(KERN_ERR "%s: dma overrun, dma %08x, req %08x..%08x\n",
    + mmc_hostname(host->mmc), dma_pos,
    + dma_start, dma_end);
    +}
    +
    static void sdhci_finish_data(struct sdhci_host *host)
    {
    struct mmc_data *data;
    @@ -749,6 +766,8 @@ static void sdhci_finish_data(struct sdh
    if (host->flags & SDHCI_USE_ADMA)
    sdhci_adma_table_post(host, data);
    else {
    + shdci_check_dma_overrun(host, data);
    +
    dma_unmap_sg(mmc_dev(host->mmc), data->sg,
    data->sg_len, (data->flags & MMC_DATA_READ) ?
    DMA_FROM_DEVICE : DMA_TO_DEVICE);
    --
    Ben (ben@fluff.org, http://www.fluff.org/)

    'a smiley only costs 4 bytes'


    \
     
     \ /
      Last update: 2008-12-02 16:45    [W:0.021 / U:30.620 seconds]
    ©2003-2016 Jasper Spaans. hosted at Digital OceanAdvertise on this site