Skip to content

Commit

Permalink
ipc4: msg: avoid sending duplicated reply message
Browse files Browse the repository at this point in the history
In multicore case, IPC message is dispatched from primary core to
secondary core which send reply message to host. Primary core will
do nothing if IPC_TASK_SECONDARY_CORE is set. But in rare case, the
secondary code finish the reply message and clear this flag before
the ipc thread in primary core check this flag, then primary core
also send reply message again. This results to the reply message being
inserted two times in ipc message list and infinite loop when visiting
the list.

This patch will check msg_reply state and do nothing if it is prepared
. We don't need to init reply message since it is initialized after
deleting from the ipc list.

Signed-off-by: Rander Wang <[email protected]>
  • Loading branch information
RanderWang committed Sep 5, 2023
1 parent 176aec7 commit 5a67152
Showing 1 changed file with 55 additions and 2 deletions.
57 changes: 55 additions & 2 deletions src/ipc/ipc4/handler.c
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ struct ipc4_msg_data {
static struct ipc4_msg_data msg_data;

/* fw sends a fw ipc message to send the status of the last host ipc message */
static struct ipc_msg msg_reply;
static struct ipc_msg msg_reply = {0, 0, 0, 0, LIST_INIT(msg_reply.list)};

static struct ipc_msg msg_notify;

Expand Down Expand Up @@ -1303,7 +1303,6 @@ void ipc_cmd(struct ipc_cmd_hdr *_hdr)
msg_reply.tx_size = 0;
msg_reply.header = in->primary.dat;
msg_reply.extension = in->extension.dat;
list_init(&msg_reply.list);

target = in->primary.r.msg_tgt;

Expand All @@ -1330,9 +1329,63 @@ void ipc_cmd(struct ipc_cmd_hdr *_hdr)
char *data = ipc->comp_data;
struct ipc4_message_reply reply;

/* Process flow and time stamp for IPC4 msg processed on secondary core :
* core 0 (primary core) core x (secondary core)
* # IPC msg thread #IPC delayed worker #core x idc thread
* ipc_task_ops.run()
* ipc_do_cmd()
* msg_reply.header = in->primary.dat
* ipc4_process_on_core(x)
* mask |= SECONDARY_CORE
* idc_send_message()
* Case 1:
* // Ipc msg processed by secondary core idc_ipc()
* if ((mask & SECONDARY_CORE)) ipc_cmd()
* return; ipc_msg_send()
* mask &= ~SECONDARY_CORE
*
* ipc_platform_send_msg
* ----------------------------------------------------------------------------
* Case 2:
* idc_ipc()
* ipc_cmd()
* //Prepare reply msg
* msg_reply.header =
* reply.primary.dat;
* ipc_msg_send()
* mask &= ~SECONDARY_CORE
*
* if ((mask & IPC_TASK_SECONDARY_CORE))
* return;
* // Ipc reply msg was prepared, so return
* if (msg_reply.header != in->primary.dat)
* return;
* ipc_platform_send_msg
* ----------------------------------------------------------------------------
* Case 3:
* idc_ipc()
* ipc_cmd()
* //Prepare reply msg
* msg_reply.header =
* reply.primary.dat;
* ipc_msg_send()
* mask &= ~SECONDARY_CORE
*
* ipc_platform_send_msg
*
* if ((mask & IPC_TASK_SECONDARY_CORE))
* return;
* // Ipc reply msg was prepared, so return
* if (msg_reply.header != in->primary.dat)
* return;
*/

/* Reply prepared by secondary core */
if ((ipc->task_mask & IPC_TASK_SECONDARY_CORE) && cpu_is_primary(cpu_get_id()))
return;
/* Reply has been prepared by secondary core */
if (msg_reply.header != in->primary.dat)
return;

/* Do not send reply for SET_DX if we are going to enter D3
* The reply is going to be sent as part of the power down
Expand Down

0 comments on commit 5a67152

Please sign in to comment.