Skip to content

Commit 2ca80d4

Browse files
committed
module: cadence / ipc4: Fix memory leak of notification IPC message
Each notification that that is sent by the module could cause a memory leak in theory. Notification is only sent in case of DRAIN or EOL and multiple notification sending will be blocked by the eos_notification_sent flag. Since pipelines cannot recover from EOS state, this is theoretical until that is fixed, but it is a bug in the code never the less. Follow the example of other modules and store and allocate the notification message for the lifetime of the module to manage the allocation properly. Fixes: f6cfc4c ("module: cadence / ipc4: Support for EOS handling and notification to host") Reported-by: Jyri Sarha <jyri.sarha@linux.intel.com> Signed-off-by: Peter Ujfalusi <peter.ujfalusi@linux.intel.com>
1 parent c351193 commit 2ca80d4

2 files changed

Lines changed: 53 additions & 26 deletions

File tree

src/audio/module_adapter/module/cadence_ipc4.c

Lines changed: 50 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -217,6 +217,32 @@ static int cadence_configure_codec_params(struct processing_module *mod)
217217
return -EINVAL;
218218
}
219219

220+
static struct ipc_msg *cadence_codec_notification_init(struct processing_module *mod)
221+
{
222+
struct comp_dev *dev = mod->dev;
223+
struct comp_ipc_config *ipc_config = &dev->ipc_config;
224+
struct sof_ipc4_notify_module_data *msg_module_data;
225+
union ipc4_notification_header primary;
226+
struct ipc_msg *msg;
227+
228+
primary.dat = 0;
229+
primary.r.notif_type = SOF_IPC4_MODULE_NOTIFICATION;
230+
primary.r.type = SOF_IPC4_GLB_NOTIFICATION;
231+
primary.r.rsp = SOF_IPC4_MESSAGE_DIR_MSG_REQUEST;
232+
primary.r.msg_tgt = SOF_IPC4_MESSAGE_TARGET_FW_GEN_MSG;
233+
msg = ipc_msg_w_ext_init(primary.dat, 0, sizeof(*msg_module_data));
234+
if (!msg)
235+
return NULL;
236+
237+
msg_module_data = (struct sof_ipc4_notify_module_data *)msg->tx_data;
238+
msg_module_data->instance_id = IPC4_INST_ID(ipc_config->id);
239+
msg_module_data->module_id = IPC4_MOD_ID(ipc_config->id);
240+
msg_module_data->event_id = SOF_IPC4_NOTIFY_MODULE_EVENTID_COMPR_MAGIC_VAL;
241+
msg_module_data->event_data_size = 0;
242+
243+
return msg;
244+
}
245+
220246
static int cadence_codec_init(struct processing_module *mod)
221247
{
222248
struct module_data *codec = &mod->priv;
@@ -237,6 +263,13 @@ static int cadence_codec_init(struct processing_module *mod)
237263
}
238264

239265
codec->private = cd;
266+
cd->msg = cadence_codec_notification_init(mod);
267+
if (!cd->msg) {
268+
comp_err(dev, "failed to allocate IPC notification template");
269+
ret = -ENOMEM;
270+
goto free_cd;
271+
}
272+
240273
memcpy_s(&cd->base_cfg, sizeof(cd->base_cfg), &cfg->base_cfg, sizeof(cd->base_cfg));
241274

242275
codec->mpd.init_done = 0;
@@ -253,7 +286,7 @@ static int cadence_codec_init(struct processing_module *mod)
253286
if (!setup_cfg->data) {
254287
comp_err(dev, "failed to alloc setup config");
255288
ret = -ENOMEM;
256-
goto free_cd;
289+
goto free_notification;
257290
}
258291

259292
setup_cfg->size = size;
@@ -315,6 +348,8 @@ static int cadence_codec_init(struct processing_module *mod)
315348
free_cfg:
316349
if (setup_cfg)
317350
mod_free(mod, setup_cfg->data);
351+
free_notification:
352+
ipc_msg_free(cd->msg);
318353
free_cd:
319354
mod_free(mod, cd);
320355

@@ -472,30 +507,10 @@ static int cadence_codec_process(struct processing_module *mod, struct sof_sourc
472507
}
473508

474509
if (codec->mpd.eos_reached && !codec->mpd.eos_notification_sent) {
475-
struct ipc_msg msg_proto;
476-
struct comp_ipc_config *ipc_config = &dev->ipc_config;
477-
union ipc4_notification_header *primary =
478-
(union ipc4_notification_header *)&msg_proto.header;
479-
struct sof_ipc4_notify_module_data *msg_module_data;
480-
struct ipc_msg *msg;
481-
482-
memset_s(&msg_proto, sizeof(msg_proto), 0, sizeof(msg_proto));
483-
primary->r.notif_type = SOF_IPC4_MODULE_NOTIFICATION;
484-
primary->r.type = SOF_IPC4_GLB_NOTIFICATION;
485-
primary->r.rsp = SOF_IPC4_MESSAGE_DIR_MSG_REQUEST;
486-
primary->r.msg_tgt = SOF_IPC4_MESSAGE_TARGET_FW_GEN_MSG;
487-
msg = ipc_msg_w_ext_init(msg_proto.header, msg_proto.extension,
488-
sizeof(*msg_module_data));
489-
if (msg) {
490-
msg_module_data = (struct sof_ipc4_notify_module_data *)msg->tx_data;
491-
msg_module_data->instance_id = IPC4_INST_ID(ipc_config->id);
492-
msg_module_data->module_id = IPC4_MOD_ID(ipc_config->id);
493-
msg_module_data->event_id = SOF_IPC4_NOTIFY_MODULE_EVENTID_COMPR_MAGIC_VAL;
494-
msg_module_data->event_data_size = 0;
495-
496-
ipc_msg_send(msg, NULL, false);
497-
codec->mpd.eos_notification_sent = true;
498-
}
510+
struct cadence_codec_data *cd = module_get_private_data(mod);
511+
512+
ipc_msg_send(cd->msg, NULL, false);
513+
codec->mpd.eos_notification_sent = true;
499514

500515
/* Set EOS for the sink as we are not going to produce more data */
501516
audio_buffer_set_eos(sof_audio_buffer_from_sink(sinks[0]));
@@ -568,13 +583,22 @@ static bool cadence_is_ready_to_process(struct processing_module *mod,
568583
return true;
569584
}
570585

586+
static int ipc4_cadence_codec_free(struct processing_module *mod)
587+
{
588+
struct cadence_codec_data *cd = module_get_private_data(mod);
589+
590+
ipc_msg_free(cd->msg);
591+
592+
return cadence_codec_free(mod);
593+
}
594+
571595
static const struct module_interface cadence_codec_interface = {
572596
.init = cadence_codec_init,
573597
.prepare = cadence_codec_prepare,
574598
.process = cadence_codec_process,
575599
.set_configuration = cadence_codec_set_configuration,
576600
.reset = cadence_codec_reset,
577-
.free = cadence_codec_free,
601+
.free = ipc4_cadence_codec_free,
578602
.is_ready_to_process = cadence_is_ready_to_process,
579603
};
580604

src/include/sof/audio/module_adapter/module/cadence.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,10 +51,13 @@ struct cadence_api {
5151
xa_codec_func_t *api;
5252
};
5353

54+
struct ipc_msg;
55+
5456
struct cadence_codec_data {
5557
#if CONFIG_IPC_MAJOR_4
5658
struct ipc4_base_module_cfg base_cfg;
5759
uint32_t direction;
60+
struct ipc_msg *msg;
5861
#endif
5962
char name[LIB_NAME_MAX_LEN];
6063
void *self;

0 commit comments

Comments
 (0)