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:
Adrian Bonislawski 2023-05-16 19:26:28 +02:00 committed by Michal Wasko
parent 54959a83ac
commit 4832dc9388
4 changed files with 70 additions and 9 deletions

View File

@ -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;

View File

@ -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

View File

@ -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;

View File

@ -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