diff options
author | Jürg Billeter <j@bitron.ch> | 2014-11-25 09:10:17 -0500 |
---|---|---|
committer | Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com> | 2014-12-23 04:13:03 -0500 |
commit | ee4b876bbee2c5c53518110849f23c117eec099c (patch) | |
tree | 31f305444af7cc69dce3a9ae45f1fed89cc726ae /drivers/dma | |
parent | 1ed1315f9b63c45f57f607e7ad2dac066b101f16 (diff) |
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')
-rw-r--r-- | drivers/dma/sh/rcar-dmac.c | 14 |
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, | |||
679 | desc->hwdescs.size = size; | 679 | desc->hwdescs.size = size; |
680 | } | 680 | } |
681 | 681 | ||
682 | static void rcar_dmac_fill_hwdesc(struct rcar_dmac_chan *chan, | 682 | static int rcar_dmac_fill_hwdesc(struct rcar_dmac_chan *chan, |
683 | struct rcar_dmac_desc *desc) | 683 | struct rcar_dmac_desc *desc) |
684 | { | 684 | { |
685 | struct rcar_dmac_xfer_chunk *chunk; | 685 | struct rcar_dmac_xfer_chunk *chunk; |
686 | struct rcar_dmac_hw_desc *hwdesc; | 686 | struct rcar_dmac_hw_desc *hwdesc; |
@@ -689,7 +689,7 @@ static void rcar_dmac_fill_hwdesc(struct rcar_dmac_chan *chan, | |||
689 | 689 | ||
690 | hwdesc = desc->hwdescs.mem; | 690 | hwdesc = desc->hwdescs.mem; |
691 | if (!hwdesc) | 691 | if (!hwdesc) |
692 | return; | 692 | return -ENOMEM; |
693 | 693 | ||
694 | list_for_each_entry(chunk, &desc->chunks, node) { | 694 | list_for_each_entry(chunk, &desc->chunks, node) { |
695 | hwdesc->sar = chunk->src_addr; | 695 | hwdesc->sar = chunk->src_addr; |
@@ -697,6 +697,8 @@ static void rcar_dmac_fill_hwdesc(struct rcar_dmac_chan *chan, | |||
697 | hwdesc->tcr = chunk->size >> desc->xfer_shift; | 697 | hwdesc->tcr = chunk->size >> desc->xfer_shift; |
698 | hwdesc++; | 698 | hwdesc++; |
699 | } | 699 | } |
700 | |||
701 | return 0; | ||
700 | } | 702 | } |
701 | 703 | ||
702 | /* ----------------------------------------------------------------------------- | 704 | /* ----------------------------------------------------------------------------- |
@@ -917,8 +919,10 @@ rcar_dmac_chan_prep_sg(struct rcar_dmac_chan *chan, struct scatterlist *sgl, | |||
917 | * additional complexity remains to be investigated. | 919 | * additional complexity remains to be investigated. |
918 | */ | 920 | */ |
919 | desc->hwdescs.use = !highmem && nchunks > 1; | 921 | desc->hwdescs.use = !highmem && nchunks > 1; |
920 | if (desc->hwdescs.use) | 922 | if (desc->hwdescs.use) { |
921 | rcar_dmac_fill_hwdesc(chan, desc); | 923 | if (rcar_dmac_fill_hwdesc(chan, desc) < 0) |
924 | desc->hwdescs.use = false; | ||
925 | } | ||
922 | 926 | ||
923 | return &desc->async_tx; | 927 | return &desc->async_tx; |
924 | } | 928 | } |