diff options
author | Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com> | 2015-01-27 14:58:53 +0100 |
---|---|---|
committer | Vinod Koul <vinod.koul@intel.com> | 2015-02-16 05:03:33 +0100 |
commit | f7638c904bf87eac5bd823ef2debaef8251686b8 (patch) | |
tree | 4e9d7587f6068af7623dd94ebe3d068985b1c31a /drivers/dma | |
parent | dmaengine: rcar-dmac: Fix spinlock issues in interrupt (diff) | |
download | linux-f7638c904bf87eac5bd823ef2debaef8251686b8.tar.xz linux-f7638c904bf87eac5bd823ef2debaef8251686b8.zip |
dmaengine: rcar-dmac: Fix oops due to unintialized list in error ISR
The error interrupt handler stops and reinitializes all channels. This
causes a crash for channels that have never been used, as their
descriptor lists are uninitialized. Fix it by initializing the
descriptor lists at probe time.
Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
Acked-by: Geert Uytterhoeven <geert+renesas@glider.be>
Signed-off-by: Vinod Koul <vinod.koul@intel.com>
Diffstat (limited to 'drivers/dma')
-rw-r--r-- | drivers/dma/sh/rcar-dmac.c | 21 |
1 files changed, 11 insertions, 10 deletions
diff --git a/drivers/dma/sh/rcar-dmac.c b/drivers/dma/sh/rcar-dmac.c index 5a6b85527107..2eb65e1bf938 100644 --- a/drivers/dma/sh/rcar-dmac.c +++ b/drivers/dma/sh/rcar-dmac.c @@ -929,11 +929,6 @@ static int rcar_dmac_alloc_chan_resources(struct dma_chan *chan) struct rcar_dmac_chan *rchan = to_rcar_dmac_chan(chan); int ret; - INIT_LIST_HEAD(&rchan->desc.free); - INIT_LIST_HEAD(&rchan->desc.pending); - INIT_LIST_HEAD(&rchan->desc.active); - INIT_LIST_HEAD(&rchan->desc.done); - INIT_LIST_HEAD(&rchan->desc.wait); INIT_LIST_HEAD(&rchan->desc.chunks_free); INIT_LIST_HEAD(&rchan->desc.pages); @@ -970,11 +965,11 @@ static void rcar_dmac_free_chan_resources(struct dma_chan *chan) rchan->mid_rid = -EINVAL; } - list_splice(&rchan->desc.free, &list); - list_splice(&rchan->desc.pending, &list); - list_splice(&rchan->desc.active, &list); - list_splice(&rchan->desc.done, &list); - list_splice(&rchan->desc.wait, &list); + list_splice_init(&rchan->desc.free, &list); + list_splice_init(&rchan->desc.pending, &list); + list_splice_init(&rchan->desc.active, &list); + list_splice_init(&rchan->desc.done, &list); + list_splice_init(&rchan->desc.wait, &list); list_for_each_entry(desc, &list, node) rcar_dmac_realloc_hwdesc(rchan, desc, 0); @@ -1519,6 +1514,12 @@ static int rcar_dmac_chan_probe(struct rcar_dmac *dmac, spin_lock_init(&rchan->lock); + INIT_LIST_HEAD(&rchan->desc.free); + INIT_LIST_HEAD(&rchan->desc.pending); + INIT_LIST_HEAD(&rchan->desc.active); + INIT_LIST_HEAD(&rchan->desc.done); + INIT_LIST_HEAD(&rchan->desc.wait); + /* Request the channel interrupt. */ sprintf(pdev_irqname, "ch%u", index); irq = platform_get_irq_byname(pdev, pdev_irqname); |