mirror of https://github.com/thesofproject/sof.git
ipc4: Fix chain DMA trigger handling
We need to deliver the PPL_STATUS_SCHEDULED from pipeline_trigger() to calling ipc4_process_chain_dma() function. Added "bool *delay" parameter to ipc4_trigger_chain_dma() for that, since there is no clean way to use IPC4 status values for that purpose. The most complex is the case where an active stream is shut down with a single message (both active and allocate bits zero). In this situation the stream has to be paused and reset in another thread, but the freeing the pipeline has to be done in messaging thread, since chained DMA pipelines are not cleaned up automatically. Signed-off-by: Jyri Sarha <jyri.sarha@intel.com>
This commit is contained in:
parent
880857b3f7
commit
35f2e5f84f
|
@ -51,7 +51,7 @@ struct comp_dev *ipc4_get_comp_dev(uint32_t comp_id);
|
|||
int ipc4_add_comp_dev(struct comp_dev *dev);
|
||||
const struct comp_driver *ipc4_get_drv(uint8_t *uuid);
|
||||
int ipc4_create_chain_dma(struct ipc *ipc, struct ipc4_chain_dma *cdma);
|
||||
int ipc4_trigger_chain_dma(struct ipc *ipc, struct ipc4_chain_dma *cdma);
|
||||
int ipc4_trigger_chain_dma(struct ipc *ipc, struct ipc4_chain_dma *cdma, bool *delay);
|
||||
#else
|
||||
#error "No or invalid IPC MAJOR version selected."
|
||||
#endif
|
||||
|
|
|
@ -454,6 +454,7 @@ static int ipc4_process_chain_dma(struct ipc4_message_request *ipc4)
|
|||
{
|
||||
struct ipc4_chain_dma cdma;
|
||||
struct ipc *ipc = ipc_get();
|
||||
bool delay = false;
|
||||
int ret;
|
||||
|
||||
memcpy_s(&cdma, sizeof(cdma), ipc4, sizeof(cdma));
|
||||
|
@ -471,13 +472,25 @@ static int ipc4_process_chain_dma(struct ipc4_message_request *ipc4)
|
|||
}
|
||||
|
||||
atomic_set(&msg_data.delayed_reply, 1);
|
||||
ret = ipc4_trigger_chain_dma(ipc, &cdma);
|
||||
ret = ipc4_trigger_chain_dma(ipc, &cdma, &delay);
|
||||
/* it is not scheduled in another thread */
|
||||
if (ret != PPL_STATUS_SCHEDULED) {
|
||||
if (!delay) {
|
||||
atomic_set(&msg_data.delayed_reply, 0);
|
||||
msg_data.delayed_error = 0;
|
||||
} else {
|
||||
ret = 0;
|
||||
} else if (!cdma.primary.r.allocate) {
|
||||
uint32_t pipeline_id = IPC4_COMP_ID(cdma.primary.r.host_dma_id
|
||||
+ IPC4_MAX_MODULE_COUNT,
|
||||
cdma.primary.r.link_dma_id);
|
||||
|
||||
/* waiting for pipeline reset done */
|
||||
ipc_wait_for_compound_msg();
|
||||
ret = ipc_pipeline_free(ipc, pipeline_id);
|
||||
if (ret < 0) {
|
||||
tr_err(&ipc_tr, "failed to free chain dma %d", ret);
|
||||
ret = IPC4_BAD_STATE;
|
||||
} else {
|
||||
ret = IPC4_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
|
|
@ -722,12 +722,13 @@ int ipc4_create_chain_dma(struct ipc *ipc, struct ipc4_chain_dma *cdma)
|
|||
return ret;
|
||||
}
|
||||
|
||||
int ipc4_trigger_chain_dma(struct ipc *ipc, struct ipc4_chain_dma *cdma)
|
||||
int ipc4_trigger_chain_dma(struct ipc *ipc, struct ipc4_chain_dma *cdma,
|
||||
bool *delay)
|
||||
{
|
||||
struct ipc_comp_dev *ipc_pipe;
|
||||
struct comp_dev *host;
|
||||
uint32_t pipeline_id;
|
||||
int ret;
|
||||
int ret = 0;
|
||||
|
||||
pipeline_id = IPC4_COMP_ID(cdma->primary.r.host_dma_id + IPC4_MAX_MODULE_COUNT,
|
||||
cdma->primary.r.link_dma_id);
|
||||
|
@ -746,6 +747,10 @@ int ipc4_trigger_chain_dma(struct ipc *ipc, struct ipc4_chain_dma *cdma)
|
|||
if (ret < 0) {
|
||||
tr_err(&ipc_tr, "failed to disable chain dma %d", ret);
|
||||
return IPC4_BAD_STATE;
|
||||
} else if (ret == PPL_STATUS_SCHEDULED) {
|
||||
/* pipeline reset will be done by schedule thread */
|
||||
*delay = true;
|
||||
return IPC4_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -789,6 +794,9 @@ int ipc4_trigger_chain_dma(struct ipc *ipc, struct ipc4_chain_dma *cdma)
|
|||
}
|
||||
}
|
||||
|
||||
if (ret == PPL_STATUS_SCHEDULED)
|
||||
*delay = true;
|
||||
|
||||
return IPC4_SUCCESS;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue