mirror of https://github.com/thesofproject/sof.git
host: fix playback failed from second time issue
For host with gateway, we need create extra dma_sg_elem * period_count for hd->config.element_list, and free them at host_reset() time, otherwise, the hd->local elements may be broken if we use them for config.element_list. Signed-off-by: Keyon Jie <yang.jie@linux.intel.com>
This commit is contained in:
parent
b0f8e5d5c2
commit
bad1261098
|
@ -411,6 +411,10 @@ static int create_local_elems(struct comp_dev *dev)
|
||||||
{
|
{
|
||||||
struct host_data *hd = comp_get_drvdata(dev);
|
struct host_data *hd = comp_get_drvdata(dev);
|
||||||
struct dma_sg_elem *e;
|
struct dma_sg_elem *e;
|
||||||
|
#if defined CONFIG_DMA_GW
|
||||||
|
struct dma_sg_elem *ec;
|
||||||
|
struct dma_sg_elem *local_elem;
|
||||||
|
#endif
|
||||||
struct list_item *elist;
|
struct list_item *elist;
|
||||||
struct list_item *tlist;
|
struct list_item *tlist;
|
||||||
int i;
|
int i;
|
||||||
|
@ -434,13 +438,21 @@ static int create_local_elems(struct comp_dev *dev)
|
||||||
list_item_append(&e->list, &hd->local.elem_list);
|
list_item_append(&e->list, &hd->local.elem_list);
|
||||||
#if defined CONFIG_DMA_GW
|
#if defined CONFIG_DMA_GW
|
||||||
/*
|
/*
|
||||||
* for dma gateway, we don't allocate extra sg elements, so,
|
* for dma gateway, we don't allocate extra sg elements in
|
||||||
* just reuse local elements for config.elem_list.
|
* host_buffer, so, we need create them here and add them
|
||||||
|
* to config.elem_list.
|
||||||
* And, as the first element has been added at host_new, so
|
* And, as the first element has been added at host_new, so
|
||||||
* add from the 2nd element here
|
* add from the 2nd element here.
|
||||||
*/
|
*/
|
||||||
if (i >= 1)
|
if (!i)
|
||||||
list_item_append(&e->list, &hd->config.elem_list);
|
continue;
|
||||||
|
/* allocate new host DMA elem and add it to our list */
|
||||||
|
ec = rzalloc(RZONE_RUNTIME, RFLAGS_NONE, sizeof(*ec));
|
||||||
|
if (!ec)
|
||||||
|
goto unwind;
|
||||||
|
|
||||||
|
*ec = *e;
|
||||||
|
list_item_append(&ec->list, &hd->config.elem_list);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -452,6 +464,15 @@ unwind:
|
||||||
list_item_del(&e->list);
|
list_item_del(&e->list);
|
||||||
rfree(e);
|
rfree(e);
|
||||||
}
|
}
|
||||||
|
#if defined CONFIG_DMA_GW
|
||||||
|
local_elem = list_first_item(&hd->config.elem_list,
|
||||||
|
struct dma_sg_elem, list);
|
||||||
|
list_for_item_safe(elist, tlist, &local_elem->list) {
|
||||||
|
ec = container_of(elist, struct dma_sg_elem, list);
|
||||||
|
list_item_del(&ec->list);
|
||||||
|
rfree(ec);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
trace_host_error("el0");
|
trace_host_error("el0");
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
|
@ -712,7 +733,6 @@ static int host_reset(struct comp_dev *dev)
|
||||||
|
|
||||||
/* free all host DMA elements */
|
/* free all host DMA elements */
|
||||||
list_for_item_safe(elist, tlist, &hd->host.elem_list) {
|
list_for_item_safe(elist, tlist, &hd->host.elem_list) {
|
||||||
|
|
||||||
e = container_of(elist, struct dma_sg_elem, list);
|
e = container_of(elist, struct dma_sg_elem, list);
|
||||||
list_item_del(&e->list);
|
list_item_del(&e->list);
|
||||||
rfree(e);
|
rfree(e);
|
||||||
|
@ -720,7 +740,6 @@ static int host_reset(struct comp_dev *dev)
|
||||||
|
|
||||||
/* free all local DMA elements */
|
/* free all local DMA elements */
|
||||||
list_for_item_safe(elist, tlist, &hd->local.elem_list) {
|
list_for_item_safe(elist, tlist, &hd->local.elem_list) {
|
||||||
|
|
||||||
e = container_of(elist, struct dma_sg_elem, list);
|
e = container_of(elist, struct dma_sg_elem, list);
|
||||||
list_item_del(&e->list);
|
list_item_del(&e->list);
|
||||||
rfree(e);
|
rfree(e);
|
||||||
|
@ -729,6 +748,21 @@ static int host_reset(struct comp_dev *dev)
|
||||||
#if defined CONFIG_DMA_GW
|
#if defined CONFIG_DMA_GW
|
||||||
dma_stop(hd->dma, hd->chan);
|
dma_stop(hd->dma, hd->chan);
|
||||||
dma_channel_put(hd->dma, hd->chan);
|
dma_channel_put(hd->dma, hd->chan);
|
||||||
|
|
||||||
|
e = list_first_item(&hd->config.elem_list,
|
||||||
|
struct dma_sg_elem, list);
|
||||||
|
/*
|
||||||
|
* here free dma_sg_elem those allocated in create_local_elems(),
|
||||||
|
* we should keep header and the first local elem after reset
|
||||||
|
*/
|
||||||
|
list_for_item_safe(elist, tlist, &e->list) {
|
||||||
|
e = container_of(elist, struct dma_sg_elem, list);
|
||||||
|
/* should not free the header, finished */
|
||||||
|
if (elist == &hd->config.elem_list)
|
||||||
|
break;
|
||||||
|
list_item_del(&e->list);
|
||||||
|
rfree(e);
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
host_pointer_reset(dev);
|
host_pointer_reset(dev);
|
||||||
|
|
Loading…
Reference in New Issue