diff --git a/src/audio/copier/host_copier.h b/src/audio/copier/host_copier.h index 28605ed9c3ab..9db9028a54d7 100644 --- a/src/audio/copier/host_copier.h +++ b/src/audio/copier/host_copier.h @@ -22,6 +22,10 @@ #include #include "copier.h" +#ifdef CONFIG_SOF_TELEMETRY_IO_PERFORMANCE_MEASUREMENTS +struct io_perf_data_item; +#endif + typedef void (*copy_callback_t)(struct comp_dev *dev, size_t bytes); struct host_data; @@ -112,6 +116,9 @@ struct host_data { uint64_t next_sync; uint64_t period_in_cycles; #endif +#ifdef CONFIG_SOF_TELEMETRY_IO_PERFORMANCE_MEASUREMENTS + struct io_perf_data_item *io_perf_host_byte_count; +#endif }; int host_common_new(struct host_data *hd, struct comp_dev *dev, diff --git a/src/audio/dai-zephyr.c b/src/audio/dai-zephyr.c index 06ac05507ff4..6dda66899c26 100644 --- a/src/audio/dai-zephyr.c +++ b/src/audio/dai-zephyr.c @@ -425,7 +425,7 @@ dai_dma_cb(struct dai_data *dd, struct comp_dev *dev, uint32_t bytes, } #ifdef CONFIG_SOF_TELEMETRY_IO_PERFORMANCE_MEASUREMENTS /* Increment performance counters */ - io_perf_monitor_update_data(dd->io_perf_bytes_count, bytes); + io_perf_monitor_update_data(dd->io_perf_dai_byte_count, bytes); #endif return dma_status; @@ -558,12 +558,12 @@ __cold int dai_common_new(struct dai_data *dd, struct comp_dev *dev, /* ignore perf meas init on case of other dai types */ if (perf_type != IO_PERF_INVALID_ID) { struct io_perf_data_item init_data = {perf_type, - cpu_get_id(), + dai_cfg->dai_index, perf_dir, IO_PERF_POWERED_UP_ENABLED, IO_PERF_D0IX_POWER_MODE, 0, 0, 0 }; - io_perf_monitor_init_data(&dd->io_perf_bytes_count, &init_data); + io_perf_monitor_init_data(&dd->io_perf_dai_byte_count, &init_data); } #endif @@ -617,7 +617,7 @@ __cold void dai_common_free(struct dai_data *dd) assert_can_be_cold(); #ifdef CONFIG_SOF_TELEMETRY_IO_PERFORMANCE_MEASUREMENTS - io_perf_monitor_release_slot(dd->io_perf_bytes_count); + io_perf_monitor_release_slot(dd->io_perf_dai_byte_count); #endif if (dd->group) diff --git a/src/audio/host-legacy.c b/src/audio/host-legacy.c index a16b3f74e1c3..7f919dbd2eea 100644 --- a/src/audio/host-legacy.c +++ b/src/audio/host-legacy.c @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include @@ -250,6 +251,10 @@ void host_common_update(struct host_data *hd, struct comp_dev *dev, uint32_t byt if (ret < 0) return; +#ifdef CONFIG_SOF_TELEMETRY_IO_PERFORMANCE_MEASUREMENTS + io_perf_monitor_update_data(hd->io_perf_host_byte_count, bytes); +#endif + hd->total_data_processed += bytes; /* new local period, update host buffer position blks @@ -599,6 +604,14 @@ static struct comp_dev *host_new(const struct comp_driver *drv, void host_common_free(struct host_data *hd) { +#ifdef CONFIG_SOF_TELEMETRY_IO_PERFORMANCE_MEASUREMENTS + /* Check for NULL just in case the params() step is omitted */ + if (hd->io_perf_host_byte_count) { + io_perf_monitor_release_slot(hd->io_perf_host_byte_count); + hd->io_perf_host_byte_count = NULL; + } +#endif + dma_put(hd->dma); ipc_msg_free(hd->msg); @@ -829,6 +842,25 @@ int host_common_params(struct host_data *hd, struct comp_dev *dev, pcm_get_conversion_function(audio_stream_get_frm_fmt(&hd->local_buffer->stream), audio_stream_get_frm_fmt(&hd->local_buffer->stream)); +#ifdef CONFIG_SOF_TELEMETRY_IO_PERFORMANCE_MEASUREMENTS + if (!hd->io_perf_host_byte_count) { + /* On the Host side, unlike the DAI side, the port direction values (INPUT/OUTPUT) + * match the stream direction enum values (CAPTURE/PLAYBACK), so we can directly + * use params->direction here. + */ + struct io_perf_data_item init_data = { + IO_PERF_HDA_ID, + hd->chan->index, + params->direction, + IO_PERF_POWERED_UP_ENABLED, + IO_PERF_D0IX_POWER_MODE, + 0, 0, 0 + }; + + io_perf_monitor_init_data(&hd->io_perf_host_byte_count, &init_data); + } +#endif + out: hd->cb_dev = dev; diff --git a/src/audio/host-zephyr.c b/src/audio/host-zephyr.c index bdb5c5759274..613b38bcd00f 100644 --- a/src/audio/host-zephyr.c +++ b/src/audio/host-zephyr.c @@ -24,6 +24,7 @@ #include #include #include +#include #include #include #include @@ -262,6 +263,10 @@ void host_common_update(struct host_data *hd, struct comp_dev *dev, uint32_t byt return; } +#ifdef CONFIG_SOF_TELEMETRY_IO_PERFORMANCE_MEASUREMENTS + io_perf_monitor_update_data(hd->io_perf_host_byte_count, bytes); +#endif + hd->total_data_processed += bytes; /* new local period, update host buffer position blks @@ -771,6 +776,14 @@ __cold void host_common_free(struct host_data *hd) { assert_can_be_cold(); +#ifdef CONFIG_SOF_TELEMETRY_IO_PERFORMANCE_MEASUREMENTS + /* Check for NULL just in case the params() step is omitted */ + if (hd->io_perf_host_byte_count) { + io_perf_monitor_release_slot(hd->io_perf_host_byte_count); + hd->io_perf_host_byte_count = NULL; + } +#endif + sof_dma_put(hd->dma); ipc_msg_free(hd->msg); @@ -1074,6 +1087,24 @@ int host_common_params(struct host_data *hd, struct comp_dev *dev, hd->copy = hd->copy_type == COMP_COPY_ONE_SHOT ? host_copy_one_shot : host_copy_normal; +#ifdef CONFIG_SOF_TELEMETRY_IO_PERFORMANCE_MEASUREMENTS + if (!hd->io_perf_host_byte_count) { + /* On the Host side, unlike the DAI side, the port direction values (INPUT/OUTPUT) + * match the stream direction enum values (CAPTURE/PLAYBACK), so we can directly + * use params->direction here. + */ + struct io_perf_data_item init_data = { + IO_PERF_HDA_ID, + hd->chan->index, + params->direction, + IO_PERF_POWERED_UP_ENABLED, + IO_PERF_D0IX_POWER_MODE, + 0, 0, 0 + }; + io_perf_monitor_init_data(&hd->io_perf_host_byte_count, &init_data); + } +#endif + return 0; err_free_block_cfg: diff --git a/src/debug/telemetry/performance_monitor.c b/src/debug/telemetry/performance_monitor.c index 250102edf5e1..b7aedc5ffa7c 100644 --- a/src/debug/telemetry/performance_monitor.c +++ b/src/debug/telemetry/performance_monitor.c @@ -128,7 +128,7 @@ static bool perf_bitmap_is_bit_clear(struct perf_bitmap * const bitmap, size_t b struct perf_data_item_comp *perf_data_getnext(void) { - int idx; + size_t idx; int ret = perf_bitmap_alloc(&performance_data_bitmap, &idx); if (ret < 0) @@ -138,8 +138,10 @@ struct perf_data_item_comp *perf_data_getnext(void) * ,and always set bit on bitmap alloc. */ ret = perf_bitmap_setbit(&performance_data_bitmap, idx); - if (ret < 0) + if (ret < 0) { + perf_bitmap_free(&performance_data_bitmap, idx); return NULL; + } return &perf_data[idx]; } @@ -445,24 +447,30 @@ int io_perf_monitor_init(void) static struct io_perf_data_item *io_perf_monitor_get_next_slot(struct io_perf_monitor_ctx *self) { - int idx; + size_t idx; int ret; k_spinlock_key_t key = k_spin_lock(&self->lock); ret = perf_bitmap_alloc(&self->io_performance_data_bitmap, &idx); if (ret < 0) - return NULL; + goto out_unlock; /* ref. FW did not set the bits, but here we do it to not have to use * isFree() check that the bitarray does not provide yet. Instead we will use isClear * ,and always set bit on bitmap alloc. */ ret = perf_bitmap_setbit(&self->io_performance_data_bitmap, idx); - if (ret < 0) - return NULL; + if (ret < 0) { + perf_bitmap_free(&self->io_performance_data_bitmap, idx); + goto out_unlock; + } k_spin_unlock(&self->lock, key); return &self->io_perf_data[idx]; + +out_unlock: + k_spin_unlock(&self->lock, key); + return NULL; } int io_perf_monitor_release_slot(struct io_perf_data_item *item) diff --git a/src/include/sof/lib/dai-zephyr.h b/src/include/sof/lib/dai-zephyr.h index 8ff739fa42d5..cb996e147c4f 100644 --- a/src/include/sof/lib/dai-zephyr.h +++ b/src/include/sof/lib/dai-zephyr.h @@ -164,7 +164,7 @@ struct dai_data { #endif #ifdef CONFIG_SOF_TELEMETRY_IO_PERFORMANCE_MEASUREMENTS /* io performance measurement */ - struct io_perf_data_item *io_perf_bytes_count; + struct io_perf_data_item *io_perf_dai_byte_count; #endif /* Copier gain params */ struct copier_gain_params *gain_data;