host: add R/W pointers check for playback

Here add R/W pointers check for playback, make sure the next
copy size is not bigger than the host avail bytes.

Signed-off-by: Keyon Jie <yang.jie@linux.intel.com>
This commit is contained in:
Keyon Jie 2017-02-11 10:17:51 +08:00 committed by Liam Girdwood
parent 0eeb6ca7d2
commit 1e524a17f0
1 changed files with 25 additions and 7 deletions

View File

@ -138,7 +138,7 @@ static void host_dma_cb_playback(struct comp_dev *dev,
struct host_data *hd = comp_get_drvdata(dev);
struct dma_sg_elem *local_elem, *source_elem, *sink_elem;
struct comp_buffer *dma_buffer;
uint32_t next_size;
uint32_t next_size, need_copy = 0;
local_elem = list_first_item(&hd->config.elem_list,
struct dma_sg_elem, list);
@ -158,7 +158,7 @@ static void host_dma_cb_playback(struct comp_dev *dev,
#endif
/* recalc available buffer space */
comp_update_buffer_consume(hd->dma_buffer);
comp_update_buffer_produce(hd->dma_buffer);
/* new local period, update host buffer position blks */
hd->host_pos_read += local_elem->size;
@ -166,8 +166,6 @@ static void host_dma_cb_playback(struct comp_dev *dev,
/* buffer overlap ? */
if (hd->host_pos_read >= hd->host_size)
hd->host_pos_read = 0;
if (hd->host_pos)
*hd->host_pos = hd->host_pos_read;
host_update_buffer_consume(hd);
/* send IPC message to driver if needed */
@ -200,7 +198,7 @@ static void host_dma_cb_playback(struct comp_dev *dev,
}
next_size = hd->period->size;
if (local_elem->src + hd->period->size > hd->source->current_end)
if (local_elem->src + next_size > hd->source->current_end)
next_size = hd->source->current_end - local_elem->src;
if (local_elem->dest + next_size > hd->sink->current_end)
next_size = hd->sink->current_end - local_elem->dest;
@ -209,13 +207,33 @@ static void host_dma_cb_playback(struct comp_dev *dev,
if (next_size != hd->period->size)
hd->split_remaining = hd->period->size - next_size;
} else {
need_copy = 1;
next_size = next_size < hd->split_remaining ?
next_size : hd->split_remaining;
hd->split_remaining -= next_size;
}
local_elem->size = next_size;
if (hd->split_remaining) {
/* check if avail is enough, otherwise, drain the last bytes and stop */
if (hd->host_avail < local_elem->size) {
if (hd->host_avail == 0) {
/* end of stream, stop */
next->size = 0;
need_copy = 0;
goto next_copy;
}
/* end of stream, drain the last bytes */
local_elem->size = hd->host_avail;
/* the split_remaining may not be copied anymore, but, let's make it
correct. we have only hd->host_avail data, so the split_remaining
should be (next_size - hd->host_avail) bigger */
hd->split_remaining += next_size - hd->host_avail;
}
next_copy:
if (need_copy) {
next->src = local_elem->src;
next->dest = local_elem->dest;
next->size = local_elem->size;
@ -266,7 +284,7 @@ static void host_dma_cb_capture(struct comp_dev *dev,
*hd->host_pos = hd->host_pos_read;
/* recalc available buffer space */
comp_update_buffer_produce(hd->dma_buffer);
comp_update_buffer_consume(hd->dma_buffer);
/* send IPC message to driver if needed */
hd->host_period_pos += local_elem->size;