Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
61 changes: 37 additions & 24 deletions src/ipc/ipc-zephyr.c
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,9 @@
#include <autoconf.h>

#include <zephyr/kernel.h>
#include <zephyr/ipc/ipc_service.h>
#include <zephyr/ipc/backends/intel_adsp_host_ipc.h>

#include <intel_adsp_ipc.h>
#include <sof/ipc/common.h>

#include <sof/ipc/schedule.h>
Expand Down Expand Up @@ -58,34 +59,39 @@ LOG_MODULE_DECLARE(ipc, CONFIG_SOF_LOG_LEVEL);
* When IPC message is read fills ipc_cmd_hdr.
*/
static uint32_t g_last_data, g_last_ext_data;
static struct ipc_ept sof_ipc_ept;
static struct ipc_ept_cfg sof_ipc_ept_cfg;

BUILD_ASSERT(sizeof(struct ipc_cmd_hdr) == sizeof(uint32_t) * 2,
"ipc_cmd_hdr must be exactly two 32-bit words");

/**
* @brief cAVS IPC Message Handler Callback function.
* @brief SOF IPC receive callback for Zephyr IPC service.
*
* See @ref (*intel_adsp_ipc_handler_t) for function signature description.
* @return false so BUSY on the other side will not be cleared immediately but
* will remain set until message would have been processed by scheduled task, i.e.
* until ipc_platform_complete_cmd() call.
* This callback is invoked by the Zephyr IPC service backend when a compact 2-word IPC message
* arrives from the host. It stores the raw header words in g_last_data/g_last_ext_data and
* schedules the SOF IPC task to process the command via ipc_platform_do_cmd().
*/
static bool message_handler(const struct device *dev, void *arg, uint32_t data, uint32_t ext_data)
static void sof_ipc_receive_cb(const void *data, size_t len, void *priv)
{
struct ipc *ipc = (struct ipc *)arg;

struct ipc *ipc = (struct ipc *)priv;
const uint32_t *msg = data;
k_spinlock_key_t key;

__ASSERT(len == sizeof(uint32_t) * 2, "Unexpected IPC message length: %zu", len);
__ASSERT(data, "IPC data pointer is NULL");

key = k_spin_lock(&ipc->lock);

g_last_data = data;
g_last_ext_data = ext_data;
g_last_data = msg[0];
g_last_ext_data = msg[1];

#if CONFIG_DEBUG_IPC_COUNTERS
increment_ipc_received_counter();
#endif
ipc_schedule_process(ipc);

k_spin_unlock(&ipc->lock, key);

return false;
}

#ifdef CONFIG_PM_DEVICE
Expand Down Expand Up @@ -159,9 +165,6 @@ static int ipc_device_resume_handler(const struct device *dev, void *arg)
ipc->task_mask = 0;
ipc->pm_prepare_D3 = false;

/* attach handlers */
intel_adsp_ipc_set_message_handler(INTEL_ADSP_IPC_HOST_DEV, message_handler, ipc);

/* schedule task */
#if CONFIG_TWB_IPC_TASK
scheduler_twb_task_init(&ipc->ipc_task, SOF_UUID(zipc_task_uuid),
Expand Down Expand Up @@ -254,7 +257,9 @@ enum task_state ipc_platform_do_cmd(struct ipc *ipc)
void ipc_platform_complete_cmd(struct ipc *ipc)
{
ARG_UNUSED(ipc);
intel_adsp_ipc_complete(INTEL_ADSP_IPC_HOST_DEV);
int ret = ipc_service_release_rx_buffer(&sof_ipc_ept, NULL);

__ASSERT(ret == 0, "ipc_service_release_rx_buffer() failed: %d", ret);

#if CONFIG_DEBUG_IPC_COUNTERS
increment_ipc_processed_counter();
Expand All @@ -263,30 +268,31 @@ void ipc_platform_complete_cmd(struct ipc *ipc)

int ipc_platform_send_msg(const struct ipc_msg *msg)
{
if (!intel_adsp_ipc_is_complete(INTEL_ADSP_IPC_HOST_DEV))
if (ipc_service_get_tx_buffer_size(&sof_ipc_ept) == 0)
return -EBUSY;

/* prepare the message and copy to mailbox */
struct ipc_cmd_hdr *hdr = ipc_prepare_to_send(msg);

return intel_adsp_ipc_send_message(INTEL_ADSP_IPC_HOST_DEV, hdr->pri, hdr->ext);
return ipc_service_send(&sof_ipc_ept, hdr, sizeof(*hdr));
}

void ipc_platform_send_msg_direct(const struct ipc_msg *msg)
{
/* prepare the message and copy to mailbox */
struct ipc_cmd_hdr *hdr = ipc_prepare_to_send(msg);

intel_adsp_ipc_send_message_emergency(INTEL_ADSP_IPC_HOST_DEV, hdr->pri, hdr->ext);
(void)ipc_service_send_critical(&sof_ipc_ept, hdr, sizeof(*hdr));
Copy link

Copilot AI Dec 9, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The return value of ipc_service_send_critical() is silently discarded with a void cast. If this function can fail, the caller has no way to detect or handle the failure. Consider logging an error or adding an assertion to catch failures in this critical path.

Suggested change
(void)ipc_service_send_critical(&sof_ipc_ept, hdr, sizeof(*hdr));
int ret = ipc_service_send_critical(&sof_ipc_ept, hdr, sizeof(*hdr));
if (ret != 0) {
tr_err(&ipc_tr, "ipc_service_send_critical() failed: %d", ret);
}

Copilot uses AI. Check for mistakes.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we should check/report this failure (since its likely time critical).

}

int ipc_platform_poll_is_host_ready(void)
{
return intel_adsp_ipc_is_complete(INTEL_ADSP_IPC_HOST_DEV);
return ipc_service_get_tx_buffer_size(&sof_ipc_ept) > 0;
}

int platform_ipc_init(struct ipc *ipc)
{
int ret;

ipc_set_drvdata(ipc, NULL);

/* schedule task */
Expand All @@ -300,8 +306,15 @@ int platform_ipc_init(struct ipc *ipc)
#endif
/* configure interrupt - work is done internally by Zephyr API */

/* attach handlers */
intel_adsp_ipc_set_message_handler(INTEL_ADSP_IPC_HOST_DEV, message_handler, ipc);
sof_ipc_ept_cfg.name = "sof_ipc";
sof_ipc_ept_cfg.prio = 0;
sof_ipc_ept_cfg.cb.received = sof_ipc_receive_cb;
sof_ipc_ept_cfg.priv = ipc;

ret = ipc_service_register_endpoint(INTEL_ADSP_IPC_HOST_DEV,
&sof_ipc_ept, &sof_ipc_ept_cfg);
Comment on lines +314 to +315
Copy link

Copilot AI Dec 9, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The code still references INTEL_ADSP_IPC_HOST_DEV macro directly. While migrating to the generic ipc_service API, this hardcoded Intel-specific device reference limits portability. Consider abstracting this behind a platform-agnostic macro or devicetree reference to fully achieve the stated goal of allowing other vendors to integrate their own IPC backends.

Copilot uses AI. Check for mistakes.
if (ret < 0)
return ret;
#ifdef CONFIG_PM
intel_adsp_ipc_set_suspend_handler(INTEL_ADSP_IPC_HOST_DEV,
ipc_device_suspend_handler, ipc);
Expand Down
2 changes: 1 addition & 1 deletion west.yml
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ manifest:

- name: zephyr
repo-path: zephyr
revision: 769ba82aa5ec482af0c4649ba075065e901fbe69
revision: pull/100682/head
remote: zephyrproject

# Import some projects listed in zephyr/west.yml@revision
Expand Down
Loading