mirror of https://github.com/thesofproject/sof.git
ipc4: multi pipeline set state on different cores
This will allow to correctly set multiple pipelines state even if they are allocated on different cores. ipc4_set_pipeline_state will check if several cores are involved - set ppl state if only current core requested - process IPC on another core if only single secondary core requested - send IDC messages if several secondary cores involved Signed-off-by: Adrian Bonislawski <adrian.bonislawski@intel.com> Signed-off-by: Jaska Uimonen <jaska.uimonen@intel.com>
This commit is contained in:
parent
54959a83ac
commit
4832dc9388
|
@ -315,6 +315,33 @@ static int idc_reset(uint32_t comp_id)
|
|||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Executes IDC pipeline set state message.
|
||||
* \param[in] ppl_id Pipeline id to be triggered.
|
||||
* \return Error code.
|
||||
*/
|
||||
static int idc_ppl_state(uint32_t ppl_id)
|
||||
{
|
||||
#if CONFIG_IPC_MAJOR_4
|
||||
struct ipc *ipc = ipc_get();
|
||||
struct idc *idc = *idc_get();
|
||||
struct idc_payload *payload = idc_payload_get(idc, cpu_get_id());
|
||||
struct ipc_comp_dev *ppl_icd;
|
||||
uint32_t cmd = *(uint32_t *)payload;
|
||||
bool delayed = false;
|
||||
|
||||
ppl_icd = ipc_get_comp_by_ppl_id(ipc, COMP_TYPE_PIPELINE, ppl_id);
|
||||
if (!ppl_icd) {
|
||||
tr_err(&idc_tr, "idc: comp %d not found", ppl_id);
|
||||
return IPC4_INVALID_RESOURCE_ID;
|
||||
}
|
||||
|
||||
return set_pipeline_state(ppl_icd, cmd, &delayed);
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
static void idc_prepare_d0ix(void)
|
||||
{
|
||||
/* set prepare_d0ix flag, which indicates that in the next
|
||||
|
@ -400,6 +427,9 @@ void idc_cmd(struct idc_msg *msg)
|
|||
case iTS(IDC_MSG_RESET):
|
||||
ret = idc_reset(msg->extension);
|
||||
break;
|
||||
case iTS(IDC_MSG_PPL_STATE):
|
||||
ret = idc_ppl_state(msg->extension);
|
||||
break;
|
||||
case iTS(IDC_MSG_PREPARE_D0ix):
|
||||
idc_prepare_d0ix();
|
||||
break;
|
||||
|
|
|
@ -46,6 +46,7 @@ typedef uint32_t ipc_comp;
|
|||
#define ipc_from_pipe_new(x) ((struct ipc4_pipeline_create *)x)
|
||||
#define ipc_from_pipe_connect(x) ((struct ipc4_module_bind_unbind *)x)
|
||||
|
||||
struct ipc_comp_dev;
|
||||
const struct comp_driver *ipc4_get_comp_drv(int module_id);
|
||||
struct comp_dev *ipc4_get_comp_dev(uint32_t comp_id);
|
||||
int ipc4_add_comp_dev(struct comp_dev *dev);
|
||||
|
@ -57,6 +58,7 @@ int ipc4_trigger_chain_dma(struct ipc *ipc, struct ipc4_chain_dma *cdma, bool *d
|
|||
int ipc4_process_on_core(uint32_t core, bool blocking);
|
||||
int ipc4_pipeline_complete(struct ipc *ipc, uint32_t comp_id);
|
||||
int ipc4_find_dma_config(struct ipc_config_dai *dai, uint8_t *data_buffer, uint32_t size);
|
||||
int set_pipeline_state(struct ipc_comp_dev *ppl_icd, uint32_t cmd, bool *delayed);
|
||||
#else
|
||||
#error "No or invalid IPC MAJOR version selected."
|
||||
#endif
|
||||
|
|
|
@ -215,8 +215,8 @@ static bool is_any_ppl_active(void)
|
|||
* ERROR Stop EOS |______\ SAVE
|
||||
* /
|
||||
*/
|
||||
static int set_pipeline_state(struct ipc_comp_dev *ppl_icd, uint32_t cmd,
|
||||
bool *delayed)
|
||||
int set_pipeline_state(struct ipc_comp_dev *ppl_icd, uint32_t cmd,
|
||||
bool *delayed)
|
||||
{
|
||||
struct ipc_comp_dev *host = NULL;
|
||||
struct ipc *ipc = ipc_get();
|
||||
|
@ -404,6 +404,8 @@ static int ipc4_set_pipeline_state(struct ipc4_message_request *ipc4)
|
|||
struct ipc *ipc = ipc_get();
|
||||
uint32_t cmd, ppl_count, id;
|
||||
const uint32_t *ppl_id;
|
||||
bool use_idc = false;
|
||||
uint32_t idx;
|
||||
int ret = 0;
|
||||
int i;
|
||||
|
||||
|
@ -425,6 +427,21 @@ static int ipc4_set_pipeline_state(struct ipc4_message_request *ipc4)
|
|||
ppl_id = &id;
|
||||
}
|
||||
|
||||
for (i = 0; i < ppl_count; i++) {
|
||||
ppl_icd = ipc_get_comp_by_ppl_id(ipc, COMP_TYPE_PIPELINE, ppl_id[i]);
|
||||
if (!ppl_icd) {
|
||||
tr_err(&ipc_tr, "ipc: comp %d not found", ppl_id[i]);
|
||||
return IPC4_INVALID_RESOURCE_ID;
|
||||
}
|
||||
|
||||
if (i) {
|
||||
if (ppl_icd->core != idx)
|
||||
use_idc = true;
|
||||
} else {
|
||||
idx = ppl_icd->core;
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < ppl_count; i++) {
|
||||
bool delayed = false;
|
||||
|
||||
|
@ -435,15 +452,23 @@ static int ipc4_set_pipeline_state(struct ipc4_message_request *ipc4)
|
|||
}
|
||||
|
||||
/* Pass IPC to target core
|
||||
* Note: current implementation supports only a case with
|
||||
* all pipelines in cmd allocated on the same core
|
||||
* or use idc if more than one core used
|
||||
*/
|
||||
if (!cpu_is_me(ppl_icd->core))
|
||||
return ipc4_process_on_core(ppl_icd->core, false);
|
||||
if (!cpu_is_me(ppl_icd->core)) {
|
||||
if (use_idc) {
|
||||
struct idc_msg msg = { IDC_MSG_PPL_STATE,
|
||||
IDC_MSG_PPL_STATE_EXT(ppl_id[i]), ppl_icd->core,
|
||||
sizeof(cmd), &cmd, };
|
||||
|
||||
ipc_compound_pre_start(state.primary.r.type);
|
||||
ret = set_pipeline_state(ppl_icd, cmd, &delayed);
|
||||
ipc_compound_post_start(state.primary.r.type, ret, delayed);
|
||||
ret = idc_send_msg(&msg, IDC_BLOCKING);
|
||||
} else {
|
||||
return ipc4_process_on_core(ppl_icd->core, false);
|
||||
}
|
||||
} else {
|
||||
ipc_compound_pre_start(state.primary.r.type);
|
||||
ret = set_pipeline_state(ppl_icd, cmd, &delayed);
|
||||
ipc_compound_post_start(state.primary.r.type, ret, delayed);
|
||||
}
|
||||
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
|
|
|
@ -106,6 +106,10 @@
|
|||
#define IDC_MSG_UNBIND IDC_TYPE(0xE)
|
||||
#define IDC_MSG_GET_ATTRIBUTE IDC_TYPE(0xF)
|
||||
|
||||
/** \brief IDC pipeline set state message. */
|
||||
#define IDC_MSG_PPL_STATE IDC_TYPE(0xC)
|
||||
#define IDC_MSG_PPL_STATE_EXT(x) IDC_EXTENSION(x)
|
||||
|
||||
/** \brief IDC_MSG_SECONDARY_CORE_CRASHED header fields. */
|
||||
#define IDC_SCC_CORE_SHIFT 0
|
||||
#define IDC_SCC_CORE_MASK 0xff
|
||||
|
|
Loading…
Reference in New Issue