* [PATCH 1/7] ASoC: qcom: audioreach: fix module cfg blob size handling
2026-10-23 17:13 [PATCH 0/7] ASoC: qcom: AudioReach and WSA88xx fixes Srinivas Kandagatla
@ 2026-10-23 17:13 ` Srinivas Kandagatla
2026-10-23 17:34 ` sashiko-bot
2026-10-23 17:13 ` [PATCH 2/7] ASoC: codecs: wsa884x: Accept temperatures across the full trim range Srinivas Kandagatla
` (6 subsequent siblings)
7 siblings, 1 reply; 12+ messages in thread
From: Srinivas Kandagatla @ 2026-10-23 17:13 UTC (permalink / raw)
To: Mark Brown, Liam Girdwood
Cc: Jaroslav Kysela, Takashi Iwai, Krzysztof Kozlowski, Alexey Klimov,
Ravi Hothi, linux-sound, linux-arm-msm, linux-kernel, stable,
Srinivas Kandagatla
From: Ravi Hothi <ravi.hothi@oss.qualcomm.com>
audioreach_get_module_priv_data() passes mod_array->size, a byte count,
as the element count of the __le32 data[] flex array. The allocation and
the copy are four times too large, and the memcpy() can read past the end
of the topology firmware buffer. The size is also never checked against
the private data it must lie within, and a zero size makes the loop spin
forever.
Convert the size to a word count, bound the blob by the remaining private
data and reject a zero size. Also check the returned pointer before
storing it in mod->data, as an error pointer there is dereferenced when
the graph is opened.
Fixes: c7ed4c2debfd ("ASoC: qcom: audioreach: add support for static calibration")
Cc: stable@vger.kernel.org
Signed-off-by: Ravi Hothi <ravi.hothi@oss.qualcomm.com>
Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@oss.qualcomm.com>
---
sound/soc/qcom/qdsp6/topology.c | 31 ++++++++++++++++++++++++++-----
1 file changed, 26 insertions(+), 5 deletions(-)
diff --git a/sound/soc/qcom/qdsp6/topology.c b/sound/soc/qcom/qdsp6/topology.c
index faafbc5c0ad0..612d8f03e6e9 100644
--- a/sound/soc/qcom/qdsp6/topology.c
+++ b/sound/soc/qcom/qdsp6/topology.c
@@ -312,22 +312,37 @@ audioreach_get_module_priv_data(const struct snd_soc_tplg_private *private)
for (sz = 0; sz < le32_to_cpu(private->size); ) {
const struct snd_soc_tplg_vendor_array *mod_array;
+ u32 array_size;
mod_array = (struct snd_soc_tplg_vendor_array *)((u8 *)private->array + sz);
+ array_size = le32_to_cpu(mod_array->size);
+
if (le32_to_cpu(mod_array->type) == SND_SOC_AR_TPLG_MODULE_CFG_TYPE) {
struct audioreach_module_priv_data *pdata;
+ u32 nwords;
+
+ /* size is the byte count of the __le32 data[] */
+ nwords = array_size / sizeof(__le32);
+
+ /* the blob must lie within the private data */
+ if (sizeof(*pdata) + (u64)array_size >
+ le32_to_cpu(private->size) - sz)
+ return ERR_PTR(-EINVAL);
- pdata = kzalloc_flex(*pdata, data,
- le32_to_cpu(mod_array->size));
+ pdata = kzalloc_flex(*pdata, data, nwords);
if (!pdata)
return ERR_PTR(-ENOMEM);
- memcpy(pdata, ((u8 *)private->data + sz), struct_size(pdata, data,
- le32_to_cpu(mod_array->size)));
+ memcpy(pdata, ((u8 *)private->data + sz),
+ struct_size(pdata, data, nwords));
return pdata;
}
- sz = sz + le32_to_cpu(mod_array->size);
+ /* a zero size would never advance the walk */
+ if (!array_size)
+ return ERR_PTR(-EINVAL);
+
+ sz = sz + array_size;
}
return NULL;
@@ -611,6 +626,12 @@ static int audioreach_widget_load_module_common(struct snd_soc_component *compon
return mod ? PTR_ERR(mod) : -ENODEV;
mod->data = audioreach_get_module_priv_data(&tplg_w->priv);
+ if (IS_ERR(mod->data)) {
+ int rc = PTR_ERR(mod->data);
+
+ mod->data = NULL;
+ return rc;
+ }
dobj = &w->dobj;
dobj->private = mod;
--
2.47.3
^ permalink raw reply related [flat|nested] 12+ messages in thread* Re: [PATCH 1/7] ASoC: qcom: audioreach: fix module cfg blob size handling
2026-10-23 17:13 ` [PATCH 1/7] ASoC: qcom: audioreach: fix module cfg blob size handling Srinivas Kandagatla
@ 2026-10-23 17:34 ` sashiko-bot
0 siblings, 0 replies; 12+ messages in thread
From: sashiko-bot @ 2026-10-23 17:34 UTC (permalink / raw)
To: Srinivas Kandagatla; +Cc: linux-sound
Thank you for your contribution! Sashiko AI review found 3 potential issue(s) to consider:
- [High] ASoC: qcom: audioreach: module leak and UAF on priv data error
- [High] ASoC: qcom: audioreach: OOB read from array_size truncation to nwords
- [High] ASoC: qcom: audioreach: unchecked mod_array header and size in loop
--
commit 1de183e156fe039ccb5c136361b5dc13fa6c2cdc
Author: Ravi Hothi <ravi.hothi@oss.qualcomm.com>
ASoC: qcom: audioreach: fix module cfg blob size handling
This commit converts mod_array->size from a byte count to a word count when
allocating and copying module private configuration data in
audioreach_get_module_priv_data(). It also adds bounds and zero-size checks
for the blob and checks for an error pointer before storing it in mod->data.
> diff --git a/sound/soc/qcom/qdsp6/topology.c b/sound/soc/qcom/qdsp6/topology.c
> index faafbc5c0ad00..612d8f03e6e98 100644
> --- a/sound/soc/qcom/qdsp6/topology.c
> +++ b/sound/soc/qcom/qdsp6/topology.c
> @@ -312,22 +312,37 @@ audioreach_get_module_priv_data(const struct snd_soc_tplg_private *private)
>
> for (sz = 0; sz < le32_to_cpu(private->size); ) {
> const struct snd_soc_tplg_vendor_array *mod_array;
> + u32 array_size;
>
> mod_array = (struct snd_soc_tplg_vendor_array *)((u8 *)private->array + sz);
> + array_size = le32_to_cpu(mod_array->size);
> +
> if (le32_to_cpu(mod_array->type) == SND_SOC_AR_TPLG_MODULE_CFG_TYPE) {
> struct audioreach_module_priv_data *pdata;
> + u32 nwords;
> +
> + /* size is the byte count of the __le32 data[] */
> + nwords = array_size / sizeof(__le32);
> +
> + /* the blob must lie within the private data */
> + if (sizeof(*pdata) + (u64)array_size >
> + le32_to_cpu(private->size) - sz)
> + return ERR_PTR(-EINVAL);
>
> - pdata = kzalloc_flex(*pdata, data,
> - le32_to_cpu(mod_array->size));
> + pdata = kzalloc_flex(*pdata, data, nwords);
> if (!pdata)
> return ERR_PTR(-ENOMEM);
>
> - memcpy(pdata, ((u8 *)private->data + sz), struct_size(pdata, data,
> - le32_to_cpu(mod_array->size)));
> + memcpy(pdata, ((u8 *)private->data + sz),
> + struct_size(pdata, data, nwords));
> return pdata;
> }
[Severity: High]
What happens here if array_size is not a multiple of sizeof(__le32) (or is 0)?
When array_size is not 4-byte aligned, integer division truncates nwords down,
so kzalloc_flex() allocates nwords * sizeof(__le32) bytes for pdata->data[],
which is 1 to 3 bytes smaller than array_size. However, the subsequent
memcpy() copies the struct audioreach_module_priv_data header directly from
private->data + sz, leaving the untruncated array_size in pdata->size.
When the graph is later opened, audioreach_set_module_config() in
sound/soc/qcom/qdsp6/audioreach.c uses that untruncated pdata->size for
memcpy():
int size = le32_to_cpu(module->data->size);
...
memcpy(p, module->data->data, size);
Wouldn't that read up to 3 bytes past the end of the pdata->data[] slab
allocation? Also, because this branch returns before the !array_size check
below, a zero array_size for SND_SOC_AR_TPLG_MODULE_CFG_TYPE is not rejected.
>
> - sz = sz + le32_to_cpu(mod_array->size);
> + /* a zero size would never advance the walk */
> + if (!array_size)
> + return ERR_PTR(-EINVAL);
> +
> + sz = sz + array_size;
> }
[Severity: High]
Can a malformed vendor array header or size still read past private->array or
spin in this loop?
At the start of the loop in audioreach_get_module_priv_data(), the condition
sz < le32_to_cpu(private->size) only guarantees at least 1 byte remains, so
reading mod_array->size and mod_array->type can read past the end of
private->array if fewer than 8 bytes remain.
In addition, when mod_array->type is not SND_SOC_AR_TPLG_MODULE_CFG_TYPE,
array_size is only checked for zero and is not bounded against
le32_to_cpu(private->size) - sz or sizeof(*mod_array). Because sz is a signed
int and array_size is u32, advancing sz with sz = sz + array_size at any
sz > 0 (for example, on the second vendor array) with array_size == (u32)-sz
passes the !array_size check and wraps sz back to 0 in 32-bit arithmetic,
causing an infinite loop or an out-of-bounds read.
>
> return NULL;
> @@ -611,6 +626,12 @@ static int audioreach_widget_load_module_common(struct snd_soc_component *compon
> return mod ? PTR_ERR(mod) : -ENODEV;
>
> mod->data = audioreach_get_module_priv_data(&tplg_w->priv);
> + if (IS_ERR(mod->data)) {
> + int rc = PTR_ERR(mod->data);
> +
> + mod->data = NULL;
> + return rc;
> + }
[Severity: High]
Does returning rc here before setting w->dobj.private = mod leak mod and leave
a dangling mod->widget pointer?
Before audioreach_get_module_priv_data() is called in
audioreach_widget_load_module_common(), audioreach_parse_common_tokens() ->
audioreach_tplg_alloc_module() has already inserted mod into apm->modules_idr,
linked mod->node into cont->modules_list, and set mod->widget = w:
ret = idr_alloc_u32(&apm->modules_idr, mod, &module_id,
INT_MAX, GFP_KERNEL);
...
list_add_tail(&mod->node, &cont->modules_list);
mod->container = cont;
mod->widget = w;
cont->num_modules++;
When audioreach_get_module_priv_data() returns an ERR_PTR(), returning rc
before assigning dobj->private = mod causes two issues depending on the caller:
1. For widget loaders whose error is propagated by audioreach_widget_ready()
(such as audioreach_widget_load_pga()), soc_tplg_dapm_widget_create() in
sound/soc/soc-topology.c runs its error path:
ready_err:
soc_tplg_remove_widget(snd_soc_dapm_to_component(widget->dapm),
&widget->dobj, SOC_TPLG_PASS_WIDGET);
snd_soc_dapm_free_widget(widget);
Because dobj->private is still NULL, audioreach_widget_unload() returns early:
mod = dobj->private;
if (!mod)
return 0;
As a result, mod is leaked in apm->modules_idr and cont->modules_list (which
also prevents cont, sg, and info from being freed), and mod->widget becomes a
dangling pointer to the freed snd_soc_dapm_widget. Subsequent calls to
audioreach_find_module() iterate apm->modules_idr and dereference
module->widget->name, causing a use-after-free:
idr_for_each_entry(&apm->modules_idr, module, id) {
if (!strcmp(name, module->widget->name))
return module;
}
2. For widget loaders whose return value is ignored by
audioreach_widget_ready() (such as audioreach_widget_load_buffer() and
audioreach_widget_load_enc_dec_cnv()), topology loading succeeds with mod
still linked in cont->modules_list, mod->data == NULL, and
w->dobj.private == NULL. If a MODULE_ID_SMECNS_V2 module is opened with
mod->data == NULL, audioreach_set_media_format() ->
audioreach_set_module_config() dereferences module->data->size without a NULL
check.
--
Sashiko AI review · https://sashiko.dev/#/patchset/20261023171316.819857-1-srinivas.kandagatla@oss.qualcomm.com?part=1
^ permalink raw reply [flat|nested] 12+ messages in thread
* [PATCH 2/7] ASoC: codecs: wsa884x: Accept temperatures across the full trim range
2026-10-23 17:13 [PATCH 0/7] ASoC: qcom: AudioReach and WSA88xx fixes Srinivas Kandagatla
2026-10-23 17:13 ` [PATCH 1/7] ASoC: qcom: audioreach: fix module cfg blob size handling Srinivas Kandagatla
@ 2026-10-23 17:13 ` Srinivas Kandagatla
2026-10-23 17:28 ` sashiko-bot
2026-10-23 17:13 ` [PATCH 3/7] ASoC: codecs: wsa883x: " Srinivas Kandagatla
` (5 subsequent siblings)
7 siblings, 1 reply; 12+ messages in thread
From: Srinivas Kandagatla @ 2026-10-23 17:13 UTC (permalink / raw)
To: Mark Brown, Liam Girdwood
Cc: Jaroslav Kysela, Takashi Iwai, Krzysztof Kozlowski, Alexey Klimov,
Ravi Hothi, linux-sound, linux-arm-msm, linux-kernel,
Srinivas Kandagatla, stable
wsa884x_get_temp() rejects any reading outside 5..45 degC with -EAGAIN.
A speaker that has been playing, or sits in a warm laptop, easily runs
above 45 degC, so its temperature becomes unreadable when it matters.
The check only needs to drop bogus conversions, such as the all-zero
reading before the PA is first enabled. Bound it by the -10..150 degC
two-point trim range instead.
Fixes: 6b99dc62d940 ("ASoC: codecs: wsa884x: Implement temperature reading and hwmon")
Cc: stable@vger.kernel.org
Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@oss.qualcomm.com>
---
sound/soc/codecs/wsa884x.c | 11 ++++++-----
1 file changed, 6 insertions(+), 5 deletions(-)
diff --git a/sound/soc/codecs/wsa884x.c b/sound/soc/codecs/wsa884x.c
index a367c94bfb4d..f0857c0588d5 100644
--- a/sound/soc/codecs/wsa884x.c
+++ b/sound/soc/codecs/wsa884x.c
@@ -720,10 +720,11 @@
/*
* Device will report senseless data in many cases, so discard any measurements
- * outside of valid range.
+ * outside of the two-point trim range. Do not narrow this to ambient: a
+ * speaker that has been playing easily runs well above 45 degC.
*/
-#define WSA884X_LOW_TEMP_THRESHOLD 5
-#define WSA884X_HIGH_TEMP_THRESHOLD 45
+#define WSA884X_LOW_TEMP_THRESHOLD WSA884X_T1_TEMP
+#define WSA884X_HIGH_TEMP_THRESHOLD WSA884X_T2_TEMP
struct wsa884x_priv {
struct regmap *regmap;
@@ -1929,8 +1930,8 @@ static int wsa884x_get_temp(struct wsa884x_priv *wsa884x, long *temp)
dev_dbg(wsa884x->dev, "Measured temp %ld (dmeas=%d, d1=%d, d2=%d)\n",
val, dmeas, d1, d2);
- if ((val > WSA884X_LOW_TEMP_THRESHOLD) &&
- (val < WSA884X_HIGH_TEMP_THRESHOLD)) {
+ if (val >= WSA884X_LOW_TEMP_THRESHOLD &&
+ val <= WSA884X_HIGH_TEMP_THRESHOLD) {
wsa884x->temperature = val;
*temp = val * 1000;
ret = 0;
--
2.47.3
^ permalink raw reply related [flat|nested] 12+ messages in thread* Re: [PATCH 2/7] ASoC: codecs: wsa884x: Accept temperatures across the full trim range
2026-10-23 17:13 ` [PATCH 2/7] ASoC: codecs: wsa884x: Accept temperatures across the full trim range Srinivas Kandagatla
@ 2026-10-23 17:28 ` sashiko-bot
0 siblings, 0 replies; 12+ messages in thread
From: sashiko-bot @ 2026-10-23 17:28 UTC (permalink / raw)
To: Srinivas Kandagatla; +Cc: linux-sound
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [Medium] ASoC: wsa884x: unsigned cache corrupts negative temp in wsa884x_get_temp()
--
commit 9c63fc2fea2dd9c9655f1be7d3c6ce519dba204c
Author: Srinivas Kandagatla <srinivas.kandagatla@oss.qualcomm.com>
ASoC: codecs: wsa884x: Accept temperatures across the full trim range
This commit expands the valid temperature threshold range in wsa884x_get_temp()
from 5..45 degC to the full two-point trim range of -10..150 degC
(WSA884X_T1_TEMP..WSA884X_T2_TEMP) so that valid speaker temperatures are not
rejected with -EAGAIN.
> diff --git a/sound/soc/codecs/wsa884x.c b/sound/soc/codecs/wsa884x.c
> index a367c94bfb4d6..f0857c0588d51 100644
> --- a/sound/soc/codecs/wsa884x.c
> +++ b/sound/soc/codecs/wsa884x.c
> @@ -720,10 +720,11 @@
>
> /*
> * Device will report senseless data in many cases, so discard any measurements
> - * outside of valid range.
> + * outside of the two-point trim range. Do not narrow this to ambient: a
> + * speaker that has been playing easily runs well above 45 degC.
> */
> -#define WSA884X_LOW_TEMP_THRESHOLD 5
> -#define WSA884X_HIGH_TEMP_THRESHOLD 45
> +#define WSA884X_LOW_TEMP_THRESHOLD WSA884X_T1_TEMP
> +#define WSA884X_HIGH_TEMP_THRESHOLD WSA884X_T2_TEMP
>
> struct wsa884x_priv {
> struct regmap *regmap;
> @@ -1929,8 +1930,8 @@ static int wsa884x_get_temp(struct wsa884x_priv *wsa884x, long *temp)
> dev_dbg(wsa884x->dev, "Measured temp %ld (dmeas=%d, d1=%d, d2=%d)\n",
> val, dmeas, d1, d2);
>
> - if ((val > WSA884X_LOW_TEMP_THRESHOLD) &&
> - (val < WSA884X_HIGH_TEMP_THRESHOLD)) {
> + if (val >= WSA884X_LOW_TEMP_THRESHOLD &&
> + val <= WSA884X_HIGH_TEMP_THRESHOLD) {
> wsa884x->temperature = val;
> *temp = val * 1000;
> ret = 0;
[Severity: Medium]
With WSA884X_LOW_TEMP_THRESHOLD lowered to WSA884X_T1_TEMP (-10L),
wsa884x_get_temp() in sound/soc/codecs/wsa884x.c now accepts negative
temperatures in the range [-10, -1] degC.
However, struct wsa884x_priv still declares the cached temperature field as
unsigned:
struct wsa884x_priv {
...
struct mutex sp_lock;
unsigned int temperature;
bool pa_on;
};
When wsa884x_hwmon_read() -> wsa884x_get_temp() is called while the power
amplifier is off (wsa884x->pa_on is false) and the measured val is negative,
storing val into wsa884x->temperature wraps around modulo 2^32.
If the speaker power amplifier is subsequently enabled via wsa884x_spkr_event()
(setting wsa884x->pa_on = true on SND_SOC_DAPM_POST_PMU) and a hwmon consumer
reads the temperature again, wsa884x_get_temp() returns the cached reading:
if (wsa884x->pa_on) {
/*
* Reading temperature is possible only when Power Amplifier is
* off. Report last cached data.
*/
*temp = wsa884x->temperature * 1000;
return 0;
}
Because wsa884x->temperature is unsigned int, wsa884x->temperature * 1000 is
evaluated using 32-bit unsigned arithmetic and then zero-extended to long *temp
on 64-bit platforms, reporting ~4.29 billion millidegrees C instead of a
negative temperature.
Should temperature in struct wsa884x_priv be changed to a signed type such as
int or long?
--
Sashiko AI review · https://sashiko.dev/#/patchset/20261023171316.819857-1-srinivas.kandagatla@oss.qualcomm.com?part=2
^ permalink raw reply [flat|nested] 12+ messages in thread
* [PATCH 3/7] ASoC: codecs: wsa883x: Accept temperatures across the full trim range
2026-10-23 17:13 [PATCH 0/7] ASoC: qcom: AudioReach and WSA88xx fixes Srinivas Kandagatla
2026-10-23 17:13 ` [PATCH 1/7] ASoC: qcom: audioreach: fix module cfg blob size handling Srinivas Kandagatla
2026-10-23 17:13 ` [PATCH 2/7] ASoC: codecs: wsa884x: Accept temperatures across the full trim range Srinivas Kandagatla
@ 2026-10-23 17:13 ` Srinivas Kandagatla
2026-10-23 17:25 ` sashiko-bot
2026-10-23 17:13 ` [PATCH 4/7] ASoC: codecs: wsa884x: disable runtime PM on unbind Srinivas Kandagatla
` (4 subsequent siblings)
7 siblings, 1 reply; 12+ messages in thread
From: Srinivas Kandagatla @ 2026-10-23 17:13 UTC (permalink / raw)
To: Mark Brown, Liam Girdwood
Cc: Jaroslav Kysela, Takashi Iwai, Krzysztof Kozlowski, Alexey Klimov,
Ravi Hothi, linux-sound, linux-arm-msm, linux-kernel,
Srinivas Kandagatla, stable
wsa883x_get_temp() rejects any reading outside 5..45 degC with -EAGAIN,
so a speaker that has been playing, or sits in a warm chassis, becomes
unreadable above 45 degC.
Bound the check by the -10..150 degC two-point trim range instead, and
use inclusive comparisons, as in_range() excludes the upper bound.
Fixes: a02c42d41af7 ("ASoC: codecs: wsa883x: Implement temperature reading and hwmon")
Cc: stable@vger.kernel.org
Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@oss.qualcomm.com>
---
sound/soc/codecs/wsa883x.c | 13 +++++++------
1 file changed, 7 insertions(+), 6 deletions(-)
diff --git a/sound/soc/codecs/wsa883x.c b/sound/soc/codecs/wsa883x.c
index 442cf9f3eaac..ccd4404c1644 100644
--- a/sound/soc/codecs/wsa883x.c
+++ b/sound/soc/codecs/wsa883x.c
@@ -456,10 +456,11 @@
/*
* Device will report senseless data in many cases, so discard any measurements
- * outside of valid range.
+ * outside of the two-point trim range. Do not narrow this to ambient: a
+ * speaker that has been playing easily runs well above 45 degC.
*/
-#define WSA883X_LOW_TEMP_THRESHOLD 5
-#define WSA883X_HIGH_TEMP_THRESHOLD 45
+#define WSA883X_LOW_TEMP_THRESHOLD WSA883X_T1_TEMP
+#define WSA883X_HIGH_TEMP_THRESHOLD WSA883X_T2_TEMP
struct wsa883x_priv {
struct regmap *regmap;
@@ -1430,7 +1431,7 @@ static int wsa883x_get_temp(struct wsa883x_priv *wsa883x, long *temp)
unsigned int dmeas_msb = 0, dmeas_lsb = 0;
int d1, d2, dmeas;
unsigned int mask;
- int ret, range;
+ int ret;
long val;
guard(mutex)(&wsa883x->sp_lock);
@@ -1493,8 +1494,8 @@ static int wsa883x_get_temp(struct wsa883x_priv *wsa883x, long *temp)
}
val = WSA883X_T1_TEMP + (((dmeas - d1) * (WSA883X_T2_TEMP - WSA883X_T1_TEMP)) / (d2 - d1));
- range = WSA883X_HIGH_TEMP_THRESHOLD - WSA883X_LOW_TEMP_THRESHOLD;
- if (in_range(val, WSA883X_LOW_TEMP_THRESHOLD, range)) {
+ if (val >= WSA883X_LOW_TEMP_THRESHOLD &&
+ val <= WSA883X_HIGH_TEMP_THRESHOLD) {
wsa883x->temperature = val;
*temp = val * 1000;
ret = 0;
--
2.47.3
^ permalink raw reply related [flat|nested] 12+ messages in thread* Re: [PATCH 3/7] ASoC: codecs: wsa883x: Accept temperatures across the full trim range
2026-10-23 17:13 ` [PATCH 3/7] ASoC: codecs: wsa883x: " Srinivas Kandagatla
@ 2026-10-23 17:25 ` sashiko-bot
0 siblings, 0 replies; 12+ messages in thread
From: sashiko-bot @ 2026-10-23 17:25 UTC (permalink / raw)
To: Srinivas Kandagatla; +Cc: linux-sound
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [Medium] ASoC: wsa883x: unsigned cache in wsa883x_get_temp() corrupts negative temps
--
commit 48fab137fbfecfa73800bb6d589df9724b78ae8e
Author: Srinivas Kandagatla <srinivas.kandagatla@oss.qualcomm.com>
ASoC: codecs: wsa883x: Accept temperatures across the full trim range
This commit expands the valid temperature threshold range in
wsa883x_get_temp() from 5..45 degC to the full -10..150 degC two-point
trim range using inclusive comparisons.
> diff --git a/sound/soc/codecs/wsa883x.c b/sound/soc/codecs/wsa883x.c
> index 442cf9f3eaac7..ccd4404c1644e 100644
> --- a/sound/soc/codecs/wsa883x.c
> +++ b/sound/soc/codecs/wsa883x.c
> @@ -456,10 +456,11 @@
>
> /*
> * Device will report senseless data in many cases, so discard any measurements
> - * outside of valid range.
> + * outside of the two-point trim range. Do not narrow this to ambient: a
> + * speaker that has been playing easily runs well above 45 degC.
> */
> -#define WSA883X_LOW_TEMP_THRESHOLD 5
> -#define WSA883X_HIGH_TEMP_THRESHOLD 45
> +#define WSA883X_LOW_TEMP_THRESHOLD WSA883X_T1_TEMP
> +#define WSA883X_HIGH_TEMP_THRESHOLD WSA883X_T2_TEMP
>
> struct wsa883x_priv {
> struct regmap *regmap;
> @@ -1430,7 +1431,7 @@ static int wsa883x_get_temp(struct wsa883x_priv *wsa883x, long *temp)
> unsigned int dmeas_msb = 0, dmeas_lsb = 0;
> int d1, d2, dmeas;
> unsigned int mask;
> - int ret, range;
> + int ret;
> long val;
>
> guard(mutex)(&wsa883x->sp_lock);
> @@ -1493,8 +1494,8 @@ static int wsa883x_get_temp(struct wsa883x_priv *wsa883x, long *temp)
> }
>
> val = WSA883X_T1_TEMP + (((dmeas - d1) * (WSA883X_T2_TEMP - WSA883X_T1_TEMP)) / (d2 - d1));
> - range = WSA883X_HIGH_TEMP_THRESHOLD - WSA883X_LOW_TEMP_THRESHOLD;
> - if (in_range(val, WSA883X_LOW_TEMP_THRESHOLD, range)) {
> + if (val >= WSA883X_LOW_TEMP_THRESHOLD &&
> + val <= WSA883X_HIGH_TEMP_THRESHOLD) {
> wsa883x->temperature = val;
> *temp = val * 1000;
> ret = 0;
[Severity: Medium]
With WSA883X_LOW_TEMP_THRESHOLD lowered to WSA883X_T1_TEMP (-10L), val in
wsa883x_get_temp() can now be negative (-10 to -1 degC). However,
wsa883x->temperature is declared as unsigned int in struct wsa883x_priv:
struct wsa883x_priv {
...
struct mutex sp_lock;
unsigned int temperature;
bool pa_on;
};
When wsa883x_get_temp() is called while wsa883x->pa_on is false and caches
a negative val into wsa883x->temperature, it wraps around as a 32-bit
unsigned value. If a subsequent call to wsa883x_get_temp() occurs while
wsa883x->pa_on is true:
if (wsa883x->pa_on) {
/*
* Reading temperature is possible only when Power Amplifier is
* off. Report last cached data.
*/
*temp = wsa883x->temperature * 1000;
return 0;
}
wsa883x->temperature * 1000 is evaluated in 32-bit unsigned arithmetic and
zero-extended into *temp (type long) on 64-bit architectures, reporting a
corrupted positive value around 4.29 billion millidegrees C instead of a
negative temperature.
Should temperature in struct wsa883x_priv be changed to a signed type such
as int or long?
--
Sashiko AI review · https://sashiko.dev/#/patchset/20261023171316.819857-1-srinivas.kandagatla@oss.qualcomm.com?part=3
^ permalink raw reply [flat|nested] 12+ messages in thread
* [PATCH 4/7] ASoC: codecs: wsa884x: disable runtime PM on unbind
2026-10-23 17:13 [PATCH 0/7] ASoC: qcom: AudioReach and WSA88xx fixes Srinivas Kandagatla
` (2 preceding siblings ...)
2026-10-23 17:13 ` [PATCH 3/7] ASoC: codecs: wsa883x: " Srinivas Kandagatla
@ 2026-10-23 17:13 ` Srinivas Kandagatla
2026-10-23 17:13 ` [PATCH 5/7] ASoC: codecs: wsa883x: " Srinivas Kandagatla
` (3 subsequent siblings)
7 siblings, 0 replies; 12+ messages in thread
From: Srinivas Kandagatla @ 2026-10-23 17:13 UTC (permalink / raw)
To: Mark Brown, Liam Girdwood
Cc: Jaroslav Kysela, Takashi Iwai, Krzysztof Kozlowski, Alexey Klimov,
Ravi Hothi, linux-sound, linux-arm-msm, linux-kernel,
Srinivas Kandagatla
Probe enables runtime PM but nothing disables it on unbind. The pending
autosuspend then runs wsa884x_runtime_suspend() after the devm-managed
regmap is freed, and dereferences NULL:
Unable to handle kernel NULL pointer dereference at virtual address 0000000000000020
pc : regcache_cache_only+0x18/0x80
lr : wsa884x_runtime_suspend+0x24/0x40 [snd_soc_wsa884x]
Use devm_pm_runtime_enable() so runtime PM is disabled before the regmap
is freed.
Fixes: aa21a7d4f68a ("ASoC: codecs: wsa884x: Add WSA884x family of speakers")
Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@oss.qualcomm.com>
---
sound/soc/codecs/wsa884x.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/sound/soc/codecs/wsa884x.c b/sound/soc/codecs/wsa884x.c
index f0857c0588d5..3c008224d32e 100644
--- a/sound/soc/codecs/wsa884x.c
+++ b/sound/soc/codecs/wsa884x.c
@@ -2125,7 +2125,9 @@ static int wsa884x_probe(struct sdw_slave *pdev,
pm_runtime_use_autosuspend(dev);
pm_runtime_mark_last_busy(dev);
pm_runtime_set_active(dev);
- pm_runtime_enable(dev);
+ ret = devm_pm_runtime_enable(dev);
+ if (ret)
+ return ret;
return devm_snd_soc_register_component(dev,
&wsa884x_component_drv,
--
2.47.3
^ permalink raw reply related [flat|nested] 12+ messages in thread* [PATCH 5/7] ASoC: codecs: wsa883x: disable runtime PM on unbind
2026-10-23 17:13 [PATCH 0/7] ASoC: qcom: AudioReach and WSA88xx fixes Srinivas Kandagatla
` (3 preceding siblings ...)
2026-10-23 17:13 ` [PATCH 4/7] ASoC: codecs: wsa884x: disable runtime PM on unbind Srinivas Kandagatla
@ 2026-10-23 17:13 ` Srinivas Kandagatla
2026-10-23 17:13 ` [PATCH 6/7] ASoC: codecs: wsa884x: Fix VI sense port channel count Srinivas Kandagatla
` (2 subsequent siblings)
7 siblings, 0 replies; 12+ messages in thread
From: Srinivas Kandagatla @ 2026-10-23 17:13 UTC (permalink / raw)
To: Mark Brown, Liam Girdwood
Cc: Jaroslav Kysela, Takashi Iwai, Krzysztof Kozlowski, Alexey Klimov,
Ravi Hothi, linux-sound, linux-arm-msm, linux-kernel,
Srinivas Kandagatla
Probe enables runtime PM but nothing disables it on unbind, or when
registering the component fails. A pending autosuspend can then run
wsa883x_runtime_suspend() after the devm-managed regmap is freed, and
dereference NULL, as seen on wsa884x.
Use devm_pm_runtime_enable() so runtime PM is disabled before the regmap
is freed.
Fixes: 43b8c7dc85a1 ("ASoC: codecs: add wsa883x amplifier support")
Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@oss.qualcomm.com>
---
sound/soc/codecs/wsa883x.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/sound/soc/codecs/wsa883x.c b/sound/soc/codecs/wsa883x.c
index ccd4404c1644..b09ee3db7ed5 100644
--- a/sound/soc/codecs/wsa883x.c
+++ b/sound/soc/codecs/wsa883x.c
@@ -1669,7 +1669,9 @@ static int wsa883x_probe(struct sdw_slave *pdev,
pm_runtime_use_autosuspend(dev);
pm_runtime_mark_last_busy(dev);
pm_runtime_set_active(dev);
- pm_runtime_enable(dev);
+ ret = devm_pm_runtime_enable(dev);
+ if (ret)
+ goto err;
ret = devm_snd_soc_register_component(dev,
&wsa883x_component_drv,
--
2.47.3
^ permalink raw reply related [flat|nested] 12+ messages in thread* [PATCH 6/7] ASoC: codecs: wsa884x: Fix VI sense port channel count
2026-10-23 17:13 [PATCH 0/7] ASoC: qcom: AudioReach and WSA88xx fixes Srinivas Kandagatla
` (4 preceding siblings ...)
2026-10-23 17:13 ` [PATCH 5/7] ASoC: codecs: wsa883x: " Srinivas Kandagatla
@ 2026-10-23 17:13 ` Srinivas Kandagatla
2026-10-23 17:13 ` [PATCH 7/7] ASoC: codecs: wsa883x: " Srinivas Kandagatla
2026-10-26 20:04 ` [PATCH 0/7] ASoC: qcom: AudioReach and WSA88xx fixes Mark Brown
7 siblings, 0 replies; 12+ messages in thread
From: Srinivas Kandagatla @ 2026-10-23 17:13 UTC (permalink / raw)
To: Mark Brown, Liam Girdwood
Cc: Jaroslav Kysela, Takashi Iwai, Krzysztof Kozlowski, Alexey Klimov,
Ravi Hothi, linux-sound, linux-arm-msm, linux-kernel,
Srinivas Kandagatla
From: Ravi Hothi <ravi.hothi@oss.qualcomm.com>
The VI sense port carries both the voltage and the current sense data
of the speaker, but it is described with max_ch = 1 and, since commit
060fac202eb8 ("ASoC: codecs: wsa884x: Correct VI sense channel mask"),
a channel mask of 0x1, so only half of the V/I pair is transferred.
Describe the port as two channels and set the channel mask back to 0x3.
Fixes: 060fac202eb8 ("ASoC: codecs: wsa884x: Correct VI sense channel mask")
Cc: Krzysztof Kozlowski <krzk@kernel.org>
Signed-off-by: Ravi Hothi <ravi.hothi@oss.qualcomm.com>
Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@oss.qualcomm.com>
---
sound/soc/codecs/wsa884x.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/sound/soc/codecs/wsa884x.c b/sound/soc/codecs/wsa884x.c
index 3c008224d32e..acf32af5aae3 100644
--- a/sound/soc/codecs/wsa884x.c
+++ b/sound/soc/codecs/wsa884x.c
@@ -859,7 +859,7 @@ static struct sdw_dpn_prop wsa884x_sink_dpn_prop[WSA884X_MAX_SWR_PORTS] = {
.num = WSA884X_PORT_VISENSE + 1,
.type = SDW_DPN_SIMPLE,
.min_ch = 1,
- .max_ch = 1,
+ .max_ch = 2,
.simple_ch_prep_sm = true,
.read_only_wordlength = true,
},
@@ -892,7 +892,7 @@ static const struct sdw_port_config wsa884x_pconfig[WSA884X_MAX_SWR_PORTS] = {
},
[WSA884X_PORT_VISENSE] = {
.num = WSA884X_PORT_VISENSE + 1,
- .ch_mask = 0x1,
+ .ch_mask = 0x3,
},
[WSA884X_PORT_CPS] = {
.num = WSA884X_PORT_CPS + 1,
--
2.47.3
^ permalink raw reply related [flat|nested] 12+ messages in thread* [PATCH 7/7] ASoC: codecs: wsa883x: Fix VI sense port channel count
2026-10-23 17:13 [PATCH 0/7] ASoC: qcom: AudioReach and WSA88xx fixes Srinivas Kandagatla
` (5 preceding siblings ...)
2026-10-23 17:13 ` [PATCH 6/7] ASoC: codecs: wsa884x: Fix VI sense port channel count Srinivas Kandagatla
@ 2026-10-23 17:13 ` Srinivas Kandagatla
2026-10-26 20:04 ` [PATCH 0/7] ASoC: qcom: AudioReach and WSA88xx fixes Mark Brown
7 siblings, 0 replies; 12+ messages in thread
From: Srinivas Kandagatla @ 2026-10-23 17:13 UTC (permalink / raw)
To: Mark Brown, Liam Girdwood
Cc: Jaroslav Kysela, Takashi Iwai, Krzysztof Kozlowski, Alexey Klimov,
Ravi Hothi, linux-sound, linux-arm-msm, linux-kernel,
Srinivas Kandagatla
From: Ravi Hothi <ravi.hothi@oss.qualcomm.com>
The VI sense port carries both the voltage and the current sense data
of the speaker, but it is described with max_ch = 1 and, since commit
ed3b274abc40 ("ASoC: codecs: wsa883x: Correct VI sense channel mask"),
a channel mask of 0x1, so only half of the V/I pair is transferred.
Describe the port as two channels and set the channel mask back to 0x3.
Fixes: ed3b274abc40 ("ASoC: codecs: wsa883x: Correct VI sense channel mask")
Cc: Krzysztof Kozlowski <krzk@kernel.org>
Signed-off-by: Ravi Hothi <ravi.hothi@oss.qualcomm.com>
Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@oss.qualcomm.com>
---
sound/soc/codecs/wsa883x.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/sound/soc/codecs/wsa883x.c b/sound/soc/codecs/wsa883x.c
index b09ee3db7ed5..17d8babc6123 100644
--- a/sound/soc/codecs/wsa883x.c
+++ b/sound/soc/codecs/wsa883x.c
@@ -552,7 +552,7 @@ static struct sdw_dpn_prop wsa_sink_dpn_prop[WSA883X_MAX_SWR_PORTS] = {
.num = WSA883X_PORT_VISENSE + 1,
.type = SDW_DPN_SIMPLE,
.min_ch = 1,
- .max_ch = 1,
+ .max_ch = 2,
.simple_ch_prep_sm = true,
.read_only_wordlength = true,
}
@@ -573,7 +573,7 @@ static const struct sdw_port_config wsa883x_pconfig[WSA883X_MAX_SWR_PORTS] = {
},
[WSA883X_PORT_VISENSE] = {
.num = WSA883X_PORT_VISENSE + 1,
- .ch_mask = 0x1,
+ .ch_mask = 0x3,
},
};
--
2.47.3
^ permalink raw reply related [flat|nested] 12+ messages in thread* Re: [PATCH 0/7] ASoC: qcom: AudioReach and WSA88xx fixes
2026-10-23 17:13 [PATCH 0/7] ASoC: qcom: AudioReach and WSA88xx fixes Srinivas Kandagatla
` (6 preceding siblings ...)
2026-10-23 17:13 ` [PATCH 7/7] ASoC: codecs: wsa883x: " Srinivas Kandagatla
@ 2026-10-26 20:04 ` Mark Brown
7 siblings, 0 replies; 12+ messages in thread
From: Mark Brown @ 2026-10-26 20:04 UTC (permalink / raw)
To: Liam Girdwood, Srinivas Kandagatla
Cc: Jaroslav Kysela, Takashi Iwai, Krzysztof Kozlowski, Alexey Klimov,
Ravi Hothi, linux-sound, linux-arm-msm, linux-kernel
On Fri, 23 Oct 2026 18:13:09 +0100, Srinivas Kandagatla wrote:
> ASoC: qcom: AudioReach and WSA88xx fixes
>
> Fixes found while bringing up speaker protection on the Lenovo ThinkPad
> T14s Gen 7 (Snapdragon X2 Elite) with WSA8845 speakers.
>
> - AudioReach: the module cfg blob size was used as an element count,
> so the allocation and copy were four times too large.
> - WSA88xx: speaker temperatures above 45 degC were rejected, runtime
> PM was left enabled on unbind (NULL dereference on wsa884x), and
> the VI sense port carried only half of the V/I pair.
>
> [...]
Applied to
https://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git for-7.4
Thanks!
[1/7] ASoC: qcom: audioreach: fix module cfg blob size handling
https://git.kernel.org/broonie/sound/c/e21fb64a8c4a
[2/7] ASoC: codecs: wsa884x: Accept temperatures across the full trim range
https://git.kernel.org/broonie/sound/c/00535515e3c1
[3/7] ASoC: codecs: wsa883x: Accept temperatures across the full trim range
https://git.kernel.org/broonie/sound/c/6a55cf0d9dd2
[4/7] ASoC: codecs: wsa884x: disable runtime PM on unbind
https://git.kernel.org/broonie/sound/c/54c121eaeed8
[5/7] ASoC: codecs: wsa883x: disable runtime PM on unbind
https://git.kernel.org/broonie/sound/c/ea63182d7195
[6/7] ASoC: codecs: wsa884x: Fix VI sense port channel count
https://git.kernel.org/broonie/sound/c/a6093f98cbfc
[7/7] ASoC: codecs: wsa883x: Fix VI sense port channel count
https://git.kernel.org/broonie/sound/c/9728b328d7ad
All being well this means that it will be integrated into the linux-next
tree (usually sometime in the next 24 hours) and sent to Linus during
the next merge window (or sooner if it is a bug fix), however if
problems are discovered then the patch may be dropped or reverted.
You may get further e-mails resulting from automated or manual testing
and review of the tree, please engage with people reporting problems and
send followup patches addressing any issues that are reported if needed.
If any updates are required or you are submitting further changes they
should be sent as incremental updates against current git, existing
patches will not be replaced.
Please add any relevant lists and maintainers to the CCs when replying
to this mail.
Thanks,
Mark
^ permalink raw reply [flat|nested] 12+ messages in thread