diff --git a/src/audio/dai-zephyr.c b/src/audio/dai-zephyr.c index 454132de150e..00401e028357 100644 --- a/src/audio/dai-zephyr.c +++ b/src/audio/dai-zephyr.c @@ -23,6 +23,7 @@ #include #include #include +#include /* zephyr_ll_user_heap() */ #include #include #include @@ -529,6 +530,17 @@ __cold int dai_common_new(struct dai_data *dd, struct comp_dev *dev, dma_sg_init(&dd->config.elem_array); dd->xrun = 0; +#ifdef CONFIG_SOF_USERSPACE_LL + /* + * copier_dai_create() uses mod_zalloc() to allocate + * the 'dd' dai data object and does not set dd->alloc_ctx. + * If LL is run in user-space, assign the 'heap' here. + */ + dd->alloc_ctx.heap = zephyr_ll_user_heap(); +#else + dd->alloc_ctx.heap = NULL; +#endif + /* I/O performance init, keep it last so the function does not reach this in case * of return on error, so that we do not waste a slot */ @@ -581,6 +593,7 @@ __cold static struct comp_dev *dai_new(const struct comp_driver *drv, struct comp_dev *dev; const struct ipc_config_dai *dai_cfg = spec; struct dai_data *dd; + struct k_heap *heap = NULL; int ret; assert_can_be_cold(); @@ -593,10 +606,12 @@ __cold static struct comp_dev *dai_new(const struct comp_driver *drv, dev->ipc_config = *config; - dd = rzalloc(SOF_MEM_FLAG_USER | SOF_MEM_FLAG_COHERENT, sizeof(*dd)); + dd = sof_heap_alloc(heap, SOF_MEM_FLAG_USER | SOF_MEM_FLAG_COHERENT, sizeof(*dd), 0); if (!dd) goto e_data; + memset(dd, 0, sizeof(*dd)); + comp_set_drvdata(dev, dd); ret = dai_common_new(dd, dev, dai_cfg); @@ -610,7 +625,7 @@ __cold static struct comp_dev *dai_new(const struct comp_driver *drv, return dev; error: - rfree(dd); + sof_heap_free(heap, dd); e_data: comp_free_device(dev); return NULL; @@ -638,7 +653,7 @@ __cold void dai_common_free(struct dai_data *dd) dai_put(dd->dai); - rfree(dd->dai_spec_config); + sof_heap_free(dd->alloc_ctx.heap, dd->dai_spec_config); } __cold static void dai_free(struct comp_dev *dev) @@ -652,7 +667,8 @@ __cold static void dai_free(struct comp_dev *dev) dai_common_free(dd); - rfree(dd); + /* heap is NULL to match what is passed in dai_new() */ + sof_heap_free(NULL, dd); comp_free_device(dev); } @@ -847,7 +863,7 @@ static int dai_set_sg_config(struct dai_data *dd, struct comp_dev *dev, uint32_t } while (--max_block_count > 0); } - err = dma_sg_alloc(NULL, &config->elem_array, SOF_MEM_FLAG_USER, + err = dma_sg_alloc(dd->alloc_ctx.heap, &config->elem_array, SOF_MEM_FLAG_USER, config->direction, period_count, period_bytes, @@ -873,8 +889,9 @@ static int dai_set_dma_config(struct dai_data *dd, struct comp_dev *dev) comp_dbg(dev, "entry"); - dma_cfg = rmalloc(SOF_MEM_FLAG_USER | SOF_MEM_FLAG_COHERENT | SOF_MEM_FLAG_DMA, - sizeof(struct dma_config)); + dma_cfg = sof_heap_alloc(dd->alloc_ctx.heap, + SOF_MEM_FLAG_USER | SOF_MEM_FLAG_COHERENT | SOF_MEM_FLAG_DMA, + sizeof(struct dma_config), 0); if (!dma_cfg) { comp_err(dev, "dma_cfg allocation failed"); return -ENOMEM; @@ -903,10 +920,11 @@ static int dai_set_dma_config(struct dai_data *dd, struct comp_dev *dev) else dma_cfg->dma_slot = config->src_dev; - dma_block_cfg = rballoc(SOF_MEM_FLAG_USER | SOF_MEM_FLAG_COHERENT | SOF_MEM_FLAG_DMA, - sizeof(struct dma_block_config) * dma_cfg->block_count); + dma_block_cfg = sof_heap_alloc(dd->alloc_ctx.heap, + SOF_MEM_FLAG_USER | SOF_MEM_FLAG_COHERENT | SOF_MEM_FLAG_DMA, + sizeof(struct dma_block_config) * dma_cfg->block_count, 0); if (!dma_block_cfg) { - rfree(dma_cfg); + sof_heap_free(dd->alloc_ctx.heap, dma_cfg); comp_err(dev, "dma_block_config allocation failed"); return -ENOMEM; } @@ -1040,7 +1058,7 @@ static int dai_set_dma_buffer(struct dai_data *dd, struct comp_dev *dev, return err; } } else { - dd->dma_buffer = buffer_alloc_range(NULL, buffer_size_preferred, buffer_size, + dd->dma_buffer = buffer_alloc_range(&dd->alloc_ctx, buffer_size_preferred, buffer_size, SOF_MEM_FLAG_USER | SOF_MEM_FLAG_DMA, addr_align, BUFFER_USAGE_NOT_SHARED); if (!dd->dma_buffer) { @@ -1128,8 +1146,8 @@ int dai_common_params(struct dai_data *dd, struct comp_dev *dev, if (err < 0) { buffer_free(dd->dma_buffer); dd->dma_buffer = NULL; - dma_sg_free(NULL, &config->elem_array); - rfree(dd->z_config); + dma_sg_free(dd->alloc_ctx.heap, &config->elem_array); + sof_heap_free(dd->alloc_ctx.heap, dd->z_config); dd->z_config = NULL; } @@ -1255,10 +1273,10 @@ void dai_common_reset(struct dai_data *dd, struct comp_dev *dev) if (!dd->delayed_dma_stop) dai_dma_release(dd, dev); - dma_sg_free(NULL, &config->elem_array); + dma_sg_free(dd->alloc_ctx.heap, &config->elem_array); if (dd->z_config) { - rfree(dd->z_config->head_block); - rfree(dd->z_config); + sof_heap_free(dd->alloc_ctx.heap, dd->z_config->head_block); + sof_heap_free(dd->alloc_ctx.heap, dd->z_config); dd->z_config = NULL; } diff --git a/src/include/sof/audio/component.h b/src/include/sof/audio/component.h index 7fc9feb53736..fed83de58374 100644 --- a/src/include/sof/audio/component.h +++ b/src/include/sof/audio/component.h @@ -23,7 +23,6 @@ #include #include #include -#include #include #include #include @@ -37,6 +36,16 @@ struct dai_hw_params; struct timestamp_data; struct dai_ts_data; +struct k_heap; +struct vregion; +struct mod_alloc_ctx { + struct k_heap *heap; + struct vregion *vreg; +}; + +/* dai.h requires definition for mod_alloc_ctx */ +#include + /** \addtogroup component_api Component API * @{ */ @@ -579,13 +588,6 @@ struct comp_ops { uint64_t (*get_total_data_processed)(struct comp_dev *dev, uint32_t stream_no, bool input); }; -struct k_heap; -struct vregion; -struct mod_alloc_ctx { - struct k_heap *heap; - struct vregion *vreg; -}; - /** * Audio component base driver "class" * - used by all other component types. diff --git a/src/include/sof/lib/dai-zephyr.h b/src/include/sof/lib/dai-zephyr.h index d25474c4816d..3e40c6e682af 100644 --- a/src/include/sof/lib/dai-zephyr.h +++ b/src/include/sof/lib/dai-zephyr.h @@ -28,6 +28,7 @@ #include #include #include +#include #include #include #include @@ -168,6 +169,8 @@ struct dai_data { #endif /* Copier gain params */ struct copier_gain_params *gain_data; + + struct mod_alloc_ctx alloc_ctx; }; /* these 3 are here to satisfy clk.c and ssp.h interconnection, will be removed leter */ diff --git a/src/ipc/ipc4/dai.c b/src/ipc/ipc4/dai.c index 9724e7578c99..87eb594aa6a9 100644 --- a/src/ipc/ipc4/dai.c +++ b/src/ipc/ipc4/dai.c @@ -387,15 +387,17 @@ __cold int dai_config(struct dai_data *dd, struct comp_dev *dev, /* allocated dai_config if not yet */ if (!dd->dai_spec_config) { size = sizeof(*copier_cfg); - dd->dai_spec_config = rzalloc(SOF_MEM_FLAG_USER, size); + dd->dai_spec_config = sof_heap_alloc(dd->alloc_ctx.heap, SOF_MEM_FLAG_USER, size, 0); if (!dd->dai_spec_config) { comp_err(dev, "No memory for size %d", size); return -ENOMEM; } + memset(dd->dai_spec_config, 0, size); + ret = memcpy_s(dd->dai_spec_config, size, copier_cfg, size); if (ret < 0) { - rfree(dd->dai_spec_config); + sof_heap_free(dd->alloc_ctx.heap, dd->dai_spec_config); dd->dai_spec_config = NULL; return -EINVAL; } diff --git a/src/lib/dai.c b/src/lib/dai.c index bd7c02edcb2d..8957bd1042f5 100644 --- a/src/lib/dai.c +++ b/src/lib/dai.c @@ -11,6 +11,7 @@ #include #include #include +#include /* for zephyr_ll_user_heap() */ #include #include #include @@ -311,6 +312,11 @@ struct dai *dai_get(uint32_t type, uint32_t index, uint32_t flags) { const struct device *dev; struct dai *d; + struct k_heap *heap = NULL; + +#ifdef CONFIG_SOF_USERSPACE_LL + heap = zephyr_ll_user_heap(); +#endif dev = dai_get_device(type, index); if (!dev) { @@ -319,10 +325,12 @@ struct dai *dai_get(uint32_t type, uint32_t index, uint32_t flags) return NULL; } - d = rzalloc(SOF_MEM_FLAG_USER | SOF_MEM_FLAG_COHERENT, sizeof(struct dai)); + d = sof_heap_alloc(heap, SOF_MEM_FLAG_USER | SOF_MEM_FLAG_COHERENT, sizeof(struct dai), 0); if (!d) return NULL; + memset(d, 0, sizeof(struct dai)); + d->index = index; d->type = type; d->dev = dev; @@ -332,7 +340,7 @@ struct dai *dai_get(uint32_t type, uint32_t index, uint32_t flags) if (dai_probe(d->dev)) { tr_err(&dai_tr, "dai_get: failed to probe dai with index %d type %d", index, type); - rfree(d); + sof_heap_free(heap, d); return NULL; } @@ -343,6 +351,11 @@ struct dai *dai_get(uint32_t type, uint32_t index, uint32_t flags) void dai_put(struct dai *dai) { int ret; + struct k_heap *heap = NULL; + +#ifdef CONFIG_SOF_USERSPACE_LL + heap = zephyr_ll_user_heap(); +#endif ret = dai_remove(dai->dev); if (ret < 0) { @@ -350,7 +363,7 @@ void dai_put(struct dai *dai) dai->index, ret); } - rfree(dai); + sof_heap_free(heap, dai); } #else static inline const struct dai_type_info *dai_find_type(uint32_t type) diff --git a/zephyr/syscall/sof_dma.c b/zephyr/syscall/sof_dma.c index ed69ffc78423..f12a29aa1efb 100644 --- a/zephyr/syscall/sof_dma.c +++ b/zephyr/syscall/sof_dma.c @@ -109,19 +109,28 @@ static inline void z_vrfy_sof_dma_release_channel(struct sof_dma *dma, */ static inline struct dma_block_config *deep_copy_dma_blk_cfg_list(struct dma_config *cfg) { - struct dma_block_config *kern_cfg = - rmalloc(0, sizeof(*kern_cfg) * cfg->block_count); + struct dma_block_config *kern_cfg; struct dma_block_config *kern_prev = NULL, *kern_next, *user_next; int i = 0; + if (!cfg->block_count) + return NULL; + + kern_cfg = rmalloc(0, sizeof(*kern_cfg) * cfg->block_count); if (!kern_cfg) return NULL; for (user_next = cfg->head_block, kern_next = kern_cfg; user_next; - user_next = user_next->next_block, kern_next++) { - if (++i > cfg->block_count) - goto err; + user_next = user_next->next_block, kern_next++, i++) { + if (i == cfg->block_count) { + /* last block can point to first one */ + if (user_next != cfg->head_block) + goto err; + + kern_prev->next_block = kern_cfg; + break; + } if (k_usermode_from_copy(kern_next, user_next, sizeof(*kern_next))) goto err;