Skip to content

Commit

Permalink
dmaengine: mv_xor: fix oops when channels fail to initialise
Browse files Browse the repository at this point in the history
When a channel fails to initialise, we error out and clean up any
previously unregistered channels by walking the entire xordev->channels
array.  Unfortunately, there are paths which end up storing an error
pointer in this array, which we then try and dereference in the cleanup
code, which causes an oops.

Fix this by avoiding writing invalid pointers to this array in the first
place.

Tested-by: Aaro Koskinen <aaro.koskinen@iki.fi>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
  • Loading branch information
Russell King authored and Dan Williams committed Dec 13, 2013
1 parent d16695a commit 0be8253
Showing 1 changed file with 13 additions and 11 deletions.
24 changes: 13 additions & 11 deletions drivers/dma/mv_xor.c
Original file line number Diff line number Diff line change
Expand Up @@ -1199,6 +1199,7 @@ static int mv_xor_probe(struct platform_device *pdev)
int i = 0;

for_each_child_of_node(pdev->dev.of_node, np) {
struct mv_xor_chan *chan;
dma_cap_mask_t cap_mask;
int irq;

Expand All @@ -1216,21 +1217,21 @@ static int mv_xor_probe(struct platform_device *pdev)
goto err_channel_add;
}

xordev->channels[i] =
mv_xor_channel_add(xordev, pdev, i,
cap_mask, irq);
if (IS_ERR(xordev->channels[i])) {
ret = PTR_ERR(xordev->channels[i]);
xordev->channels[i] = NULL;
chan = mv_xor_channel_add(xordev, pdev, i,
cap_mask, irq);
if (IS_ERR(chan)) {
ret = PTR_ERR(chan);
irq_dispose_mapping(irq);
goto err_channel_add;
}

xordev->channels[i] = chan;
i++;
}
} else if (pdata && pdata->channels) {
for (i = 0; i < MV_XOR_MAX_CHANNELS; i++) {
struct mv_xor_channel_data *cd;
struct mv_xor_chan *chan;
int irq;

cd = &pdata->channels[i];
Expand All @@ -1245,13 +1246,14 @@ static int mv_xor_probe(struct platform_device *pdev)
goto err_channel_add;
}

xordev->channels[i] =
mv_xor_channel_add(xordev, pdev, i,
cd->cap_mask, irq);
if (IS_ERR(xordev->channels[i])) {
ret = PTR_ERR(xordev->channels[i]);
chan = mv_xor_channel_add(xordev, pdev, i,
cd->cap_mask, irq);
if (IS_ERR(chan)) {
ret = PTR_ERR(chan);
goto err_channel_add;
}

xordev->channels[i] = chan;
}
}

Expand Down

0 comments on commit 0be8253

Please sign in to comment.