* [PATCH AUTOSEL 6.12 22/69] ASoC: soc-dapm: set bias_level if snd_soc_dapm_set_bias_level() was successed
[not found] <20250804003119.3620476-1-sashal@kernel.org>
@ 2025-08-04 0:30 ` Sasha Levin
2025-08-04 0:31 ` [PATCH AUTOSEL 6.12 55/69] ASoC: core: Check for rtd == NULL in snd_soc_remove_pcm_runtime() Sasha Levin
2025-08-04 0:31 ` [PATCH AUTOSEL 6.12 69/69] ASoC: qcom: use drvdata instead of component to keep id Sasha Levin
2 siblings, 0 replies; 3+ messages in thread
From: Sasha Levin @ 2025-08-04 0:30 UTC (permalink / raw)
To: patches, stable
Cc: Kuninori Morimoto, Mark Brown, Sasha Levin, lgirdwood,
linux-sound
From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
[ Upstream commit f40ecc2743652c0b0f19935f81baf57c601eb7f0 ]
ASoC has 2 functions to set bias level.
(A) snd_soc_dapm_force_bias_level()
(B) snd_soc_dapm_set_bias_level()
snd_soc_dapm_force_bias_level() (A) will set dapm->bias_level (a) if
successed.
(A) int snd_soc_dapm_force_bias_level(...)
{
...
if (ret == 0)
(a) dapm->bias_level = level;
...
}
snd_soc_dapm_set_bias_level() (B) is also a function that sets bias_level.
It will call snd_soc_dapm_force_bias_level() (A) inside, but doesn't
set dapm->bias_level by itself. One note is that (A) might not be called.
(B) static int snd_soc_dapm_set_bias_level(...)
{
...
ret = snd_soc_card_set_bias_level(...);
...
if (dapm != &card->dapm)
(A) ret = snd_soc_dapm_force_bias_level(...);
...
ret = snd_soc_card_set_bias_level_post(...);
...
}
dapm->bias_level will be set if (A) was called, but might not be set
if (B) was called, even though it calles set_bias_level() function.
We should set dapm->bias_level if we calls
snd_soc_dapm_set_bias_level() (B), too.
Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Link: https://patch.msgid.link/87qzyn4g4h.wl-kuninori.morimoto.gx@renesas.com
Signed-off-by: Mark Brown <broonie@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
LLM Generated explanations, may be completely bogus:
Based on my analysis, here's my assessment:
**Backport Status: YES**
This commit should be backported to stable kernel trees for the
following reasons:
1. **Bug Fix**: This is a clear bug fix that addresses an inconsistency
in bias level management. The commit message clearly explains that
`snd_soc_dapm_set_bias_level()` doesn't always update
`dapm->bias_level`, particularly when dealing with card-level DAPM
contexts where `snd_soc_dapm_force_bias_level()` is not called.
2. **Small and Contained**: The fix is minimal - it only adds 4 lines of
code:
```c
/* success */
if (ret == 0)
snd_soc_dapm_init_bias_level(dapm, level);
```
This ensures that `dapm->bias_level` is always updated when the bias
level change succeeds.
3. **Important Correctness Issue**: The inconsistency could lead to
incorrect bias level tracking, which affects power management
decisions in the ASoC subsystem. Code that checks `dapm->bias_level`
(as shown in lines like `if (dapm->bias_level == SND_SOC_BIAS_ON)`)
may make wrong decisions if the bias level isn't properly tracked.
4. **No Architectural Changes**: This is a straightforward fix that
doesn't introduce new features or change the architecture. It simply
ensures consistent behavior between the two bias level setting
functions.
5. **Low Risk**: The change only affects the success path (when `ret ==
0`) and uses an existing inline function
`snd_soc_dapm_init_bias_level()` that simply sets `dapm->bias_level =
level`. This is the same operation that
`snd_soc_dapm_force_bias_level()` performs on success.
6. **Affects User-Facing Functionality**: Incorrect bias level tracking
can lead to power management issues, potentially causing audio
devices to not power up/down correctly, which directly impacts users.
The commit fixes a real bug where the DAPM bias level state could become
out of sync with the actual hardware state, particularly for card-level
DAPM contexts. This is exactly the type of bug fix that stable kernels
should include - it's small, targeted, fixes a real issue, and has
minimal risk of introducing regressions.
sound/soc/soc-dapm.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c
index 99521c784a9b..196799b2fe24 100644
--- a/sound/soc/soc-dapm.c
+++ b/sound/soc/soc-dapm.c
@@ -740,6 +740,10 @@ static int snd_soc_dapm_set_bias_level(struct snd_soc_dapm_context *dapm,
out:
trace_snd_soc_bias_level_done(dapm, level);
+ /* success */
+ if (ret == 0)
+ snd_soc_dapm_init_bias_level(dapm, level);
+
return ret;
}
--
2.39.5
^ permalink raw reply related [flat|nested] 3+ messages in thread
* [PATCH AUTOSEL 6.12 55/69] ASoC: core: Check for rtd == NULL in snd_soc_remove_pcm_runtime()
[not found] <20250804003119.3620476-1-sashal@kernel.org>
2025-08-04 0:30 ` [PATCH AUTOSEL 6.12 22/69] ASoC: soc-dapm: set bias_level if snd_soc_dapm_set_bias_level() was successed Sasha Levin
@ 2025-08-04 0:31 ` Sasha Levin
2025-08-04 0:31 ` [PATCH AUTOSEL 6.12 69/69] ASoC: qcom: use drvdata instead of component to keep id Sasha Levin
2 siblings, 0 replies; 3+ messages in thread
From: Sasha Levin @ 2025-08-04 0:31 UTC (permalink / raw)
To: patches, stable
Cc: Peter Ujfalusi, Bard Liao, Ranjani Sridharan, Liam Girdwood,
Kai Vehmanen, Mark Brown, Sasha Levin, lgirdwood, linux-sound
From: Peter Ujfalusi <peter.ujfalusi@linux.intel.com>
[ Upstream commit 2d91cb261cac6d885954b8f5da28b5c176c18131 ]
snd_soc_remove_pcm_runtime() might be called with rtd == NULL which will
leads to null pointer dereference.
This was reproduced with topology loading and marking a link as ignore
due to missing hardware component on the system.
On module removal the soc_tplg_remove_link() would call
snd_soc_remove_pcm_runtime() with rtd == NULL since the link was ignored,
no runtime was created.
Signed-off-by: Peter Ujfalusi <peter.ujfalusi@linux.intel.com>
Reviewed-by: Bard Liao <yung-chuan.liao@linux.intel.com>
Reviewed-by: Ranjani Sridharan <ranjani.sridharan@linux.intel.com>
Reviewed-by: Liam Girdwood <liam.r.girdwood@intel.com>
Reviewed-by: Kai Vehmanen <kai.vehmanen@linux.intel.com>
Link: https://patch.msgid.link/20250619084222.559-3-peter.ujfalusi@linux.intel.com
Signed-off-by: Mark Brown <broonie@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
LLM Generated explanations, may be completely bogus:
**YES**
This commit should be backported to stable kernel trees. The analysis
reveals this is a critical NULL pointer dereference fix that prevents
kernel crashes.
**Key reasons for backporting:**
1. **Fixes a Real Crash**: The commit adds a NULL check to prevent a
kernel panic that occurs when `snd_soc_remove_pcm_runtime()` is
called with `rtd == NULL`. The code change shows this clearly:
```c
+ if (!rtd)
+ return;
```
Without this check, the subsequent line
`snd_soc_card_remove_dai_link(card, rtd->dai_link)` would dereference
NULL.
2. **Minimal and Safe Fix**: The change is extremely small (3 lines) and
defensive - it simply adds a NULL check with early return. This
follows the stable kernel rule of minimal, contained fixes.
3. **Affects Production Systems**: The commit message indicates this
occurs during topology loading when hardware components are missing -
a real-world scenario. The issue manifests on module removal when
`soc_tplg_remove_link()` calls the function with NULL.
4. **Well-Reviewed**: The commit has 5 Reviewed-by tags from Intel ASoC
maintainers, indicating thorough review and consensus on the fix.
5. **No Side Effects**: The fix has no architectural changes or new
features - it purely adds defensive programming to prevent crashes.
The function already had EXPORT_SYMBOL_GPL, indicating it's part of
the kernel API that could be called from various contexts.
This is exactly the type of commit stable trees want: a small, obvious
fix for a real crash scenario with no risk of regression.
sound/soc/soc-core.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c
index e3c8d4f20b9c..4ac870c2dafa 100644
--- a/sound/soc/soc-core.c
+++ b/sound/soc/soc-core.c
@@ -1138,6 +1138,9 @@ static int snd_soc_compensate_channel_connection_map(struct snd_soc_card *card,
void snd_soc_remove_pcm_runtime(struct snd_soc_card *card,
struct snd_soc_pcm_runtime *rtd)
{
+ if (!rtd)
+ return;
+
lockdep_assert_held(&client_mutex);
/*
--
2.39.5
^ permalink raw reply related [flat|nested] 3+ messages in thread
* [PATCH AUTOSEL 6.12 69/69] ASoC: qcom: use drvdata instead of component to keep id
[not found] <20250804003119.3620476-1-sashal@kernel.org>
2025-08-04 0:30 ` [PATCH AUTOSEL 6.12 22/69] ASoC: soc-dapm: set bias_level if snd_soc_dapm_set_bias_level() was successed Sasha Levin
2025-08-04 0:31 ` [PATCH AUTOSEL 6.12 55/69] ASoC: core: Check for rtd == NULL in snd_soc_remove_pcm_runtime() Sasha Levin
@ 2025-08-04 0:31 ` Sasha Levin
2 siblings, 0 replies; 3+ messages in thread
From: Sasha Levin @ 2025-08-04 0:31 UTC (permalink / raw)
To: patches, stable
Cc: Srinivas Kandagatla, Kuninori Morimoto, Mark Brown, Sasha Levin,
linux-sound, linux-arm-msm
From: Srinivas Kandagatla <srini@kernel.org>
[ Upstream commit 8167f4f42572818fa8153be2b03e4c2120846603 ]
Qcom lpass is using component->id to keep DAI ID (A).
(S) static int lpass_platform_pcmops_open(
sruct snd_soc_component *component,
struct snd_pcm_substream *substream)
{ ^^^^^^^^^(B0)
...
(B1) struct snd_soc_pcm_runtime *soc_runtime = snd_soc_substream_to_rtd(substream);
(B2) struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(soc_runtime, 0);
...
(B3) unsigned int dai_id = cpu_dai->driver->id;
(A) component->id = dai_id;
...
}
This driver can get dai_id from substream (B0 - B3).
In this driver, below functions get dai_id from component->id (A).
(X) lpass_platform_pcmops_suspend()
(Y) lpass_platform_pcmops_resume()
(Z) lpass_platform_copy()
Here, (Z) can get it from substream (B0 - B3), don't need to use
component->id (A). On suspend/resume (X)(Y), dai_id can only be obtained
from component->id (A), because there is no substream (B0) in function
parameter.
But, component->id (A) itself should not be used for such purpose.
It is intilialized at snd_soc_component_initialize(), and parsed its ID
(= component->id) from device name (a).
int snd_soc_component_initialize(...)
{
...
if (!component->name) {
(a) component->name = fmt_single_name(dev, &component->id);
... ^^^^^^^^^^^^^
}
...
}
Unfortunately, current code is broken to start with.
There are many regmaps that the driver cares about, however its only
managing one (either dp or i2s) in component suspend/resume path.
I2S regmap is mandatory however other regmaps are setup based on flags
like "hdmi_port_enable" and "codec_dma_enable".
Correct thing for suspend/resume path to handle is by checking these
flags, instead of using component->id.
Signed-off-by: Srinivas Kandagatla <srini@kernel.org>
Suggested-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Link: https://patch.msgid.link/87a56ouuob.wl-kuninori.morimoto.gx@renesas.com
Signed-off-by: Mark Brown <broonie@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
LLM Generated explanations, may be completely bogus:
**YES**
This commit should be backported to stable kernel trees for the
following reasons:
**1. Fixes a Real Bug with User Impact:**
- The driver was misusing `component->id` to store DAI ID information,
overwriting the ASoC framework's intended use of this field
- This caused incomplete suspend/resume handling - only one regmap
(either HDMI or I2S) was being handled instead of both when needed
- Users would experience audio failures after suspend/resume cycles,
especially on systems with both HDMI and I2S audio interfaces
**2. Clear Architectural Violation Being Fixed:**
The commit message and code analysis show that `component->id` is
initialized by the ASoC framework during
`snd_soc_component_initialize()` based on device name parsing. The
driver was incorrectly overwriting this value with DAI ID, breaking the
abstraction layer between driver and framework.
**3. Limited Scope and Low Risk:**
- Changes are confined to 3 functions in a single file (`lpass-
platform.c`)
- The fix replaces the problematic `component->id` usage with proper
flag checking (`drvdata->hdmi_port_enable`)
- No API changes or new features added
- The author (Srinivas Kandagatla) is an experienced ASoC maintainer
**4. Improves Suspend/Resume Reliability:**
The fix ensures both HDMI and I2S regmaps are properly handled during
suspend/resume based on actual driver capabilities rather than an
incorrectly stored ID. This makes power management more robust and
predictable.
**5. Long-Standing Issue:**
The problematic code has existed since late 2020 (commits b1824968221c
and 8d1bfc04c974), affecting multiple kernel versions and potentially
many Qualcomm-based devices in the field.
**Backport Recommendation:**
Should be backported to all stable kernels from 5.10 onwards that
contain the original problematic commits. This is a medium-high priority
fix that improves audio subsystem reliability without introducing new
risks.
sound/soc/qcom/lpass-platform.c | 27 +++++++++++++++++----------
1 file changed, 17 insertions(+), 10 deletions(-)
diff --git a/sound/soc/qcom/lpass-platform.c b/sound/soc/qcom/lpass-platform.c
index addd2c4bdd3e..b6a33b1f4f7e 100644
--- a/sound/soc/qcom/lpass-platform.c
+++ b/sound/soc/qcom/lpass-platform.c
@@ -202,7 +202,6 @@ static int lpass_platform_pcmops_open(struct snd_soc_component *component,
struct regmap *map;
unsigned int dai_id = cpu_dai->driver->id;
- component->id = dai_id;
data = kzalloc(sizeof(*data), GFP_KERNEL);
if (!data)
return -ENOMEM;
@@ -1190,13 +1189,14 @@ static int lpass_platform_pcmops_suspend(struct snd_soc_component *component)
{
struct lpass_data *drvdata = snd_soc_component_get_drvdata(component);
struct regmap *map;
- unsigned int dai_id = component->id;
- if (dai_id == LPASS_DP_RX)
+ if (drvdata->hdmi_port_enable) {
map = drvdata->hdmiif_map;
- else
- map = drvdata->lpaif_map;
+ regcache_cache_only(map, true);
+ regcache_mark_dirty(map);
+ }
+ map = drvdata->lpaif_map;
regcache_cache_only(map, true);
regcache_mark_dirty(map);
@@ -1207,14 +1207,19 @@ static int lpass_platform_pcmops_resume(struct snd_soc_component *component)
{
struct lpass_data *drvdata = snd_soc_component_get_drvdata(component);
struct regmap *map;
- unsigned int dai_id = component->id;
+ int ret;
- if (dai_id == LPASS_DP_RX)
+ if (drvdata->hdmi_port_enable) {
map = drvdata->hdmiif_map;
- else
- map = drvdata->lpaif_map;
+ regcache_cache_only(map, false);
+ ret = regcache_sync(map);
+ if (ret)
+ return ret;
+ }
+ map = drvdata->lpaif_map;
regcache_cache_only(map, false);
+
return regcache_sync(map);
}
@@ -1224,7 +1229,9 @@ static int lpass_platform_copy(struct snd_soc_component *component,
unsigned long bytes)
{
struct snd_pcm_runtime *rt = substream->runtime;
- unsigned int dai_id = component->id;
+ struct snd_soc_pcm_runtime *soc_runtime = snd_soc_substream_to_rtd(substream);
+ struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(soc_runtime, 0);
+ unsigned int dai_id = cpu_dai->driver->id;
int ret = 0;
void __iomem *dma_buf = (void __iomem *) (rt->dma_area + pos +
--
2.39.5
^ permalink raw reply related [flat|nested] 3+ messages in thread
end of thread, other threads:[~2025-08-04 0:34 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
[not found] <20250804003119.3620476-1-sashal@kernel.org>
2025-08-04 0:30 ` [PATCH AUTOSEL 6.12 22/69] ASoC: soc-dapm: set bias_level if snd_soc_dapm_set_bias_level() was successed Sasha Levin
2025-08-04 0:31 ` [PATCH AUTOSEL 6.12 55/69] ASoC: core: Check for rtd == NULL in snd_soc_remove_pcm_runtime() Sasha Levin
2025-08-04 0:31 ` [PATCH AUTOSEL 6.12 69/69] ASoC: qcom: use drvdata instead of component to keep id Sasha Levin
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).