From 2a368acd0bed051f56441f54bb5fd8bb9686e884 Mon Sep 17 00:00:00 2001 From: Laurentiu Mihalcea Date: Tue, 28 Nov 2023 14:21:07 +0200 Subject: [PATCH] audio: host-zephyr: Allocate DMA block configuration on heap Currently, the DMA block configuration (struct dma_block_config) is placed on the stack during host_common_params(). Later on, host_copy_one_shot() tries to re-configure the DMAC driver using the same block configuration that's located in a stack frame that's no longer valid. As such, allocate a DMA block configuration on the heap during host_common_params() which can be used later on (e.g: during host_copy_one_shot()) to reconfigure the DMAC. Signed-off-by: Laurentiu Mihalcea --- src/audio/host-zephyr.c | 25 +++++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/src/audio/host-zephyr.c b/src/audio/host-zephyr.c index fd629838aba0..23a6ef10e5de 100644 --- a/src/audio/host-zephyr.c +++ b/src/audio/host-zephyr.c @@ -736,7 +736,7 @@ int host_common_params(struct host_data *hd, struct comp_dev *dev, struct dma_sg_config *config = &hd->config; struct dma_sg_elem *sg_elem; struct dma_config *dma_cfg = &hd->z_config; - struct dma_block_config dma_block_cfg; + struct dma_block_config *dma_block_cfg; uint32_t period_count; uint32_t period_bytes; uint32_t buffer_size; @@ -890,12 +890,20 @@ int host_common_params(struct host_data *hd, struct comp_dev *dev, hd->chan->period = config->period; memset(dma_cfg, 0, sizeof(*dma_cfg)); - memset(&dma_block_cfg, 0, sizeof(dma_block_cfg)); + + dma_block_cfg = rzalloc(SOF_MEM_ZONE_RUNTIME, 0, + SOF_MEM_CAPS_RAM, + sizeof(*dma_block_cfg)); + + if (!dma_block_cfg) { + comp_err(dev, "host_common_params: dma_block_config allocation failed"); + return -ENOMEM; + } dma_cfg->block_count = 1; dma_cfg->source_data_size = config->src_width; dma_cfg->dest_data_size = config->dest_width; - dma_cfg->head_block = &dma_block_cfg; + dma_cfg->head_block = dma_block_cfg; for (i = 0; i < config->elem_array.count; i++) { sg_elem = config->elem_array.elems + i; @@ -912,16 +920,16 @@ int host_common_params(struct host_data *hd, struct comp_dev *dev, buffer_addr = addr; } - dma_block_cfg.block_size = buffer_bytes; + dma_block_cfg->block_size = buffer_bytes; switch (config->direction) { case DMA_DIR_LMEM_TO_HMEM: dma_cfg->channel_direction = MEMORY_TO_HOST; - dma_block_cfg.source_address = buffer_addr; + dma_block_cfg->source_address = buffer_addr; break; case DMA_DIR_HMEM_TO_LMEM: dma_cfg->channel_direction = HOST_TO_MEMORY; - dma_block_cfg.dest_address = buffer_addr; + dma_block_cfg->dest_address = buffer_addr; break; } @@ -929,6 +937,7 @@ int host_common_params(struct host_data *hd, struct comp_dev *dev, if (err < 0) { comp_err(dev, "host_params(): dma_config() failed"); dma_release_channel(hd->dma->z_dev, hd->chan->index); + rfree(dma_block_cfg); hd->chan = NULL; return err; } @@ -938,6 +947,7 @@ int host_common_params(struct host_data *hd, struct comp_dev *dev, if (err < 0) { comp_err(dev, "host_params(): dma_get_attribute()"); + rfree(dma_block_cfg); return err; } @@ -1024,6 +1034,9 @@ void host_common_reset(struct host_data *hd, uint16_t state) hd->dma_buffer = NULL; } + /* free DMA block configuration */ + rfree(hd->z_config.head_block); + /* reset buffer pointers */ hd->local_pos = 0; hd->report_pos = 0;