From c6e666acf108783676fd6a9f4f66c8781c9f2919 Mon Sep 17 00:00:00 2001 From: Tomasz Leman Date: Tue, 10 Feb 2026 13:10:02 +0100 Subject: [PATCH 1/4] west: Changes from pull request in review This commit will be replaced with actual zephyr update after necessary changes are merged. Signed-off-by: Tomasz Leman --- west.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/west.yml b/west.yml index 572114fd905d..3de633b7349e 100644 --- a/west.yml +++ b/west.yml @@ -43,7 +43,7 @@ manifest: - name: zephyr repo-path: zephyr - revision: f6a32b27dc17bdb4e1ba4ad84de0c56ca71e257d + revision: pull/103820/head remote: zephyrproject # Import some projects listed in zephyr/west.yml@revision From 1876585f46bdfded233fb4684e4f60ff39d67a68 Mon Sep 17 00:00:00 2001 From: Tomasz Leman Date: Tue, 10 Feb 2026 14:41:33 +0100 Subject: [PATCH 2/4] ipc4: logging: Add dynamic log level control via logs_mask Implement dynamic log level selection based on the logs_mask field from the IPC4_ENABLE_LOGS command, allowing the host to control firmware logging verbosity at runtime. Previously, logging was enabled with a fixed compile-time level (CONFIG_SOF_LOG_LEVEL), preventing dynamic control. This change parses the logs_mask[0] bits 0-4 to determine the requested log level and passes it to the backend. Mask bit mapping to Zephyr log levels: - bit 0 (critical/error) -> LOG_LEVEL_ERR (1) - bit 1 (high/warning) -> LOG_LEVEL_WRN (2) - bit 2 (medium) -> LOG_LEVEL_INF (3) - bit 3 (low/info) -> LOG_LEVEL_INF (3) - bit 4 (verbose/debug) -> LOG_LEVEL_DBG (4) The highest set bit determines the maximum log level. This allows the host to request ERROR-only logging for quiet operation, or DEBUG for verbose troubleshooting, without firmware recompilation. Additionally, log_backend_enable() is now always called (it is idempotent and safe for reconfiguration), removing the previous check that prevented level changes on already-active backends. A TODO comment documents that the mask handling should be improved with proper macros or structs in the future for better code maintainability, but the current implementation is sufficient. Signed-off-by: Tomasz Leman --- src/ipc/ipc4/logging.c | 45 +++++++++++++++++++++++++++++++++++++++--- 1 file changed, 42 insertions(+), 3 deletions(-) diff --git a/src/ipc/ipc4/logging.c b/src/ipc/ipc4/logging.c index feb0863f64b7..b5361ff5944e 100644 --- a/src/ipc/ipc4/logging.c +++ b/src/ipc/ipc4/logging.c @@ -140,14 +140,53 @@ int ipc4_logging_enable_logs(bool first_block, log_state = (const struct ipc4_log_state_info *)data; if (log_state->enable) { + uint32_t log_level = LOG_LEVEL_NONE; /* Default if no bits set */ + uint32_t mask = log_state->logs_mask[0]; + + /* TODO: Improve mask handling for better code maintainability + * The logs_mask bits should be defined using proper macros or a struct + * to improve readability and maintainability. Current hardcoded bit + * positions are sufficient for now but should be refactored in the future. + * Possible improvements: + * - Define IPC4_LOG_MASK_* macros for each bit position + * - Create a struct with bitfields for each priority level + * - Add proper documentation in IPC4 specification headers + */ + + /* Determine log level from mask bits 0-4 (priority levels) + * bit 0: critical & error -> LOG_LEVEL_ERR + * bit 1: high & warning -> LOG_LEVEL_WRN + * bit 2: medium -> LOG_LEVEL_INF + * bit 3: low & info -> LOG_LEVEL_INF + * bit 4: verbose & debug -> LOG_LEVEL_DBG + * Check highest bit set to determine maximum log level + */ + if (mask & BIT(4)) + log_level = LOG_LEVEL_DBG; + else if (mask & (BIT(3) | BIT(2))) + log_level = LOG_LEVEL_INF; + else if (mask & BIT(1)) + log_level = LOG_LEVEL_WRN; + else if (mask & BIT(0)) + log_level = LOG_LEVEL_ERR; + adsp_mtrace_log_init(mtrace_log_hook); /* Initialize work queue if not already initialized */ if (!log_work.work.handler) k_work_init_delayable(&log_work, log_work_handler); - /* Enable backend if not already active */ - if (!log_backend_is_active(log_backend)) - log_backend_enable(log_backend, mtrace_log_hook, CONFIG_SOF_LOG_LEVEL); + /* Enable backend with determined log level + * + * Note: If CONFIG_LOG_RUNTIME_FILTERING is not enabled, the log_level + * parameter has no effect - all logs are filtered at compile-time only. + * + * Note: Setting log_level to LOG_LEVEL_NONE will result in no logs being + * output, as all runtime filters will be set to NONE. This behavior will + * be useful in the future when per-source filtering can be specified via + * IPC, allowing selective enabling of specific log sources while keeping + * others disabled. + */ + log_backend_enable(log_backend, mtrace_log_hook, log_level); mtrace_aging_timer = log_state->aging_timer_period; if (mtrace_aging_timer < IPC4_MTRACE_AGING_TIMER_MIN_MS) { From 86eafb3b3539e093d1309b9d37d93e6ab73449fb Mon Sep 17 00:00:00 2001 From: Tomasz Leman Date: Tue, 10 Feb 2026 21:30:40 +0100 Subject: [PATCH 3/4] boards: ace_4.0: Enable runtime log filtering with ERROR default level Enable CONFIG_LOG_RUNTIME_FILTERING and set CONFIG_LOG_RUNTIME_DEFAULT_LEVEL to 1 (ERROR) for all Intel ADSP ACE 4.0 platforms. This provides quiet firmware boot with minimal logging overhead while maintaining full DEBUG compile-time capability for dynamic log level control via IPC. Platforms configured: - intel_adsp_ace40_nvl - intel_adsp_ace40_nvls With these settings: - Firmware boots showing only ERROR level logs (quiet startup) - Host can dynamically increase verbosity to INFO or DEBUG via IPC4_ENABLE_LOGS without recompilation - All log macros (LOG_ERR, LOG_INF, etc.) remain compiled in Runtime filtering default level is set to INFO (3) in debug_overlay.conf to maintain current debug build behavior where logs start at INFO level. This ensures the same feature set is tested with runtime filtering enabled. This works in conjunction with the IPC4 logging handler changes that parse logs_mask to set the appropriate runtime filter level. Signed-off-by: Tomasz Leman --- app/boards/intel_adsp_ace40_nvl.conf | 2 ++ app/boards/intel_adsp_ace40_nvls.conf | 2 ++ app/debug_overlay.conf | 7 +++++++ 3 files changed, 11 insertions(+) diff --git a/app/boards/intel_adsp_ace40_nvl.conf b/app/boards/intel_adsp_ace40_nvl.conf index 75652f508d53..0f60dc5569b1 100644 --- a/app/boards/intel_adsp_ace40_nvl.conf +++ b/app/boards/intel_adsp_ace40_nvl.conf @@ -55,6 +55,8 @@ CONFIG_PM_DEVICE_RUNTIME_ASYNC=n # Zephyr / logging CONFIG_LOG_BACKEND_ADSP=n CONFIG_WINSTREAM_CONSOLE=n +CONFIG_LOG_RUNTIME_FILTERING=y +CONFIG_LOG_RUNTIME_DEFAULT_LEVEL=1 # Zephyr / debug: temporary, until fixed CONFIG_GDBSTUB=n diff --git a/app/boards/intel_adsp_ace40_nvls.conf b/app/boards/intel_adsp_ace40_nvls.conf index 75652f508d53..0f60dc5569b1 100644 --- a/app/boards/intel_adsp_ace40_nvls.conf +++ b/app/boards/intel_adsp_ace40_nvls.conf @@ -55,6 +55,8 @@ CONFIG_PM_DEVICE_RUNTIME_ASYNC=n # Zephyr / logging CONFIG_LOG_BACKEND_ADSP=n CONFIG_WINSTREAM_CONSOLE=n +CONFIG_LOG_RUNTIME_FILTERING=y +CONFIG_LOG_RUNTIME_DEFAULT_LEVEL=1 # Zephyr / debug: temporary, until fixed CONFIG_GDBSTUB=n diff --git a/app/debug_overlay.conf b/app/debug_overlay.conf index 914210d4184d..4cb2bc767023 100644 --- a/app/debug_overlay.conf +++ b/app/debug_overlay.conf @@ -23,3 +23,10 @@ CONFIG_COLD_STORE_EXECUTE_DEBUG=y CONFIG_GDBSTUB=y CONFIG_GDBSTUB_ENTER_IMMEDIATELY=n + +# Logging options +# Set default runtime log level to INFO (3) to maintain expected behavior in SOF CI. +# This ensures firmware starts with INFO level logging, same as previous configuration. +# Testing with runtime filtering enabled ensures the same feature set is validated. +# Note: This setting has no effect if CONFIG_LOG_RUNTIME_FILTERING is disabled. +CONFIG_LOG_RUNTIME_DEFAULT_LEVEL=3 From fb830e5f84ec69e35567c90ed66050544b638e43 Mon Sep 17 00:00:00 2001 From: Tomasz Leman Date: Wed, 11 Feb 2026 12:34:49 +0100 Subject: [PATCH 4/4] drc: Export log_dynamic symbol for LLEXT with runtime filtering Export log_dynamic_drc symbol when CONFIG_LOG_RUNTIME_FILTERING is enabled to fix LLEXT module linking failure. When runtime filtering is enabled, LOG_MODULE_REGISTER() creates both log_const_ and log_dynamic_ structures. LLEXT modules need to link against these symbols at load time. Previously, only log_const_drc was exported, causing the LLEXT linker to fail with: llext: llext_link_plt: PLT: cannot find idx 46 name log_dynamic_drc llext: do_llext_load: Failed to link, ret -2 lib_manager: llext_manager_link_single: linking failed: -2 This prevented the DRC module from loading when built as LLEXT with runtime log filtering enabled. The fix conditionally exports log_dynamic_drc when runtime filtering is configured, allowing the LLEXT module to resolve all required logging symbols. Signed-off-by: Tomasz Leman --- src/audio/drc/drc_log.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/audio/drc/drc_log.c b/src/audio/drc/drc_log.c index f16feaabcedd..d2e0f1efe7ea 100644 --- a/src/audio/drc/drc_log.c +++ b/src/audio/drc/drc_log.c @@ -11,3 +11,6 @@ SOF_DEFINE_REG_UUID(drc); LOG_MODULE_REGISTER(drc, CONFIG_SOF_LOG_LEVEL); DECLARE_TR_CTX(drc_tr, SOF_UUID(drc_uuid), LOG_LEVEL_INFO); EXPORT_SYMBOL(log_const_drc); +#ifdef CONFIG_LOG_RUNTIME_FILTERING +EXPORT_SYMBOL(log_dynamic_drc); +#endif