Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

zephyr: buffer: host: dai: Introduction of functions that allocate a buffer from a range #9145

Merged
merged 5 commits into from
Jun 25, 2024
Merged
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
158 changes: 137 additions & 21 deletions src/audio/buffer.c
Original file line number Diff line number Diff line change
Expand Up @@ -32,45 +32,31 @@ DECLARE_SOF_RT_UUID("buffer", buffer_uuid, 0x42544c92, 0x8e92, 0x4e41,
0xb6, 0x79, 0x34, 0x51, 0x9f, 0x1c, 0x1d, 0x28);
DECLARE_TR_CTX(buffer_tr, SOF_UUID(buffer_uuid), LOG_LEVEL_INFO);

struct comp_buffer *buffer_alloc(uint32_t size, uint32_t caps, uint32_t flags, uint32_t align,
bool is_shared)
static struct comp_buffer *buffer_alloc_struct(void *stream_addr, size_t size, uint32_t caps,
uint32_t flags, bool is_shared)
{
struct comp_buffer *buffer;
void *stream_addr;

tr_dbg(&buffer_tr, "buffer_alloc()");

/* validate request */
if (size == 0) {
tr_err(&buffer_tr, "buffer_alloc(): new size = %u is invalid",
size);
return NULL;
}
tr_dbg(&buffer_tr, "buffer_alloc_struct()");

/* allocate new buffer */
enum mem_zone zone = is_shared ? SOF_MEM_ZONE_RUNTIME_SHARED : SOF_MEM_ZONE_RUNTIME;

buffer = rzalloc(zone, 0, SOF_MEM_CAPS_RAM, sizeof(*buffer));

if (!buffer) {
tr_err(&buffer_tr, "buffer_alloc(): could not alloc structure");
tr_err(&buffer_tr, "buffer_alloc_struct(): could not alloc structure");
return NULL;
}

CORE_CHECK_STRUCT_INIT(buffer, is_shared);

buffer->is_shared = is_shared;
stream_addr = rballoc_align(0, caps, size, align);
if (!stream_addr) {
rfree(buffer);
tr_err(&buffer_tr, "buffer_alloc(): could not alloc size = %u bytes of type = %u",
size, caps);
return NULL;
}
buffer->caps = caps;

/* From here no more uncached access to the buffer object, except its list headers */
audio_stream_set_addr(&buffer->stream, stream_addr);
buffer_init(buffer, size, caps);
buffer_init_stream(buffer, size);

audio_stream_set_underrun(&buffer->stream, !!(flags & SOF_BUF_UNDERRUN_PERMITTED));
audio_stream_set_overrun(&buffer->stream, !!(flags & SOF_BUF_OVERRUN_PERMITTED));
Expand All @@ -81,6 +67,36 @@ struct comp_buffer *buffer_alloc(uint32_t size, uint32_t caps, uint32_t flags, u
return buffer;
}

struct comp_buffer *buffer_alloc(size_t size, uint32_t caps, uint32_t flags, uint32_t align,
bool is_shared)
{
struct comp_buffer *buffer;
void *stream_addr;

tr_dbg(&buffer_tr, "buffer_alloc()");

/* validate request */
if (size == 0) {
tr_err(&buffer_tr, "buffer_alloc(): new size = %zu is invalid", size);
return NULL;
}

stream_addr = rballoc_align(0, caps, size, align);
if (!stream_addr) {
tr_err(&buffer_tr, "buffer_alloc(): could not alloc size = %zu bytes of type = %u",
size, caps);
return NULL;
}

buffer = buffer_alloc_struct(stream_addr, size, caps, flags, is_shared);
if (!buffer) {
tr_err(&buffer_tr, "buffer_alloc(): could not alloc buffer structure");
rfree(stream_addr);
}

return buffer;
}

#if CONFIG_ZEPHYR_DP_SCHEDULER
int buffer_create_shadow_dp_queue(struct comp_buffer *buffer, bool at_input)
{
Expand Down Expand Up @@ -148,6 +164,49 @@ int buffer_sync_shadow_dp_queue(struct comp_buffer *buffer, size_t limit)
}
#endif /* CONFIG_ZEPHYR_DP_SCHEDULER */

struct comp_buffer *buffer_alloc_range(size_t preferred_size, size_t minimum_size, uint32_t caps,
softwarecki marked this conversation as resolved.
Show resolved Hide resolved
uint32_t flags, uint32_t align, bool is_shared)
{
struct comp_buffer *buffer;
size_t size;
void *stream_addr = NULL;

tr_dbg(&buffer_tr, "buffer_alloc_range(): %zu -- %zu bytes", minimum_size, preferred_size);

/* validate request */
if (minimum_size == 0 || preferred_size < minimum_size) {
tr_err(&buffer_tr, "buffer_alloc_range(): new size range %zu -- %zu is invalid",
minimum_size, preferred_size);
return NULL;
}

/* Align preferred size to a multiple of the minimum size */
if (preferred_size % minimum_size)
preferred_size += minimum_size - preferred_size % minimum_size;

for (size = preferred_size; size >= minimum_size; size -= minimum_size) {
stream_addr = rballoc_align(0, caps, size, align);
if (stream_addr)
break;
}

tr_dbg(&buffer_tr, "buffer_alloc_range(): allocated %zu bytes", size);

if (!stream_addr) {
tr_err(&buffer_tr, "buffer_alloc_range(): could not alloc size = %zu bytes of type = %u",
minimum_size, caps);
return NULL;
}

buffer = buffer_alloc_struct(stream_addr, size, caps, flags, is_shared);
if (!buffer) {
tr_err(&buffer_tr, "buffer_alloc_range(): could not alloc buffer structure");
rfree(stream_addr);
}

return buffer;
}

void buffer_zero(struct comp_buffer *buffer)
{
buf_dbg(buffer, "stream_zero()");
Expand Down Expand Up @@ -193,7 +252,64 @@ int buffer_set_size(struct comp_buffer *buffer, uint32_t size, uint32_t alignmen
if (new_ptr)
buffer->stream.addr = new_ptr;

buffer_init(buffer, size, buffer->caps);
buffer_init_stream(buffer, size);

return 0;
}

int buffer_set_size_range(struct comp_buffer *buffer, size_t preferred_size, size_t minimum_size,
uint32_t alignment)
{
void *ptr = audio_stream_get_addr(&buffer->stream);
const size_t actual_size = audio_stream_get_size(&buffer->stream);
void *new_ptr = NULL;
size_t new_size;

CORE_CHECK_STRUCT(buffer);

/* validate request */
if (minimum_size == 0 || preferred_size < minimum_size) {
buf_err(buffer, "resize size range %zu -- %zu is invalid", minimum_size,
preferred_size);
return -EINVAL;
}

/* Align preferred size to a multiple of the minimum size */
if (preferred_size % minimum_size)
preferred_size += minimum_size - preferred_size % minimum_size;
Copy link
Collaborator

Choose a reason for hiding this comment

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

in fact wondering, whether it would be better to align down? Doesn't seem important though


if (preferred_size == actual_size)
return 0;

if (!alignment) {
for (new_size = preferred_size; new_size >= minimum_size;
new_size -= minimum_size) {
new_ptr = rbrealloc(ptr, SOF_MEM_FLAG_NO_COPY, buffer->caps, new_size,
actual_size);
if (new_ptr)
break;
}
} else {
for (new_size = preferred_size; new_size >= minimum_size;
new_size -= minimum_size) {
new_ptr = rbrealloc_align(ptr, SOF_MEM_FLAG_NO_COPY, buffer->caps, new_size,
actual_size, alignment);
if (new_ptr)
break;
}
}

/* we couldn't allocate bigger chunk */
if (!new_ptr && new_size > actual_size) {
buf_err(buffer, "resize can't alloc %zu bytes type %u", new_size, buffer->caps);
return -ENOMEM;
}

/* use bigger chunk, else just use the old chunk but set smaller */
if (new_ptr)
buffer->stream.addr = new_ptr;

buffer_init_stream(buffer, new_size);

return 0;
}
Expand Down
14 changes: 9 additions & 5 deletions src/audio/dai-zephyr.c
Original file line number Diff line number Diff line change
Expand Up @@ -797,6 +797,7 @@ static int dai_set_dma_buffer(struct dai_data *dd, struct comp_dev *dev,
uint32_t period_count;
uint32_t period_bytes;
uint32_t buffer_size;
uint32_t buffer_size_preferred;
softwarecki marked this conversation as resolved.
Show resolved Hide resolved
uint32_t addr_align;
uint32_t align;
int err;
Expand Down Expand Up @@ -873,21 +874,23 @@ static int dai_set_dma_buffer(struct dai_data *dd, struct comp_dev *dev,
comp_err(dev, "dai_set_dma_buffer(): no valid dma buffer period count");
return -EINVAL;
}

buffer_size = ALIGN_UP(period_count * period_bytes, align);
*pc = period_count;
period_count = MAX(period_count,
SOF_DIV_ROUND_UP(dd->ipc_config.dma_buffer_size, period_bytes));
buffer_size_preferred = ALIGN_UP(period_count * period_bytes, align);

/* alloc DMA buffer or change its size if exists */
if (dd->dma_buffer) {
err = buffer_set_size(dd->dma_buffer, buffer_size, addr_align);
err = buffer_set_size_range(dd->dma_buffer, buffer_size_preferred, buffer_size,
addr_align);

if (err < 0) {
comp_err(dev, "dai_set_dma_buffer(): buffer_size = %u failed", buffer_size);
return err;
}
} else {
dd->dma_buffer = buffer_alloc(buffer_size, SOF_MEM_CAPS_DMA, 0,
addr_align, false);
dd->dma_buffer = buffer_alloc_range(buffer_size_preferred, buffer_size,
SOF_MEM_CAPS_DMA, 0, addr_align, false);
if (!dd->dma_buffer) {
comp_err(dev, "dai_set_dma_buffer(): failed to alloc dma buffer");
return -ENOMEM;
Expand All @@ -904,6 +907,7 @@ static int dai_set_dma_buffer(struct dai_data *dd, struct comp_dev *dev,
dd->sampling = get_sample_bytes(hw_params.frame_fmt);
}

*pc = audio_stream_get_size(&dd->dma_buffer->stream) / period_bytes;
dd->fast_mode = dd->ipc_config.feature_mask & BIT(IPC4_COPIER_FAST_MODE);
return 0;
}
Expand Down
12 changes: 8 additions & 4 deletions src/audio/host-zephyr.c
Original file line number Diff line number Diff line change
Expand Up @@ -748,6 +748,7 @@ int host_common_params(struct host_data *hd, struct comp_dev *dev,
uint32_t period_count;
uint32_t period_bytes;
uint32_t buffer_size;
uint32_t buffer_size_preferred;
uint32_t addr_align;
uint32_t align;
int i, channel, err;
Expand Down Expand Up @@ -821,25 +822,27 @@ int host_common_params(struct host_data *hd, struct comp_dev *dev,
/* calculate DMA buffer size */
round_up_size = (params->frame_fmt == SOF_IPC_FRAME_S24_3LE) ? (3 * align) : align;
buffer_size = ROUND_UP(period_bytes, round_up_size) * period_count;
buffer_size_preferred = buffer_size;
if (hd->ipc_host.dma_buffer_size != 0)
buffer_size = ROUND_UP(hd->ipc_host.dma_buffer_size, buffer_size);
buffer_size_preferred = ROUND_UP(hd->ipc_host.dma_buffer_size, buffer_size);

/* alloc DMA buffer or change its size if exists */
/*
* Host DMA buffer cannot be shared. So we actually don't need to lock,
* but we have to write back caches after we finish anywae
*/
if (hd->dma_buffer) {
err = buffer_set_size(hd->dma_buffer, buffer_size, addr_align);
err = buffer_set_size_range(hd->dma_buffer, buffer_size_preferred, buffer_size,
addr_align);
softwarecki marked this conversation as resolved.
Show resolved Hide resolved
if (err < 0) {
comp_err(dev, "host_params(): buffer_set_size() failed, buffer_size = %u",
buffer_size);
return err;
}
} else {
/* allocate not shared buffer */
hd->dma_buffer = buffer_alloc(buffer_size, SOF_MEM_CAPS_DMA, 0,
addr_align, false);
hd->dma_buffer = buffer_alloc_range(buffer_size_preferred, buffer_size,
SOF_MEM_CAPS_DMA, 0, addr_align, false);
if (!hd->dma_buffer) {
comp_err(dev, "host_params(): failed to alloc dma buffer");
return -ENOMEM;
Expand All @@ -861,6 +864,7 @@ int host_common_params(struct host_data *hd, struct comp_dev *dev,
config->dest_width = config->src_width;
hd->dma_buffer_size = audio_stream_get_size(&hd->dma_buffer->stream);
}
buffer_size = audio_stream_get_size(&hd->dma_buffer->stream);

/* create SG DMA elems for local DMA buffer */
err = create_local_elems(hd, dev, period_count, buffer_size / period_count,
Expand Down
11 changes: 6 additions & 5 deletions src/include/sof/audio/buffer.h
Original file line number Diff line number Diff line change
Expand Up @@ -188,8 +188,10 @@ struct buffer_cb_free {
} while (0)

/* pipeline buffer creation and destruction */
struct comp_buffer *buffer_alloc(uint32_t size, uint32_t caps, uint32_t flags, uint32_t align,
struct comp_buffer *buffer_alloc(size_t size, uint32_t caps, uint32_t flags, uint32_t align,
bool is_shared);
struct comp_buffer *buffer_alloc_range(size_t preferred_size, size_t minimum_size, uint32_t caps,
uint32_t flags, uint32_t align, bool is_shared);
struct comp_buffer *buffer_new(const struct sof_ipc_buffer *desc, bool is_shared);
#if CONFIG_ZEPHYR_DP_SCHEDULER
/*
Expand Down Expand Up @@ -226,6 +228,8 @@ int buffer_create_shadow_dp_queue(struct comp_buffer *buffer, bool at_input);
int buffer_sync_shadow_dp_queue(struct comp_buffer *buffer, size_t limit);
#endif /* CONFIG_ZEPHYR_DP_SCHEDULER */
int buffer_set_size(struct comp_buffer *buffer, uint32_t size, uint32_t alignment);
int buffer_set_size_range(struct comp_buffer *buffer, size_t preferred_size, size_t minimum_size,
uint32_t alignment);
void buffer_free(struct comp_buffer *buffer);
void buffer_zero(struct comp_buffer *buffer);

Expand Down Expand Up @@ -286,11 +290,8 @@ static inline void buffer_reset_pos(struct comp_buffer *buffer, void *data)
}

/* Run-time buffer re-configuration calls this too, so it must use cached access */
static inline void buffer_init(struct comp_buffer *buffer,
uint32_t size, uint32_t caps)
static inline void buffer_init_stream(struct comp_buffer *buffer, size_t size)
{
buffer->caps = caps;

/* addr should be set in alloc function */
audio_stream_init(&buffer->stream, buffer->stream.addr, size);
}
Expand Down