mailman.alsa-project.org
Sign In Sign Up
Manage this list Sign In Sign Up

Keyboard Shortcuts

Thread View

  • j: Next unread message
  • k: Previous unread message
  • j a: Jump to all threads
  • j l: Jump to MailingList overview

Sound-open-firmware

Thread Start a new thread
Download
Threads by month
  • ----- 2026 -----
  • March
  • February
  • January
  • ----- 2025 -----
  • December
  • November
  • October
  • September
  • August
  • July
  • June
  • May
  • April
  • March
  • February
  • January
  • ----- 2024 -----
  • December
  • November
  • October
  • September
  • August
  • July
  • June
  • May
  • April
  • March
  • February
  • January
  • ----- 2023 -----
  • December
  • November
  • October
  • September
  • August
  • July
  • June
  • May
  • April
  • March
  • February
  • January
  • ----- 2022 -----
  • December
  • November
  • October
  • September
  • August
  • July
  • June
  • May
  • April
  • March
  • February
  • January
  • ----- 2021 -----
  • December
  • November
  • October
  • September
  • August
  • July
  • June
  • May
  • April
  • March
  • February
  • January
  • ----- 2020 -----
  • December
  • November
  • October
  • September
  • August
  • July
  • June
  • May
  • April
  • March
  • February
  • January
  • ----- 2019 -----
  • December
  • November
  • October
  • September
  • August
  • July
  • June
  • May
  • April
  • March
  • February
  • January
  • ----- 2018 -----
  • December
  • November
  • October
  • September
  • August
  • July
  • June
  • May
  • April
  • March
  • February
  • January
  • ----- 2017 -----
  • December
  • November
  • October
  • September
  • August
  • July
  • June
  • May
  • April
  • March
  • February
  • January
  • ----- 2016 -----
  • December
  • November
  • October
sound-open-firmware@alsa-project.org

February 2026

  • 7 participants
  • 6 discussions
[PATCH 0/2] ASoC: SOF: Fix IPC reliability and post-resume SoundWire init
by Cole Leavitt 19 Feb '26

19 Feb '26
Two fixes for SOF IPC4 reliability issues observed on Lenovo ThinkPad P16 Gen 3 (Arrow Lake-S, CS42L43 + CS35L56 over SoundWire): 1. Replace the broken delayed_ipc_tx_msg mechanism with a bounded retry loop. The old deferred dispatch silently drops messages during D0i3 transitions, causing 500ms+ hangs per IPC chunk. 2. Add a platform ops callback (dai_link_hw_ready) so Intel HDA platforms can wait for SoundWire slave initialization before ALH copier setup. Without this, the DSP enters an unrecoverable wedged state when userspace opens a PCM before slaves finish re-enumerating after resume. Tested on ThinkPad P16 Gen 3 with repeated suspend/resume cycles and concurrent audio playback. Cole Leavitt (2): ASoC: SOF: Replace IPC TX busy deferral with bounded retry ASoC: SOF: Add platform ops callback for DAI link hardware readiness sound/soc/sof/intel/cnl.c | 17 ++--------- sound/soc/sof/intel/hda-common-ops.c | 1 + sound/soc/sof/intel/hda-ipc.c | 17 ++--------- sound/soc/sof/intel/hda.c | 44 ++++++++++++++++++++++++++++ sound/soc/sof/intel/hda.h | 14 ++++----- sound/soc/sof/intel/mtl.c | 17 ++--------- sound/soc/sof/ipc4-topology.c | 8 +++++ sound/soc/sof/ipc4.c | 17 +++++++++-- sound/soc/sof/sof-priv.h | 3 ++ 9 files changed, 83 insertions(+), 55 deletions(-) base-commit: 2687c848e57820651b9f69d30c4710f4219f7dbf -- 2.52.0
3 7
0 0
[PATCH 1/2] ASoC: SOF: Replace IPC TX busy deferral with bounded retry
by Cole Leavitt 14 Feb '26

14 Feb '26
The SOF IPC4 platform send_msg functions (hda_dsp_ipc4_send_msg, mtl_ipc_send_msg, cnl_ipc4_send_msg) previously stored the message in delayed_ipc_tx_msg and returned 0 when the TX register was busy. The deferred message was supposed to be dispatched from the IRQ handler when the DSP acknowledged the previous message. This mechanism silently drops messages during D0i3 power transitions because the IRQ handler never fires while the DSP is in a low-power state. The caller then hangs in wait_event_timeout() for up to 500ms per IPC chunk, causing multi-second audio stalls under CPU load. Fix this by making the platform send_msg functions return -EBUSY immediately when the TX register is busy (safe since they execute under spin_lock_irq in sof_ipc_send_msg), and adding a bounded retry loop with usleep_range() in ipc4_tx_msg_unlocked() which only holds the tx_mutex (a sleepable context). The retry loop attempts up to 50 iterations with 100-200us delays, bounding the maximum busy-wait to approximately 10ms instead of the previous 500ms timeout. Also remove the now-dead delayed_ipc_tx_msg field from sof_intel_hda_dev, the dispatch code, and the ack_received tracking variable from all three IRQ thread handlers (hda_dsp_ipc4_irq_thread, mtl_ipc_irq_thread, cnl_ipc4_irq_thread). Signed-off-by: Cole Leavitt <cole(a)unwrap.rs> --- sound/soc/sof/intel/cnl.c | 17 ++--------------- sound/soc/sof/intel/hda-ipc.c | 17 ++--------------- sound/soc/sof/intel/hda.h | 8 -------- sound/soc/sof/intel/mtl.c | 17 ++--------------- sound/soc/sof/ipc4.c | 17 +++++++++++++++-- 5 files changed, 21 insertions(+), 55 deletions(-) diff --git a/sound/soc/sof/intel/cnl.c b/sound/soc/sof/intel/cnl.c index 0cc5725515e7..a2c6c7894a0f 100644 --- a/sound/soc/sof/intel/cnl.c +++ b/sound/soc/sof/intel/cnl.c @@ -37,7 +37,6 @@ irqreturn_t cnl_ipc4_irq_thread(int irq, void *context) { struct sof_ipc4_msg notification_data = {{ 0 }}; struct snd_sof_dev *sdev = context; - bool ack_received = false; bool ipc_irq = false; u32 hipcida, hipctdr; @@ -51,7 +50,6 @@ irqreturn_t cnl_ipc4_irq_thread(int irq, void *context) cnl_ipc_dsp_done(sdev); ipc_irq = true; - ack_received = true; } if (hipctdr & CNL_DSP_REG_HIPCTDR_BUSY) { @@ -101,13 +99,6 @@ irqreturn_t cnl_ipc4_irq_thread(int irq, void *context) /* This interrupt is not shared so no need to return IRQ_NONE. */ dev_dbg_ratelimited(sdev->dev, "nothing to do in IPC IRQ thread\n"); - if (ack_received) { - struct sof_intel_hda_dev *hdev = sdev->pdata->hw_pdata; - - if (hdev->delayed_ipc_tx_msg) - cnl_ipc4_send_msg(sdev, hdev->delayed_ipc_tx_msg); - } - return IRQ_HANDLED; } EXPORT_SYMBOL_NS(cnl_ipc4_irq_thread, "SND_SOC_SOF_INTEL_CNL"); @@ -266,12 +257,8 @@ int cnl_ipc4_send_msg(struct snd_sof_dev *sdev, struct snd_sof_ipc_msg *msg) struct sof_intel_hda_dev *hdev = sdev->pdata->hw_pdata; struct sof_ipc4_msg *msg_data = msg->msg_data; - if (hda_ipc4_tx_is_busy(sdev)) { - hdev->delayed_ipc_tx_msg = msg; - return 0; - } - - hdev->delayed_ipc_tx_msg = NULL; + if (hda_ipc4_tx_is_busy(sdev)) + return -EBUSY; /* send the message via mailbox */ if (msg_data->data_size) diff --git a/sound/soc/sof/intel/hda-ipc.c b/sound/soc/sof/intel/hda-ipc.c index 94425c510861..78449452041c 100644 --- a/sound/soc/sof/intel/hda-ipc.c +++ b/sound/soc/sof/intel/hda-ipc.c @@ -106,12 +106,8 @@ int hda_dsp_ipc4_send_msg(struct snd_sof_dev *sdev, struct snd_sof_ipc_msg *msg) struct sof_intel_hda_dev *hdev = sdev->pdata->hw_pdata; struct sof_ipc4_msg *msg_data = msg->msg_data; - if (hda_ipc4_tx_is_busy(sdev)) { - hdev->delayed_ipc_tx_msg = msg; - return 0; - } - - hdev->delayed_ipc_tx_msg = NULL; + if (hda_ipc4_tx_is_busy(sdev)) + return -EBUSY; /* send the message via mailbox */ if (msg_data->data_size) @@ -168,7 +164,6 @@ irqreturn_t hda_dsp_ipc4_irq_thread(int irq, void *context) { struct sof_ipc4_msg notification_data = {{ 0 }}; struct snd_sof_dev *sdev = context; - bool ack_received = false; bool ipc_irq = false; u32 hipcie, hipct; @@ -182,7 +177,6 @@ irqreturn_t hda_dsp_ipc4_irq_thread(int irq, void *context) hda_dsp_ipc_dsp_done(sdev); ipc_irq = true; - ack_received = true; } if (hipct & HDA_DSP_REG_HIPCT_BUSY) { @@ -236,13 +230,6 @@ irqreturn_t hda_dsp_ipc4_irq_thread(int irq, void *context) /* This interrupt is not shared so no need to return IRQ_NONE. */ dev_dbg_ratelimited(sdev->dev, "nothing to do in IPC IRQ thread\n"); - if (ack_received) { - struct sof_intel_hda_dev *hdev = sdev->pdata->hw_pdata; - - if (hdev->delayed_ipc_tx_msg) - hda_dsp_ipc4_send_msg(sdev, hdev->delayed_ipc_tx_msg); - } - return IRQ_HANDLED; } EXPORT_SYMBOL_NS(hda_dsp_ipc4_irq_thread, "SND_SOC_SOF_INTEL_HDA_COMMON"); diff --git a/sound/soc/sof/intel/hda.h b/sound/soc/sof/intel/hda.h index 562fe8be79c1..ac9f76a5ef97 100644 --- a/sound/soc/sof/intel/hda.h +++ b/sound/soc/sof/intel/hda.h @@ -549,14 +549,6 @@ struct sof_intel_hda_dev { /* work queue for mic privacy state change notification sending */ struct sof_ace3_mic_privacy mic_privacy; - - /* - * Pointing to the IPC message if immediate sending was not possible - * because the downlink communication channel was BUSY at the time. - * The message will be re-tried when the channel becomes free (the ACK - * is received from the DSP for the previous message) - */ - struct snd_sof_ipc_msg *delayed_ipc_tx_msg; }; static inline struct hdac_bus *sof_to_bus(struct snd_sof_dev *s) diff --git a/sound/soc/sof/intel/mtl.c b/sound/soc/sof/intel/mtl.c index 095dcf1a18e4..24dec128f589 100644 --- a/sound/soc/sof/intel/mtl.c +++ b/sound/soc/sof/intel/mtl.c @@ -101,12 +101,8 @@ static int mtl_ipc_send_msg(struct snd_sof_dev *sdev, struct snd_sof_ipc_msg *ms struct sof_intel_hda_dev *hdev = sdev->pdata->hw_pdata; struct sof_ipc4_msg *msg_data = msg->msg_data; - if (hda_ipc4_tx_is_busy(sdev)) { - hdev->delayed_ipc_tx_msg = msg; - return 0; - } - - hdev->delayed_ipc_tx_msg = NULL; + if (hda_ipc4_tx_is_busy(sdev)) + return -EBUSY; /* send the message via mailbox */ if (msg_data->data_size) @@ -559,7 +555,6 @@ static irqreturn_t mtl_ipc_irq_thread(int irq, void *context) { struct sof_ipc4_msg notification_data = {{ 0 }}; struct snd_sof_dev *sdev = context; - bool ack_received = false; bool ipc_irq = false; u32 hipcida; u32 hipctdr; @@ -576,7 +571,6 @@ static irqreturn_t mtl_ipc_irq_thread(int irq, void *context) mtl_ipc_dsp_done(sdev); ipc_irq = true; - ack_received = true; } if (hipctdr & MTL_DSP_REG_HFIPCXTDR_BUSY) { @@ -628,13 +622,6 @@ static irqreturn_t mtl_ipc_irq_thread(int irq, void *context) dev_dbg_ratelimited(sdev->dev, "nothing to do in IPC IRQ thread\n"); } - if (ack_received) { - struct sof_intel_hda_dev *hdev = sdev->pdata->hw_pdata; - - if (hdev->delayed_ipc_tx_msg) - mtl_ipc_send_msg(sdev, hdev->delayed_ipc_tx_msg); - } - return IRQ_HANDLED; } diff --git a/sound/soc/sof/ipc4.c b/sound/soc/sof/ipc4.c index a4a090e6724a..2e24308ef9cc 100644 --- a/sound/soc/sof/ipc4.c +++ b/sound/soc/sof/ipc4.c @@ -365,20 +365,33 @@ static int ipc4_wait_tx_done(struct snd_sof_ipc *ipc, void *reply_data) return ret; } +#define SOF_IPC4_TX_BUSY_RETRIES 50 +#define SOF_IPC4_TX_BUSY_DELAY_US 100 +#define SOF_IPC4_TX_BUSY_DELAY_MAX_US 200 + static int ipc4_tx_msg_unlocked(struct snd_sof_ipc *ipc, void *msg_data, size_t msg_bytes, void *reply_data, size_t reply_bytes) { struct sof_ipc4_msg *ipc4_msg = msg_data; struct snd_sof_dev *sdev = ipc->sdev; - int ret; + int ret, i; if (msg_bytes > ipc->max_payload_size || reply_bytes > ipc->max_payload_size) return -EINVAL; sof_ipc4_log_header(sdev->dev, "ipc tx ", msg_data, true); - ret = sof_ipc_send_msg(sdev, msg_data, msg_bytes, reply_bytes); + for (i = 0; i < SOF_IPC4_TX_BUSY_RETRIES; i++) { + ret = sof_ipc_send_msg(sdev, msg_data, msg_bytes, reply_bytes); + if (ret != -EBUSY) + break; + usleep_range(SOF_IPC4_TX_BUSY_DELAY_US, + SOF_IPC4_TX_BUSY_DELAY_MAX_US); + } + if (i == SOF_IPC4_TX_BUSY_RETRIES) + dev_dbg(sdev->dev, "%s: TX still busy after %d retries\n", + __func__, i); if (ret) { dev_err_ratelimited(sdev->dev, "%s: ipc message send for %#x|%#x failed: %d\n", -- 2.52.0
1 0
0 0
[PATCH AUTOSEL 6.19-6.12] ASoC: SOF: ipc4: Support for sending payload along with LARGE_CONFIG_GET
by Sasha Levin 14 Feb '26

14 Feb '26
From: Peter Ujfalusi <peter.ujfalusi(a)linux.intel.com> [ Upstream commit d96cb0b86d6e8bbbbfa425771606f6c1aebc318e ] There are message types when we would need to send a payload along with the LARGE_CONFIG_GET message to provide information to the firmware on what data is requested. Such cases are the ALSA Kcontrol related messages when the high level param_id tells only the type of the control, but the ID/index of the exact control is specified in the payload area. The caller must place the payload for TX before calling the set_get_data() and this payload will be sent alongside with the message to the firmware. The data area will be overwritten by the received data from firmware. Signed-off-by: Peter Ujfalusi <peter.ujfalusi(a)linux.intel.com> Reviewed-by: Seppo Ingalsuo <seppo.ingalsuo(a)linux.intel.com> Reviewed-by: Ranjani Sridharan <ranjani.sridharan(a)linux.intel.com> Reviewed-by: Bard Liao <yung-chuan.liao(a)linux.intel.com> Reviewed-by: Kai Vehmanen <kai.vehmanen(a)linux.intel.com> Link: https://patch.msgid.link/20251217143945.2667-7-peter.ujfalusi@linux.intel.c… Signed-off-by: Mark Brown <broonie(a)kernel.org> Signed-off-by: Sasha Levin <sashal(a)kernel.org> --- LLM Generated explanations, may be completely bogus: Now I have a complete understanding. Here's my analysis: --- ## Comprehensive Analysis ### 1. COMMIT MESSAGE ANALYSIS The subject is "ASoC: SOF: ipc4: Support for sending payload along with LARGE_CONFIG_GET". The commit message says: > "There are message types when we would need to send a payload along with the LARGE_CONFIG_GET message to provide information to the firmware on what data is requested." The specific case it mentions is for ALSA Kcontrol-related messages where the `param_id` only tells the type of control (switch or enum), but the **ID/index of the exact control is specified in the payload area**. Without this patch, the firmware **cannot know which control** is being queried. The message also says: "The data area will be overwritten by the received data from firmware." This explains the `kmemdup` approach — the TX payload needs to be saved before it's overwritten by the RX response. ### 2. CODE CHANGE ANALYSIS **The Bug:** In `sof_ipc4_refresh_generic_control()` (in `ipc4-control.c`, line 243-285), the caller: 1. Allocates `sof_ipc4_control_msg_payload` 2. Sets `data->id = cdata->index` and `data->num_elems = scontrol->num_channels` 3. Points `msg->data_ptr = data` and `msg->data_size = data_size` 4. Calls `sof_ipc4_set_get_kcontrol_data(scontrol, false, true)` (set=false → GET operation) This flows into `sof_ipc4_set_get_data()`. In the **old code** (before this patch), when `set=false` (GET), the code did: ```c tx_size = 0; rx_size = chunk_size; ``` This means `tx_size = 0` — **the payload containing `id` and `num_elems` is NEVER sent to the firmware**. The firmware receives a LARGE_CONFIG_GET request without knowing which specific switch/enum control is being queried. For switch and enum controls (param_ids 200 and 201), the param_id alone is not enough — the firmware needs the control ID in the payload to know which specific control to return data for. **The Fix:** The patch adds a helper function `sof_ipc4_tx_payload_for_get_data()` that checks if the message is for switch or enum controls (param_id 200 or 201). If so, it: 1. Uses `kmemdup()` to save the TX payload (because `data_ptr` will be overwritten by the response) 2. Sets `tx_size` and `tx.data_ptr` in the GET path so the payload IS sent 3. Properly frees the backup buffer on all code paths (error and success) **What happens without the fix:** When firmware sends a notification that a switch/enum control changed, the `comp_data_dirty` flag is set. On the next `sof_ipc4_switch_get()` or `sof_ipc4_enum_get()` call, `sof_ipc4_refresh_generic_control()` tries to fetch the new control values from firmware, but **fails** because the firmware can't identify which control to return data for (it receives no payload with the GET request). This means ALSA mixer applications (like `alsamixer`, PulseAudio/PipeWire) get **wrong or stale control values** — a functional bug for real audio users. ### 3. CLASSIFICATION This is a **functional bug fix**. Without it, reading switch/enum kcontrol values from SOF firmware after a notification fails to return correct data. The commit message frames it as "support for" but it is really fixing broken functionality — the `sof_ipc4_refresh_generic_control` function was already calling `set_get_data` with a payload expecting it to be sent, but the lower layer was silently discarding it. It is NOT a new feature — the switch/enum control GET path already exists (since v6.7). The payload was already being prepared by the caller. The bug is that the IPC layer was not transmitting it. ### 4. SCOPE AND RISK ASSESSMENT - **Files changed:** 1 (`sound/soc/sof/ipc4.c`) - **Lines added:** ~50 (new helper function + modifications to existing function) - **Complexity:** Moderate — adds a `kmemdup`/`kfree` for specific param_ids - **Risk:** Low — the change only affects the GET path for switch/enum controls (param_ids 200, 201). All other GET operations continue to behave exactly as before (`sof_ipc4_tx_payload_for_get_data` returns false, no change in behavior). - **Memory management:** The `kmemdup` buffer is properly freed on all paths (early error return, normal exit). - **Self-contained:** Yes, the patch only modifies `ipc4.c` and adds an include for constants that already exist in the tree. ### 5. USER IMPACT - **Who is affected:** All Intel SOF audio users with switch or enum kcontrols that receive firmware notifications (this is common for hardware-managed controls on modern Intel platforms like Meteor Lake and newer). - **Symptom:** ALSA kcontrols report stale/wrong values after firmware changes them (e.g., mic privacy hardware switches, audio routing enums). - **Severity:** Medium-high — incorrect audio control states affect real audio functionality. ### 6. STABILITY INDICATORS - **4 Reviewed-by tags** from Intel SOF team members (Seppo Ingalsuo, Ranjani Sridharan, Bard Liao, Kai Vehmanen) - **Accepted by Mark Brown** (ASoC subsystem maintainer) - **Author is subsystem maintainer** (Peter Ujfalusi is a SOF maintainer) ### 7. DEPENDENCY CHECK - Requires `SOF_IPC4_SWITCH_CONTROL_PARAM_ID` and `SOF_IPC4_ENUM_CONTROL_PARAM_ID` from `ipc4-topology.h` — these were added in v6.7 (commit `4a2fd607b7ca`) - Requires `sof_ipc4_refresh_generic_control` which was added in v6.8 (commit `f5eb9945cf9c`) - The patch adds `#include "ipc4-topology.h"` to ipc4.c — this is a trivial include addition - The `SOF_IPC4_MOD_EXT_MSG_PARAM_ID_MASK` is in `include/sound/sof/ipc4/header.h` (available in all relevant stable trees) - **Self-contained:** The patch applies cleanly without other dependencies beyond what's already in stable trees ≥6.7 ### 8. CONCERNS - This is part of a larger patch series (patch 7 of N), but examining the code shows it is **self-contained** — it modifies only `sof_ipc4_set_get_data()` in `ipc4.c`, not the callers - The commit message says "Support for sending payload" which sounds like a feature, but the analysis shows it's fixing an existing broken GET path for switch/enum controls - The `sof_ipc4_tx_payload_for_get_data` helper uses a switch statement that currently only matches 2 param_ids — if future param_ids need this treatment, they'd need to be added, but that's expected for an explicitly enumerated list ### CONCLUSION This commit fixes a real functional bug where ALSA switch and enum kcontrol GET operations from SOF firmware fail to send the required payload (control ID/index) to the firmware, causing the firmware to not know which control is being queried. This results in incorrect/stale control values being reported to userspace audio applications. The fix is small (~50 lines in one file), self-contained, well-reviewed by 4 domain experts, low-risk (only affects 2 specific param_ids in the GET path), and fixes a real user-visible audio issue. It applies cleanly to stable trees v6.7+. However, the critical concern is that this is labeled as "patch 7" of a series, and the remaining patches in the series likely depend on this behavior. Without knowing if the other patches add callers that depend on this, the standalone value is limited to fixing `sof_ipc4_refresh_generic_control()` which was already sending payloads that were being silently dropped. The existing caller (`sof_ipc4_refresh_generic_control`) does set `data->id` and `data->num_elems` before calling the GET, expecting it to be sent — so this IS fixing existing broken functionality, not just enabling future functionality. The fix addresses a real bug for SOF audio users and meets stable criteria. **YES** sound/soc/sof/ipc4.c | 44 ++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 42 insertions(+), 2 deletions(-) diff --git a/sound/soc/sof/ipc4.c b/sound/soc/sof/ipc4.c index a4a090e6724a6..20d723f48fff0 100644 --- a/sound/soc/sof/ipc4.c +++ b/sound/soc/sof/ipc4.c @@ -15,6 +15,7 @@ #include "sof-audio.h" #include "ipc4-fw-reg.h" #include "ipc4-priv.h" +#include "ipc4-topology.h" #include "ipc4-telemetry.h" #include "ops.h" @@ -433,6 +434,23 @@ static int sof_ipc4_tx_msg(struct snd_sof_dev *sdev, void *msg_data, size_t msg_ return ret; } +static bool sof_ipc4_tx_payload_for_get_data(struct sof_ipc4_msg *tx) +{ + /* + * Messages that require TX payload with LARGE_CONFIG_GET. + * The TX payload is placed into the IPC message data section by caller, + * which needs to be copied to temporary buffer since the received data + * will overwrite it. + */ + switch (tx->extension & SOF_IPC4_MOD_EXT_MSG_PARAM_ID_MASK) { + case SOF_IPC4_MOD_EXT_MSG_PARAM_ID(SOF_IPC4_SWITCH_CONTROL_PARAM_ID): + case SOF_IPC4_MOD_EXT_MSG_PARAM_ID(SOF_IPC4_ENUM_CONTROL_PARAM_ID): + return true; + default: + return false; + } +} + static int sof_ipc4_set_get_data(struct snd_sof_dev *sdev, void *data, size_t payload_bytes, bool set) { @@ -444,6 +462,8 @@ static int sof_ipc4_set_get_data(struct snd_sof_dev *sdev, void *data, struct sof_ipc4_msg tx = {{ 0 }}; struct sof_ipc4_msg rx = {{ 0 }}; size_t remaining = payload_bytes; + void *tx_payload_for_get = NULL; + size_t tx_data_size = 0; size_t offset = 0; size_t chunk_size; int ret; @@ -469,10 +489,20 @@ static int sof_ipc4_set_get_data(struct snd_sof_dev *sdev, void *data, tx.extension |= SOF_IPC4_MOD_EXT_MSG_FIRST_BLOCK(1); + if (sof_ipc4_tx_payload_for_get_data(&tx)) { + tx_data_size = min(ipc4_msg->data_size, payload_limit); + tx_payload_for_get = kmemdup(ipc4_msg->data_ptr, tx_data_size, + GFP_KERNEL); + if (!tx_payload_for_get) + return -ENOMEM; + } + /* ensure the DSP is in D0i0 before sending IPC */ ret = snd_sof_dsp_set_power_state(sdev, &target_state); - if (ret < 0) + if (ret < 0) { + kfree(tx_payload_for_get); return ret; + } /* Serialise IPC TX */ mutex_lock(&sdev->ipc->tx_mutex); @@ -506,7 +536,15 @@ static int sof_ipc4_set_get_data(struct snd_sof_dev *sdev, void *data, rx.data_size = chunk_size; rx.data_ptr = ipc4_msg->data_ptr + offset; - tx_size = 0; + if (tx_payload_for_get) { + tx_size = tx_data_size; + tx.data_size = tx_size; + tx.data_ptr = tx_payload_for_get; + } else { + tx_size = 0; + tx.data_size = 0; + tx.data_ptr = NULL; + } rx_size = chunk_size; } @@ -553,6 +591,8 @@ static int sof_ipc4_set_get_data(struct snd_sof_dev *sdev, void *data, mutex_unlock(&sdev->ipc->tx_mutex); + kfree(tx_payload_for_get); + return ret; } -- 2.51.0
1 0
0 0
[bug report] ASoC: SOF: sof-audio: Add support for loopback capture
by Dan Carpenter 10 Feb '26

10 Feb '26
[ Smatch checking is paused while we raise funding. #SadFace https://lore.kernel.org/all/aTaiGSbWZ9DJaGo7@stanley.mountain/ -dan ] Hello Ranjani Sridharan, Commit c4b37c21c75d ("ASoC: SOF: sof-audio: Add support for loopback capture") from Feb 4, 2026 (linux-next), leads to the following Smatch static checker warning: sound/soc/sof/sof-audio.c:534 sof_prepare_widgets_in_path() error: uninitialized symbol 'widget_ops'. sound/soc/sof/sof-audio.c 478 static int 479 sof_prepare_widgets_in_path(struct snd_sof_dev *sdev, struct snd_soc_dapm_widget *widget, 480 struct snd_pcm_hw_params *fe_params, 481 struct snd_sof_platform_stream_params *platform_params, 482 struct snd_pcm_hw_params *pipeline_params, int dir, 483 struct snd_soc_dapm_widget_list *list) 484 { 485 const struct sof_ipc_tplg_ops *tplg_ops = sof_ipc_get_ops(sdev, tplg); 486 struct snd_sof_widget *swidget = widget->dobj.private; 487 const struct sof_ipc_tplg_widget_ops *widget_ops; 488 struct snd_soc_dapm_path *p; 489 int ret; 490 491 if (is_virtual_widget(sdev, widget, __func__)) 492 return 0; 493 494 if (!swidget) 495 goto sink_prepare; ^^^^^^^^^^^^^^^^^ widget_ops is uninitialized. 496 497 widget_ops = tplg_ops ? tplg_ops->widget : NULL; 498 if (!widget_ops) 499 return 0; 500 501 if (swidget->spipe && swidget->spipe->direction_valid && 502 !sof_widget_in_same_direction(swidget, dir)) 503 return 0; 504 505 /* skip widgets already prepared or aggregated DAI widgets*/ 506 if (!widget_ops[widget->id].ipc_prepare || swidget->prepared || 507 is_aggregated_dai(swidget)) 508 goto sink_prepare; 509 510 /* prepare the source widget */ 511 ret = widget_ops[widget->id].ipc_prepare(swidget, fe_params, platform_params, 512 pipeline_params, dir); 513 if (ret < 0) { 514 dev_err(sdev->dev, "failed to prepare widget %s\n", widget->name); 515 return ret; 516 } 517 518 swidget->prepared = true; 519 520 sink_prepare: 521 /* prepare all widgets in the sink paths */ 522 snd_soc_dapm_widget_for_each_sink_path(widget, p) { 523 if (!widget_in_list(list, p->sink)) 524 continue; 525 526 if (!p->walking && p->sink->dobj.private) { 527 p->walking = true; 528 ret = sof_prepare_widgets_in_path(sdev, p->sink, fe_params, 529 platform_params, pipeline_params, dir, 530 list); 531 p->walking = false; 532 if (ret < 0) { 533 /* unprepare the source widget */ --> 534 if (widget_ops[widget->id].ipc_unprepare && 535 swidget && swidget->prepared && swidget->use_count == 0) { We need to check that swidget is non-NULL first before checking widget_ops[widget->id].ipc_unprepare, otherwise widget_ops is uninitialized and it leads to a crash. Wait, the zero day bot already reported this on Jan 5th. https://lore.kernel.org/all/202512232221.Ub3HwrFz-lkp@intel.com/ 536 widget_ops[widget->id].ipc_unprepare(swidget); 537 swidget->prepared = false; 538 } 539 return ret; 540 } 541 } 542 } 543 544 return 0; 545 } regards, dan carpenter
1 0
0 0
[PATCH] ASoC: SOF: Intel: select CONFIG_SND_HDA_EXT_CORE from SND_SOC_SOF_HDA_COMMON
by Arnd Bergmann 09 Feb '26

09 Feb '26
From: Arnd Bergmann <arnd(a)arndb.de> The _hda_dsp_stream_put() function now depends on the snd_hdac_ext_stream_release() interface from SND_HDA_EXT_CORE: x86_64-linux-ld: vmlinux.o: in function `_hda_dsp_stream_put': hda-stream.c:(.text+0xfac605): undefined reference to `snd_hdac_ext_stream_release' Select this symbol the same way the other users do. Fixes: 89e1d632bb29 ("ASoC: SOF: Intel: add hda_dsp_stream_pair_get/put helpers") Signed-off-by: Arnd Bergmann <arnd(a)arndb.de> --- --- sound/soc/sof/intel/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/sound/soc/sof/intel/Kconfig b/sound/soc/sof/intel/Kconfig index 0c8acb1db662..0e52225bddae 100644 --- a/sound/soc/sof/intel/Kconfig +++ b/sound/soc/sof/intel/Kconfig @@ -325,6 +325,7 @@ config SND_SOC_SOF_NOVALAKE config SND_SOC_SOF_HDA_COMMON tristate + select SND_HDA_EXT_CORE config SND_SOC_SOF_HDA_GENERIC tristate -- 2.39.5
2 1
0 0
[bug report] ASoC: SOF: ipc4-control: Add support for generic bytes control
by Dan Carpenter 06 Feb '26

06 Feb '26
[ Smatch checking is paused while we raise funding. #SadFace https://lore.kernel.org/all/aTaiGSbWZ9DJaGo7@stanley.mountain/ -dan ] Hello Peter Ujfalusi, Commit 2a28b5240f2b ("ASoC: SOF: ipc4-control: Add support for generic bytes control") from Dec 17, 2025 (linux-next), leads to the following Smatch static checker warning: sound/soc/sof/ipc4-control.c:365 sof_ipc4_refresh_bytes_control() warn: missing error code here? '_dev_err()' failed. 'ret' = '0' sound/soc/sof/ipc4-control.c 324 static int 325 sof_ipc4_refresh_bytes_control(struct snd_sof_control *scontrol, bool lock) 326 { 327 struct sof_ipc4_control_data *cdata = scontrol->ipc_control_data; 328 struct snd_soc_component *scomp = scontrol->scomp; 329 struct sof_ipc4_control_msg_payload *msg_data; 330 struct sof_abi_hdr *data = cdata->data; 331 struct sof_ipc4_msg *msg = &cdata->msg; 332 size_t data_size; 333 int ret = 0; 334 335 if (!scontrol->comp_data_dirty) 336 return 0; 337 338 if (!pm_runtime_active(scomp->dev)) 339 return 0; 340 341 data_size = scontrol->max_size - sizeof(*data); 342 if (data_size < sizeof(*msg_data)) 343 data_size = sizeof(*msg_data); 344 345 msg_data = kzalloc(data_size, GFP_KERNEL); 346 if (!msg_data) 347 return -ENOMEM; 348 349 msg->extension = SOF_IPC4_MOD_EXT_MSG_PARAM_ID(data->type); 350 351 msg_data->id = cdata->index; 352 msg_data->num_elems = 0; /* ignored for bytes */ 353 354 msg->data_ptr = msg_data; 355 msg->data_size = data_size; 356 357 scontrol->comp_data_dirty = false; 358 ret = sof_ipc4_set_get_kcontrol_data(scontrol, false, lock); 359 if (!ret) { 360 if (msg->data_size > scontrol->max_size - sizeof(*data)) { 361 dev_err(scomp->dev, 362 "%s: no space for data in %s (%zu, %zu)\n", 363 __func__, scontrol->name, msg->data_size, 364 scontrol->max_size - sizeof(*data)); --> 365 goto out; ret = -EINVAL; 366 } 367 368 data->size = msg->data_size; 369 scontrol->size = sizeof(*cdata) + sizeof(*data) + data->size; 370 memcpy(data->data, msg->data_ptr, data->size); 371 } else { 372 dev_err(scomp->dev, "Failed to read control data for %s\n", 373 scontrol->name); 374 scontrol->comp_data_dirty = true; 375 } 376 377 out: 378 msg->data_ptr = NULL; 379 msg->data_size = 0; 380 381 kfree(msg_data); 382 383 return ret; 384 } regards, dan carpenter
1 0
0 0

HyperKitty Powered by HyperKitty version 1.3.12.