diff options
author | Guennadi Liakhovetski <g.liakhovetski@gmx.de> | 2010-02-10 11:32:38 -0500 |
---|---|---|
committer | Dan Williams <dan.j.williams@intel.com> | 2010-02-10 14:01:06 -0500 |
commit | 8f98781e0f15207b6ab33bee1fae05428be0475b (patch) | |
tree | 31830720fd57bd11191e85bbdc98eaefe061f127 /drivers/dma | |
parent | b953df7c70740cd7593072ebec77a8f658505630 (diff) |
async-tx: fix buffer submission error handling in ipu_idma.c
If submitting new buffer failed, a wrong descriptor gets completed and it
doesn't check, if a callback is at all defined, which can lead to an Oops. Fix
these bugs and make ipu_update_channel_buffer() void, because it never fails.
Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
Diffstat (limited to 'drivers/dma')
-rw-r--r-- | drivers/dma/ipu/ipu_idmac.c | 25 |
1 files changed, 7 insertions, 18 deletions
diff --git a/drivers/dma/ipu/ipu_idmac.c b/drivers/dma/ipu/ipu_idmac.c index 9a5bc1a7389e..e80bae1673fa 100644 --- a/drivers/dma/ipu/ipu_idmac.c +++ b/drivers/dma/ipu/ipu_idmac.c | |||
@@ -761,12 +761,10 @@ static void ipu_select_buffer(enum ipu_channel channel, int buffer_n) | |||
761 | * @buffer_n: buffer number to update. | 761 | * @buffer_n: buffer number to update. |
762 | * 0 or 1 are the only valid values. | 762 | * 0 or 1 are the only valid values. |
763 | * @phyaddr: buffer physical address. | 763 | * @phyaddr: buffer physical address. |
764 | * @return: Returns 0 on success or negative error code on failure. This | ||
765 | * function will fail if the buffer is set to ready. | ||
766 | */ | 764 | */ |
767 | /* Called under spin_lock(_irqsave)(&ichan->lock) */ | 765 | /* Called under spin_lock(_irqsave)(&ichan->lock) */ |
768 | static int ipu_update_channel_buffer(struct idmac_channel *ichan, | 766 | static void ipu_update_channel_buffer(struct idmac_channel *ichan, |
769 | int buffer_n, dma_addr_t phyaddr) | 767 | int buffer_n, dma_addr_t phyaddr) |
770 | { | 768 | { |
771 | enum ipu_channel channel = ichan->dma_chan.chan_id; | 769 | enum ipu_channel channel = ichan->dma_chan.chan_id; |
772 | uint32_t reg; | 770 | uint32_t reg; |
@@ -806,8 +804,6 @@ static int ipu_update_channel_buffer(struct idmac_channel *ichan, | |||
806 | } | 804 | } |
807 | 805 | ||
808 | spin_unlock_irqrestore(&ipu_data.lock, flags); | 806 | spin_unlock_irqrestore(&ipu_data.lock, flags); |
809 | |||
810 | return 0; | ||
811 | } | 807 | } |
812 | 808 | ||
813 | /* Called under spin_lock_irqsave(&ichan->lock) */ | 809 | /* Called under spin_lock_irqsave(&ichan->lock) */ |
@@ -816,7 +812,6 @@ static int ipu_submit_buffer(struct idmac_channel *ichan, | |||
816 | { | 812 | { |
817 | unsigned int chan_id = ichan->dma_chan.chan_id; | 813 | unsigned int chan_id = ichan->dma_chan.chan_id; |
818 | struct device *dev = &ichan->dma_chan.dev->device; | 814 | struct device *dev = &ichan->dma_chan.dev->device; |
819 | int ret; | ||
820 | 815 | ||
821 | if (async_tx_test_ack(&desc->txd)) | 816 | if (async_tx_test_ack(&desc->txd)) |
822 | return -EINTR; | 817 | return -EINTR; |
@@ -827,14 +822,7 @@ static int ipu_submit_buffer(struct idmac_channel *ichan, | |||
827 | * could make it conditional on status >= IPU_CHANNEL_ENABLED, but | 822 | * could make it conditional on status >= IPU_CHANNEL_ENABLED, but |
828 | * doing it again shouldn't hurt either. | 823 | * doing it again shouldn't hurt either. |
829 | */ | 824 | */ |
830 | ret = ipu_update_channel_buffer(ichan, buf_idx, | 825 | ipu_update_channel_buffer(ichan, buf_idx, sg_dma_address(sg)); |
831 | sg_dma_address(sg)); | ||
832 | |||
833 | if (ret < 0) { | ||
834 | dev_err(dev, "Updating sg %p on channel 0x%x buffer %d failed!\n", | ||
835 | sg, chan_id, buf_idx); | ||
836 | return ret; | ||
837 | } | ||
838 | 826 | ||
839 | ipu_select_buffer(chan_id, buf_idx); | 827 | ipu_select_buffer(chan_id, buf_idx); |
840 | dev_dbg(dev, "Updated sg %p on channel 0x%x buffer %d\n", | 828 | dev_dbg(dev, "Updated sg %p on channel 0x%x buffer %d\n", |
@@ -1379,10 +1367,11 @@ static irqreturn_t idmac_interrupt(int irq, void *dev_id) | |||
1379 | 1367 | ||
1380 | if (likely(sgnew) && | 1368 | if (likely(sgnew) && |
1381 | ipu_submit_buffer(ichan, descnew, sgnew, ichan->active_buffer) < 0) { | 1369 | ipu_submit_buffer(ichan, descnew, sgnew, ichan->active_buffer) < 0) { |
1382 | callback = desc->txd.callback; | 1370 | callback = descnew->txd.callback; |
1383 | callback_param = desc->txd.callback_param; | 1371 | callback_param = descnew->txd.callback_param; |
1384 | spin_unlock(&ichan->lock); | 1372 | spin_unlock(&ichan->lock); |
1385 | callback(callback_param); | 1373 | if (callback) |
1374 | callback(callback_param); | ||
1386 | spin_lock(&ichan->lock); | 1375 | spin_lock(&ichan->lock); |
1387 | } | 1376 | } |
1388 | 1377 | ||