From 0823a0636d63129313f8fa247097ad10e8c8132a Mon Sep 17 00:00:00 2001 From: Anant Garg Date: Wed, 4 Nov 2026 18:01:50 +0530 Subject: [PATCH] ASoC: SOF: ipc: Rate-limit IPC transmission error messages When an audio DSP fails to properly reinitialize or desynchronizes after a system suspend/resume cycle, subsequent stream parameter setup requests fail with -EINVAL. In response, userspace audio servers (such as PipeWire) attempt to restart the PCM stream immediately in a rapid retry loop. This unthrottled loop can flood system logs with millions of lines, consuming tens of gigabytes and exhausting root filesystems. Mitigate this logging storm by converting dev_err() to dev_err_ratelimited() in ipc3_wait_tx_done() and ipc4_wait_tx_done(), and adding spcm_err_ratelimited() in sof-audio.h for stream preparation error paths. Closes: https://github.com/thesofproject/sof/issues/10442 Signed-off-by: Anant Garg --- sound/soc/sof/ipc3-pcm.c | 6 +++--- sound/soc/sof/ipc3.c | 17 +++++++++-------- sound/soc/sof/ipc4.c | 8 ++++---- sound/soc/sof/pcm.c | 4 ++-- sound/soc/sof/sof-audio.h | 6 ++++++ 5 files changed, 24 insertions(+), 17 deletions(-) diff --git a/sound/soc/sof/ipc3-pcm.c b/sound/soc/sof/ipc3-pcm.c index b95e888c0adb84..4e6fe714a246eb 100644 --- a/sound/soc/sof/ipc3-pcm.c +++ b/sound/soc/sof/ipc3-pcm.c @@ -119,9 +119,9 @@ static int sof_ipc3_pcm_hw_params(struct snd_soc_component *component, ret = sof_ipc_tx_message(sdev->ipc, &pcm, sizeof(pcm), &ipc_params_reply, sizeof(ipc_params_reply)); if (ret < 0) { - spcm_err(spcm, substream->stream, - "STREAM_PCM_PARAMS ipc failed for stream_tag %d\n", - pcm.params.stream_tag); + spcm_err_ratelimited(spcm, substream->stream, + "STREAM_PCM_PARAMS ipc failed for stream_tag %d\n", + pcm.params.stream_tag); return ret; } diff --git a/sound/soc/sof/ipc3.c b/sound/soc/sof/ipc3.c index 85bb22bbe18d08..235ebac1731b7f 100644 --- a/sound/soc/sof/ipc3.c +++ b/sound/soc/sof/ipc3.c @@ -298,17 +298,17 @@ static int ipc3_wait_tx_done(struct snd_sof_ipc *ipc, void *reply_data) msecs_to_jiffies(sdev->ipc_timeout)); if (ret == 0) { - dev_err(sdev->dev, - "ipc tx timed out for %#x (msg/reply size: %d/%zu)\n", - hdr->cmd, hdr->size, msg->reply_size); + dev_err_ratelimited(sdev->dev, + "ipc tx timed out for %#x (msg/reply size: %d/%zu)\n", + hdr->cmd, hdr->size, msg->reply_size); snd_sof_handle_fw_exception(ipc->sdev, "IPC timeout"); ret = -ETIMEDOUT; } else { ret = msg->reply_error; if (ret < 0) { - dev_err(sdev->dev, - "ipc tx error for %#x (msg/reply size: %d/%zu): %d\n", - hdr->cmd, hdr->size, msg->reply_size, ret); + dev_err_ratelimited(sdev->dev, + "ipc tx error for %#x (msg/reply size: %d/%zu): %d\n", + hdr->cmd, hdr->size, msg->reply_size, ret); } else { if (sof_debug_check_flag(SOF_DBG_PRINT_IPC_SUCCESS_LOGS)) ipc3_log_header(sdev->dev, "ipc tx succeeded", hdr->cmd); @@ -371,8 +371,9 @@ static int sof_ipc3_tx_msg(struct snd_sof_dev *sdev, void *msg_data, size_t msg_ /* ensure the DSP is in D0 before sending a new IPC */ ret = snd_sof_dsp_set_power_state(sdev, &target_state); if (ret < 0) { - dev_err(sdev->dev, "%s: resuming DSP failed: %d\n", - __func__, ret); + dev_err_ratelimited(sdev->dev, + "%s: resuming DSP failed: %d\n", + __func__, ret); return ret; } } diff --git a/sound/soc/sof/ipc4.c b/sound/soc/sof/ipc4.c index bf3a122ee651e8..a07b9d874257a0 100644 --- a/sound/soc/sof/ipc4.c +++ b/sound/soc/sof/ipc4.c @@ -412,15 +412,15 @@ static int ipc4_wait_tx_done(struct snd_sof_ipc *ipc, void *reply_data) ret = wait_event_timeout(msg->waitq, msg->ipc_complete, msecs_to_jiffies(sdev->ipc_timeout)); if (ret == 0) { - dev_err(sdev->dev, "ipc timed out for %#x|%#x\n", - ipc4_msg->primary, ipc4_msg->extension); + dev_err_ratelimited(sdev->dev, "ipc timed out for %#x|%#x\n", + ipc4_msg->primary, ipc4_msg->extension); snd_sof_handle_fw_exception(ipc->sdev, "IPC timeout"); return -ETIMEDOUT; } if (msg->reply_error) { - dev_err(sdev->dev, "ipc error for msg %#x|%#x\n", - ipc4_msg->primary, ipc4_msg->extension); + dev_err_ratelimited(sdev->dev, "ipc error for msg %#x|%#x\n", + ipc4_msg->primary, ipc4_msg->extension); ret = msg->reply_error; } else { if (reply_data) { diff --git a/sound/soc/sof/pcm.c b/sound/soc/sof/pcm.c index 0161c0ae8bbdb4..c67e1c0d8b7aff 100644 --- a/sound/soc/sof/pcm.c +++ b/sound/soc/sof/pcm.c @@ -351,8 +351,8 @@ static int sof_pcm_prepare(struct snd_soc_component *component, ret = sof_pcm_hw_params(component, substream, &spcm->params[substream->stream]); if (ret < 0) { - spcm_err(spcm, substream->stream, - "failed to set hw_params after resume\n"); + spcm_err_ratelimited(spcm, substream->stream, + "failed to set hw_params after resume\n"); return ret; } diff --git a/sound/soc/sof/sof-audio.h b/sound/soc/sof/sof-audio.h index 10b41ab18b7990..feb1311bdd869a 100644 --- a/sound/soc/sof/sof-audio.h +++ b/sound/soc/sof/sof-audio.h @@ -668,6 +668,12 @@ struct snd_sof_widget *snd_sof_find_swidget_by_comp_id(struct snd_sof_dev *sdev, (__spcm)->pcm.pcm_name, __dir, \ ##__VA_ARGS__) +#define spcm_err_ratelimited(__spcm, __dir, __fmt, ...) \ + dev_err_ratelimited((__spcm)->scomp->dev, "%s: pcm%u (%s), dir %d: " __fmt, \ + __func__, le32_to_cpu((__spcm)->pcm.pcm_id), \ + (__spcm)->pcm.pcm_name, __dir, \ + ##__VA_ARGS__) + #if IS_ENABLED(CONFIG_SND_SOC_SOF_COMPRESS) void snd_sof_compr_fragment_elapsed(struct snd_compr_stream *cstream); void snd_sof_compr_init_elapsed_work(struct work_struct *work);