Skip to content

Commit

Permalink
dmaengine: rcar-dmac: Fix oops due to unintialized list in error ISR
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Laurent Pinchart authored and Vinod Koul committed Feb 16, 2015
1 parent f391507 commit f7638c9
Showing 1 changed file with 11 additions and 10 deletions.
21 changes: 11 additions & 10 deletions drivers/dma/sh/rcar-dmac.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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);
Expand Down

0 comments on commit f7638c9

Please sign in to comment.