diff --git a/src/drivers/intel/cavs/ipc.c b/src/drivers/intel/cavs/ipc.c index 0435dc02152f..67528d6748b4 100644 --- a/src/drivers/intel/cavs/ipc.c +++ b/src/drivers/intel/cavs/ipc.c @@ -200,9 +200,10 @@ enum task_state ipc_platform_do_cmd(void *data) void ipc_platform_complete_cmd(void *data) { -#if CONFIG_SUECREEK struct ipc *ipc = data; -#endif + + if (!cpu_is_me(ipc->core)) + return; /* write 1 to clear busy, and trigger interrupt to host*/ #if CAVS_VERSION == CAVS_VERSION_1_5 diff --git a/src/idc/idc.c b/src/idc/idc.c index 3ec1274f4405..582e6813bc06 100644 --- a/src/idc/idc.c +++ b/src/idc/idc.c @@ -7,6 +7,7 @@ #include #include #include +#include #include #include #include @@ -120,9 +121,11 @@ int idc_wait_in_blocking_mode(uint32_t target_core, bool (*cond)(int)) static void idc_ipc(void) { struct ipc *ipc = ipc_get(); - ipc_cmd_hdr *hdr = ipc->comp_data; - ipc_cmd(hdr); + ipc_cmd(ipc->comp_data); + + /* Signal the host */ + ipc_platform_complete_cmd(ipc); } /** diff --git a/src/include/sof/ipc/common.h b/src/include/sof/ipc/common.h index 33a7dcdcb518..a53010a02f69 100644 --- a/src/include/sof/ipc/common.h +++ b/src/include/sof/ipc/common.h @@ -68,6 +68,7 @@ struct ipc { struct list_item msg_list; /* queue of messages to be sent */ bool is_notification_pending; /* notification is being sent to host */ + unsigned int core; /* core, processing the IPC */ struct list_item comp_list; /* list of component devices */ @@ -190,8 +191,9 @@ void ipc_cmd(ipc_cmd_hdr *hdr); /** * \brief IPC message to be processed on other core. * @param[in] core Core id for IPC to be processed on. + * @param[in] blocking Process in blocking mode: wait for completion. * @return 1 if successful (reply sent by other core), error code otherwise. */ -int ipc_process_on_core(uint32_t core); +int ipc_process_on_core(uint32_t core, bool blocking); #endif /* __SOF_DRIVERS_IPC_H__ */ diff --git a/src/ipc/ipc-common.c b/src/ipc/ipc-common.c index 4e7386c78a30..f88412558a37 100644 --- a/src/ipc/ipc-common.c +++ b/src/ipc/ipc-common.c @@ -38,8 +38,9 @@ DECLARE_SOF_UUID("ipc", ipc_uuid, 0xbe60f97d, 0x78df, 0x4796, DECLARE_TR_CTX(ipc_tr, SOF_UUID(ipc_uuid), LOG_LEVEL_INFO); -int ipc_process_on_core(uint32_t core) +int ipc_process_on_core(uint32_t core, bool blocking) { + struct ipc *ipc = ipc_get(); struct idc_msg msg = { .header = IDC_MSG_IPC, .core = core, }; int ret; @@ -49,8 +50,19 @@ int ipc_process_on_core(uint32_t core) return -EACCES; } + /* The other core will write there its response */ + dcache_invalidate_region((void *)MAILBOX_HOSTBOX_BASE, + ((struct sof_ipc_cmd_hdr *)ipc->comp_data)->size); + + /* + * If the primary core is waiting for secondary cores to complete, it + * will also reply to the host + */ + if (!blocking) + ipc->core = core; + /* send IDC message */ - ret = idc_send_msg(&msg, IDC_BLOCKING); + ret = idc_send_msg(&msg, blocking ? IDC_BLOCKING : IDC_NON_BLOCKING); if (ret < 0) return ret; diff --git a/src/ipc/ipc3/dai.c b/src/ipc/ipc3/dai.c index c4403c465760..8dfa2929182e 100644 --- a/src/ipc/ipc3/dai.c +++ b/src/ipc/ipc3/dai.c @@ -191,17 +191,27 @@ int ipc_comp_dai_config(struct ipc *ipc, struct ipc_config_dai *common_config, if (!comp_on_core[i]) continue; - ret = ipc_process_on_core(i); + /* + * TODO: can secondary cores execute dai_config() in + * parallel? Then we could just wait for the last of + * them. For now execute them sequentially. + */ + ret = ipc_process_on_core(i, true); if (ret < 0) - return ret; + break; /* check whether IPC failed on secondary core */ mailbox_hostbox_read(&reply, sizeof(reply), 0, sizeof(reply)); - if (reply.error < 0) + if (reply.error < 0) { /* error reply already written */ - return 1; + ret = 1; + break; + } } + + /* We have waited until all secondary cores configured their DAIs */ + ipc->core = PLATFORM_PRIMARY_CORE_ID; } return ret; diff --git a/src/ipc/ipc3/handler.c b/src/ipc/ipc3/handler.c index c5d1c034e7cd..a2fbabb4c828 100644 --- a/src/ipc/ipc3/handler.c +++ b/src/ipc/ipc3/handler.c @@ -207,7 +207,7 @@ static int ipc_stream_pcm_params(uint32_t stream) /* check core */ if (!cpu_is_me(pcm_dev->core)) - return ipc_process_on_core(pcm_dev->core); + return ipc_process_on_core(pcm_dev->core, false); tr_dbg(&ipc_tr, "ipc: comp %d -> params", pcm_params.comp_id); @@ -319,7 +319,7 @@ static int ipc_stream_pcm_free(uint32_t header) /* check core */ if (!cpu_is_me(pcm_dev->core)) - return ipc_process_on_core(pcm_dev->core); + return ipc_process_on_core(pcm_dev->core, false); tr_dbg(&ipc_tr, "ipc: comp %d -> free", free_req.comp_id); @@ -356,7 +356,7 @@ static int ipc_stream_position(uint32_t header) /* check core */ if (!cpu_is_me(pcm_dev->core)) - return ipc_process_on_core(pcm_dev->core); + return ipc_process_on_core(pcm_dev->core, false); tr_info(&ipc_tr, "ipc: comp %d -> position", stream.comp_id); @@ -405,7 +405,7 @@ static int ipc_stream_trigger(uint32_t header) /* check core */ if (!cpu_is_me(pcm_dev->core)) - return ipc_process_on_core(pcm_dev->core); + return ipc_process_on_core(pcm_dev->core, false); tr_dbg(&ipc_tr, "ipc: comp %d -> trigger cmd 0x%x", stream.comp_id, ipc_command); @@ -1109,7 +1109,7 @@ static int ipc_comp_value(uint32_t header, uint32_t cmd) /* check core */ if (!cpu_is_me(comp_dev->core)) - return ipc_process_on_core(comp_dev->core); + return ipc_process_on_core(comp_dev->core, false); tr_dbg(&ipc_tr, "ipc: comp %d -> cmd %d", data->comp_id, data->cmd); @@ -1169,7 +1169,7 @@ static int ipc_glb_tplg_comp_new(uint32_t header) /* check core */ if (!cpu_is_me(comp->core)) - return ipc_process_on_core(comp->core); + return ipc_process_on_core(comp->core, false); tr_dbg(&ipc_tr, "ipc: pipe %d comp %d -> new (type %d)", comp->pipeline_id, comp->id, comp->type); @@ -1205,7 +1205,7 @@ static int ipc_glb_tplg_buffer_new(uint32_t header) /* check core */ if (!cpu_is_me(ipc_buffer.comp.core)) - return ipc_process_on_core(ipc_buffer.comp.core); + return ipc_process_on_core(ipc_buffer.comp.core, false); tr_dbg(&ipc_tr, "ipc: pipe %d buffer %d -> new (0x%x bytes)", ipc_buffer.comp.pipeline_id, ipc_buffer.comp.id, @@ -1242,7 +1242,7 @@ static int ipc_glb_tplg_pipe_new(uint32_t header) /* check core */ if (!cpu_is_me(ipc_pipeline.core)) - return ipc_process_on_core(ipc_pipeline.core); + return ipc_process_on_core(ipc_pipeline.core, false); tr_dbg(&ipc_tr, "ipc: pipe %d -> new", ipc_pipeline.pipeline_id); @@ -1495,6 +1495,7 @@ void ipc_boot_complete_msg(ipc_cmd_hdr *header, uint32_t *data) void ipc_cmd(ipc_cmd_hdr *_hdr) { struct sof_ipc_cmd_hdr *hdr = ipc_from_hdr(_hdr); + struct ipc *ipc = ipc_get(); struct sof_ipc_reply reply; uint32_t type = 0; int ret; @@ -1505,6 +1506,10 @@ void ipc_cmd(ipc_cmd_hdr *_hdr) goto out; } + if (!cpu_is_secondary(cpu_get_id())) + /* A new IPC from the host, delivered to the primary core */ + ipc->core = PLATFORM_PRIMARY_CORE_ID; + type = iGS(hdr->cmd); switch (type) { diff --git a/src/ipc/ipc3/helper.c b/src/ipc/ipc3/helper.c index 0e2008129e84..a32c1402f14d 100644 --- a/src/ipc/ipc3/helper.c +++ b/src/ipc/ipc3/helper.c @@ -513,7 +513,7 @@ int ipc_pipeline_free(struct ipc *ipc, uint32_t comp_id) /* check core */ if (!cpu_is_me(ipc_pipe->core)) - return ipc_process_on_core(ipc_pipe->core); + return ipc_process_on_core(ipc_pipe->core, false); /* free buffer and remove from list */ ret = pipeline_free(ipc_pipe->pipeline); @@ -548,7 +548,7 @@ int ipc_pipeline_complete(struct ipc *ipc, uint32_t comp_id) /* check core */ if (!cpu_is_me(ipc_pipe->core)) - return ipc_process_on_core(ipc_pipe->core); + return ipc_process_on_core(ipc_pipe->core, false); p = ipc_pipe->pipeline; @@ -653,7 +653,7 @@ int ipc_buffer_free(struct ipc *ipc, uint32_t buffer_id) /* check core */ if (!cpu_is_me(ibd->core)) - return ipc_process_on_core(ibd->core); + return ipc_process_on_core(ibd->core, false); /* try to find sink/source components to check if they still exists */ list_for_item(clist, &ipc->comp_list) { @@ -707,7 +707,7 @@ static int ipc_comp_to_buffer_connect(struct ipc_comp_dev *comp, int ret; if (!cpu_is_me(comp->core)) - return ipc_process_on_core(comp->core); + return ipc_process_on_core(comp->core, false); tr_dbg(&ipc_tr, "ipc: comp sink %d, source %d -> connect", buffer->id, comp->id); @@ -739,7 +739,7 @@ static int ipc_buffer_to_comp_connect(struct ipc_comp_dev *buffer, int ret; if (!cpu_is_me(comp->core)) - return ipc_process_on_core(comp->core); + return ipc_process_on_core(comp->core, false); tr_dbg(&ipc_tr, "ipc: comp sink %d, source %d -> connect", comp->id, buffer->id); @@ -856,7 +856,7 @@ int ipc_comp_free(struct ipc *ipc, uint32_t comp_id) /* check core */ if (!cpu_is_me(icd->core)) - return ipc_process_on_core(icd->core); + return ipc_process_on_core(icd->core, false); /* check state */ if (icd->cd->state != COMP_STATE_READY)