From e385ea63f44b475e034a78b6d8bc6bb50caf72ca Mon Sep 17 00:00:00 2001 From: David Brownell Date: Tue, 2 Sep 2008 14:35:46 -0700 Subject: mmc: at91_mci: don't use coherent dma buffers At91_mci is abusing dma_free_coherent(), which may not be called with IRQs disabled. I saw "mkfs.ext3" on an MMC card objecting voluminously as each write completed: WARNING: at arch/arm/mm/consistent.c:368 dma_free_coherent+0x2c/0x224() [] (dump_stack+0x0/0x14) from [] (warn_on_slowpath+0x4c/0x68) [] (warn_on_slowpath+0x0/0x68) from [] (dma_free_coherent+0x2c/0x224) r6:00008008 r5:ffc06000 r4:00000000 [] (dma_free_coherent+0x0/0x224) from [] (at91_mci_irq+0x374/0x420) [] (at91_mci_irq+0x0/0x420) from [] (handle_IRQ_event+0x2c/0x6c) ... This bug has been around for a LONG time. The MM warning is from late 2005, but the driver merged a year later ... so I'm puzzled why nobody noticed this before now. The fix involves noting that this buffer shouldn't be DMA-coherent; it's just used for normal DMA writes. So replace it with standard kmalloc() buffering and DMA mapping calls. This is the quickie fix. A better one would not rely on allocating large bounce buffers. (Note that dma_alloc_coherent could have failed too, but that case was ignored... kmalloc is a bit more likely to fail though.) Signed-off-by: David Brownell Acked-by: Pierre Ossman Cc: Andrew Victor Acked-by: Nicolas Ferre Cc: Russell King Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/mmc/host/at91_mci.c | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) (limited to 'drivers/mmc') diff --git a/drivers/mmc/host/at91_mci.c b/drivers/mmc/host/at91_mci.c index 6915f40ac8ab..1f8b5b36222c 100644 --- a/drivers/mmc/host/at91_mci.c +++ b/drivers/mmc/host/at91_mci.c @@ -621,12 +621,21 @@ static void at91_mci_send_command(struct at91mci_host *host, struct mmc_command if (cpu_is_at91sam9260 () || cpu_is_at91sam9263()) if (host->total_length < 12) host->total_length = 12; - host->buffer = dma_alloc_coherent(NULL, - host->total_length, - &host->physical_address, GFP_KERNEL); + + host->buffer = kmalloc(host->total_length, GFP_KERNEL); + if (!host->buffer) { + pr_debug("Can't alloc tx buffer\n"); + cmd->error = -ENOMEM; + mmc_request_done(host->mmc, host->request); + return; + } at91_mci_sg_to_dma(host, data); + host->physical_address = dma_map_single(NULL, + host->buffer, host->total_length, + DMA_TO_DEVICE); + pr_debug("Transmitting %d bytes\n", host->total_length); at91_mci_write(host, ATMEL_PDC_TPR, host->physical_address); @@ -694,7 +703,10 @@ static void at91_mci_completed_command(struct at91mci_host *host, unsigned int s cmd->resp[3] = at91_mci_read(host, AT91_MCI_RSPR(3)); if (host->buffer) { - dma_free_coherent(NULL, host->total_length, host->buffer, host->physical_address); + dma_unmap_single(NULL, + host->physical_address, host->total_length, + DMA_TO_DEVICE); + kfree(host->buffer); host->buffer = NULL; } -- cgit v1.2.3 From 55c381e4896be2611da87088acfad74b361239ab Mon Sep 17 00:00:00 2001 From: Russell King Date: Thu, 4 Sep 2008 14:07:22 +0100 Subject: [ARM] omap: convert OMAP drivers to use ioremap() Signed-off-by: Russell King --- drivers/mmc/host/omap.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'drivers/mmc') diff --git a/drivers/mmc/host/omap.c b/drivers/mmc/host/omap.c index c16028872bbb..1e50bf56c2ce 100644 --- a/drivers/mmc/host/omap.c +++ b/drivers/mmc/host/omap.c @@ -1455,7 +1455,9 @@ static int __init mmc_omap_probe(struct platform_device *pdev) host->irq = irq; host->phys_base = host->mem_res->start; - host->virt_base = (void __iomem *) IO_ADDRESS(host->phys_base); + host->virt_base = ioremap(res->start, res->end - res->start + 1); + if (!host->virt_base) + goto err_ioremap; if (cpu_is_omap24xx()) { host->iclk = clk_get(&pdev->dev, "mmc_ick"); @@ -1510,6 +1512,8 @@ err_free_iclk: clk_put(host->iclk); } err_free_mmc_host: + iounmap(host->virt_base); +err_ioremap: kfree(host); err_free_mem_region: release_mem_region(res->start, res->end - res->start + 1); @@ -1536,6 +1540,7 @@ static int mmc_omap_remove(struct platform_device *pdev) if (host->fclk && !IS_ERR(host->fclk)) clk_put(host->fclk); + iounmap(host->virt_base); release_mem_region(pdev->resource[0].start, pdev->resource[0].end - pdev->resource[0].start + 1); -- cgit v1.2.3 From 7c8ad9828e793573877fd60868bb5d2f1e3b64da Mon Sep 17 00:00:00 2001 From: Russell King Date: Fri, 5 Sep 2008 15:13:24 +0100 Subject: [ARM] omap: fix a load of "warning: symbol 'xxx' was not declared. Should it be static?" Signed-off-by: Russell King --- drivers/mmc/host/omap.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/mmc') diff --git a/drivers/mmc/host/omap.c b/drivers/mmc/host/omap.c index 1e50bf56c2ce..1b9fc3c6b875 100644 --- a/drivers/mmc/host/omap.c +++ b/drivers/mmc/host/omap.c @@ -172,7 +172,7 @@ struct mmc_omap_host { struct omap_mmc_platform_data *pdata; }; -void mmc_omap_fclk_offdelay(struct mmc_omap_slot *slot) +static void mmc_omap_fclk_offdelay(struct mmc_omap_slot *slot) { unsigned long tick_ns; @@ -182,7 +182,7 @@ void mmc_omap_fclk_offdelay(struct mmc_omap_slot *slot) } } -void mmc_omap_fclk_enable(struct mmc_omap_host *host, unsigned int enable) +static void mmc_omap_fclk_enable(struct mmc_omap_host *host, unsigned int enable) { unsigned long flags; -- cgit v1.2.3