From 4832dc93881db0a3ad9565b65e822b8ac6fbed52 Mon Sep 17 00:00:00 2001 From: Adrian Bonislawski Date: Tue, 16 May 2023 19:26:28 +0200 Subject: [PATCH] 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 Signed-off-by: Jaska Uimonen --- src/idc/idc.c | 30 +++++++++++++++++++++++ src/include/sof/ipc/topology.h | 2 ++ src/ipc/ipc4/handler.c | 45 ++++++++++++++++++++++++++-------- zephyr/include/rtos/idc.h | 4 +++ 4 files changed, 71 insertions(+), 10 deletions(-) diff --git a/src/idc/idc.c b/src/idc/idc.c index 8b6d0b9337c1..70087f097f46 100644 --- a/src/idc/idc.c +++ b/src/idc/idc.c @@ -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; diff --git a/src/include/sof/ipc/topology.h b/src/include/sof/ipc/topology.h index fc42a7559f0a..2819649a07e4 100644 --- a/src/include/sof/ipc/topology.h +++ b/src/include/sof/ipc/topology.h @@ -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 diff --git a/src/ipc/ipc4/handler.c b/src/ipc/ipc4/handler.c index 3e47a2ca0d9b..ecb8285c6105 100644 --- a/src/ipc/ipc4/handler.c +++ b/src/ipc/ipc4/handler.c @@ -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); - - 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; diff --git a/zephyr/include/rtos/idc.h b/zephyr/include/rtos/idc.h index 74c960efbc4e..7a061733a114 100644 --- a/zephyr/include/rtos/idc.h +++ b/zephyr/include/rtos/idc.h @@ -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