Skip to content

Commit b5f3faf

Browse files
ujfalusilgirdwood
authored andcommitted
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 17c5a3b commit b5f3faf

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;
@@ -263,7 +296,7 @@ static int cadence_codec_init(struct processing_module *mod)
263296
if (!setup_cfg->data) {
264297
comp_err(dev, "failed to alloc setup config");
265298
ret = -ENOMEM;
266-
goto free_cd;
299+
goto free_notification;
267300
}
268301

269302
setup_cfg->size = size;
@@ -329,6 +362,8 @@ static int cadence_codec_init(struct processing_module *mod)
329362
free_cfg:
330363
if (setup_cfg)
331364
mod_free(mod, setup_cfg->data);
365+
free_notification:
366+
ipc_msg_free(cd->msg);
332367
free_cd:
333368
mod_free(mod, cd);
334369

@@ -466,30 +501,10 @@ static int cadence_codec_process(struct processing_module *mod, struct sof_sourc
466501
}
467502

468503
if (codec->mpd.eos_reached && !codec->mpd.eos_notification_sent) {
469-
struct ipc_msg msg_proto;
470-
struct comp_ipc_config *ipc_config = &dev->ipc_config;
471-
union ipc4_notification_header *primary =
472-
(union ipc4_notification_header *)&msg_proto.header;
473-
struct sof_ipc4_notify_module_data *msg_module_data;
474-
struct ipc_msg *msg;
475-
476-
memset_s(&msg_proto, sizeof(msg_proto), 0, sizeof(msg_proto));
477-
primary->r.notif_type = SOF_IPC4_MODULE_NOTIFICATION;
478-
primary->r.type = SOF_IPC4_GLB_NOTIFICATION;
479-
primary->r.rsp = SOF_IPC4_MESSAGE_DIR_MSG_REQUEST;
480-
primary->r.msg_tgt = SOF_IPC4_MESSAGE_TARGET_FW_GEN_MSG;
481-
msg = ipc_msg_w_ext_init(msg_proto.header, msg_proto.extension,
482-
sizeof(*msg_module_data));
483-
if (msg) {
484-
msg_module_data = (struct sof_ipc4_notify_module_data *)msg->tx_data;
485-
msg_module_data->instance_id = IPC4_INST_ID(ipc_config->id);
486-
msg_module_data->module_id = IPC4_MOD_ID(ipc_config->id);
487-
msg_module_data->event_id = SOF_IPC4_NOTIFY_MODULE_EVENTID_COMPR_MAGIC_VAL;
488-
msg_module_data->event_data_size = 0;
489-
490-
ipc_msg_send(msg, NULL, false);
491-
codec->mpd.eos_notification_sent = true;
492-
}
504+
struct cadence_codec_data *cd = module_get_private_data(mod);
505+
506+
ipc_msg_send(cd->msg, NULL, false);
507+
codec->mpd.eos_notification_sent = true;
493508

494509
/* Set EOS for the sink as we are not going to produce more data */
495510
audio_buffer_set_eos(sof_audio_buffer_from_sink(sinks[0]));
@@ -546,13 +561,22 @@ static bool cadence_is_ready_to_process(struct processing_module *mod,
546561
return true;
547562
}
548563

564+
static int ipc4_cadence_codec_free(struct processing_module *mod)
565+
{
566+
struct cadence_codec_data *cd = module_get_private_data(mod);
567+
568+
ipc_msg_free(cd->msg);
569+
570+
return cadence_codec_free(mod);
571+
}
572+
549573
static const struct module_interface cadence_codec_interface = {
550574
.init = cadence_codec_init,
551575
.prepare = cadence_codec_prepare,
552576
.process = cadence_codec_process,
553577
.set_configuration = cadence_codec_set_configuration,
554578
.reset = cadence_codec_reset,
555-
.free = cadence_codec_free,
579+
.free = ipc4_cadence_codec_free,
556580
.is_ready_to_process = cadence_is_ready_to_process,
557581
};
558582

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)