Skip to content

Commit

Permalink
ipc4: multi pipeline set state on different cores
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
abonislawski authored and mwasko committed Jul 31, 2023
1 parent 54959a8 commit 4832dc9
Show file tree
Hide file tree
Showing 4 changed files with 71 additions and 10 deletions.
30 changes: 30 additions & 0 deletions src/idc/idc.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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;
Expand Down
2 changes: 2 additions & 0 deletions src/include/sof/ipc/topology.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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
Expand Down
45 changes: 35 additions & 10 deletions src/ipc/ipc4/handler.c
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down Expand Up @@ -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;

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

Expand All @@ -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);

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 (!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, };

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;
Expand Down
4 changes: 4 additions & 0 deletions zephyr/include/rtos/idc.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down

0 comments on commit 4832dc9

Please sign in to comment.