Skip to content

Commit 34f9a9f

Browse files
committed
dp: convert to user-space
Run DP threads in user-space. Move all the respective memory and kobjects to a dedicated memory domain. Work around Zephyr inability to remove memory domains on Xtensa. Signed-off-by: Guennadi Liakhovetski <guennadi.liakhovetski@linux.intel.com>
1 parent 00b7532 commit 34f9a9f

11 files changed

Lines changed: 548 additions & 194 deletions

File tree

src/audio/buffers/comp_buffer.c

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#include <rtos/cache.h>
1919
#include <sof/lib/notifier.h>
2020
#include <sof/list.h>
21+
#include <sof/schedule/dp_schedule.h>
2122
#include <rtos/spinlock.h>
2223
#include <rtos/symbol.h>
2324
#include <ipc/topology.h>
@@ -158,8 +159,16 @@ static void comp_buffer_free(struct sof_audio_buffer *audio_buffer)
158159
/* In case some listeners didn't unregister from buffer's callbacks */
159160
notifier_unregister_all(NULL, buffer);
160161

162+
struct k_heap *heap = buffer->audio_buffer.heap;
163+
161164
rfree(buffer->stream.addr);
162-
sof_heap_free(buffer->audio_buffer.heap, buffer);
165+
sof_heap_free(heap, buffer);
166+
if (heap) {
167+
struct dp_heap_user *mod_heap_user = container_of(heap, struct dp_heap_user, heap);
168+
169+
if (!--mod_heap_user->client_count)
170+
rfree(mod_heap_user);
171+
}
163172
}
164173

165174
APP_TASK_DATA static const struct source_ops comp_buffer_source_ops = {

src/audio/module_adapter/module/generic.c

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ int module_load_config(struct comp_dev *dev, const void *cfg, size_t size)
7878
return ret;
7979
}
8080

81-
static void mod_resource_init(struct processing_module *mod)
81+
void mod_resource_init(struct processing_module *mod)
8282
{
8383
struct module_data *md = &mod->priv;
8484
/* Init memory list */
@@ -116,7 +116,6 @@ int module_init(struct processing_module *mod)
116116
return -EIO;
117117
}
118118

119-
mod_resource_init(mod);
120119
#if CONFIG_MODULE_MEMORY_API_DEBUG && defined(__ZEPHYR__)
121120
mod->priv.resources.rsrc_mngr = k_current_get();
122121
#endif
@@ -181,6 +180,19 @@ static void container_put(struct processing_module *mod, struct module_resource
181180
list_item_append(&container->list, &res->free_cont_list);
182181
}
183182

183+
#if CONFIG_USERSPACE
184+
void mod_heap_info(struct processing_module *mod, size_t *size, uintptr_t *start)
185+
{
186+
struct module_resources *res = &mod->priv.resources;
187+
188+
if (size)
189+
*size = res->heap->heap.init_bytes;
190+
191+
if (start)
192+
*start = (uintptr_t)container_of(res->heap, struct dp_heap_user, heap);
193+
}
194+
#endif
195+
184196
/**
185197
* Allocates aligned buffer memory block for module.
186198
* @param mod Pointer to the module this memory block is allocated for.

src/audio/module_adapter/module_adapter.c

Lines changed: 37 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -58,30 +58,33 @@ struct comp_dev *module_adapter_new(const struct comp_driver *drv,
5858
#define PAGE_SZ HOST_PAGE_SIZE
5959
#endif
6060

61-
static struct k_heap *module_adapter_dp_heap_new(const struct comp_ipc_config *config)
61+
static struct dp_heap_user *module_adapter_dp_heap_new(const struct comp_ipc_config *config,
62+
size_t *heap_size)
6263
{
6364
/* src-lite with 8 channels has been seen allocating 14k in one go */
6465
/* FIXME: the size will be derived from configuration */
65-
const size_t heap_size = 20 * 1024;
66+
const size_t buf_size = 20 * 1024;
6667

6768
/* Keep uncached to match the default SOF heap! */
6869
uint8_t *mod_heap_mem = rballoc_align(SOF_MEM_FLAG_USER | SOF_MEM_FLAG_COHERENT,
69-
heap_size, PAGE_SZ);
70+
buf_size, PAGE_SZ);
7071

7172
if (!mod_heap_mem)
7273
return NULL;
7374

74-
struct k_heap *mod_heap = (struct k_heap *)mod_heap_mem;
75-
const size_t heap_prefix_size = ALIGN_UP(sizeof(*mod_heap), 8);
75+
struct dp_heap_user *mod_heap_user = (struct dp_heap_user *)mod_heap_mem;
76+
struct k_heap *mod_heap = &mod_heap_user->heap;
77+
const size_t heap_prefix_size = ALIGN_UP(sizeof(*mod_heap_user), 4);
7678
void *mod_heap_buf = mod_heap_mem + heap_prefix_size;
7779

78-
k_heap_init(mod_heap, mod_heap_buf, heap_size - heap_prefix_size);
80+
*heap_size = buf_size - heap_prefix_size;
81+
k_heap_init(mod_heap, mod_heap_buf, *heap_size);
7982
#ifdef __ZEPHYR__
8083
mod_heap->heap.init_mem = mod_heap_buf;
81-
mod_heap->heap.init_bytes = heap_size - heap_prefix_size;
84+
mod_heap->heap.init_bytes = *heap_size;
8285
#endif
8386

84-
return mod_heap;
87+
return mod_heap_user;
8588
}
8689

8790
static struct processing_module *module_adapter_mem_alloc(const struct comp_driver *drv,
@@ -97,16 +100,21 @@ static struct processing_module *module_adapter_mem_alloc(const struct comp_driv
97100
*/
98101
uint32_t flags = config->proc_domain == COMP_PROCESSING_DOMAIN_DP ?
99102
SOF_MEM_FLAG_USER | SOF_MEM_FLAG_COHERENT : SOF_MEM_FLAG_USER;
103+
struct dp_heap_user *mod_heap_user;
104+
size_t heap_size;
100105

101106
if (config->proc_domain == COMP_PROCESSING_DOMAIN_DP && IS_ENABLED(CONFIG_USERSPACE) &&
102107
!IS_ENABLED(CONFIG_SOF_USERSPACE_USE_DRIVER_HEAP)) {
103-
mod_heap = module_adapter_dp_heap_new(config);
104-
if (!mod_heap) {
108+
mod_heap_user = module_adapter_dp_heap_new(config, &heap_size);
109+
if (!mod_heap_user) {
105110
comp_cl_err(drv, "Failed to allocate DP module heap");
106111
return NULL;
107112
}
113+
mod_heap = &mod_heap_user->heap;
108114
} else {
109115
mod_heap = drv->user_heap;
116+
mod_heap_user = NULL;
117+
heap_size = 0;
110118
}
111119

112120
struct processing_module *mod = sof_heap_alloc(mod_heap, flags, sizeof(*mod), 0);
@@ -118,6 +126,7 @@ static struct processing_module *module_adapter_mem_alloc(const struct comp_driv
118126

119127
memset(mod, 0, sizeof(*mod));
120128
mod->priv.resources.heap = mod_heap;
129+
mod_resource_init(mod);
121130

122131
/*
123132
* Would be difficult to optimize the allocation to use cache. Only if
@@ -138,26 +147,35 @@ static struct processing_module *module_adapter_mem_alloc(const struct comp_driv
138147
mod->dev = dev;
139148
dev->mod = mod;
140149

150+
if (mod_heap_user)
151+
mod_heap_user->client_count++;
152+
141153
return mod;
142154

143155
err:
144156
sof_heap_free(mod_heap, mod);
145157
emod:
146-
if (mod_heap != drv->user_heap)
147-
rfree(mod_heap);
158+
rfree(mod_heap_user);
148159

149160
return NULL;
150161
}
151162

152163
static void module_adapter_mem_free(struct processing_module *mod)
153164
{
154165
struct k_heap *mod_heap = mod->priv.resources.heap;
166+
struct dp_heap_user *mod_heap_user = container_of(mod_heap, struct dp_heap_user, heap);
155167

168+
/*
169+
* In principle it shouldn't even be needed to free individual objects
170+
* on the module heap since we're freeing the heap itself too
171+
*/
156172
#if CONFIG_IPC_MAJOR_4
157173
sof_heap_free(mod_heap, mod->priv.cfg.input_pins);
158174
#endif
159175
sof_heap_free(mod_heap, mod->dev);
160176
sof_heap_free(mod_heap, mod);
177+
if (!mod_heap || !--mod_heap_user->client_count)
178+
rfree(mod_heap_user);
161179
}
162180

163181
/*
@@ -1378,11 +1396,16 @@ void module_adapter_free(struct comp_dev *dev)
13781396
comp_dbg(dev, "start");
13791397

13801398
if (dev->task) {
1381-
/* Run DP module's .free() method in its thread context */
1399+
/*
1400+
* Run DP module's .free() method in its thread context.
1401+
* Unlike with other IPCs we first run module's .free() in
1402+
* thread context, then cancel the thread, and then execute
1403+
* final clean up
1404+
*/
13821405
#if CONFIG_USERSPACE && !CONFIG_SOF_USERSPACE_PROXY
13831406
scheduler_dp_thread_ipc(mod, SOF_IPC4_MOD_DELETE_INSTANCE, NULL);
13841407
#endif
1385-
schedule_task_cancel(dev->task);
1408+
schedule_task_free(dev->task);
13861409
}
13871410

13881411
ret = module_free(mod);

src/include/sof/audio/component_ext.h

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -44,8 +44,6 @@ struct comp_dev *comp_new_ipc4(struct ipc4_module_init_instance *module_init);
4444
/** See comp_ops::free */
4545
static inline void comp_free(struct comp_dev *dev)
4646
{
47-
struct task *task = dev->is_shared ||
48-
dev->ipc_config.proc_domain == COMP_PROCESSING_DOMAIN_DP ? dev->task : NULL;
4947
const struct comp_driver *drv = dev->drv;
5048

5149
assert(drv->ops.free);
@@ -55,12 +53,6 @@ static inline void comp_free(struct comp_dev *dev)
5553
* be freed after this.
5654
*/
5755
drv->ops.free(dev);
58-
59-
/* free task if shared component or DP task*/
60-
if (task) {
61-
schedule_task_free(task);
62-
sof_heap_free(drv->user_heap, task);
63-
}
6456
}
6557

6658
/**

src/include/sof/audio/module_adapter/module/generic.h

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -191,9 +191,19 @@ struct module_processing_data {
191191
int module_load_config(struct comp_dev *dev, const void *cfg, size_t size);
192192
int module_init(struct processing_module *mod);
193193
void *mod_balloc_align(struct processing_module *mod, size_t size, size_t alignment);
194+
void mod_resource_init(struct processing_module *mod);
195+
void mod_heap_info(struct processing_module *mod, size_t *size, uintptr_t *start);
196+
#if defined(__ZEPHYR__) && defined(CONFIG_SOF_FULL_ZEPHYR_APPLICATION)
194197
__syscall void *mod_alloc_ext(struct processing_module *mod, uint32_t flags, size_t size,
195198
size_t alignment);
196199
__syscall int mod_free(struct processing_module *mod, const void *ptr);
200+
#else
201+
void *z_impl_mod_alloc_ext(struct processing_module *mod, uint32_t flags, size_t size,
202+
size_t alignment);
203+
int z_impl_mod_free(struct processing_module *mod, const void *ptr);
204+
#define mod_alloc_ext z_impl_mod_alloc_ext
205+
#define mod_free z_impl_mod_free
206+
#endif
197207

198208
/**
199209
* Allocates aligned memory block for module.
@@ -234,17 +244,21 @@ struct comp_data_blob_handler *mod_data_blob_handler_new(struct processing_modul
234244
void mod_data_blob_handler_free(struct processing_module *mod, struct comp_data_blob_handler *dbh);
235245
#endif
236246
#if CONFIG_FAST_GET
247+
#if defined(__ZEPHYR__) && defined(CONFIG_SOF_FULL_ZEPHYR_APPLICATION)
237248
__syscall const void *mod_fast_get(struct processing_module *mod, const void * const dram_ptr,
238249
size_t size);
250+
#else
251+
const void *z_impl_mod_fast_get(struct processing_module *mod, const void * const dram_ptr,
252+
size_t size);
253+
#define mod_fast_get z_impl_mod_fast_get
254+
#endif
239255
void mod_fast_put(struct processing_module *mod, const void *sram_ptr);
240256
#endif
241257
void mod_free_all(struct processing_module *mod);
242258
int module_prepare(struct processing_module *mod,
243259
struct sof_source **sources, int num_of_sources,
244260
struct sof_sink **sinks, int num_of_sinks);
245261

246-
#include <zephyr/syscalls/generic.h>
247-
248262
static inline
249263
bool generic_module_is_ready_to_process(struct processing_module *mod,
250264
struct sof_source **sources,
@@ -454,4 +468,8 @@ static inline uint32_t module_get_lpt(struct processing_module *mod)
454468
return mod->dev->period;
455469
}
456470

471+
#if defined(__ZEPHYR__) && defined(CONFIG_SOF_FULL_ZEPHYR_APPLICATION)
472+
#include <zephyr/syscalls/generic.h>
473+
#endif
474+
457475
#endif /* __SOF_AUDIO_MODULE_GENERIC__ */

src/include/sof/schedule/dp_schedule.h

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -109,12 +109,18 @@ union scheduler_dp_thread_ipc_param {
109109
} pipeline_state;
110110
};
111111

112+
struct dp_heap_user {
113+
struct k_heap heap;
114+
/* So far relying on linear processing of serialized IPCs, but might need protection */
115+
unsigned int client_count; /* devices and buffers */
116+
};
117+
112118
#if CONFIG_ZEPHYR_DP_SCHEDULER
113-
int scheduler_dp_thread_ipc(struct processing_module *pmod, enum sof_ipc4_module_type cmd,
119+
int scheduler_dp_thread_ipc(struct processing_module *pmod, unsigned int cmd,
114120
union scheduler_dp_thread_ipc_param *param);
115121
#else
116122
static inline int scheduler_dp_thread_ipc(struct processing_module *pmod,
117-
enum sof_ipc4_module_type cmd,
123+
unsigned int cmd,
118124
union scheduler_dp_thread_ipc_param *param)
119125
{
120126
return 0;

src/ipc/ipc4/helper.c

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
#include <sof/lib/memory.h>
2424
#include <sof/list.h>
2525
#include <sof/platform.h>
26+
#include <sof/schedule/dp_schedule.h>
2627
#include <sof/schedule/ll_schedule_domain.h>
2728
#include <rtos/symbol.h>
2829
#include <rtos/wait.h>
@@ -601,6 +602,14 @@ __cold int ipc_comp_connect(struct ipc *ipc, ipc_pipe_comp_connect *_connect)
601602
return IPC4_OUT_OF_MEMORY;
602603
}
603604

605+
#if CONFIG_ZEPHYR_DP_SCHEDULER
606+
if (dp_heap) {
607+
struct dp_heap_user *dp_user = container_of(dp_heap, struct dp_heap_user, heap);
608+
609+
dp_user->client_count++;
610+
}
611+
#endif
612+
604613
/*
605614
* set min_free_space and min_available in sink/src api of created buffer.
606615
* buffer is connected like:

0 commit comments

Comments
 (0)