Commit 8f98781e authored by Guennadi Liakhovetski's avatar Guennadi Liakhovetski Committed by Dan Williams

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: default avatarGuennadi Liakhovetski <g.liakhovetski@gmx.de>
Signed-off-by: default avatarDan Williams <dan.j.williams@intel.com>
parent b953df7c
...@@ -761,12 +761,10 @@ static void ipu_select_buffer(enum ipu_channel channel, int buffer_n) ...@@ -761,12 +761,10 @@ static void ipu_select_buffer(enum ipu_channel channel, int buffer_n)
* @buffer_n: buffer number to update. * @buffer_n: buffer number to update.
* 0 or 1 are the only valid values. * 0 or 1 are the only valid values.
* @phyaddr: buffer physical address. * @phyaddr: buffer physical address.
* @return: Returns 0 on success or negative error code on failure. This
* function will fail if the buffer is set to ready.
*/ */
/* Called under spin_lock(_irqsave)(&ichan->lock) */ /* Called under spin_lock(_irqsave)(&ichan->lock) */
static int ipu_update_channel_buffer(struct idmac_channel *ichan, static void ipu_update_channel_buffer(struct idmac_channel *ichan,
int buffer_n, dma_addr_t phyaddr) int buffer_n, dma_addr_t phyaddr)
{ {
enum ipu_channel channel = ichan->dma_chan.chan_id; enum ipu_channel channel = ichan->dma_chan.chan_id;
uint32_t reg; uint32_t reg;
...@@ -806,8 +804,6 @@ static int ipu_update_channel_buffer(struct idmac_channel *ichan, ...@@ -806,8 +804,6 @@ static int ipu_update_channel_buffer(struct idmac_channel *ichan,
} }
spin_unlock_irqrestore(&ipu_data.lock, flags); spin_unlock_irqrestore(&ipu_data.lock, flags);
return 0;
} }
/* Called under spin_lock_irqsave(&ichan->lock) */ /* Called under spin_lock_irqsave(&ichan->lock) */
...@@ -816,7 +812,6 @@ static int ipu_submit_buffer(struct idmac_channel *ichan, ...@@ -816,7 +812,6 @@ static int ipu_submit_buffer(struct idmac_channel *ichan,
{ {
unsigned int chan_id = ichan->dma_chan.chan_id; unsigned int chan_id = ichan->dma_chan.chan_id;
struct device *dev = &ichan->dma_chan.dev->device; struct device *dev = &ichan->dma_chan.dev->device;
int ret;
if (async_tx_test_ack(&desc->txd)) if (async_tx_test_ack(&desc->txd))
return -EINTR; return -EINTR;
...@@ -827,14 +822,7 @@ static int ipu_submit_buffer(struct idmac_channel *ichan, ...@@ -827,14 +822,7 @@ static int ipu_submit_buffer(struct idmac_channel *ichan,
* could make it conditional on status >= IPU_CHANNEL_ENABLED, but * could make it conditional on status >= IPU_CHANNEL_ENABLED, but
* doing it again shouldn't hurt either. * doing it again shouldn't hurt either.
*/ */
ret = ipu_update_channel_buffer(ichan, buf_idx, ipu_update_channel_buffer(ichan, buf_idx, sg_dma_address(sg));
sg_dma_address(sg));
if (ret < 0) {
dev_err(dev, "Updating sg %p on channel 0x%x buffer %d failed!\n",
sg, chan_id, buf_idx);
return ret;
}
ipu_select_buffer(chan_id, buf_idx); ipu_select_buffer(chan_id, buf_idx);
dev_dbg(dev, "Updated sg %p on channel 0x%x buffer %d\n", 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,10 +1367,11 @@ static irqreturn_t idmac_interrupt(int irq, void *dev_id)
if (likely(sgnew) && if (likely(sgnew) &&
ipu_submit_buffer(ichan, descnew, sgnew, ichan->active_buffer) < 0) { ipu_submit_buffer(ichan, descnew, sgnew, ichan->active_buffer) < 0) {
callback = desc->txd.callback; callback = descnew->txd.callback;
callback_param = desc->txd.callback_param; callback_param = descnew->txd.callback_param;
spin_unlock(&ichan->lock); spin_unlock(&ichan->lock);
callback(callback_param); if (callback)
callback(callback_param);
spin_lock(&ichan->lock); spin_lock(&ichan->lock);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment