From eb10f2511f92f301accdde0ce7a0165efb173298 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Wed, 26 Mar 2025 12:56:51 +0100 Subject: [PATCH 1/2] audio: rate-limit "no bytes to copy" messages When tearing down streams, when some of the pipelines have already been deleted and some are still active, the remaining active pipelines might experience no-data conditions. Currently this is logged on every LL-scheduler period, i.e. every millisecond. This isn't adding any useful information and in fact can create a flood of outgoing IPC notifications, eventually blocking valid IPC replies and leading to IPC timeouts. Rate-limit these logging entries to fix the problem and relax the log. Signed-off-by: Guennadi Liakhovetski --- src/audio/copier/host_copier.h | 4 +++- src/audio/host-zephyr.c | 27 ++++++++++++++++++++++++--- 2 files changed, 27 insertions(+), 4 deletions(-) diff --git a/src/audio/copier/host_copier.h b/src/audio/copier/host_copier.h index 08cbba43be27..fe7a98de0804 100644 --- a/src/audio/copier/host_copier.h +++ b/src/audio/copier/host_copier.h @@ -67,7 +67,9 @@ struct host_data { uint16_t stream_tag; uint16_t no_stream_position; /**< 1 means don't send stream position */ uint64_t total_data_processed; - uint8_t cont_update_posn; /**< 1 means continuous update stream position */ + uint64_t nobytes_last_logged; /**< uptime, when "no bytes" was last logged */ + unsigned int n_skipped; /**< number of "no bytes" skipped */ + uint8_t cont_update_posn; /**< 1 means continuous update stream position */ /* host component attributes */ enum comp_copy_type copy_type; /**< Current host copy type */ diff --git a/src/audio/host-zephyr.c b/src/audio/host-zephyr.c index 43d8686db9f8..f17a7d18119a 100644 --- a/src/audio/host-zephyr.c +++ b/src/audio/host-zephyr.c @@ -359,6 +359,9 @@ static void host_dma_cb(struct comp_dev *dev, size_t bytes) host_common_one_shot(hd, bytes); } +/* Minimum time between 2 consecutive "no bytes to copy" messages in milliseconds */ +#define SOF_MIN_NO_BYTES_INTERVAL_MS 20 + /** * Calculates bytes to be copied in normal mode. * @param dev Host component device. @@ -403,9 +406,26 @@ static uint32_t host_get_copy_bytes_normal(struct host_data *hd, struct comp_dev if (!(hd->ipc_host.feature_mask & BIT(IPC4_COPIER_FAST_MODE))) dma_copy_bytes = MIN(hd->period_bytes, dma_copy_bytes); - if (!dma_copy_bytes) - comp_info(dev, "no bytes to copy, available samples: %d, free_samples: %d", - avail_samples, free_samples); + bool reset_skipped = false; + uint64_t now = k_uptime_get(); + uint64_t delta = now - hd->nobytes_last_logged; + + if (!dma_copy_bytes) { + if (delta > SOF_MIN_NO_BYTES_INTERVAL_MS) { + hd->nobytes_last_logged = now; + comp_warn(dev, "no bytes to copy, available samples: %d, free_samples: %d", + avail_samples, free_samples); + reset_skipped = true; + } else { + hd->n_skipped++; + } + } + + if (hd->n_skipped && (reset_skipped || dma_copy_bytes)) { + comp_warn(dev, "Skipped %u no-bytes events in last %llu ms", + hd->n_skipped, delta); + hd->n_skipped = 0; + } /* dma_copy_bytes should be aligned to minimum possible chunk of * data to be copied by dma. @@ -659,6 +679,7 @@ static struct comp_dev *host_new(const struct comp_driver *drv, if (!hd) goto e_data; + hd->nobytes_last_logged = k_uptime_get(); comp_set_drvdata(dev, hd); ret = host_common_new(hd, dev, ipc_host, dev->ipc_config.id); From 3b108b780d04ac5d80c6aa1809e44c94971cc770 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Tue, 25 Mar 2025 16:15:57 +0100 Subject: [PATCH 2/2] Reapply "ipc: move most functions to run from DRAM" This restores commit 0e53393001c9d5e81b0078340c3e49ef98fe1e56. Signed-off-by: Guennadi Liakhovetski --- src/include/sof/ipc/topology.h | 2 - src/ipc/ipc-common.c | 9 ++- src/ipc/ipc-helper.c | 20 +++++-- src/ipc/ipc4/handler.c | 104 ++++++++++++++++++++++++--------- src/ipc/ipc4/helper.c | 83 ++++++++++++++++++++------ 5 files changed, 165 insertions(+), 53 deletions(-) diff --git a/src/include/sof/ipc/topology.h b/src/include/sof/ipc/topology.h index 5605c6ef9837..3503c7a407d8 100644 --- a/src/include/sof/ipc/topology.h +++ b/src/include/sof/ipc/topology.h @@ -49,8 +49,6 @@ typedef uint32_t ipc_comp; struct ipc_comp_dev; const struct comp_driver *ipc4_get_comp_drv(uint32_t module_id); struct comp_dev *ipc4_get_comp_dev(uint32_t comp_id); -int ipc4_add_comp_dev(struct comp_dev *dev); -const struct comp_driver *ipc4_get_drv(const void *uuid); int ipc4_chain_manager_create(struct ipc4_chain_dma *cdma); int ipc4_chain_dma_state(struct comp_dev *dev, struct ipc4_chain_dma *cdma); int ipc4_create_chain_dma(struct ipc *ipc, struct ipc4_chain_dma *cdma); diff --git a/src/ipc/ipc-common.c b/src/ipc/ipc-common.c index 8f72ac1ba91b..3c81064cb7cd 100644 --- a/src/ipc/ipc-common.c +++ b/src/ipc/ipc-common.c @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include @@ -188,12 +189,14 @@ static void schedule_ipc_worker(void) #endif } -void ipc_msg_send_direct(struct ipc_msg *msg, void *data) +__cold void ipc_msg_send_direct(struct ipc_msg *msg, void *data) { struct ipc *ipc = ipc_get(); k_spinlock_key_t key; int ret; + assert_can_be_cold(); + key = k_spin_lock(&ipc->lock); /* copy mailbox data to message if not already copied */ @@ -280,8 +283,10 @@ void ipc_schedule_process(struct ipc *ipc) #endif } -int ipc_init(struct sof *sof) +__cold int ipc_init(struct sof *sof) { + assert_can_be_cold(); + tr_dbg(&ipc_tr, "ipc_init()"); /* init ipc data */ diff --git a/src/ipc/ipc-helper.c b/src/ipc/ipc-helper.c index 1d1b651d1c49..65910767d95e 100644 --- a/src/ipc/ipc-helper.c +++ b/src/ipc/ipc-helper.c @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -37,8 +38,10 @@ LOG_MODULE_DECLARE(ipc, CONFIG_SOF_LOG_LEVEL); -static bool valid_ipc_buffer_desc(const struct sof_ipc_buffer *desc) +__cold static bool valid_ipc_buffer_desc(const struct sof_ipc_buffer *desc) { + assert_can_be_cold(); + if (desc->caps >= SOF_MEM_CAPS_LOWEST_INVALID) return false; @@ -47,10 +50,12 @@ static bool valid_ipc_buffer_desc(const struct sof_ipc_buffer *desc) } /* create a new component in the pipeline */ -struct comp_buffer *buffer_new(const struct sof_ipc_buffer *desc, bool is_shared) +__cold struct comp_buffer *buffer_new(const struct sof_ipc_buffer *desc, bool is_shared) { struct comp_buffer *buffer; + assert_can_be_cold(); + tr_info(&buffer_tr, "buffer new size 0x%x id %d.%d flags 0x%x", desc->size, desc->comp.pipeline_id, desc->comp.id, desc->flags); @@ -75,6 +80,7 @@ struct comp_buffer *buffer_new(const struct sof_ipc_buffer *desc, bool is_shared return buffer; } +/* Called from multiple locations, including ipc_get_comp_by_ppl_id(), so cannot be cold */ int32_t ipc_comp_pipe_id(const struct ipc_comp_dev *icd) { switch (icd->type) { @@ -177,9 +183,11 @@ int comp_verify_params(struct comp_dev *dev, uint32_t flag, } EXPORT_SYMBOL(comp_verify_params); -int comp_buffer_connect(struct comp_dev *comp, uint32_t comp_core, - struct comp_buffer *buffer, uint32_t dir) +__cold int comp_buffer_connect(struct comp_dev *comp, uint32_t comp_core, + struct comp_buffer *buffer, uint32_t dir) { + assert_can_be_cold(); + /* check if it's a connection between cores */ if (buffer->core != comp_core) { #if CONFIG_INCOHERENT @@ -258,13 +266,15 @@ int ipc_pipeline_complete(struct ipc *ipc, uint32_t comp_id) ipc_ppl_sink->cd); } -int ipc_comp_free(struct ipc *ipc, uint32_t comp_id) +__cold int ipc_comp_free(struct ipc *ipc, uint32_t comp_id) { struct ipc_comp_dev *icd; struct comp_buffer *buffer; struct comp_buffer *safe; uint32_t flags; + assert_can_be_cold(); + /* check whether component exists */ icd = ipc_get_comp_by_id(ipc, comp_id); if (!icd) { diff --git a/src/ipc/ipc4/handler.c b/src/ipc/ipc4/handler.c index 65056289e71d..dbffb96e415d 100644 --- a/src/ipc/ipc4/handler.c +++ b/src/ipc/ipc4/handler.c @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -131,18 +132,22 @@ static inline const struct ipc4_pipeline_set_state_data *ipc4_get_pipeline_data( /* * Global IPC Operations. */ -static int ipc4_new_pipeline(struct ipc4_message_request *ipc4) +__cold static int ipc4_new_pipeline(struct ipc4_message_request *ipc4) { struct ipc *ipc = ipc_get(); + assert_can_be_cold(); + return ipc_pipeline_new(ipc, (ipc_pipe_new *)ipc4); } -static int ipc4_delete_pipeline(struct ipc4_message_request *ipc4) +__cold static int ipc4_delete_pipeline(struct ipc4_message_request *ipc4) { struct ipc4_pipeline_delete *pipe; struct ipc *ipc = ipc_get(); + assert_can_be_cold(); + pipe = (struct ipc4_pipeline_delete *)ipc4; tr_dbg(&ipc_tr, "ipc4 delete pipeline %x:", (uint32_t)pipe->primary.r.instance_id); @@ -229,11 +234,13 @@ static int ipc4_pcm_params(struct ipc_comp_dev *pcm_dev) return err; } -static bool is_any_ppl_active(void) +__cold static bool is_any_ppl_active(void) { struct ipc_comp_dev *icd; struct list_item *clist; + assert_can_be_cold(); + list_for_item(clist, &ipc_get()->comp_list) { icd = container_of(clist, struct ipc_comp_dev, list); if (icd->type != COMP_TYPE_PIPELINE) @@ -562,15 +569,14 @@ static int ipc_wait_for_compound_msg(void) } #endif -const struct ipc4_pipeline_set_state_data *ipc4_get_pipeline_data_wrapper(void) +__cold const struct ipc4_pipeline_set_state_data *ipc4_get_pipeline_data_wrapper(void) { - const struct ipc4_pipeline_set_state_data *ppl_data; - - ppl_data = ipc4_get_pipeline_data(); + assert_can_be_cold(); - return ppl_data; + return ipc4_get_pipeline_data(); } +/* Entry point for ipc4_pipeline_trigger(), therefore cannot be cold */ static int ipc4_set_pipeline_state(struct ipc4_message_request *ipc4) { const struct ipc4_pipeline_set_state_data *ppl_data; @@ -700,11 +706,13 @@ static int ipc4_set_pipeline_state(struct ipc4_message_request *ipc4) } #if CONFIG_LIBRARY_MANAGER -static int ipc4_load_library(struct ipc4_message_request *ipc4) +__cold static int ipc4_load_library(struct ipc4_message_request *ipc4) { struct ipc4_module_load_library library; int ret; + assert_can_be_cold(); + library.header.dat = ipc4->primary.dat; ret = lib_manager_load_library(library.header.r.dma_id, library.header.r.lib_id, @@ -716,8 +724,10 @@ static int ipc4_load_library(struct ipc4_message_request *ipc4) } #endif -static int ipc4_process_chain_dma(struct ipc4_message_request *ipc4) +__cold static int ipc4_process_chain_dma(struct ipc4_message_request *ipc4) { + assert_can_be_cold(); + #if CONFIG_COMP_CHAIN_DMA struct ipc_comp_dev *cdma_comp; struct ipc *ipc = ipc_get(); @@ -771,8 +781,10 @@ static int ipc4_process_chain_dma(struct ipc4_message_request *ipc4) #endif } -static int ipc4_process_ipcgtw_cmd(struct ipc4_message_request *ipc4) +__cold static int ipc4_process_ipcgtw_cmd(struct ipc4_message_request *ipc4) { + assert_can_be_cold(); + #if CONFIG_IPC4_GATEWAY struct ipc *ipc = ipc_get(); uint32_t reply_size = 0; @@ -880,14 +892,15 @@ __cold static int ipc4_init_module_instance(struct ipc4_message_request *ipc4) { struct ipc4_module_init_instance module_init; struct comp_dev *dev; + + assert_can_be_cold(); + /* we only need the common header here, all we have from the IPC */ int ret = memcpy_s(&module_init, sizeof(module_init), ipc4, sizeof(*ipc4)); if (ret < 0) return IPC4_FAILURE; - assert_can_be_cold(); - tr_dbg(&ipc_tr, "ipc4_init_module_instance %x : %x", (uint32_t)module_init.primary.r.module_id, @@ -908,10 +921,13 @@ __cold static int ipc4_init_module_instance(struct ipc4_message_request *ipc4) return 0; } -static int ipc4_bind_module_instance(struct ipc4_message_request *ipc4) +__cold static int ipc4_bind_module_instance(struct ipc4_message_request *ipc4) { struct ipc4_module_bind_unbind bu; struct ipc *ipc = ipc_get(); + + assert_can_be_cold(); + int ret = memcpy_s(&bu, sizeof(bu), ipc4, sizeof(*ipc4)); if (ret < 0) @@ -924,10 +940,13 @@ static int ipc4_bind_module_instance(struct ipc4_message_request *ipc4) return ipc_comp_connect(ipc, (ipc_pipe_comp_connect *)&bu); } -static int ipc4_unbind_module_instance(struct ipc4_message_request *ipc4) +__cold static int ipc4_unbind_module_instance(struct ipc4_message_request *ipc4) { struct ipc4_module_bind_unbind bu; struct ipc *ipc = ipc_get(); + + assert_can_be_cold(); + int ret = memcpy_s(&bu, sizeof(bu), ipc4, sizeof(*ipc4)); if (ret < 0) @@ -940,7 +959,7 @@ static int ipc4_unbind_module_instance(struct ipc4_message_request *ipc4) return ipc_comp_disconnect(ipc, (ipc_pipe_comp_connect *)&bu); } -static int ipc4_get_vendor_config_module_instance(struct comp_dev *dev, +__cold static int ipc4_get_vendor_config_module_instance(struct comp_dev *dev, const struct comp_driver *drv, bool init_block, bool final_block, @@ -952,6 +971,8 @@ static int ipc4_get_vendor_config_module_instance(struct comp_dev *dev, int ret; struct ipc4_vendor_error *error; + assert_can_be_cold(); + if (init_block && final_block) { /* we use data_off_size as in/out, * save value to new variable so it can be used as out size @@ -1033,7 +1054,7 @@ static int ipc4_get_vendor_config_module_instance(struct comp_dev *dev, return IPC4_SUCCESS; } -static int ipc4_get_large_config_module_instance(struct ipc4_message_request *ipc4) +__cold static int ipc4_get_large_config_module_instance(struct ipc4_message_request *ipc4) { struct ipc4_module_large_config_reply reply; struct ipc4_module_large_config config; @@ -1041,6 +1062,9 @@ static int ipc4_get_large_config_module_instance(struct ipc4_message_request *ip const struct comp_driver *drv; struct comp_dev *dev = NULL; uint32_t data_offset; + + assert_can_be_cold(); + int ret = memcpy_s(&config, sizeof(config), ipc4, sizeof(*ipc4)); if (ret < 0) @@ -1125,7 +1149,7 @@ static int ipc4_get_large_config_module_instance(struct ipc4_message_request *ip return ret; } -static int ipc4_set_vendor_config_module_instance(struct comp_dev *dev, +__cold static int ipc4_set_vendor_config_module_instance(struct comp_dev *dev, const struct comp_driver *drv, uint32_t module_id, uint32_t instance_id, @@ -1136,6 +1160,8 @@ static int ipc4_set_vendor_config_module_instance(struct comp_dev *dev, { int ret; + assert_can_be_cold(); + /* Old FW comment: bursted configs */ if (init_block && final_block) { const struct sof_tlv *tlv = (struct sof_tlv *)data; @@ -1188,11 +1214,14 @@ static int ipc4_set_vendor_config_module_instance(struct comp_dev *dev, data_off_size, data); } -static int ipc4_set_large_config_module_instance(struct ipc4_message_request *ipc4) +__cold static int ipc4_set_large_config_module_instance(struct ipc4_message_request *ipc4) { struct ipc4_module_large_config config; struct comp_dev *dev = NULL; const struct comp_driver *drv; + + assert_can_be_cold(); + int ret = memcpy_s(&config, sizeof(config), ipc4, sizeof(*ipc4)); if (ret < 0) @@ -1256,11 +1285,14 @@ static int ipc4_set_large_config_module_instance(struct ipc4_message_request *ip return ret; } -static int ipc4_delete_module_instance(struct ipc4_message_request *ipc4) +__cold static int ipc4_delete_module_instance(struct ipc4_message_request *ipc4) { struct ipc4_module_delete_instance module; struct ipc *ipc = ipc_get(); uint32_t comp_id; + + assert_can_be_cold(); + int ret = memcpy_s(&module, sizeof(module), ipc4, sizeof(*ipc4)); if (ret < 0) @@ -1282,10 +1314,13 @@ static int ipc4_delete_module_instance(struct ipc4_message_request *ipc4) } /* disable power gating on core 0 */ -static int ipc4_module_process_d0ix(struct ipc4_message_request *ipc4) +__cold static int ipc4_module_process_d0ix(struct ipc4_message_request *ipc4) { struct ipc4_module_set_d0ix d0ix; uint32_t module_id, instance_id; + + assert_can_be_cold(); + int ret = memcpy_s(&d0ix, sizeof(d0ix), ipc4, sizeof(*ipc4)); if (ret < 0) @@ -1311,12 +1346,15 @@ static int ipc4_module_process_d0ix(struct ipc4_message_request *ipc4) } /* enable/disable cores according to the state mask */ -static int ipc4_module_process_dx(struct ipc4_message_request *ipc4) +__cold static int ipc4_module_process_dx(struct ipc4_message_request *ipc4) { struct ipc4_module_set_dx dx; struct ipc4_dx_state_info dx_info; uint32_t module_id, instance_id; uint32_t core_id; + + assert_can_be_cold(); + int ret = memcpy_s(&dx, sizeof(dx), ipc4, sizeof(*ipc4)); if (ret < 0) @@ -1402,11 +1440,13 @@ static int ipc4_module_process_dx(struct ipc4_message_request *ipc4) return IPC4_SUCCESS; } -static int ipc4_process_module_message(struct ipc4_message_request *ipc4) +__cold static int ipc4_process_module_message(struct ipc4_message_request *ipc4) { uint32_t type; int ret; + assert_can_be_cold(); + type = ipc4->primary.r.type; switch (type) { @@ -1451,9 +1491,12 @@ static int ipc4_process_module_message(struct ipc4_message_request *ipc4) return ret; } -struct ipc_cmd_hdr *mailbox_validate(void) +__cold struct ipc_cmd_hdr *mailbox_validate(void) { struct ipc_cmd_hdr *hdr = ipc_get()->comp_data; + + assert_can_be_cold(); + return hdr; } @@ -1479,18 +1522,22 @@ struct ipc_cmd_hdr *ipc_prepare_to_send(const struct ipc_msg *msg) return &msg_data.msg_out; } -void ipc_boot_complete_msg(struct ipc_cmd_hdr *header, uint32_t data) +__cold void ipc_boot_complete_msg(struct ipc_cmd_hdr *header, uint32_t data) { + assert_can_be_cold(); + header->pri = SOF_IPC4_FW_READY; header->ext = 0; } #if defined(CONFIG_PM_DEVICE) && defined(CONFIG_INTEL_ADSP_IPC) -void ipc_send_failed_power_transition_response(void) +__cold void ipc_send_failed_power_transition_response(void) { struct ipc4_message_request *request = ipc_from_hdr(&msg_data.msg_in); struct ipc4_message_reply response; + assert_can_be_cold(); + response.primary.r.status = IPC4_POWER_TRANSITION_FAILED; response.primary.r.rsp = SOF_IPC4_MESSAGE_DIR_MSG_REPLY; response.primary.r.msg_tgt = request->primary.r.msg_tgt; @@ -1503,8 +1550,10 @@ void ipc_send_failed_power_transition_response(void) } #endif /* defined(CONFIG_PM_DEVICE) && defined(CONFIG_INTEL_ADSP_IPC) */ -void ipc_send_panic_notification(void) +__cold void ipc_send_panic_notification(void) { + assert_can_be_cold(); + msg_notify.header = SOF_IPC4_NOTIF_HEADER(SOF_IPC4_EXCEPTION_CAUGHT); msg_notify.extension = cpu_get_id(); msg_notify.tx_size = 0; @@ -1530,6 +1579,7 @@ static bool is_notification_queued(struct ipc_msg *msg) return queued; } +/* Called from ipc_send_buffer_status_notify(), which is currently "hot" */ void ipc_send_buffer_status_notify(void) { /* a single msg_notify object is used */ diff --git a/src/ipc/ipc4/helper.c b/src/ipc/ipc4/helper.c index 10a871259b49..f727d212f179 100644 --- a/src/ipc/ipc4/helper.c +++ b/src/ipc/ipc4/helper.c @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include @@ -60,6 +61,9 @@ LOG_MODULE_DECLARE(ipc, CONFIG_SOF_LOG_LEVEL); extern struct tr_ctx comp_tr; +static const struct comp_driver *ipc4_get_drv(const void *uuid); +static int ipc4_add_comp_dev(struct comp_dev *dev); + void ipc_build_stream_posn(struct sof_ipc_stream_posn *posn, uint32_t type, uint32_t id) { @@ -96,12 +100,15 @@ static const struct comp_driver *ipc4_library_get_comp_drv(char *data) return ipc4_get_drv(data); } #else -static inline char *ipc4_get_comp_new_data(void) +__cold static inline char *ipc4_get_comp_new_data(void) { + assert_can_be_cold(); + return (char *)MAILBOX_HOSTBOX_BASE; } #endif +/* Only called from ipc4_init_module_instance(), which is __cold */ __cold struct comp_dev *comp_new_ipc4(struct ipc4_module_init_instance *module_init) { struct comp_ipc_config ipc_config; @@ -192,6 +199,7 @@ __cold struct comp_dev *comp_new_ipc4(struct ipc4_module_init_instance *module_i return dev; } +/* Called from ipc4_set_pipeline_state(), so cannot be cold */ struct ipc_comp_dev *ipc_get_comp_by_ppl_id(struct ipc *ipc, uint16_t type, uint32_t ppl_id, uint32_t ignore_remote) @@ -220,12 +228,14 @@ struct ipc_comp_dev *ipc_get_comp_by_ppl_id(struct ipc *ipc, uint16_t type, return NULL; } -static int ipc4_create_pipeline(struct ipc4_pipeline_create *pipe_desc) +__cold static int ipc4_create_pipeline(struct ipc4_pipeline_create *pipe_desc) { struct ipc_comp_dev *ipc_pipe; struct pipeline *pipe; struct ipc *ipc = ipc_get(); + assert_can_be_cold(); + /* check whether pipeline id is already taken or in use */ ipc_pipe = ipc_get_pipeline_by_id(ipc, pipe_desc->primary.r.instance_id); if (ipc_pipe) { @@ -269,10 +279,13 @@ static int ipc4_create_pipeline(struct ipc4_pipeline_create *pipe_desc) return IPC4_SUCCESS; } -int ipc_pipeline_new(struct ipc *ipc, ipc_pipe_new *_pipe_desc) +/* Only called from ipc4_new_pipeline(), which is __cold */ +__cold int ipc_pipeline_new(struct ipc *ipc, ipc_pipe_new *_pipe_desc) { struct ipc4_pipeline_create *pipe_desc = ipc_from_pipe_new(_pipe_desc); + assert_can_be_cold(); + tr_dbg(&ipc_tr, "ipc: pipeline id = %u", (uint32_t)pipe_desc->primary.r.instance_id); /* pass IPC to target core */ @@ -282,20 +295,24 @@ int ipc_pipeline_new(struct ipc *ipc, ipc_pipe_new *_pipe_desc) return ipc4_create_pipeline(pipe_desc); } -static inline int ipc_comp_free_remote(struct comp_dev *dev) +__cold static inline int ipc_comp_free_remote(struct comp_dev *dev) { struct idc_msg msg = { IDC_MSG_FREE, IDC_MSG_FREE_EXT(dev->ipc_config.id), dev->ipc_config.core,}; + assert_can_be_cold(); + return idc_send_msg(&msg, IDC_BLOCKING); } -static int ipc_pipeline_module_free(uint32_t pipeline_id) +__cold static int ipc_pipeline_module_free(uint32_t pipeline_id) { struct ipc *ipc = ipc_get(); struct ipc_comp_dev *icd; int ret; + assert_can_be_cold(); + icd = ipc_get_comp_by_ppl_id(ipc, COMP_TYPE_COMPONENT, pipeline_id, IPC_COMP_ALL); while (icd) { struct comp_buffer *buffer; @@ -334,11 +351,14 @@ static int ipc_pipeline_module_free(uint32_t pipeline_id) return IPC4_SUCCESS; } -int ipc_pipeline_free(struct ipc *ipc, uint32_t comp_id) +/* Only called from ipc4_delete_pipeline(), which is __cold */ +__cold int ipc_pipeline_free(struct ipc *ipc, uint32_t comp_id) { struct ipc_comp_dev *ipc_pipe; int ret; + assert_can_be_cold(); + /* check whether pipeline exists */ ipc_pipe = ipc_get_pipeline_by_id(ipc, comp_id); if (!ipc_pipe) @@ -368,12 +388,14 @@ int ipc_pipeline_free(struct ipc *ipc, uint32_t comp_id) return IPC4_SUCCESS; } -static struct comp_buffer *ipc4_create_buffer(struct comp_dev *src, bool is_shared, - uint32_t buf_size, uint32_t src_queue, - uint32_t dst_queue) +__cold static struct comp_buffer *ipc4_create_buffer(struct comp_dev *src, bool is_shared, + uint32_t buf_size, uint32_t src_queue, + uint32_t dst_queue) { struct sof_ipc_buffer ipc_buf; + assert_can_be_cold(); + memset(&ipc_buf, 0, sizeof(ipc_buf)); ipc_buf.size = buf_size; ipc_buf.comp.id = IPC4_COMP_ID(src_queue, dst_queue); @@ -450,7 +472,8 @@ static int ll_wait_finished_on_core(struct comp_dev *dev) #endif -int ipc_comp_connect(struct ipc *ipc, ipc_pipe_comp_connect *_connect) +/* Only called from ipc4_bind_module_instance(), which is __cold */ +__cold int ipc_comp_connect(struct ipc *ipc, ipc_pipe_comp_connect *_connect) { struct ipc4_module_bind_unbind *bu; struct comp_buffer *buffer; @@ -465,6 +488,8 @@ int ipc_comp_connect(struct ipc *ipc, ipc_pipe_comp_connect *_connect) int src_id, sink_id; int ret; + assert_can_be_cold(); + bu = (struct ipc4_module_bind_unbind *)_connect; src_id = IPC4_COMP_ID(bu->primary.r.module_id, bu->primary.r.instance_id); sink_id = IPC4_COMP_ID(bu->extension.r.dst_module_id, bu->extension.r.dst_instance_id); @@ -668,7 +693,8 @@ int ipc_comp_connect(struct ipc *ipc, ipc_pipe_comp_connect *_connect) * during run-time. The only way to change pipeline topology is to delete the whole * pipeline and create it in modified form. */ -int ipc_comp_disconnect(struct ipc *ipc, ipc_pipe_comp_connect *_connect) +/* Only called from ipc4_unbind_module_instance(), which is __cold */ +__cold int ipc_comp_disconnect(struct ipc *ipc, ipc_pipe_comp_connect *_connect) { struct ipc4_module_bind_unbind *bu; struct comp_buffer *buffer = NULL; @@ -679,6 +705,8 @@ int ipc_comp_disconnect(struct ipc *ipc, ipc_pipe_comp_connect *_connect) int ret, ret1; bool cross_core_unbind; + assert_can_be_cold(); + bu = (struct ipc4_module_bind_unbind *)_connect; src_id = IPC4_COMP_ID(bu->primary.r.module_id, bu->primary.r.instance_id); sink_id = IPC4_COMP_ID(bu->extension.r.dst_module_id, bu->extension.r.dst_instance_id); @@ -759,12 +787,15 @@ int ipc_comp_disconnect(struct ipc *ipc, ipc_pipe_comp_connect *_connect) } #if CONFIG_COMP_CHAIN_DMA -int ipc4_chain_manager_create(struct ipc4_chain_dma *cdma) +/* Only called from ipc4_process_chain_dma(), which is __cold */ +__cold int ipc4_chain_manager_create(struct ipc4_chain_dma *cdma) { const struct sof_uuid uuid = SOF_REG_UUID(chain_dma); const struct comp_driver *drv; struct comp_dev *dev; + assert_can_be_cold(); + drv = ipc4_get_drv(&uuid); if (!drv) return -EINVAL; @@ -783,7 +814,8 @@ int ipc4_chain_manager_create(struct ipc4_chain_dma *cdma) return ipc4_add_comp_dev(dev); } -int ipc4_chain_dma_state(struct comp_dev *dev, struct ipc4_chain_dma *cdma) +/* Only called from ipc4_process_chain_dma(), which is __cold */ +__cold int ipc4_chain_dma_state(struct comp_dev *dev, struct ipc4_chain_dma *cdma) { const bool allocate = cdma->primary.r.allocate; const bool enable = cdma->primary.r.enable; @@ -792,6 +824,8 @@ int ipc4_chain_dma_state(struct comp_dev *dev, struct ipc4_chain_dma *cdma) struct list_item *clist, *_tmp; int ret; + assert_can_be_cold(); + if (!dev) return -EINVAL; @@ -823,12 +857,14 @@ int ipc4_chain_dma_state(struct comp_dev *dev, struct ipc4_chain_dma *cdma) } #endif -static int ipc4_update_comps_direction(struct ipc *ipc, uint32_t ppl_id) +__cold static int ipc4_update_comps_direction(struct ipc *ipc, uint32_t ppl_id) { struct ipc_comp_dev *icd; struct list_item *clist; struct comp_buffer *src_buf; + assert_can_be_cold(); + list_for_item(clist, &ipc->comp_list) { icd = container_of(clist, struct ipc_comp_dev, list); if (icd->type != COMP_TYPE_COMPONENT) @@ -904,7 +940,7 @@ int ipc4_process_on_core(uint32_t core, bool blocking) return IPC4_SUCCESS; } -const struct comp_driver *ipc4_get_drv(const void *uuid) +__cold static const struct comp_driver *ipc4_get_drv(const void *uuid) { const struct sof_uuid *const sof_uuid = (const struct sof_uuid *)uuid; struct comp_driver_list *drivers = comp_drivers_get(); @@ -913,6 +949,8 @@ const struct comp_driver *ipc4_get_drv(const void *uuid) struct comp_driver_info *info; uint32_t flags; + assert_can_be_cold(); + irq_local_disable(flags); /* search driver list with UUID */ @@ -940,13 +978,22 @@ const struct comp_driver *ipc4_get_drv(const void *uuid) return drv; } -const struct comp_driver *ipc4_get_comp_drv(uint32_t module_id) +/* + * Called from + * - ipc4_get_large_config_module_instance() + * - ipc4_set_large_config_module_instance() + * - comp_new_ipc4() + * all of which are __cold + */ +__cold const struct comp_driver *ipc4_get_comp_drv(uint32_t module_id) { const struct sof_man_fw_desc *desc = NULL; const struct comp_driver *drv; const struct sof_man_module *mod; uint32_t entry_index; + assert_can_be_cold(); + #ifdef RIMAGE_MANIFEST desc = (const struct sof_man_fw_desc *)IMR_BOOT_LDR_MANIFEST_BASE; #else @@ -1012,11 +1059,13 @@ struct comp_dev *ipc4_get_comp_dev(uint32_t comp_id) } EXPORT_SYMBOL(ipc4_get_comp_dev); -int ipc4_add_comp_dev(struct comp_dev *dev) +__cold static int ipc4_add_comp_dev(struct comp_dev *dev) { struct ipc *ipc = ipc_get(); struct ipc_comp_dev *icd; + assert_can_be_cold(); + /* check id for duplicates */ icd = ipc_get_comp_by_id(ipc, dev->ipc_config.id); if (icd) {