Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 27 additions & 0 deletions posix/include/rtos/mutex.h
Original file line number Diff line number Diff line change
Expand Up @@ -62,4 +62,31 @@ static inline int sys_mutex_unlock(struct sys_mutex *mutex)
return 0;
}

/**
* @brief User-space accessible mutex stub for host/testbench builds.
*/
struct sof_umutex {
struct k_mutex mutex; /**< Inline k_mutex for POSIX (no dynamic alloc needed) */
};

static inline int sof_umutex_init(struct sof_umutex *umutex)
{
return k_mutex_init(&umutex->mutex);
}

static inline int sof_umutex_lock(struct sof_umutex *umutex, k_timeout_t timeout)
{
return k_mutex_lock(&umutex->mutex, timeout);
}

static inline int sof_umutex_unlock(struct sof_umutex *umutex)
{
return k_mutex_unlock(&umutex->mutex);
}

static inline void sof_umutex_free(struct sof_umutex *umutex)
{
/* No-op on POSIX — no kernel objects to free */
}

#endif
13 changes: 13 additions & 0 deletions posix/include/rtos/umutex.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
// SPDX-License-Identifier: BSD-3-Clause
//
// Copyright(c) 2026 Intel Corporation.
//

#ifndef __POSIX_RTOS_UMUTEX_H__
#define __POSIX_RTOS_UMUTEX_H__

#include <rtos/mutex.h>

/* sof_umutex type and operations are defined in rtos/mutex.h for POSIX */

#endif /* __POSIX_RTOS_UMUTEX_H__ */
132 changes: 83 additions & 49 deletions src/audio/dai-zephyr.c
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
#include <sof/lib/notifier.h>
#include <sof/lib/uuid.h>
#include <sof/lib/dma.h>
#include <sof/schedule/ll_schedule_domain.h> /* zephyr_ll_user_heap() */
#include <sof/list.h>
#include <rtos/spinlock.h>
#include <rtos/string.h>
Expand Down Expand Up @@ -225,55 +226,62 @@ __cold int dai_set_config(struct dai *dai, struct ipc_config_dai *common_config,
/* called from ipc/ipc3/dai.c */
int dai_get_handshake(struct dai *dai, int direction, int stream_id)
{
k_spinlock_key_t key = k_spin_lock(&dai->lock);
const struct dai_properties *props = dai_get_properties(dai->dev, direction,
stream_id);
int hs_id = props->dma_hs_id;
struct dai_properties props;
int ret;

k_spin_unlock(&dai->lock, key);
sof_umutex_lock(&dai->lock, K_FOREVER);
ret = dai_get_properties_copy(dai->dev, direction, stream_id, &props);
sof_umutex_unlock(&dai->lock);
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

answering my earlier question: yes the spinlock is replaced

if (ret < 0)
Comment on lines 226 to +235
return ret;

return hs_id;
return props.dma_hs_id;
}

/* called from ipc/ipc3/dai.c and ipc/ipc4/dai.c */
int dai_get_fifo_depth(struct dai *dai, int direction)
{
const struct dai_properties *props;
k_spinlock_key_t key;
int fifo_depth;
struct dai_properties props;
int ret;

if (!dai)
return 0;

key = k_spin_lock(&dai->lock);
props = dai_get_properties(dai->dev, direction, 0);
fifo_depth = props->fifo_depth;
k_spin_unlock(&dai->lock, key);
sof_umutex_lock(&dai->lock, K_FOREVER);
ret = dai_get_properties_copy(dai->dev, direction, 0, &props);
sof_umutex_unlock(&dai->lock);
if (ret < 0)
return 0;

return fifo_depth;
return props.fifo_depth;
}

int dai_get_stream_id(struct dai *dai, int direction)
{
k_spinlock_key_t key = k_spin_lock(&dai->lock);
const struct dai_properties *props = dai_get_properties(dai->dev, direction, 0);
int stream_id = props->stream_id;
struct dai_properties props;
int ret;

k_spin_unlock(&dai->lock, key);
sof_umutex_lock(&dai->lock, K_FOREVER);
ret = dai_get_properties_copy(dai->dev, direction, 0, &props);
sof_umutex_unlock(&dai->lock);
if (ret < 0)
return ret;

return stream_id;
return props.stream_id;
}

static int dai_get_fifo(struct dai *dai, int direction, int stream_id)
{
k_spinlock_key_t key = k_spin_lock(&dai->lock);
const struct dai_properties *props = dai_get_properties(dai->dev, direction,
stream_id);
int fifo_address = props->fifo_address;
struct dai_properties props;
int ret;

k_spin_unlock(&dai->lock, key);
sof_umutex_lock(&dai->lock, K_FOREVER);
ret = dai_get_properties_copy(dai->dev, direction, stream_id, &props);
sof_umutex_unlock(&dai->lock);
if (ret < 0)
return ret;

return fifo_address;
return props.fifo_address;
}

/* this is called by DMA driver every time descriptor has completed */
Expand Down Expand Up @@ -501,6 +509,7 @@ __cold int dai_common_new(struct dai_data *dd, struct comp_dev *dev,
const struct ipc_config_dai *dai_cfg)
{
uint32_t dir;
int ret;

assert_can_be_cold();

Expand All @@ -524,11 +533,27 @@ __cold int dai_common_new(struct dai_data *dd, struct comp_dev *dev,
return -ENODEV;
}

k_spinlock_init(&dd->dai->lock);
ret = sof_umutex_init(&dd->dai->lock);
if (ret < 0) {
dai_put(dd->dai);
comp_err(dev, "sof_umutex_init() failed: %d", ret);
return ret;
}

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
*/
Expand Down Expand Up @@ -581,6 +606,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();
Expand All @@ -593,10 +619,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);
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

just NULL

if (!dd)
goto e_data;

memset(dd, 0, sizeof(*dd));

comp_set_drvdata(dev, dd);

ret = dai_common_new(dd, dev, dai_cfg);
Expand All @@ -610,7 +638,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;
Expand All @@ -636,9 +664,11 @@ __cold void dai_common_free(struct dai_data *dd)

dai_release_llp_slot(dd);

sof_umutex_free(&dd->dai->lock);

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)
Expand All @@ -652,7 +682,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);
}

Expand Down Expand Up @@ -847,7 +878,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,
Expand All @@ -873,8 +904,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;
Expand Down Expand Up @@ -903,10 +935,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;
}
Expand Down Expand Up @@ -1040,7 +1073,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) {
Expand Down Expand Up @@ -1128,8 +1161,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;
}

Expand Down Expand Up @@ -1255,10 +1288,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;
}

Expand Down Expand Up @@ -1948,17 +1981,18 @@ static int dai_ts_stop_op(struct comp_dev *dev)

uint32_t dai_get_init_delay_ms(struct dai *dai)
{
const struct dai_properties *props;
k_spinlock_key_t key;
uint32_t init_delay;
struct dai_properties props;
uint32_t init_delay = 0;
int ret;

if (!dai)
return 0;

key = k_spin_lock(&dai->lock);
props = dai_get_properties(dai->dev, 0, 0);
init_delay = props->reg_init_delay;
k_spin_unlock(&dai->lock, key);
sof_umutex_lock(&dai->lock, K_FOREVER);
ret = dai_get_properties_copy(dai->dev, 0, 0, &props);
if (!ret)
init_delay = props.reg_init_delay;
sof_umutex_unlock(&dai->lock);

return init_delay;
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

props is a local variable, so it doesn't need to be protected by the spinlock. So you could just do return ret ? 0 : props.reg_init_delay;
BTW, is the spinlock replaced by a userspace-accessible locking mechanism in a later commit?

}
Expand Down
18 changes: 10 additions & 8 deletions src/include/sof/audio/component.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@
#include <rtos/idc.h>
#include <rtos/mutex.h>
#include <rtos/userspace_helper.h>
#include <sof/lib/dai.h>
#include <sof/schedule/schedule.h>
#include <ipc/control.h>
#include <sof/ipc/topology.h>
Expand All @@ -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 <sof/lib/dai.h>

/** \addtogroup component_api Component API
* @{
*/
Expand Down Expand Up @@ -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.
Expand Down
6 changes: 5 additions & 1 deletion src/include/sof/lib/dai-zephyr.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,13 @@
#include <sof/lib/dma.h>
#include <sof/list.h>
#include <rtos/sof.h>
#include <rtos/umutex.h>
#include <rtos/spinlock.h>
#include <sof/trace/trace.h>
#include <sof/ipc/topology.h>
#include <sof/audio/pcm_converter.h>
#include <sof/audio/ipc-config.h>
#include <sof/audio/component.h>
#include <ipc/dai.h>
#include <errno.h>
#include <stddef.h>
Expand All @@ -52,7 +54,7 @@ struct dai {
uint32_t dma_dev;
const struct device *dev;
const struct dai_data *dd;
struct k_spinlock lock; /* protect properties */
struct sof_umutex lock; /* protect properties */
};

union hdalink_cfg {
Expand Down Expand Up @@ -168,6 +170,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 */
Expand Down
Loading
Loading