summaryrefslogtreecommitdiff
path: root/drivers/dma/sh
diff options
context:
space:
mode:
authorJürg Billeter <j@bitron.ch>2014-11-25 15:10:17 +0100
committerLaurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>2014-12-23 11:13:03 +0200
commitee4b876bbee2c5c53518110849f23c117eec099c (patch)
tree31f305444af7cc69dce3a9ae45f1fed89cc726ae /drivers/dma/sh
parent1ed1315f9b63c45f57f607e7ad2dac066b101f16 (diff)
downloadlinux-ee4b876bbee2c5c53518110849f23c117eec099c.tar.gz
linux-ee4b876bbee2c5c53518110849f23c117eec099c.tar.xz
dmaengine: rcar-dmac: Handle hardware descriptor allocation failure
If the atomic DMA coherent pool is too small, disable use of hardware descriptor lists instead of crashing the system: ERROR: 256 KiB atomic DMA coherent pool is too small! Please increase it with coherent_pool= kernel parameter! Unable to handle kernel NULL pointer dereference at virtual address 00000004 Internal error: Oops: a07 [#1] PREEMPT SMP ARM PC is at rcar_dmac_chan_reinit+0x3c/0x160 LR is at _raw_spin_lock_irqsave+0x18/0x5c [<802132c0>] (rcar_dmac_chan_reinit) from [<80214818>] (rcar_dmac_isr_error+0x84/0xa0) [<80214818>] (rcar_dmac_isr_error) from [<80060484>] (handle_irq_event_percpu+0x50/0x150) [<80060484>] (handle_irq_event_percpu) from [<800605c0>] (handle_irq_event+0x3c/0x5c) [<800605c0>] (handle_irq_event) from [<8006350c>] (handle_fasteoi_irq+0xb8/0x198) [<8006350c>] (handle_fasteoi_irq) from [<8005fdb0>] (generic_handle_irq+0x20/0x30) [<8005fdb0>] (generic_handle_irq) from [<8000fcd0>] (handle_IRQ+0x50/0xc4) [<8000fcd0>] (handle_IRQ) from [<800092cc>] (gic_handle_irq+0x28/0x5c) [<800092cc>] (gic_handle_irq) from [<80012700>] (__irq_svc+0x40/0x70) Kernel panic - not syncing: Fatal exception in interrupt Signed-off-by: Jürg Billeter <j@bitron.ch> Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
Diffstat (limited to 'drivers/dma/sh')
-rw-r--r--drivers/dma/sh/rcar-dmac.c14
1 files changed, 9 insertions, 5 deletions
diff --git a/drivers/dma/sh/rcar-dmac.c b/drivers/dma/sh/rcar-dmac.c
index f71a3dc89048..29dd09ad41ff 100644
--- a/drivers/dma/sh/rcar-dmac.c
+++ b/drivers/dma/sh/rcar-dmac.c
@@ -679,8 +679,8 @@ static void rcar_dmac_realloc_hwdesc(struct rcar_dmac_chan *chan,
desc->hwdescs.size = size;
}
-static void rcar_dmac_fill_hwdesc(struct rcar_dmac_chan *chan,
- struct rcar_dmac_desc *desc)
+static int rcar_dmac_fill_hwdesc(struct rcar_dmac_chan *chan,
+ struct rcar_dmac_desc *desc)
{
struct rcar_dmac_xfer_chunk *chunk;
struct rcar_dmac_hw_desc *hwdesc;
@@ -689,7 +689,7 @@ static void rcar_dmac_fill_hwdesc(struct rcar_dmac_chan *chan,
hwdesc = desc->hwdescs.mem;
if (!hwdesc)
- return;
+ return -ENOMEM;
list_for_each_entry(chunk, &desc->chunks, node) {
hwdesc->sar = chunk->src_addr;
@@ -697,6 +697,8 @@ static void rcar_dmac_fill_hwdesc(struct rcar_dmac_chan *chan,
hwdesc->tcr = chunk->size >> desc->xfer_shift;
hwdesc++;
}
+
+ return 0;
}
/* -----------------------------------------------------------------------------
@@ -917,8 +919,10 @@ rcar_dmac_chan_prep_sg(struct rcar_dmac_chan *chan, struct scatterlist *sgl,
* additional complexity remains to be investigated.
*/
desc->hwdescs.use = !highmem && nchunks > 1;
- if (desc->hwdescs.use)
- rcar_dmac_fill_hwdesc(chan, desc);
+ if (desc->hwdescs.use) {
+ if (rcar_dmac_fill_hwdesc(chan, desc) < 0)
+ desc->hwdescs.use = false;
+ }
return &desc->async_tx;
}