From da10ef9d42ade26105c6c5f0cbb99812ed941006 Mon Sep 17 00:00:00 2001 From: Adrian Bonislawski Date: Tue, 7 Mar 2023 15:02:11 +0100 Subject: [PATCH 1/5] probe: add support for zephyr native drivers This patch ports probe component to use zephyr native drivers. Signed-off-by: Adrian Bonislawski Signed-off-by: Serhiy Katsyuba --- src/probe/probe.c | 99 +++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 96 insertions(+), 3 deletions(-) diff --git a/src/probe/probe.c b/src/probe/probe.c index 8a9704e700c2..e5b8104d9e62 100644 --- a/src/probe/probe.c +++ b/src/probe/probe.c @@ -121,6 +121,7 @@ static int probe_dma_buffer_init(struct probe_dma_buf *buffer, uint32_t size, return 0; } +#if !CONFIG_ZEPHYR_NATIVE_DRIVERS /** * \brief Request DMA and initialize DMA for probes with correct alignment, * size and specific channel. @@ -191,7 +192,67 @@ static int probe_dma_init(struct probe_dma_ext *dma, uint32_t direction) return 0; } +#else +static int probe_dma_init(struct probe_dma_ext *dma, uint32_t direction) +{ + uint32_t addr_align; + uint32_t channel; + struct dma_config dma_cfg; + struct dma_block_config dma_block_cfg; + int err = 0; + + channel = ((union ipc4_connector_node_id)dma->stream_tag).f.v_index; + + /* request DMA in the dir LMEM->HMEM with shared access */ + dma->dc.dmac = dma_get(direction, 0, DMA_DEV_HOST, + DMA_ACCESS_SHARED); + if (!dma->dc.dmac) { + tr_err(&pr_tr, "probe_dma_init(): dma->dc.dmac = NULL"); + return -ENODEV; + } + + /* get required address alignment for dma buffer */ + err = dma_get_attribute(dma->dc.dmac->z_dev, DMA_ATTR_BUFFER_ADDRESS_ALIGNMENT, + &addr_align); + if (err < 0) + return err; + + channel = dma_request_channel(dma->dc.dmac->z_dev, &channel); + if (channel < 0) { + tr_err(&pr_tr, "probe_dma_init(): dma_request_channel() failed"); + return -EINVAL; + } + dma->dc.chan = &dma->dc.dmac->chan[channel]; + + /* initialize dma buffer */ + err = probe_dma_buffer_init(&dma->dmapb, PROBE_BUFFER_LOCAL_SIZE, addr_align); + if (err < 0) + return err; + + dma_cfg.block_count = 1; + dma_cfg.source_data_size = sizeof(uint32_t); + dma_cfg.dest_data_size = sizeof(uint32_t); + dma_cfg.head_block = &dma_block_cfg; + dma_block_cfg.block_size = (uint32_t)dma->dmapb.size; + + switch (direction) { + case DMA_DIR_LMEM_TO_HMEM: + dma_cfg.channel_direction = MEMORY_TO_HOST; + dma_block_cfg.source_address = (uint32_t)dma->dmapb.addr; + break; + case DMA_DIR_HMEM_TO_LMEM: + dma_cfg.channel_direction = HOST_TO_MEMORY; + dma_block_cfg.dest_address = (uint32_t)dma->dmapb.addr; + break; + } + + err = dma_config(dma->dc.dmac->z_dev, dma->dc.chan->index, &dma_cfg); + if (err < 0) + return err; + return 0; +} +#endif /** * \brief Stop, deinit and free DMA and buffer used by probes. * @@ -200,14 +261,20 @@ static int probe_dma_init(struct probe_dma_ext *dma, uint32_t direction) static int probe_dma_deinit(struct probe_dma_ext *dma) { int err = 0; - +#if CONFIG_ZEPHYR_NATIVE_DRIVERS + err = dma_stop(dma->dc.dmac->z_dev, dma->dc.chan->index); +#else err = dma_stop_legacy(dma->dc.chan); +#endif if (err < 0) { tr_err(&pr_tr, "probe_dma_deinit(): dma_stop() failed"); return err; } - +#if CONFIG_ZEPHYR_NATIVE_DRIVERS + dma_release_channel(dma->dc.dmac->z_dev, dma->dc.chan->index); +#else dma_channel_put_legacy(dma->dc.chan); +#endif dma_put(dma->dc.dmac); rfree((void *)dma->dmapb.addr); @@ -249,10 +316,15 @@ static enum task_state probe_task(void *data) avail = _probe->ext_dma.dmapb.end_addr - _probe->ext_dma.dmapb.r_ptr; if (avail > 0) +#if CONFIG_ZEPHYR_NATIVE_DRIVERS + err = dma_reload(_probe->ext_dma.dc.dmac->z_dev, + _probe->ext_dma.dc.chan->index, 0, 0, avail); +#else err = dma_copy_to_host_nowait(&_probe->ext_dma.dc, &_probe->ext_dma.config, 0, (void *)_probe->ext_dma.dmapb.r_ptr, avail); +#endif else return SOF_TASK_STATE_RESCHEDULE; @@ -307,8 +379,11 @@ int probe_init(const struct probe_dma *probe_dma) _probe->ext_dma.stream_tag = PROBE_DMA_INVALID; return err; } - +#if CONFIG_ZEPHYR_NATIVE_DRIVERS + err = dma_start(_probe->ext_dma.dc.dmac->z_dev, _probe->ext_dma.dc.chan->index); +#else err = dma_start_legacy(_probe->ext_dma.dc.chan); +#endif if (err < 0) { tr_err(&pr_tr, "probe_init(): failed to start extraction dma"); @@ -885,9 +960,17 @@ static void probe_cb_produce(void *arg, enum notify_id type, void *data) } dma = &_probe->inject_dma[j]; /* get avail data info */ +#if CONFIG_ZEPHYR_NATIVE_DRIVERS + struct dma_status stat; + + ret = dma_get_status(dma->dc.dmac->z_dev, dma->dc.chan->index, &stat); + dma->dmapb.avail = stat.pending_length; + free_bytes = stat.free; +#else ret = dma_get_data_size_legacy(dma->dc.chan, &dma->dmapb.avail, &free_bytes); +#endif if (ret < 0) { tr_err(&pr_tr, "probe_cb_produce(): dma_get_data_size() failed, ret = %u", ret); @@ -929,10 +1012,15 @@ static void probe_cb_produce(void *arg, enum notify_id type, void *data) /* check if copy_bytes is still valid for dma copy */ if (copy_bytes > 0) { +#if CONFIG_ZEPHYR_NATIVE_DRIVERS + ret = dma_reload(dma->dc.dmac->z_dev, + dma->dc.chan->index, 0, 0, copy_bytes); +#else ret = dma_copy_to_host_nowait(&dma->dc, &dma->config, 0, (void *)dma->dmapb.r_ptr, copy_bytes); +#endif if (ret < 0) goto err; @@ -1161,7 +1249,12 @@ int probe_point_add(uint32_t count, const struct probe_point *probe) return -EINVAL; } +#if CONFIG_ZEPHYR_NATIVE_DRIVERS + if (dma_start(_probe->inject_dma[j].dc.dmac->z_dev, + _probe->inject_dma[j].dc.chan->index) < 0) { +#else if (dma_start_legacy(_probe->inject_dma[j].dc.chan) < 0) { +#endif tr_err(&pr_tr, "probe_point_add(): failed to start dma"); return -EBUSY; From c0f293df68b0058e6b91e1172140b77341fa447a Mon Sep 17 00:00:00 2001 From: Serhiy Katsyuba Date: Thu, 3 Aug 2023 18:07:29 +0200 Subject: [PATCH 2/5] audio: Put buffer state log under CONFIG_SOF_LOG_DBG_BUFFER switch comp_update_buffer_consume() and comp_update_buffer_produce() generate too much log output. Usually such amount of logs results in many log messages been dropped. It is also results in significant CPU load if selected log backend formats log messages at runtime. This patch adds a separate switch to enable these logs only when necessary. Default value is 'n'. Signed-off-by: Serhiy Katsyuba --- Kconfig.zephyr-log | 10 ++++++++++ src/audio/buffer.c | 8 ++++++++ 2 files changed, 18 insertions(+) diff --git a/Kconfig.zephyr-log b/Kconfig.zephyr-log index f536d5246350..ca0f54c64c82 100644 --- a/Kconfig.zephyr-log +++ b/Kconfig.zephyr-log @@ -51,4 +51,14 @@ config SOF_LOG_LEVEL default 3 if SOF_LOG_LEVEL_INF default 4 if SOF_LOG_LEVEL_DBG +config SOF_LOG_DBG_BUFFER + bool "Log buffer state on each consume/produce call" + default n + help + Dumps buffer struct audio_stream values on each call to comp_update_buffer_consume() + and comp_update_buffer_produce(). + WARNING: Produces too much log output which usually results in many log messaged been + dropped! Also, if selected log backend formats log messages at runtime, enabling this + option results in significant CPU load! + endmenu diff --git a/src/audio/buffer.c b/src/audio/buffer.c index d39710a7273c..e8439f84e399 100644 --- a/src/audio/buffer.c +++ b/src/audio/buffer.c @@ -228,11 +228,13 @@ void comp_update_buffer_produce(struct comp_buffer __sparse_cache *buffer, uint3 /* return if no bytes */ if (!bytes) { +#if CONFIG_SOF_LOG_DBG_BUFFER buf_dbg(buffer, "comp_update_buffer_produce(), no bytes to produce, source->comp.id = %u, source->comp.type = %u, sink->comp.id = %u, sink->comp.type = %u", buffer->source ? dev_comp_id(buffer->source) : (unsigned int)UINT32_MAX, buffer->source ? dev_comp_type(buffer->source) : (unsigned int)UINT32_MAX, buffer->sink ? dev_comp_id(buffer->sink) : (unsigned int)UINT32_MAX, buffer->sink ? dev_comp_type(buffer->sink) : (unsigned int)UINT32_MAX); +#endif return; } @@ -242,6 +244,7 @@ void comp_update_buffer_produce(struct comp_buffer __sparse_cache *buffer, uint3 notifier_event(cache_to_uncache(buffer), NOTIFIER_ID_BUFFER_PRODUCE, NOTIFIER_TARGET_CORE_LOCAL, &cb_data, sizeof(cb_data)); +#if CONFIG_SOF_LOG_DBG_BUFFER buf_dbg(buffer, "comp_update_buffer_produce(), ((buffer->avail << 16) | buffer->free) = %08x, ((buffer->id << 16) | buffer->size) = %08x", (audio_stream_get_avail_bytes(&buffer->stream) << 16) | audio_stream_get_free_bytes(&buffer->stream), @@ -251,6 +254,7 @@ void comp_update_buffer_produce(struct comp_buffer __sparse_cache *buffer, uint3 (char *)audio_stream_get_addr(&buffer->stream)) << 16 | ((char *)audio_stream_get_wptr(&buffer->stream) - (char *)audio_stream_get_addr(&buffer->stream))); +#endif } void comp_update_buffer_consume(struct comp_buffer __sparse_cache *buffer, uint32_t bytes) @@ -263,11 +267,13 @@ void comp_update_buffer_consume(struct comp_buffer __sparse_cache *buffer, uint3 /* return if no bytes */ if (!bytes) { +#if CONFIG_SOF_LOG_DBG_BUFFER buf_dbg(buffer, "comp_update_buffer_consume(), no bytes to consume, source->comp.id = %u, source->comp.type = %u, sink->comp.id = %u, sink->comp.type = %u", buffer->source ? dev_comp_id(buffer->source) : (unsigned int)UINT32_MAX, buffer->source ? dev_comp_type(buffer->source) : (unsigned int)UINT32_MAX, buffer->sink ? dev_comp_id(buffer->sink) : (unsigned int)UINT32_MAX, buffer->sink ? dev_comp_type(buffer->sink) : (unsigned int)UINT32_MAX); +#endif return; } @@ -276,6 +282,7 @@ void comp_update_buffer_consume(struct comp_buffer __sparse_cache *buffer, uint3 notifier_event(cache_to_uncache(buffer), NOTIFIER_ID_BUFFER_CONSUME, NOTIFIER_TARGET_CORE_LOCAL, &cb_data, sizeof(cb_data)); +#if CONFIG_SOF_LOG_DBG_BUFFER buf_dbg(buffer, "comp_update_buffer_consume(), (buffer->avail << 16) | buffer->free = %08x, (buffer->id << 16) | buffer->size = %08x, (buffer->r_ptr - buffer->addr) << 16 | (buffer->w_ptr - buffer->addr)) = %08x", (audio_stream_get_avail_bytes(&buffer->stream) << 16) | audio_stream_get_free_bytes(&buffer->stream), @@ -284,6 +291,7 @@ void comp_update_buffer_consume(struct comp_buffer __sparse_cache *buffer, uint3 (char *)audio_stream_get_addr(&buffer->stream)) << 16 | ((char *)audio_stream_get_wptr(&buffer->stream) - (char *)audio_stream_get_addr(&buffer->stream))); +#endif } /* From 735f8eeba1d4a85cc4d56603941d645516d5633c Mon Sep 17 00:00:00 2001 From: Serhiy Katsyuba Date: Fri, 28 Jul 2023 14:05:06 +0200 Subject: [PATCH 3/5] module_adapter: Enable buffer produce notifications required by probe Probe module subscribes to buffer produce notifications in order to perform data extraction or injection. Hence this fix is required to enable probe feature. Signed-off-by: Serhiy Katsyuba --- src/audio/module_adapter/module_adapter.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/audio/module_adapter/module_adapter.c b/src/audio/module_adapter/module_adapter.c index d40175c675db..a1e9ff9be57f 100644 --- a/src/audio/module_adapter/module_adapter.c +++ b/src/audio/module_adapter/module_adapter.c @@ -858,7 +858,7 @@ static int module_adapter_audio_stream_copy_1to1(struct comp_dev *dev) buffer_stream_writeback(sink_c, mod->output_buffers[0].size); if (mod->output_buffers[0].size) - audio_stream_produce(&sink_c->stream, mod->output_buffers[0].size); + comp_update_buffer_produce(sink_c, mod->output_buffers[0].size); /* release all buffers */ buffer_release(sink_c); @@ -973,7 +973,7 @@ static int module_adapter_audio_stream_type_copy(struct comp_dev *dev) if (!mod->skip_sink_buffer_writeback) buffer_stream_writeback(sink_c, mod->output_buffers[i].size); if (mod->output_buffers[i].size) - audio_stream_produce(&sink_c->stream, mod->output_buffers[i].size); + comp_update_buffer_produce(sink_c, mod->output_buffers[i].size); } mod->total_data_produced += mod->output_buffers[0].size; From 57c0dffe91e584f9408dffcd2481b4db4c639c3f Mon Sep 17 00:00:00 2001 From: Serhiy Katsyuba Date: Fri, 28 Jul 2023 14:24:09 +0200 Subject: [PATCH 4/5] probe: Fix injection probe creation Both extraction and injection probes require to subscribe to buffer produce notification. Hence notification subscription logic should be enabled for both types of probes. Signed-off-by: Serhiy Katsyuba --- src/probe/probe.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/probe/probe.c b/src/probe/probe.c index e5b8104d9e62..91344e08c56a 100644 --- a/src/probe/probe.c +++ b/src/probe/probe.c @@ -1164,7 +1164,7 @@ int probe_point_add(uint32_t count, const struct probe_point *probe) fw_logs = enable_logs(&probe[i]); - if (!fw_logs && probe[i].purpose == PROBE_PURPOSE_EXTRACTION) { + if (!fw_logs) { #if CONFIG_IPC_MAJOR_4 dev = ipc_get_comp_by_id(ipc_get(), IPC4_COMP_ID(buf_id->fields.module_id, From daa1231359912a406c47e24bd531f11e76ba4767 Mon Sep 17 00:00:00 2001 From: Serhiy Katsyuba Date: Fri, 28 Jul 2023 17:55:24 +0200 Subject: [PATCH 5/5] app: Enable probe for MTL Enables extraction and injection probes for MTL platform. NOTE: this commit does NOT enable probe log backend. Signed-off-by: Serhiy Katsyuba --- app/boards/intel_adsp_ace15_mtpm.conf | 3 +++ 1 file changed, 3 insertions(+) diff --git a/app/boards/intel_adsp_ace15_mtpm.conf b/app/boards/intel_adsp_ace15_mtpm.conf index c1ddb5416118..cc4fc606ceed 100644 --- a/app/boards/intel_adsp_ace15_mtpm.conf +++ b/app/boards/intel_adsp_ace15_mtpm.conf @@ -88,3 +88,6 @@ CONFIG_CLOCK_CONTROL=y CONFIG_DEBUG_COREDUMP=y CONFIG_DEBUG_COREDUMP_BACKEND_INTEL_ADSP_MEM_WINDOW=y CONFIG_DEBUG_COREDUMP_MEMORY_DUMP_MIN=y + +CONFIG_PROBE=y +CONFIG_PROBE_DMA_MAX=2