From f176f6f263e8139d5777a705ba143bceafd34d55 Mon Sep 17 00:00:00 2001 From: Jyri Sarha Date: Thu, 7 Aug 2025 13:06:20 +0300 Subject: [PATCH 01/10] Audio: Aria: All memory allocations through module API Allocate all memory through module API mod_alloc() and friends. The one rballoc() call is converted to mod_balloc(). Signed-off-by: Jyri Sarha --- src/audio/aria/aria.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/src/audio/aria/aria.c b/src/audio/aria/aria.c index ef9ced95adde..89fe11ba3457 100644 --- a/src/audio/aria/aria.c +++ b/src/audio/aria/aria.c @@ -9,7 +9,6 @@ #include #include #include -#include #include #include #include @@ -126,7 +125,7 @@ static int aria_init(struct processing_module *mod) list_init(&dev->bsource_list); list_init(&dev->bsink_list); - cd = rzalloc(SOF_MEM_FLAG_USER, sizeof(*cd)); + cd = mod_zalloc(mod, sizeof(*cd)); if (!cd) { return -ENOMEM; } @@ -145,10 +144,10 @@ static int aria_init(struct processing_module *mod) } mod_data->private = cd; - buf = rballoc(SOF_MEM_FLAG_USER, req_mem); + buf = mod_balloc(mod, req_mem); if (!buf) { - rfree(cd); + mod_free(mod, cd); comp_err(dev, "allocation failed for size %d", req_mem); return -ENOMEM; } @@ -160,8 +159,8 @@ static int aria_free(struct processing_module *mod) { struct aria_data *cd = module_get_private_data(mod); - rfree(cd->data_addr); - rfree(cd); + mod_free(mod, cd->data_addr); + mod_free(mod, cd); return 0; } From 6985a285423d9683dd2cb7be6f8e92d2c0462de8 Mon Sep 17 00:00:00 2001 From: Jyri Sarha Date: Thu, 7 Aug 2025 15:38:01 +0300 Subject: [PATCH 02/10] Audio: ASRC: Memory, blob, and fast_get allocs to module API Allocate all memory, blob handlers, and fast_get() buffers through module API mod_alloc() and friends. Signed-off-by: Jyri Sarha --- src/audio/asrc/asrc.c | 51 ++++++++++++++--------------- src/audio/asrc/asrc_farrow.c | 62 ++++++++++++++++++++---------------- src/audio/asrc/asrc_farrow.h | 8 ++--- src/audio/asrc/asrc_ipc3.c | 1 - src/audio/asrc/asrc_ipc4.c | 1 - 5 files changed, 62 insertions(+), 61 deletions(-) diff --git a/src/audio/asrc/asrc.c b/src/audio/asrc/asrc.c index 281d2f82aaf7..64632b221dac 100644 --- a/src/audio/asrc/asrc.c +++ b/src/audio/asrc/asrc.c @@ -11,7 +11,6 @@ #include #include #include -#include #include #include #include @@ -217,7 +216,7 @@ static int asrc_init(struct processing_module *mod) return -EINVAL; } - cd = rzalloc(SOF_MEM_FLAG_USER, sizeof(*cd)); + cd = mod_zalloc(mod, sizeof(*cd)); if (!cd) return -ENOMEM; @@ -242,7 +241,7 @@ static int asrc_init(struct processing_module *mod) return 0; } -static int asrc_initialize_buffers(struct asrc_farrow *src_obj) +static int asrc_initialize_buffers(struct processing_module *mod, struct asrc_farrow *src_obj) { int32_t *buf_32; int16_t *buf_16; @@ -261,7 +260,7 @@ static int asrc_initialize_buffers(struct asrc_farrow *src_obj) buffer_size = src_obj->buffer_length * sizeof(int32_t); for (ch = 0; ch < src_obj->num_channels; ch++) { - buf_32 = rzalloc(SOF_MEM_FLAG_USER, buffer_size); + buf_32 = mod_zalloc(mod, buffer_size); if (!buf_32) return -ENOMEM; @@ -272,7 +271,7 @@ static int asrc_initialize_buffers(struct asrc_farrow *src_obj) buffer_size = src_obj->buffer_length * sizeof(int16_t); for (ch = 0; ch < src_obj->num_channels; ch++) { - buf_16 = rzalloc(SOF_MEM_FLAG_USER, buffer_size); + buf_16 = mod_zalloc(mod, buffer_size); if (!buf_16) return -ENOMEM; @@ -284,7 +283,7 @@ static int asrc_initialize_buffers(struct asrc_farrow *src_obj) return 0; } -static void asrc_release_buffers(struct asrc_farrow *src_obj) +static void asrc_release_buffers(struct processing_module *mod, struct asrc_farrow *src_obj) { int32_t *buf_32; int16_t *buf_16; @@ -299,7 +298,7 @@ static void asrc_release_buffers(struct asrc_farrow *src_obj) if (buf_32) { src_obj->ring_buffers32[ch] = NULL; - rfree(buf_32); + mod_free(mod, buf_32); } } else @@ -308,7 +307,7 @@ static void asrc_release_buffers(struct asrc_farrow *src_obj) if (buf_16) { src_obj->ring_buffers16[ch] = NULL; - rfree(buf_16); + mod_free(mod, buf_16); } } } @@ -320,11 +319,11 @@ static int asrc_free(struct processing_module *mod) comp_dbg(dev, "asrc_free()"); - rfree(cd->buf); - asrc_release_buffers(cd->asrc_obj); - asrc_free_polyphase_filter(cd->asrc_obj); - rfree(cd->asrc_obj); - rfree(cd); + mod_free(mod, cd->buf); + asrc_release_buffers(mod, cd->asrc_obj); + asrc_free_polyphase_filter(mod, cd->asrc_obj); + mod_free(mod, cd->asrc_obj); + mod_free(mod, cd); return 0; } @@ -614,8 +613,7 @@ static int asrc_prepare(struct processing_module *mod, cd->buf_size = (cd->source_frames_max + cd->sink_frames_max) * frame_bytes; - cd->buf = rzalloc(SOF_MEM_FLAG_USER, - cd->buf_size); + cd->buf = mod_zalloc(mod, cd->buf_size); if (!cd->buf) { cd->buf_size = 0; comp_err(dev, "asrc_prepare(), allocation fail for size %d", @@ -632,7 +630,7 @@ static int asrc_prepare(struct processing_module *mod, /* Get required size and allocate memory for ASRC */ sample_bits = sample_bytes * 8; - ret = asrc_get_required_size(dev, &cd->asrc_size, + ret = asrc_get_required_size(mod, &cd->asrc_size, audio_stream_get_channels(&sourceb->stream), sample_bits); if (ret) { @@ -640,8 +638,7 @@ static int asrc_prepare(struct processing_module *mod, goto err_free_buf; } - cd->asrc_obj = rzalloc(SOF_MEM_FLAG_USER, - cd->asrc_size); + cd->asrc_obj = mod_zalloc(mod, cd->asrc_size); if (!cd->asrc_obj) { comp_err(dev, "asrc_prepare(), allocation fail for size %d", cd->asrc_size); @@ -659,7 +656,7 @@ static int asrc_prepare(struct processing_module *mod, fs_sec = cd->source_rate; } - ret = asrc_initialise(dev, cd->asrc_obj, audio_stream_get_channels(&sourceb->stream), + ret = asrc_initialise(mod, cd->asrc_obj, audio_stream_get_channels(&sourceb->stream), fs_prim, fs_sec, ASRC_IOF_INTERLEAVED, ASRC_IOF_INTERLEAVED, ASRC_BM_LINEAR, cd->frames, sample_bits, @@ -670,7 +667,7 @@ static int asrc_prepare(struct processing_module *mod, } /* Allocate ring buffers */ - ret = asrc_initialize_buffers(cd->asrc_obj); + ret = asrc_initialize_buffers(mod, cd->asrc_obj); /* check for errors */ if (ret) { @@ -698,12 +695,12 @@ static int asrc_prepare(struct processing_module *mod, return 0; err_free_asrc: - asrc_release_buffers(cd->asrc_obj); - rfree(cd->asrc_obj); + asrc_release_buffers(mod, cd->asrc_obj); + mod_free(mod, cd->asrc_obj); cd->asrc_obj = NULL; err_free_buf: - rfree(cd->buf); + mod_free(mod, cd->buf); cd->buf = NULL; err: @@ -865,10 +862,10 @@ static int asrc_reset(struct processing_module *mod) asrc_dai_stop_timestamp(cd); /* Free the allocations those were done in prepare() */ - asrc_release_buffers(cd->asrc_obj); - asrc_free_polyphase_filter(cd->asrc_obj); - rfree(cd->asrc_obj); - rfree(cd->buf); + asrc_release_buffers(mod, cd->asrc_obj); + asrc_free_polyphase_filter(mod, cd->asrc_obj); + mod_free(mod, cd->asrc_obj); + mod_free(mod, cd->buf); cd->asrc_obj = NULL; cd->buf = NULL; diff --git a/src/audio/asrc/asrc_farrow.c b/src/audio/asrc/asrc_farrow.c index 987a11408af0..e840a8082a3b 100644 --- a/src/audio/asrc/asrc_farrow.c +++ b/src/audio/asrc/asrc_farrow.c @@ -11,9 +11,9 @@ #include #include #include -#include #include #include +#include #include "asrc_farrow.h" LOG_MODULE_DECLARE(asrc, CONFIG_SOF_LOG_LEVEL); @@ -243,7 +243,7 @@ static const struct asrc_filter_params c_filter_params[CR_NUM] = { * Initialise the pointers to the filters, set the number of filters * and their length */ -static enum asrc_error_code initialise_filter(struct comp_dev *dev, +static enum asrc_error_code initialise_filter(struct processing_module *mod, struct asrc_farrow *src_obj); /* @@ -268,11 +268,12 @@ static enum asrc_error_code initialise_filter(struct comp_dev *dev, * Pointers to each channels data. Buffers are allocated externally. */ -enum asrc_error_code asrc_get_required_size(struct comp_dev *dev, +enum asrc_error_code asrc_get_required_size(struct processing_module *mod, int *required_size, int num_channels, int bit_depth) { + struct comp_dev *dev = mod->dev; int size; /* check for parameter errors */ @@ -318,7 +319,7 @@ enum asrc_error_code asrc_get_required_size(struct comp_dev *dev, return ASRC_EC_OK; } -enum asrc_error_code asrc_initialise(struct comp_dev *dev, +enum asrc_error_code asrc_initialise(struct processing_module *mod, struct asrc_farrow *src_obj, int num_channels, int32_t fs_prim, @@ -331,6 +332,7 @@ enum asrc_error_code asrc_initialise(struct comp_dev *dev, enum asrc_control_mode control_mode, enum asrc_operation_mode operation_mode) { + struct comp_dev *dev = mod->dev; enum asrc_error_code error_code; /* check for parameter errors */ @@ -410,7 +412,7 @@ enum asrc_error_code asrc_initialise(struct comp_dev *dev, * also sets the pointer to the corresponding * calc_impulse_response_nX function. */ - error_code = initialise_filter(dev, src_obj); + error_code = initialise_filter(mod, src_obj); /* check for errors */ if (error_code != ASRC_EC_OK) { @@ -438,10 +440,12 @@ enum asrc_error_code asrc_initialise(struct comp_dev *dev, return ASRC_EC_OK; } -enum asrc_error_code asrc_set_fs_ratio(struct comp_dev *dev, +enum asrc_error_code asrc_set_fs_ratio(struct processing_module *mod, struct asrc_farrow *src_obj, int32_t fs_prim, int32_t fs_sec) { + struct comp_dev *dev = mod->dev; + /* Check for parameter errors */ if (!src_obj) { comp_err(dev, "asrc_set_fs_ratio(), null src_obj"); @@ -490,7 +494,7 @@ enum asrc_error_code asrc_set_fs_ratio(struct comp_dev *dev, /* See initialise_asrc(...) for further information * Update the filters accordingly */ - enum asrc_error_code error_code = initialise_filter(dev, src_obj); + enum asrc_error_code error_code = initialise_filter(mod, src_obj); /* check for errors */ if (error_code != ASRC_EC_OK) { comp_err(dev, "asrc_set_fs_ratio(), failed filter initialise"); @@ -554,28 +558,29 @@ enum asrc_error_code asrc_set_output_format(struct comp_dev *dev, return ASRC_EC_OK; } -static const int32_t *__get_polyphase_filter(const int32_t *filter, size_t size) +static const int32_t *__get_polyphase_filter(struct processing_module *mod, + const int32_t *filter, size_t size) { #if CONFIG_FAST_GET - return fast_get(filter, size); + return mod_fast_get(mod, filter, size); #else return filter; #endif } -#define get_polyphase_filter(f) __get_polyphase_filter(f, sizeof(f)) +#define get_polyphase_filter(m, f) __get_polyphase_filter(m, f, sizeof(f)) -static void put_polyphase_filter(const int32_t *filter) +static void put_polyphase_filter(struct processing_module *mod, const int32_t *filter) { #if CONFIG_FAST_GET - fast_put(filter); + mod_fast_put(mod, filter); #endif } -void asrc_free_polyphase_filter(struct asrc_farrow *src_obj) +void asrc_free_polyphase_filter(struct processing_module *mod, struct asrc_farrow *src_obj) { if (src_obj && src_obj->polyphase_filters) { - put_polyphase_filter(src_obj->polyphase_filters); + put_polyphase_filter(mod, src_obj->polyphase_filters); src_obj->polyphase_filters = NULL; } } @@ -583,9 +588,10 @@ void asrc_free_polyphase_filter(struct asrc_farrow *src_obj) /* * FILTER FUNCTIONS */ -static enum asrc_error_code initialise_filter(struct comp_dev *dev, +static enum asrc_error_code initialise_filter(struct processing_module *mod, struct asrc_farrow *src_obj) { + struct comp_dev *dev = mod->dev; int fs_in; int fs_out; @@ -606,7 +612,7 @@ static enum asrc_error_code initialise_filter(struct comp_dev *dev, /* Reset coefficients for possible exit with error. */ src_obj->filter_length = 0; src_obj->num_filters = 0; - asrc_free_polyphase_filter(src_obj); + asrc_free_polyphase_filter(mod, src_obj); if (fs_in == 0 || fs_out == 0) { /* Avoid possible divisions by zero. */ @@ -622,7 +628,7 @@ static enum asrc_error_code initialise_filter(struct comp_dev *dev, c_filter_params[CR_48000TO48000].filter_length; src_obj->num_filters = c_filter_params[CR_48000TO48000].num_filters; - src_obj->polyphase_filters = get_polyphase_filter(coeff48000to48000); + src_obj->polyphase_filters = get_polyphase_filter(mod, coeff48000to48000); } else if (fs_in <= fs_out) { /* All upsampling use cases can share the same set of * filter coefficients. @@ -631,7 +637,7 @@ static enum asrc_error_code initialise_filter(struct comp_dev *dev, c_filter_params[CR_44100TO48000].filter_length; src_obj->num_filters = c_filter_params[CR_44100TO48000].num_filters; - src_obj->polyphase_filters = get_polyphase_filter(coeff44100to48000); + src_obj->polyphase_filters = get_polyphase_filter(mod, coeff44100to48000); } else if (fs_in == 48000) { switch (fs_out) { #if (CONFIG_ASRC_SUPPORT_CONVERSION_48000_TO_08000) @@ -640,7 +646,7 @@ static enum asrc_error_code initialise_filter(struct comp_dev *dev, c_filter_params[CR_48000TO08000].filter_length; src_obj->num_filters = c_filter_params[CR_48000TO08000].num_filters; - src_obj->polyphase_filters = get_polyphase_filter(coeff48000to08000); + src_obj->polyphase_filters = get_polyphase_filter(mod, coeff48000to08000); break; #endif #if (CONFIG_ASRC_SUPPORT_CONVERSION_48000_TO_11025) @@ -649,7 +655,7 @@ static enum asrc_error_code initialise_filter(struct comp_dev *dev, c_filter_params[CR_48000TO11025].filter_length; src_obj->num_filters = c_filter_params[CR_48000TO11025].num_filters; - src_obj->polyphase_filters = get_polyphase_filter(coeff48000to11025); + src_obj->polyphase_filters = get_polyphase_filter(mod, coeff48000to11025); break; #endif #if (CONFIG_ASRC_SUPPORT_CONVERSION_48000_TO_12000) @@ -658,7 +664,7 @@ static enum asrc_error_code initialise_filter(struct comp_dev *dev, c_filter_params[CR_48000TO12000].filter_length; src_obj->num_filters = c_filter_params[CR_48000TO12000].num_filters; - src_obj->polyphase_filters = get_polyphase_filter(coeff48000to12000); + src_obj->polyphase_filters = get_polyphase_filter(mod, coeff48000to12000); break; #endif #if (CONFIG_ASRC_SUPPORT_CONVERSION_48000_TO_16000) @@ -667,7 +673,7 @@ static enum asrc_error_code initialise_filter(struct comp_dev *dev, c_filter_params[CR_48000TO16000].filter_length; src_obj->num_filters = c_filter_params[CR_48000TO16000].num_filters; - src_obj->polyphase_filters = get_polyphase_filter(coeff48000to16000); + src_obj->polyphase_filters = get_polyphase_filter(mod, coeff48000to16000); break; #endif #if (CONFIG_ASRC_SUPPORT_CONVERSION_48000_TO_22050) @@ -676,7 +682,7 @@ static enum asrc_error_code initialise_filter(struct comp_dev *dev, c_filter_params[CR_48000TO22050].filter_length; src_obj->num_filters = c_filter_params[CR_48000TO22050].num_filters; - src_obj->polyphase_filters = get_polyphase_filter(coeff48000to22050); + src_obj->polyphase_filters = get_polyphase_filter(mod, coeff48000to22050); break; #endif #if (CONFIG_ASRC_SUPPORT_CONVERSION_48000_TO_24000) @@ -685,7 +691,7 @@ static enum asrc_error_code initialise_filter(struct comp_dev *dev, c_filter_params[CR_48000TO24000].filter_length; src_obj->num_filters = c_filter_params[CR_48000TO24000].num_filters; - src_obj->polyphase_filters = get_polyphase_filter(coeff48000to24000); + src_obj->polyphase_filters = get_polyphase_filter(mod, coeff48000to24000); break; #endif #if (CONFIG_ASRC_SUPPORT_CONVERSION_48000_TO_32000) @@ -694,7 +700,7 @@ static enum asrc_error_code initialise_filter(struct comp_dev *dev, c_filter_params[CR_48000TO32000].filter_length; src_obj->num_filters = c_filter_params[CR_48000TO32000].num_filters; - src_obj->polyphase_filters = get_polyphase_filter(coeff48000to32000); + src_obj->polyphase_filters = get_polyphase_filter(mod, coeff48000to32000); break; #endif #if (CONFIG_ASRC_SUPPORT_CONVERSION_48000_TO_44100) @@ -703,7 +709,7 @@ static enum asrc_error_code initialise_filter(struct comp_dev *dev, c_filter_params[CR_48000TO44100].filter_length; src_obj->num_filters = c_filter_params[CR_48000TO44100].num_filters; - src_obj->polyphase_filters = get_polyphase_filter(coeff48000to44100); + src_obj->polyphase_filters = get_polyphase_filter(mod, coeff48000to44100); break; #endif default: @@ -719,7 +725,7 @@ static enum asrc_error_code initialise_filter(struct comp_dev *dev, c_filter_params[CR_24000TO08000].filter_length; src_obj->num_filters = c_filter_params[CR_24000TO08000].num_filters; - src_obj->polyphase_filters = get_polyphase_filter(coeff24000to08000); + src_obj->polyphase_filters = get_polyphase_filter(mod, coeff24000to08000); break; #endif #if (CONFIG_ASRC_SUPPORT_CONVERSION_24000_TO_16000) @@ -728,7 +734,7 @@ static enum asrc_error_code initialise_filter(struct comp_dev *dev, c_filter_params[CR_24000TO16000].filter_length; src_obj->num_filters = c_filter_params[CR_24000TO16000].num_filters; - src_obj->polyphase_filters = get_polyphase_filter(coeff24000to16000); + src_obj->polyphase_filters = get_polyphase_filter(mod, coeff24000to16000); break; #endif default: diff --git a/src/audio/asrc/asrc_farrow.h b/src/audio/asrc/asrc_farrow.h index 766ead172d58..48e564c2d1e1 100644 --- a/src/audio/asrc/asrc_farrow.h +++ b/src/audio/asrc/asrc_farrow.h @@ -231,7 +231,7 @@ struct asrc_farrow { * @param[in] bit_depth The wordlength that will be used for representing * the PCM samples, must be 16 or 32. */ -enum asrc_error_code asrc_get_required_size(struct comp_dev *dev, +enum asrc_error_code asrc_get_required_size(struct processing_module *mod, int *required_size, int num_channels, int bit_depth); @@ -268,7 +268,7 @@ enum asrc_error_code asrc_get_required_size(struct comp_dev *dev, * @param[in] operation_mode Choose 'push' or 'pull', depending on the mode * you want your ASRC to operate in. */ -enum asrc_error_code asrc_initialise(struct comp_dev *dev, +enum asrc_error_code asrc_initialise(struct processing_module *mod, struct asrc_farrow *src_obj, int num_channels, int32_t fs_prim, @@ -286,7 +286,7 @@ enum asrc_error_code asrc_initialise(struct comp_dev *dev, * * @param[in] src_obj Pointer to the ias_src_farrow. */ -void asrc_free_polyphase_filter(struct asrc_farrow *src_obj); +void asrc_free_polyphase_filter(struct processing_module *mod, struct asrc_farrow *src_obj); /* * @brief Process the sample rate converter for one frame; the frame @@ -591,7 +591,7 @@ enum asrc_error_code asrc_update_fs_ratio(struct comp_dev *dev, * @param[in] fs_prim Primary sampling rate. * @param[in] fs_sec Secondary sampling rate. */ -enum asrc_error_code asrc_set_fs_ratio(struct comp_dev *dev, +enum asrc_error_code asrc_set_fs_ratio(struct processing_module *mod, struct asrc_farrow *src_obj, int32_t fs_prim, int32_t fs_sec); diff --git a/src/audio/asrc/asrc_ipc3.c b/src/audio/asrc/asrc_ipc3.c index 30dfbecddc6b..ca917318d7e5 100644 --- a/src/audio/asrc/asrc_ipc3.c +++ b/src/audio/asrc/asrc_ipc3.c @@ -4,7 +4,6 @@ #include #include -#include #include #include #include diff --git a/src/audio/asrc/asrc_ipc4.c b/src/audio/asrc/asrc_ipc4.c index 3e5d8bf7818f..1047799f207b 100644 --- a/src/audio/asrc/asrc_ipc4.c +++ b/src/audio/asrc/asrc_ipc4.c @@ -4,7 +4,6 @@ #include #include -#include #include #include #include From 651c2e1d6138747307ec701b7df65fa723f1bc01 Mon Sep 17 00:00:00 2001 From: Jyri Sarha Date: Thu, 7 Aug 2025 23:02:32 +0300 Subject: [PATCH 03/10] Audio: Copier: All memory allocations through module API Allocate all memory through module API mod_alloc() and friends. NOTE: copier_dai.c and copier_host.c still have their shared memory allocated through the old API. This is to be fixed once we have decided on how the shared memory allocations should work in user-space. Signed-off-by: Jyri Sarha --- src/audio/copier/copier.c | 46 ++++++++++++++++---------------- src/audio/copier/copier_host.c | 16 ++++++----- src/audio/copier/copier_ipcgtw.c | 15 +++++++---- src/audio/copier/host_copier.h | 4 +-- src/audio/copier/ipcgtw_copier.h | 6 ++--- 5 files changed, 48 insertions(+), 39 deletions(-) diff --git a/src/audio/copier/copier.c b/src/audio/copier/copier.c index f3b0a08a05fc..5ffe9576a17e 100644 --- a/src/audio/copier/copier.c +++ b/src/audio/copier/copier.c @@ -15,7 +15,6 @@ #include #include #include -#include #include #include #include @@ -82,13 +81,12 @@ static void mic_privacy_event(void *arg, enum notify_id type, void *data) } } -static int mic_privacy_configure(struct comp_dev *dev, struct copier_data *cd) +static int mic_privacy_configure(struct processing_module *mod, struct copier_data *cd) { struct mic_privacy_data *mic_priv_data; int ret; - mic_priv_data = rzalloc(SOF_MEM_FLAG_USER, - sizeof(struct mic_privacy_data)); + mic_priv_data = mod_zalloc(mod, sizeof(struct mic_privacy_data)); if (!mic_priv_data) return -ENOMEM; @@ -100,10 +98,10 @@ static int mic_privacy_configure(struct comp_dev *dev, struct copier_data *cd) uint32_t zeroing_wait_time = (mic_privacy_get_dma_zeroing_wait_time() * 1000) / ADSP_RTC_FREQUENCY; - ret = copier_gain_set_params(dev, &mic_priv_data->mic_priv_gain_params, + ret = copier_gain_set_params(mod->dev, &mic_priv_data->mic_priv_gain_params, zeroing_wait_time, SOF_DAI_INTEL_NONE); if (ret != 0) { - rfree(mic_priv_data); + mod_free(mod, mic_priv_data); return ret; } @@ -111,20 +109,23 @@ static int mic_privacy_configure(struct comp_dev *dev, struct copier_data *cd) ret = notifier_register(cd->mic_priv, NULL, NOTIFIER_ID_MIC_PRIVACY_STATE_CHANGE, mic_privacy_event, 0); + if (ret != 0) - rfree(mic_priv_data); + mod_free(mod, mic_priv_data); return ret; } -static void mic_privacy_free(struct copier_data *cd) +static void mic_privacy_free(struct processing_module *mod) { + struct copier_data *cd = module_get_private_data(mod); + if (cd->gtw_type == ipc4_gtw_dmic) mic_privacy_enable_dmic_irq(false); notifier_unregister(cd->mic_priv, NULL, NOTIFIER_ID_MIC_PRIVACY_STATE_CHANGE); - rfree(cd->mic_priv); + mod_free(mod, cd->mic_priv); } #endif @@ -141,7 +142,7 @@ __cold static int copier_init(struct processing_module *mod) assert_can_be_cold(); - cd = rzalloc(SOF_MEM_FLAG_USER, sizeof(*cd)); + cd = mod_zalloc(mod, sizeof(*cd)); if (!cd) return -ENOMEM; @@ -163,8 +164,7 @@ __cold static int copier_init(struct processing_module *mod) */ if (copier->gtw_cfg.config_length) { gtw_cfg_size = copier->gtw_cfg.config_length << 2; - gtw_cfg = rmalloc(SOF_MEM_FLAG_USER, - gtw_cfg_size); + gtw_cfg = mod_alloc(mod, gtw_cfg_size); if (!gtw_cfg) { ret = -ENOMEM; goto error_cd; @@ -191,7 +191,7 @@ __cold static int copier_init(struct processing_module *mod) switch (node_id.f.dma_type) { case ipc4_hda_host_output_class: case ipc4_hda_host_input_class: - ret = copier_host_create(dev, cd, copier, dev->pipeline); + ret = copier_host_create(mod, copier, dev->pipeline); if (ret < 0) { comp_err(dev, "unable to create host"); goto error; @@ -199,7 +199,7 @@ __cold static int copier_init(struct processing_module *mod) #if CONFIG_INTEL_ADSP_MIC_PRIVACY if (cd->direction == SOF_IPC_STREAM_CAPTURE && node_id.f.dma_type == ipc4_hda_host_output_class) { - ret = mic_privacy_configure(dev, cd); + ret = mic_privacy_configure(mod, cd); if (ret < 0) { comp_err(dev, "unable to configure mic privacy"); goto error; @@ -221,7 +221,7 @@ __cold static int copier_init(struct processing_module *mod) } #if CONFIG_INTEL_ADSP_MIC_PRIVACY if (cd->direction == SOF_IPC_STREAM_CAPTURE) { - ret = mic_privacy_configure(dev, cd); + ret = mic_privacy_configure(mod, cd); if (ret < 0) { comp_err(dev, "unable to configure mic privacy"); goto error; @@ -232,7 +232,7 @@ __cold static int copier_init(struct processing_module *mod) #if CONFIG_IPC4_GATEWAY case ipc4_ipc_output_class: case ipc4_ipc_input_class: - ret = copier_ipcgtw_create(dev, cd, copier, dev->pipeline); + ret = copier_ipcgtw_create(mod, copier, dev->pipeline); if (ret < 0) { comp_err(dev, "unable to create IPC gateway"); goto error; @@ -257,9 +257,9 @@ __cold static int copier_init(struct processing_module *mod) dev->state = COMP_STATE_READY; return 0; error: - rfree(gtw_cfg); + mod_free(mod, gtw_cfg); error_cd: - rfree(cd); + mod_free(mod, cd); return ret; } @@ -271,16 +271,16 @@ __cold static int copier_free(struct processing_module *mod) assert_can_be_cold(); #if CONFIG_INTEL_ADSP_MIC_PRIVACY - mic_privacy_free(cd); + mic_privacy_free(mod); #endif switch (dev->ipc_config.type) { case SOF_COMP_HOST: if (!cd->ipc_gtw) - copier_host_free(cd); + copier_host_free(mod); else /* handle gtw case */ - copier_ipcgtw_free(cd); + copier_ipcgtw_free(mod); break; case SOF_COMP_DAI: copier_dai_free(cd); @@ -290,8 +290,8 @@ __cold static int copier_free(struct processing_module *mod) } if (cd) - rfree(cd->gtw_cfg); - rfree(cd); + mod_free(mod, cd->gtw_cfg); + mod_free(mod, cd); return 0; } diff --git a/src/audio/copier/copier_host.c b/src/audio/copier/copier_host.c index 8315ad4535e2..92f159efafa7 100644 --- a/src/audio/copier/copier_host.c +++ b/src/audio/copier/copier_host.c @@ -131,11 +131,12 @@ __cold static int init_pipeline_reg(struct comp_dev *dev) * Sof host component can support this case so copier reuses host * component to support host gateway. */ -__cold int copier_host_create(struct comp_dev *dev, struct copier_data *cd, +__cold int copier_host_create(struct processing_module *mod, const struct ipc4_copier_module_cfg *copier_cfg, struct pipeline *pipeline) { - struct processing_module *mod = comp_mod(dev); + struct copier_data *cd = module_get_private_data(mod); + struct comp_dev *dev = mod->dev; struct comp_ipc_config *config = &dev->ipc_config; struct ipc_config_host ipc_host; struct host_data *hd; @@ -177,7 +178,7 @@ __cold int copier_host_create(struct comp_dev *dev, struct copier_data *cd, ipc_host.dma_buffer_size = copier_cfg->gtw_cfg.dma_buffer_size; ipc_host.feature_mask = copier_cfg->copier_feature_mask; - hd = rzalloc(SOF_MEM_FLAG_USER, sizeof(*hd)); + hd = mod_zalloc(mod, sizeof(*hd)); if (!hd) return -ENOMEM; @@ -187,6 +188,7 @@ __cold int copier_host_create(struct comp_dev *dev, struct copier_data *cd, goto e_data; } #if CONFIG_HOST_DMA_STREAM_SYNCHRONIZATION + /* NOTE: Should use goto e_conv this #if section, not direct return */ /* Size of a configuration without optional parameters. */ const uint32_t basic_size = sizeof(*copier_cfg) + (copier_cfg->gtw_cfg.config_length - 1) * sizeof(uint32_t); @@ -249,13 +251,15 @@ __cold int copier_host_create(struct comp_dev *dev, struct copier_data *cd, e_conv: host_common_free(hd); e_data: - rfree(hd); + mod_free(mod, hd); return ret; } -__cold void copier_host_free(struct copier_data *cd) +__cold void copier_host_free(struct processing_module *mod) { + struct copier_data *cd = module_get_private_data(mod); + assert_can_be_cold(); #if CONFIG_HOST_DMA_STREAM_SYNCHRONIZATION @@ -263,7 +267,7 @@ __cold void copier_host_free(struct copier_data *cd) delete_from_fpi_sync_group(cd->hd); #endif host_common_free(cd->hd); - rfree(cd->hd); + mod_free(mod, cd->hd); } /* This is called by DMA driver every time when DMA completes its current diff --git a/src/audio/copier/copier_ipcgtw.c b/src/audio/copier/copier_ipcgtw.c index ea518b5e12f2..0fb4600e6bbc 100644 --- a/src/audio/copier/copier_ipcgtw.c +++ b/src/audio/copier/copier_ipcgtw.c @@ -2,6 +2,7 @@ // // Copyright 2023 Intel Corporation. All rights reserved. +#include #include #include #include @@ -207,10 +208,12 @@ void copier_ipcgtw_reset(struct comp_dev *dev) } } -__cold int copier_ipcgtw_create(struct comp_dev *dev, struct copier_data *cd, +__cold int copier_ipcgtw_create(struct processing_module *mod, const struct ipc4_copier_module_cfg *copier, struct pipeline *pipeline) { + struct copier_data *cd = module_get_private_data(mod); + struct comp_dev *dev = mod->dev; struct comp_ipc_config *config = &dev->ipc_config; struct ipcgtw_data *ipcgtw_data; const struct ipc4_copier_gateway_cfg *gtw_cfg; @@ -231,7 +234,7 @@ __cold int copier_ipcgtw_create(struct comp_dev *dev, struct copier_data *cd, config->type = SOF_COMP_HOST; cd->gtw_type = ipc4_gtw_host; - ipcgtw_data = rzalloc(SOF_MEM_FLAG_USER, sizeof(*ipcgtw_data)); + ipcgtw_data = mod_zalloc(mod, sizeof(*ipcgtw_data)); if (!ipcgtw_data) return -ENOMEM; @@ -273,14 +276,16 @@ __cold int copier_ipcgtw_create(struct comp_dev *dev, struct copier_data *cd, return 0; e_ipcgtw: - rfree(ipcgtw_data); + mod_free(mod, ipcgtw_data); return ret; } -__cold void copier_ipcgtw_free(struct copier_data *cd) +__cold void copier_ipcgtw_free(struct processing_module *mod) { + struct copier_data *cd = module_get_private_data(mod); + assert_can_be_cold(); list_item_del(&cd->ipcgtw_data->item); - rfree(cd->ipcgtw_data); + mod_free(mod, cd->ipcgtw_data); } diff --git a/src/audio/copier/host_copier.h b/src/audio/copier/host_copier.h index e8f5fc58ca91..28605ed9c3ab 100644 --- a/src/audio/copier/host_copier.h +++ b/src/audio/copier/host_copier.h @@ -129,10 +129,10 @@ static inline int host_common_copy(struct host_data *hd, struct comp_dev *dev, c } void host_common_update(struct host_data *hd, struct comp_dev *dev, uint32_t bytes); void host_common_one_shot(struct host_data *hd, uint32_t bytes); -int copier_host_create(struct comp_dev *dev, struct copier_data *cd, +int copier_host_create(struct processing_module *mod, const struct ipc4_copier_module_cfg *copier_cfg, struct pipeline *pipeline); -void copier_host_free(struct copier_data *cd); +void copier_host_free(struct processing_module *mod); int copier_host_params(struct copier_data *cd, struct comp_dev *dev, struct sof_ipc_stream_params *params); void copier_host_dma_cb(struct comp_dev *dev, size_t bytes); diff --git a/src/audio/copier/ipcgtw_copier.h b/src/audio/copier/ipcgtw_copier.h index ef42ede75ddd..a9ea82914d4e 100644 --- a/src/audio/copier/ipcgtw_copier.h +++ b/src/audio/copier/ipcgtw_copier.h @@ -95,17 +95,17 @@ struct ipc4_ipc_gateway_cmd_data_reply { int copier_ipcgtw_process(const struct ipc4_ipcgtw_cmd *cmd, void *reply_payload, uint32_t *reply_payload_size); -int copier_ipcgtw_create(struct comp_dev *dev, struct copier_data *cd, +int copier_ipcgtw_create(struct processing_module *mod, const struct ipc4_copier_module_cfg *copier, struct pipeline *pipeline); #if CONFIG_IPC4_GATEWAY -void copier_ipcgtw_free(struct copier_data *cd); +void copier_ipcgtw_free(struct processing_module *mod); int copier_ipcgtw_params(struct ipcgtw_data *ipcgtw_data, struct comp_dev *dev, struct sof_ipc_stream_params *params); void copier_ipcgtw_reset(struct comp_dev *dev); #else -static inline void copier_ipcgtw_free(struct copier_data *cd) {} +static inline void copier_ipcgtw_free(struct processing_module *mod) {} static inline void copier_ipcgtw_reset(struct comp_dev *dev) {} static inline int copier_ipcgtw_params(struct ipcgtw_data *ipcgtw_data, struct comp_dev *dev, struct sof_ipc_stream_params *params) From b729416297009f680219c4d672e3072ba0984b28 Mon Sep 17 00:00:00 2001 From: Jyri Sarha Date: Fri, 5 Sep 2025 11:43:12 +0300 Subject: [PATCH 04/10] audio: copier: Fix resource leak from DMA sync code error handling The code within #if CONFIG_HOST_DMA_STREAM_SYNCHRONIZATION should free host_common resources in case of failure. The commit fixes the issue. Signed-off-by: Jyri Sarha --- src/audio/copier/copier_host.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/audio/copier/copier_host.c b/src/audio/copier/copier_host.c index 92f159efafa7..f35293d958f9 100644 --- a/src/audio/copier/copier_host.c +++ b/src/audio/copier/copier_host.c @@ -188,7 +188,6 @@ __cold int copier_host_create(struct processing_module *mod, goto e_data; } #if CONFIG_HOST_DMA_STREAM_SYNCHRONIZATION - /* NOTE: Should use goto e_conv this #if section, not direct return */ /* Size of a configuration without optional parameters. */ const uint32_t basic_size = sizeof(*copier_cfg) + (copier_cfg->gtw_cfg.config_length - 1) * sizeof(uint32_t); @@ -207,14 +206,16 @@ __cold int copier_host_create(struct processing_module *mod, if (value_ptr) { struct ipc4_copier_sync_group *sync_group; - if (value_size != sizeof(struct ipc4_copier_sync_group)) - return -EINVAL; + if (value_size != sizeof(struct ipc4_copier_sync_group)) { + ret = -EINVAL; + goto e_conv; + } sync_group = (struct ipc4_copier_sync_group *)((void *)value_ptr); ret = add_to_fpi_sync_group(dev, hd, sync_group); if (ret < 0) - return ret; + goto e_conv; } } #endif From 9a428ff107e7cd51cb63980cf95aa3fb9352c24f Mon Sep 17 00:00:00 2001 From: Jyri Sarha Date: Tue, 4 Nov 2025 00:47:36 +0200 Subject: [PATCH 05/10] module_adapter: mod API to work without resource tracking. First hackish version REVISIT --- src/audio/module_adapter/module/generic.c | 86 ++++++++++++++++++- src/audio/module_adapter/module_adapter.c | 5 +- .../sof/audio/module_adapter/module/generic.h | 3 + 3 files changed, 91 insertions(+), 3 deletions(-) diff --git a/src/audio/module_adapter/module/generic.c b/src/audio/module_adapter/module/generic.c index c4a5110c4b28..b3841f7fabba 100644 --- a/src/audio/module_adapter/module/generic.c +++ b/src/audio/module_adapter/module/generic.c @@ -71,16 +71,26 @@ int module_load_config(struct comp_dev *dev, const void *cfg, size_t size) return ret; } -static void mod_resource_init(struct processing_module *mod) +/* TODO: Comtent */ +int mod_resource_init(struct processing_module *mod) { struct module_data *md = &mod->priv; + + MEM_API_CHECK_THREAD(&md->resources); + if (md->resources.resource_count > 0) { + comp_err(mod->dev, "failed to allocate space for setup config."); + return -EBUSY; + } /* Init memory list */ list_init(&md->resources.res_list); list_init(&md->resources.free_cont_list); list_init(&md->resources.cont_chunk_list); md->resources.heap_usage = 0; md->resources.heap_high_water_mark = 0; + md->resources.tracking_enabled = true; + return 0; } +EXPORT_SYMBOL(mod_resource_init); int module_init(struct processing_module *mod) { @@ -117,7 +127,10 @@ int module_init(struct processing_module *mod) ret = interface->init(mod); if (ret) { comp_err(dev, "error %d: module specific init failed", ret); - mod_free_all(mod); + if (mod->priv.resources.tracking_enabled) + mod_free_all(mod); + else if (mod->priv.resources.resource_count) + comp_err(dev, "%u resources leaked due to failed init"); return ret; } @@ -184,6 +197,13 @@ void *mod_balloc_align(struct processing_module *mod, size_t size, size_t alignm MEM_API_CHECK_THREAD(res); + if (!res->tracking_enabled) { + ptr = rballoc_align(SOF_MEM_FLAG_USER, size, alignment); + if (ptr) + res->resource_count++; + return ptr; + } + container = container_get(mod); if (!container) return NULL; @@ -234,6 +254,13 @@ void *mod_alloc_align(struct processing_module *mod, size_t size, size_t alignme MEM_API_CHECK_THREAD(res); + if (!res->tracking_enabled) { + ptr = rmalloc_align(SOF_MEM_FLAG_USER, size, alignment); + if (ptr) + res->resource_count++; + return ptr; + } + container = container_get(mod); if (!container) return NULL; @@ -284,6 +311,13 @@ mod_data_blob_handler_new(struct processing_module *mod) MEM_API_CHECK_THREAD(res); + if (!res->tracking_enabled) { + bhp = comp_data_blob_handler_new_ext(mod->dev, false, NULL, NULL); + if (bhp) + res->resource_count++; + return bhp; + } + container = container_get(mod); if (!container) return NULL; @@ -320,6 +354,13 @@ const void *mod_fast_get(struct processing_module *mod, const void * const dram_ MEM_API_CHECK_THREAD(res); + if (!res->tracking_enabled) { + ptr = fast_get(dram_ptr, size); + if (ptr) + res->resource_count++; + return ptr; + } + container = container_get(mod); if (!container) return NULL; @@ -380,6 +421,20 @@ int mod_free(struct processing_module *mod, const void *ptr) if (!ptr) return 0; + if (!res->tracking_enabled) { + if (res->resource_count == 0) { + comp_err(mod->dev, "More resources freed than allocated."); + return -EINVAL; + } + /* TODO: static generic tracked resource free func + * that takes const ptr to treat Guennadi's cast + * allergy, so that mod_free can take non const + */ + rfree((void *)ptr); + res->resource_count--; + return 0; + } + /* Find which container keeps this memory */ list_for_item(res_list, &res->res_list) { container = container_of(res_list, struct module_resource, list); @@ -401,6 +456,18 @@ EXPORT_SYMBOL(mod_free); #if CONFIG_COMP_BLOB void mod_data_blob_handler_free(struct processing_module *mod, struct comp_data_blob_handler *dbh) { + struct module_resources *res = &mod->priv.resources; + + if (!res->tracking_enabled) { + if (res->resource_count == 0) { + comp_err(mod->dev, "More resources freed than allocated."); + return; + } + comp_data_blob_handler_free(dbh); + res->resource_count--; + return; + } + mod_free(mod, (void *)dbh); } EXPORT_SYMBOL(mod_data_blob_handler_free); @@ -409,6 +476,18 @@ EXPORT_SYMBOL(mod_data_blob_handler_free); #if CONFIG_FAST_GET void mod_fast_put(struct processing_module *mod, const void *sram_ptr) { + struct module_resources *res = &mod->priv.resources; + + if (!res->tracking_enabled) { + if (res->resource_count == 0) { + comp_err(mod->dev, "More resources freed than allocated."); + return; + } + fast_put(sram_ptr); + res->resource_count--; + return; + } + mod_free(mod, sram_ptr); } EXPORT_SYMBOL(mod_fast_put); @@ -591,6 +670,9 @@ void mod_free_all(struct processing_module *mod) struct list_item *_list; MEM_API_CHECK_THREAD(res); + + __ASSERT(res->tracking_enabled, "Resource tracking not enabled"); + /* Free all contents found in used containers */ list_for_item(list, &res->res_list) { struct module_resource *container = diff --git a/src/audio/module_adapter/module_adapter.c b/src/audio/module_adapter/module_adapter.c index c5e6c75ca649..356d42be87c3 100644 --- a/src/audio/module_adapter/module_adapter.c +++ b/src/audio/module_adapter/module_adapter.c @@ -1280,7 +1280,10 @@ void module_adapter_free(struct comp_dev *dev) buffer_free(buffer); } - mod_free_all(mod); + if (mod->priv.resources.tracking_enabled) + mod_free_all(mod); + else if (mod->priv.resources.resource_count) + comp_err(dev, "%u unfreed resources leaked", mod->priv.resources.resource_count); #if CONFIG_IPC_MAJOR_4 rfree(mod->priv.cfg.input_pins); diff --git a/src/include/sof/audio/module_adapter/module/generic.h b/src/include/sof/audio/module_adapter/module/generic.h index 7138da3a697a..3f07abf2d0dc 100644 --- a/src/include/sof/audio/module_adapter/module/generic.h +++ b/src/include/sof/audio/module_adapter/module/generic.h @@ -127,6 +127,8 @@ struct module_param { * when the module unloads. */ struct module_resources { + bool tracking_enabled; + unsigned int resource_count; struct list_item res_list; /**< Allocad resource containers */ struct list_item free_cont_list; /**< Unused memory containers */ struct list_item cont_chunk_list; /**< Memory container chunks */ @@ -188,6 +190,7 @@ struct module_processing_data { /*****************************************************************************/ int module_load_config(struct comp_dev *dev, const void *cfg, size_t size); int module_init(struct processing_module *mod); +int mod_resource_init(struct processing_module *mod); void *mod_balloc_align(struct processing_module *mod, size_t size, size_t alignment); static inline void *mod_balloc(struct processing_module *mod, size_t size) { From c347bab51885f2afba5a52548fb587252d320573 Mon Sep 17 00:00:00 2001 From: Jyri Sarha Date: Tue, 4 Nov 2025 22:41:11 +0200 Subject: [PATCH 06/10] mod_resource_init documentation --- src/audio/module_adapter/module/generic.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/audio/module_adapter/module/generic.c b/src/audio/module_adapter/module/generic.c index b3841f7fabba..4e4f40568139 100644 --- a/src/audio/module_adapter/module/generic.c +++ b/src/audio/module_adapter/module/generic.c @@ -71,7 +71,17 @@ int module_load_config(struct comp_dev *dev, const void *cfg, size_t size) return ret; } -/* TODO: Comtent */ +/** + * Initialize resource tracking and turn it on for the module. + * @param mod Pointer to the module + * @return 0 if Ok, -EBUSY if module is in wrong state. + * + * This function should be called from the module init function before + * any resource allocations are made through mod_alloc() and friends. + * If resource tracking is on, then all resources allocated through + * mod_alloc() and frieds are freed automatically when the module is + * unloaded of if its initialization fails. + */ int mod_resource_init(struct processing_module *mod) { struct module_data *md = &mod->priv; From ec458fcf2d6ed5a1fc28415bb5d249a95c08060d Mon Sep 17 00:00:00 2001 From: Jyri Sarha Date: Tue, 4 Nov 2025 23:06:12 +0200 Subject: [PATCH 07/10] get rid off casts, update free prototypes to return int --- src/audio/module_adapter/module/generic.c | 105 ++++++++++-------- .../sof/audio/module_adapter/module/generic.h | 6 +- 2 files changed, 62 insertions(+), 49 deletions(-) diff --git a/src/audio/module_adapter/module/generic.c b/src/audio/module_adapter/module/generic.c index 4e4f40568139..969a47f67cb3 100644 --- a/src/audio/module_adapter/module/generic.c +++ b/src/audio/module_adapter/module/generic.c @@ -416,35 +416,12 @@ static int free_contents(struct processing_module *mod, struct module_resource * return -EINVAL; } -/** - * Frees the memory block removes it from module's book keeping. - * @param mod Pointer to module this memory block was allocated for. - * @param ptr Pointer to the memory block. - */ -int mod_free(struct processing_module *mod, const void *ptr) +static int free_tracked_resource(struct processing_module *mod, const void *ptr) { struct module_resources *res = &mod->priv.resources; struct module_resource *container; struct list_item *res_list; - MEM_API_CHECK_THREAD(res); - if (!ptr) - return 0; - - if (!res->tracking_enabled) { - if (res->resource_count == 0) { - comp_err(mod->dev, "More resources freed than allocated."); - return -EINVAL; - } - /* TODO: static generic tracked resource free func - * that takes const ptr to treat Guennadi's cast - * allergy, so that mod_free can take non const - */ - rfree((void *)ptr); - res->resource_count--; - return 0; - } - /* Find which container keeps this memory */ list_for_item(res_list, &res->res_list) { container = container_of(res_list, struct module_resource, list); @@ -461,44 +438,80 @@ int mod_free(struct processing_module *mod, const void *ptr) return -EINVAL; } + +/** + * Frees the memory block removes it from module's book keeping. + * @param mod Pointer to module this memory block was allocated for. + * @param ptr Pointer to the memory block. + */ +int mod_free(struct processing_module *mod, void *ptr) +{ + struct module_resources *res = &mod->priv.resources; + struct module_resource *container; + struct list_item *res_list; + + MEM_API_CHECK_THREAD(res); + + if (!ptr) + return 0; + + if (res->tracking_enabled) + return free_tracked_resource(mod, ptr); + + if (res->resource_count == 0) { + comp_err(mod->dev, "More resources freed than allocated."); + return -EINVAL; + } + rfree(ptr); + res->resource_count--; + return 0; +} EXPORT_SYMBOL(mod_free); #if CONFIG_COMP_BLOB -void mod_data_blob_handler_free(struct processing_module *mod, struct comp_data_blob_handler *dbh) +int mod_data_blob_handler_free(struct processing_module *mod, struct comp_data_blob_handler *dbh) { struct module_resources *res = &mod->priv.resources; - if (!res->tracking_enabled) { - if (res->resource_count == 0) { - comp_err(mod->dev, "More resources freed than allocated."); - return; - } - comp_data_blob_handler_free(dbh); - res->resource_count--; - return; - } + MEM_API_CHECK_THREAD(res); + + if (!dbh) + return 0; - mod_free(mod, (void *)dbh); + if (res->tracking_enabled) + return free_tracked_resource(mod, dbh); + + if (res->resource_count == 0) { + comp_err(mod->dev, "More resources freed than allocated."); + return -EINVAL; + } + comp_data_blob_handler_free(dbh); + res->resource_count--; + return 0; } EXPORT_SYMBOL(mod_data_blob_handler_free); #endif #if CONFIG_FAST_GET -void mod_fast_put(struct processing_module *mod, const void *sram_ptr) +int mod_fast_put(struct processing_module *mod, const void *sram_ptr) { struct module_resources *res = &mod->priv.resources; - if (!res->tracking_enabled) { - if (res->resource_count == 0) { - comp_err(mod->dev, "More resources freed than allocated."); - return; - } - fast_put(sram_ptr); - res->resource_count--; - return; - } + MEM_API_CHECK_THREAD(res); + + if (!sram_ptr) + return 0; + + if (res->tracking_enabled) + return free_tracked_resource(mod, sram_ptr); - mod_free(mod, sram_ptr); + if (res->resource_count == 0) { + comp_err(mod->dev, "More resources freed than allocated."); + return -EINVAL; + } + fast_put(sram_ptr); + res->resource_count--; + return 0; } EXPORT_SYMBOL(mod_fast_put); #endif diff --git a/src/include/sof/audio/module_adapter/module/generic.h b/src/include/sof/audio/module_adapter/module/generic.h index 3f07abf2d0dc..6d82ac6fceb7 100644 --- a/src/include/sof/audio/module_adapter/module/generic.h +++ b/src/include/sof/audio/module_adapter/module/generic.h @@ -213,14 +213,14 @@ static inline void *mod_zalloc(struct processing_module *mod, size_t size) return ret; } -int mod_free(struct processing_module *mod, const void *ptr); +int mod_free(struct processing_module *mod, void *ptr); #if CONFIG_COMP_BLOB struct comp_data_blob_handler *mod_data_blob_handler_new(struct processing_module *mod); -void mod_data_blob_handler_free(struct processing_module *mod, struct comp_data_blob_handler *dbh); +int mod_data_blob_handler_free(struct processing_module *mod, struct comp_data_blob_handler *dbh); #endif #if CONFIG_FAST_GET const void *mod_fast_get(struct processing_module *mod, const void * const dram_ptr, size_t size); -void mod_fast_put(struct processing_module *mod, const void *sram_ptr); +int mod_fast_put(struct processing_module *mod, const void *sram_ptr); #endif void mod_free_all(struct processing_module *mod); int module_prepare(struct processing_module *mod, From 8c85580984746b9f96f67fa3edf2742fff8b0e52 Mon Sep 17 00:00:00 2001 From: Jyri Sarha Date: Tue, 4 Nov 2025 01:06:26 +0200 Subject: [PATCH 08/10] module api: Make resource tracking optional and enable it in requiring modules --- src/audio/codec/dts/dts.c | 1 + src/audio/module_adapter/module/cadence.c | 2 ++ src/audio/module_adapter/module/generic.c | 1 - src/audio/module_adapter/module/waves/waves.c | 1 + src/audio/src/src_ipc3.c | 1 + src/audio/src/src_ipc4.c | 1 + 6 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/audio/codec/dts/dts.c b/src/audio/codec/dts/dts.c index 0bc590017004..532537f80dda 100644 --- a/src/audio/codec/dts/dts.c +++ b/src/audio/codec/dts/dts.c @@ -142,6 +142,7 @@ static int dts_codec_init(struct processing_module *mod) DtsSofInterfaceVersionInfo sdk_version; comp_dbg(dev, "dts_codec_init() start"); + mod_resource_init(mod); dts_result = dtsSofInterfaceInit((DtsSofInterfaceInst **)&(codec->private), dts_effect_allocate_codec_memory, dts_effect_free_codec_memory, mod); diff --git a/src/audio/module_adapter/module/cadence.c b/src/audio/module_adapter/module/cadence.c index 05717eab6932..10df4913e7e3 100644 --- a/src/audio/module_adapter/module/cadence.c +++ b/src/audio/module_adapter/module/cadence.c @@ -267,6 +267,7 @@ static int cadence_codec_init(struct processing_module *mod) int ret; comp_dbg(dev, "cadence_codec_init() start"); + mod_resource_init(mod); cd = rzalloc(SOF_MEM_FLAG_USER, sizeof(struct cadence_codec_data)); if (!cd) { @@ -344,6 +345,7 @@ static int cadence_codec_init(struct processing_module *mod) int ret; comp_dbg(dev, "cadence_codec_init() start"); + mod_resource_init(mod); cd = rzalloc(SOF_MEM_FLAG_USER, sizeof(struct cadence_codec_data)); if (!cd) { diff --git a/src/audio/module_adapter/module/generic.c b/src/audio/module_adapter/module/generic.c index 969a47f67cb3..b088c867a895 100644 --- a/src/audio/module_adapter/module/generic.c +++ b/src/audio/module_adapter/module/generic.c @@ -129,7 +129,6 @@ int module_init(struct processing_module *mod) return -EIO; } - mod_resource_init(mod); #if CONFIG_MODULE_MEMORY_API_DEBUG && defined(__ZEPHYR__) mod->priv.resources.rsrc_mngr = k_current_get(); #endif diff --git a/src/audio/module_adapter/module/waves/waves.c b/src/audio/module_adapter/module/waves/waves.c index 624b53f5f75c..d931522946f6 100644 --- a/src/audio/module_adapter/module/waves/waves.c +++ b/src/audio/module_adapter/module/waves/waves.c @@ -667,6 +667,7 @@ static int waves_codec_init(struct processing_module *mod) void *response = NULL; comp_dbg(dev, "waves_codec_init() start"); + mod_resource_init(mod); waves_codec = mod_alloc_align(mod, sizeof(struct waves_codec_data), 16); if (!waves_codec) { diff --git a/src/audio/src/src_ipc3.c b/src/audio/src/src_ipc3.c index b161155193fc..a4b7632bc94e 100644 --- a/src/audio/src/src_ipc3.c +++ b/src/audio/src/src_ipc3.c @@ -159,6 +159,7 @@ int src_init(struct processing_module *mod) struct comp_data *cd = NULL; comp_dbg(dev, "entry"); + mod_resource_init(mod); if (dev->ipc_config.type != SOF_COMP_SRC) { comp_err(dev, "Wrong IPC config type %u", diff --git a/src/audio/src/src_ipc4.c b/src/audio/src/src_ipc4.c index 1240a86bd48e..8f5fb0110cf9 100644 --- a/src/audio/src/src_ipc4.c +++ b/src/audio/src/src_ipc4.c @@ -196,6 +196,7 @@ __cold int src_init(struct processing_module *mod) assert_can_be_cold(); comp_dbg(dev, "entry"); + mod_resource_init(mod); if (!cfg->init_data || cfg->size != sizeof(cd->ipc_config)) { comp_err(dev, "Missing or bad size (%u) init data", From fcb7693be304242885dc6a429cfadb89308b3a73 Mon Sep 17 00:00:00 2001 From: Jyri Sarha Date: Tue, 4 Nov 2025 12:00:44 +0200 Subject: [PATCH 09/10] src/audio/module_adapter/module_adapter.c: Crash on resource leak --- src/audio/module_adapter/module_adapter.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/audio/module_adapter/module_adapter.c b/src/audio/module_adapter/module_adapter.c index 356d42be87c3..5e33bfd4cb21 100644 --- a/src/audio/module_adapter/module_adapter.c +++ b/src/audio/module_adapter/module_adapter.c @@ -1280,10 +1280,12 @@ void module_adapter_free(struct comp_dev *dev) buffer_free(buffer); } - if (mod->priv.resources.tracking_enabled) + if (mod->priv.resources.tracking_enabled) { mod_free_all(mod); - else if (mod->priv.resources.resource_count) + } else if (mod->priv.resources.resource_count) { comp_err(dev, "%u unfreed resources leaked", mod->priv.resources.resource_count); + __ASSERT(0, "unfreed resources leaked"); + } #if CONFIG_IPC_MAJOR_4 rfree(mod->priv.cfg.input_pins); From 7036e9f2d39d7a280fc69ebfe7ab23ccc94b3b3d Mon Sep 17 00:00:00 2001 From: Jyri Sarha Date: Thu, 6 Nov 2025 11:48:33 +0200 Subject: [PATCH 10/10] SQUASH module api: Make resource tracking optional --- src/audio/module_adapter/module/generic.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/audio/module_adapter/module/generic.c b/src/audio/module_adapter/module/generic.c index b088c867a895..c17f3db358ce 100644 --- a/src/audio/module_adapter/module/generic.c +++ b/src/audio/module_adapter/module/generic.c @@ -446,8 +446,6 @@ static int free_tracked_resource(struct processing_module *mod, const void *ptr) int mod_free(struct processing_module *mod, void *ptr) { struct module_resources *res = &mod->priv.resources; - struct module_resource *container; - struct list_item *res_list; MEM_API_CHECK_THREAD(res);