copier: handle an allocation failure correctly

Buffer allocation can fail, return an error instead of dereferencing
a NULL pointer.

Signed-off-by: Guennadi Liakhovetski <guennadi.liakhovetski@linux.intel.com>
This commit is contained in:
Guennadi Liakhovetski 2022-09-07 11:09:24 +02:00 committed by Liam Girdwood
parent b1c514d6cd
commit b17a467c7d
1 changed files with 48 additions and 25 deletions

View File

@ -52,7 +52,7 @@ static pcm_converter_func get_converter_func(struct ipc4_audio_format *in_fmt,
enum ipc4_gateway_type type, enum ipc4_gateway_type type,
enum ipc4_direction_type); enum ipc4_direction_type);
static void create_endpoint_buffer(struct comp_dev *parent_dev, static int create_endpoint_buffer(struct comp_dev *parent_dev,
struct copier_data *cd, struct copier_data *cd,
struct comp_ipc_config *config, struct comp_ipc_config *config,
struct ipc4_copier_module_cfg *copier_cfg, struct ipc4_copier_module_cfg *copier_cfg,
@ -63,6 +63,7 @@ static void create_endpoint_buffer(struct comp_dev *parent_dev,
enum sof_ipc_frame __sparse_cache in_valid_fmt, out_valid_fmt; enum sof_ipc_frame __sparse_cache in_valid_fmt, out_valid_fmt;
enum sof_ipc_frame valid_fmt; enum sof_ipc_frame valid_fmt;
struct sof_ipc_buffer ipc_buf; struct sof_ipc_buffer ipc_buf;
struct comp_buffer *buffer;
uint32_t buf_size; uint32_t buf_size;
uint32_t mask; uint32_t mask;
int i; int i;
@ -128,16 +129,16 @@ static void create_endpoint_buffer(struct comp_dev *parent_dev,
ipc_buf.size = buf_size; ipc_buf.size = buf_size;
ipc_buf.comp.pipeline_id = config->pipeline_id; ipc_buf.comp.pipeline_id = config->pipeline_id;
ipc_buf.comp.core = config->core; ipc_buf.comp.core = config->core;
cd->endpoint_buffer[cd->endpoint_num] = buffer_new(&ipc_buf);
cd->endpoint_buffer[cd->endpoint_num]->stream.channels = buffer = buffer_new(&ipc_buf);
copier_cfg->base.audio_fmt.channels_count; if (!buffer)
cd->endpoint_buffer[cd->endpoint_num]->stream.rate = return -ENOMEM;
copier_cfg->base.audio_fmt.sampling_frequency;
cd->endpoint_buffer[cd->endpoint_num]->stream.frame_fmt = config->frame_fmt; buffer->stream.channels = copier_cfg->base.audio_fmt.channels_count;
cd->endpoint_buffer[cd->endpoint_num]->stream.valid_sample_fmt = valid_fmt; buffer->stream.rate = copier_cfg->base.audio_fmt.sampling_frequency;
cd->endpoint_buffer[cd->endpoint_num]->buffer_fmt = buffer->stream.frame_fmt = config->frame_fmt;
copier_cfg->base.audio_fmt.interleaving_style; buffer->stream.valid_sample_fmt = valid_fmt;
buffer->buffer_fmt = copier_cfg->base.audio_fmt.interleaving_style;
if (type == ipc4_gtw_alh) { if (type == ipc4_gtw_alh) {
struct sof_alh_configuration_blob *alh_blob; struct sof_alh_configuration_blob *alh_blob;
@ -150,9 +151,13 @@ static void create_endpoint_buffer(struct comp_dev *parent_dev,
} }
for (i = 0; i < SOF_IPC_MAX_CHANNELS; i++) for (i = 0; i < SOF_IPC_MAX_CHANNELS; i++)
cd->endpoint_buffer[cd->endpoint_num]->chmap[i] = (mask >> i * 4) & 0xf; buffer->chmap[i] = (mask >> i * 4) & 0xf;
cd->endpoint_buffer[cd->endpoint_num]->hw_params_configured = true; buffer->hw_params_configured = true;
cd->endpoint_buffer[cd->endpoint_num] = buffer;
return 0;
} }
/* if copier is linked to host gateway, it will manage host dma. /* if copier is linked to host gateway, it will manage host dma.
@ -169,6 +174,7 @@ static int create_host(struct comp_dev *parent_dev, struct copier_data *cd,
struct ipc_config_host ipc_host; struct ipc_config_host ipc_host;
const struct comp_driver *drv; const struct comp_driver *drv;
struct comp_dev *dev; struct comp_dev *dev;
int ret;
drv = ipc4_get_drv((uint8_t *)&host); drv = ipc4_get_drv((uint8_t *)&host);
if (!drv) if (!drv)
@ -176,15 +182,19 @@ static int create_host(struct comp_dev *parent_dev, struct copier_data *cd,
config->type = SOF_COMP_HOST; config->type = SOF_COMP_HOST;
create_endpoint_buffer(parent_dev, cd, config, copier_cfg, ipc4_gtw_host, 0); ret = create_endpoint_buffer(parent_dev, cd, config, copier_cfg, ipc4_gtw_host, 0);
if (ret < 0)
return ret;
memset(&ipc_host, 0, sizeof(ipc_host)); memset(&ipc_host, 0, sizeof(ipc_host));
ipc_host.direction = dir; ipc_host.direction = dir;
ipc_host.dma_buffer_size = copier_cfg->gtw_cfg.dma_buffer_size; ipc_host.dma_buffer_size = copier_cfg->gtw_cfg.dma_buffer_size;
dev = drv->ops.create(drv, config, &ipc_host); dev = drv->ops.create(drv, config, &ipc_host);
if (!dev) if (!dev) {
return -EINVAL; ret = -EINVAL;
goto e_buf;
}
list_init(&dev->bsource_list); list_init(&dev->bsource_list);
list_init(&dev->bsink_list); list_init(&dev->bsink_list);
@ -205,12 +215,17 @@ static int create_host(struct comp_dev *parent_dev, struct copier_data *cd,
ipc4_gtw_host, IPC4_DIRECTION(dir)); ipc4_gtw_host, IPC4_DIRECTION(dir));
if (!cd->converter[IPC4_COPIER_GATEWAY_PIN]) { if (!cd->converter[IPC4_COPIER_GATEWAY_PIN]) {
comp_err(parent_dev, "failed to get converter for host, dir %d", dir); comp_err(parent_dev, "failed to get converter for host, dir %d", dir);
return -EINVAL; ret = -EINVAL;
goto e_buf;
} }
cd->endpoint[cd->endpoint_num++] = dev; cd->endpoint[cd->endpoint_num++] = dev;
return 0; return 0;
e_buf:
buffer_free(cd->endpoint_buffer[cd->endpoint_num]);
return ret;
} }
static int init_dai(struct comp_dev *parent_dev, static int init_dai(struct comp_dev *parent_dev,
@ -227,11 +242,15 @@ static int init_dai(struct comp_dev *parent_dev,
int ret; int ret;
cd = comp_get_drvdata(parent_dev); cd = comp_get_drvdata(parent_dev);
create_endpoint_buffer(parent_dev, cd, config, copier, type, index); ret = create_endpoint_buffer(parent_dev, cd, config, copier, type, index);
if (ret < 0)
return ret;
dev = drv->ops.create(drv, config, dai); dev = drv->ops.create(drv, config, dai);
if (!dev) if (!dev) {
return -EINVAL; ret = -EINVAL;
goto e_buf;
}
if (dai->direction == SOF_IPC_STREAM_PLAYBACK) if (dai->direction == SOF_IPC_STREAM_PLAYBACK)
pipeline->sink_comp = dev; pipeline->sink_comp = dev;
@ -245,7 +264,7 @@ static int init_dai(struct comp_dev *parent_dev,
ret = comp_dai_config(dev, dai, copier); ret = comp_dai_config(dev, dai, copier);
if (ret < 0) if (ret < 0)
return ret; goto e_buf;
if (dai->direction == SOF_IPC_STREAM_PLAYBACK) { if (dai->direction == SOF_IPC_STREAM_PLAYBACK) {
comp_buffer_connect(dev, config->core, cd->endpoint_buffer[cd->endpoint_num], comp_buffer_connect(dev, config->core, cd->endpoint_buffer[cd->endpoint_num],
@ -269,6 +288,10 @@ static int init_dai(struct comp_dev *parent_dev,
cd->endpoint[cd->endpoint_num++] = dev; cd->endpoint[cd->endpoint_num++] = dev;
return 0; return 0;
e_buf:
buffer_free(cd->endpoint_buffer[cd->endpoint_num]);
return ret;
} }
/* if copier is linked to non-host gateway, it will manage link dma, /* if copier is linked to non-host gateway, it will manage link dma,