-
Notifications
You must be signed in to change notification settings - Fork 349
[WIP] sof: ipc: switch platform IPC to Zephyr service #10422
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -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> | ||
|
|
@@ -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 | ||
|
|
@@ -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), | ||
|
|
@@ -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(); | ||
|
|
@@ -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)); | ||
| } | ||
|
|
||
| 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 */ | ||
|
|
@@ -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
|
||
| if (ret < 0) | ||
| return ret; | ||
| #ifdef CONFIG_PM | ||
| intel_adsp_ipc_set_suspend_handler(INTEL_ADSP_IPC_HOST_DEV, | ||
| ipc_device_suspend_handler, ipc); | ||
|
|
||
There was a problem hiding this comment.
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.There was a problem hiding this comment.
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).