diff --git a/src/audio/base_fw.c b/src/audio/base_fw.c index 0936b21a28df..c84e37e6b5f9 100644 --- a/src/audio/base_fw.c +++ b/src/audio/base_fw.c @@ -428,6 +428,20 @@ int set_perf_meas_state(const char *data) return IPC4_SUCCESS; } +static int extended_global_perf_data_get(uint32_t *data_off_size, char *data) +{ + int ret; + struct extended_global_perf_data *perf_data = (struct extended_global_perf_data *)data; + + ret = get_extended_performance_data(perf_data); + if (ret < 0) + return ret; + *data_off_size = sizeof(*perf_data) + + perf_data->perf_item_count * sizeof(struct ext_perf_data_item); + + return IPC4_SUCCESS; +} + static int global_perf_data_get(uint32_t *data_off_size, char *data) { int ret; @@ -481,6 +495,8 @@ static int basefw_get_large_config(struct comp_dev *dev, return basefw_modules_info_get(data_offset, data); case IPC4_LIBRARIES_INFO_GET: return basefw_libraries_info_get(data_offset, data); + case IPC4_EXTENDED_GLOBAL_PERF_DATA: + return extended_global_perf_data_get(data_offset, data); case IPC4_GLOBAL_PERF_DATA: return global_perf_data_get(data_offset, data); /* TODO: add more support */ diff --git a/src/debug/telemetry/telemetry.c b/src/debug/telemetry/telemetry.c index 1d31ce4af370..29bc3cdf6c42 100644 --- a/src/debug/telemetry/telemetry.c +++ b/src/debug/telemetry/telemetry.c @@ -205,6 +205,67 @@ int free_performance_data(struct perf_data_item_comp *item) return IPC4_SUCCESS; } +int get_extended_performance_data(struct extended_global_perf_data * const ext_global_perf_data) +{ + if (!ext_global_perf_data) + return -EINVAL; + + size_t slots_count; + size_t slot_idx = 0; + uint64_t total_dsp_cycles[CONFIG_MAX_CORE_COUNT]; + + /* TODO + * Seting temporary values here. + * Replace this with actual total dsp cycles info once it is available. + */ + for (size_t core_id = 0; core_id < CONFIG_MAX_CORE_COUNT; ++core_id) + total_dsp_cycles[core_id] = 1; + + for (size_t core_id = 0; core_id < CONFIG_MAX_CORE_COUNT; ++core_id) { + if (!(cpu_enabled_cores() & BIT(core_id))) + continue; + + memset(&ext_global_perf_data->perf_items[slot_idx], 0, + sizeof(struct ext_perf_data_item)); + /* 0 is id of base_fw */ + ext_global_perf_data->perf_items[slot_idx].resource_id = 0 + core_id; + ext_global_perf_data->perf_items[slot_idx].module_total_dsp_cycles_consumed = + total_dsp_cycles[core_id]; + ++slot_idx; + } + + slots_count = perf_bitmap_get_occupied(&performance_data_bitmap) + slot_idx; + ext_global_perf_data->perf_item_count = slots_count; + + for (size_t idx = 0; idx < perf_bitmap_get_size(&performance_data_bitmap) && + slot_idx < slots_count; ++idx) { + if (perf_bitmap_is_bit_clear(&performance_data_bitmap, idx)) + continue; + + ext_global_perf_data->perf_items[slot_idx].resource_id = + perf_data_[idx].item.resource_id; + ext_global_perf_data->perf_items[slot_idx].power_mode = + perf_data_[idx].item.power_mode; + ext_global_perf_data->perf_items[slot_idx].is_removed = + perf_data_[idx].item.is_removed; + ext_global_perf_data->perf_items[slot_idx].module_total_dsp_iterations = + perf_data_[idx].total_iteration_count; + ext_global_perf_data->perf_items[slot_idx].module_total_dsp_cycles_consumed = + perf_data_[idx].total_cycles_consumed; + ext_global_perf_data->perf_items[slot_idx].module_peak_dsp_cycles = + perf_data_[idx].item.peak_kcps * 1000; + ext_global_perf_data->perf_items[slot_idx].module_peak_restricted_cycles = + perf_data_[idx].restricted_peak_cycles; + ext_global_perf_data->perf_items[slot_idx].module_total_restricted_cycles_consumed = + perf_data_[idx].restricted_total_cycles; + ext_global_perf_data->perf_items[slot_idx].module_total_restricted_iterations = + perf_data_[idx].restricted_total_iterations; + ext_global_perf_data->perf_items[slot_idx].rsvd = 0; + ++slot_idx; + } + return IPC4_SUCCESS; +} + //============================================================================================== /* Systic variables, one set per core */ diff --git a/src/include/ipc4/base_fw.h b/src/include/ipc4/base_fw.h index 804e6d64dbcc..739b5d429621 100644 --- a/src/include/ipc4/base_fw.h +++ b/src/include/ipc4/base_fw.h @@ -742,6 +742,39 @@ struct perf_data_item { uint32_t avg_kcps; } __packed __aligned(4); +struct ext_perf_data_item { + /* ID of the FW component */ + uint32_t resource_id; + /* 0 - D0, 1 - D0i3. */ + uint32_t power_mode : 1; + uint32_t rsvd : 30; + /* the component still exists (0) or has been already deleted (1) */ + uint32_t is_removed : 1; + /* peak number of DSP cycles used by a module */ + uint32_t module_peak_dsp_cycles; + /* total number of DSP used since by a module start of measurements, */ + uint64_t module_total_dsp_cycles_consumed; + /* how many times a module was executed */ + uint64_t module_total_dsp_iterations; + /* peak number of cycles used by a module. + * It is measured against DSP wall clock + */ + uint32_t module_peak_restricted_cycles; + /* total number of cycles used by a module since start of + * measurements. It is measured against DSP wall clock + */ + uint64_t module_total_restricted_cycles_consumed; + /* how many times a module invoke */ + uint64_t module_total_restricted_iterations; +} __packed __aligned(4); + +struct extended_global_perf_data { + /* Specifies number of items in perf_items array. */ + uint32_t perf_item_count; + /* Array of extended global performance measurements. */ + struct ext_perf_data_item perf_items[0]; +} __packed __aligned(4); + struct perf_data_item_comp { struct perf_data_item item; /* Total iteration count of module instance */ diff --git a/src/include/sof/debug/telemetry/telemetry.h b/src/include/sof/debug/telemetry/telemetry.h index 7d5c0d6104fe..f0644bc5b2de 100644 --- a/src/include/sof/debug/telemetry/telemetry.h +++ b/src/include/sof/debug/telemetry/telemetry.h @@ -104,4 +104,6 @@ int free_performance_data(struct perf_data_item_comp *item); int get_performance_data(struct global_perf_data * const global_perf_data); +int get_extended_performance_data(struct extended_global_perf_data * const ext_global_perf_data); + #endif /*__SOF_TELEMETRY_H__ */