Skip to content
Open
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
90 changes: 80 additions & 10 deletions src/audio/pipeline/pipeline-graph.c
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
#include <rtos/interrupt.h>
#include <rtos/symbol.h>
#include <rtos/alloc.h>
#include <rtos/userspace_helper.h>
#include <sof/lib/mm_heap.h>
#include <sof/lib/uuid.h>
#include <sof/compiler_attributes.h>
Expand Down Expand Up @@ -44,20 +45,69 @@ DECLARE_TR_CTX(pipe_tr, SOF_UUID(pipe_uuid), LOG_LEVEL_INFO);
/* lookup table to determine busy/free pipeline metadata objects */
struct pipeline_posn {
bool posn_offset[PPL_POSN_OFFSETS]; /**< available offsets */
#ifndef CONFIG_SOF_USERSPACE_LL
struct k_spinlock lock; /**< lock mechanism */
#endif
};
/* the pipeline position lookup table */
static SHARED_DATA struct pipeline_posn pipeline_posn_shared;
static APP_SYSUSER_BSS SHARED_DATA struct pipeline_posn pipeline_posn_shared;

#ifdef CONFIG_SOF_USERSPACE_LL
/* Mutex pointer in user-accessible partition so user-space threads
* can read the pointer for syscalls. Kept outside the SHARED_DATA
* struct to avoid kernel object tracking issues.
*/
static APP_SYSUSER_BSS struct k_mutex *pipeline_posn_mutex;
#endif

/**
* \brief Retrieves pipeline position structure.
* \return Pointer to pipeline position structure.
*/
static inline struct pipeline_posn *pipeline_posn_get(void)
{
#ifdef CONFIG_SOF_USERSPACE_LL
return &pipeline_posn_shared;
#else
return sof_get()->pipeline_posn;
#endif
}

/*
* Position table locking. User-space LL cannot use a spinlock (disabling
* interrupts is privileged), so it uses a mutex; the config split is kept
* here so the callers below stay identical for both configurations.
*/
#ifdef CONFIG_SOF_USERSPACE_LL
typedef int pipeline_posn_key_t;

static inline pipeline_posn_key_t pipeline_posn_lock(struct pipeline_posn *posn)
{
(void)posn;
k_mutex_lock(pipeline_posn_mutex, K_FOREVER);
return 0;
}

static inline void pipeline_posn_unlock(struct pipeline_posn *posn, pipeline_posn_key_t key)
{
(void)posn;
(void)key;
k_mutex_unlock(pipeline_posn_mutex);
}
#else
typedef k_spinlock_key_t pipeline_posn_key_t;

static inline pipeline_posn_key_t pipeline_posn_lock(struct pipeline_posn *posn)
{
return k_spin_lock(&posn->lock);
}

static inline void pipeline_posn_unlock(struct pipeline_posn *posn, pipeline_posn_key_t key)
{
k_spin_unlock(&posn->lock, key);
}
#endif

/**
* \brief Retrieves first free pipeline position offset.
* \param[in,out] posn_offset Pipeline position offset to be set.
Expand All @@ -68,9 +118,7 @@ static inline int pipeline_posn_offset_get(uint32_t *posn_offset)
struct pipeline_posn *pipeline_posn = pipeline_posn_get();
int ret = -EINVAL;
uint32_t i;
k_spinlock_key_t key;

key = k_spin_lock(&pipeline_posn->lock);
pipeline_posn_key_t key = pipeline_posn_lock(pipeline_posn);

for (i = 0; i < PPL_POSN_OFFSETS; ++i) {
if (!pipeline_posn->posn_offset[i]) {
Expand All @@ -81,8 +129,7 @@ static inline int pipeline_posn_offset_get(uint32_t *posn_offset)
}
}


k_spin_unlock(&pipeline_posn->lock, key);
pipeline_posn_unlock(pipeline_posn, key);

return ret;
}
Expand All @@ -95,20 +142,34 @@ static inline void pipeline_posn_offset_put(uint32_t posn_offset)
{
struct pipeline_posn *pipeline_posn = pipeline_posn_get();
int i = posn_offset / sizeof(struct sof_ipc_stream_posn);
k_spinlock_key_t key;

key = k_spin_lock(&pipeline_posn->lock);
pipeline_posn_key_t key = pipeline_posn_lock(pipeline_posn);

pipeline_posn->posn_offset[i] = false;

k_spin_unlock(&pipeline_posn->lock, key);
pipeline_posn_unlock(pipeline_posn, key);
}

void pipeline_posn_init(struct sof *sof)
{
sof->pipeline_posn = &pipeline_posn_shared;
#ifdef CONFIG_SOF_USERSPACE_LL
pipeline_posn_mutex = k_object_alloc(K_OBJ_MUTEX);
if (!pipeline_posn_mutex) {
pipe_cl_err("pipeline posn mutex alloc failed");
k_panic();
}
k_mutex_init(pipeline_posn_mutex);
#else
k_spinlock_init(&sof->pipeline_posn->lock);
#endif
}

#ifdef CONFIG_SOF_USERSPACE_LL
void pipeline_posn_grant_access(struct k_thread *thread)
{
k_thread_access_grant(thread, pipeline_posn_mutex);
}
#endif

/* create new pipeline - returns pipeline id or negative error */
struct pipeline *pipeline_new(struct k_heap *heap, uint32_t pipeline_id, uint32_t priority,
Expand Down Expand Up @@ -140,12 +201,21 @@ struct pipeline *pipeline_new(struct k_heap *heap, uint32_t pipeline_id, uint32_
p->pipeline_id = pipeline_id;
p->status = COMP_STATE_INIT;
p->trigger.cmd = COMP_TRIGGER_NO_ACTION;

#ifndef CONFIG_SOF_USERSPACE_LL
/*
* pipe_tr lives in the .trace_ctx section, which is not mapped into
* the sysuser partition, so it cannot be read from a user-mode thread.
* The copy is also unnecessary in that configuration: with Zephyr
Comment on lines +205 to +209
* logging the pipe_*() macros use the global pipe_tr, not p->tctx.
*/
ret = memcpy_s(&p->tctx, sizeof(struct tr_ctx), &pipe_tr,
sizeof(struct tr_ctx));
if (ret < 0) {
pipe_err(p, "failed to copy trace settings");
goto free;
}
#endif

ret = pipeline_posn_offset_get(&p->posn_offset);
if (ret < 0) {
Expand Down
8 changes: 8 additions & 0 deletions src/include/sof/audio/pipeline.h
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,14 @@ int pipeline_complete(struct pipeline *p, struct comp_dev *source,
*/
void pipeline_posn_init(struct sof *sof);

#ifdef CONFIG_SOF_USERSPACE_LL
/**
* \brief Grants user-space thread access to pipeline position mutex.
* \param[in] thread Thread to grant access to.
*/
void pipeline_posn_grant_access(struct k_thread *thread);
#endif

/**
* \brief Resets the pipeline and free runtime resources.
* \param[in] p pipeline.
Expand Down
6 changes: 6 additions & 0 deletions src/init/init.c
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
#include <sof/schedule/dp_schedule.h>
#include <sof/schedule/ll_schedule.h>
#include <sof/schedule/ll_schedule_domain.h>
#include <sof/audio/pipeline.h>
#include <ipc/trace.h>
#if CONFIG_IPC_MAJOR_4
#include <ipc4/fw_reg.h>
Expand Down Expand Up @@ -232,6 +233,11 @@ __cold static int primary_core_init(int argc, char *argv[], struct sof *sof)
zephyr_ll_user_resources_init();
#endif

/* init pipeline position offsets - must be before platform_init()
* which calls ipc_init() -> ipc_user_init() that needs the posn mutex.
*/
pipeline_posn_init(sof);

/* init the platform */
if (platform_init(sof) < 0)
sof_panic(SOF_IPC_PANIC_PLATFORM);
Expand Down
1 change: 1 addition & 0 deletions src/ipc/ipc-common.c
Original file line number Diff line number Diff line change
Expand Up @@ -466,6 +466,7 @@ __cold static void ipc_user_init(void)
sof_panic(SOF_IPC_PANIC_IPC);
}
user_ll_grant_access(&ipc_user_thread, PLATFORM_PRIMARY_CORE_ID);
pipeline_posn_grant_access(&ipc_user_thread);
k_mem_domain_add_thread(zephyr_ll_mem_domain(), &ipc_user_thread);

k_thread_cpu_pin(&ipc_user_thread, PLATFORM_PRIMARY_CORE_ID);
Expand Down
3 changes: 0 additions & 3 deletions zephyr/wrapper.c
Original file line number Diff line number Diff line change
Expand Up @@ -177,9 +177,6 @@ int task_main_start(struct sof *sof)
/* init default audio components */
sys_comp_init(sof);

/* init pipeline position offsets */
pipeline_posn_init(sof);

return 0;
}

Expand Down
Loading