diff --git a/drivers/mmc/host/pxamci.c b/drivers/mmc/host/pxamci.c index 91e25683b397..657901eecfce 100644 --- a/drivers/mmc/host/pxamci.c +++ b/drivers/mmc/host/pxamci.c @@ -142,6 +142,10 @@ static void pxamci_setup_data(struct pxamci_host *host, struct mmc_data *data) host->dma_dir); for (i = 0; i < host->dma_len; i++) { + unsigned int length = sg_dma_len(&data->sg[i]); + host->sg_cpu[i].dcmd = dcmd | length; + if (length & 31 && !(data->flags & MMC_DATA_READ)) + host->sg_cpu[i].dcmd |= DCMD_ENDIRQEN; if (data->flags & MMC_DATA_READ) { host->sg_cpu[i].dsadr = host->res->start + MMC_RXFIFO; host->sg_cpu[i].dtadr = sg_dma_address(&data->sg[i]); @@ -149,7 +153,6 @@ static void pxamci_setup_data(struct pxamci_host *host, struct mmc_data *data) host->sg_cpu[i].dsadr = sg_dma_address(&data->sg[i]); host->sg_cpu[i].dtadr = host->res->start + MMC_TXFIFO; } - host->sg_cpu[i].dcmd = dcmd | sg_dma_len(&data->sg[i]); host->sg_cpu[i].ddadr = host->sg_dma + (i + 1) * sizeof(struct pxa_dma_desc); } @@ -414,8 +417,18 @@ static const struct mmc_host_ops pxamci_ops = { static void pxamci_dma_irq(int dma, void *devid) { - printk(KERN_ERR "DMA%d: IRQ???\n", dma); - DCSR(dma) = DCSR_STARTINTR|DCSR_ENDINTR|DCSR_BUSERR; + struct pxamci_host *host = devid; + int dcsr = DCSR(dma); + DCSR(dma) = dcsr & ~DCSR_STOPIRQEN; + + if (dcsr & DCSR_ENDINTR) { + writel(BUF_PART_FULL, host->base + MMC_PRTBUF); + } else { + printk(KERN_ERR "%s: DMA error on channel %d (DCSR=%#x)\n", + mmc_hostname(host->mmc), dma, dcsr); + host->data->error = -EIO; + pxamci_data_done(host, 0); + } } static irqreturn_t pxamci_detect_irq(int irq, void *devid)