* FAILED: patch "[PATCH] ALSA: aoa: i2sbus: clear stale prepared state" failed to apply to 5.10-stable tree
@ 2026-05-01 10:31 gregkh
2026-05-01 17:27 ` [PATCH 5.10.y 1/2] ALSA: aoa: Use guard() for mutex locks Sasha Levin
0 siblings, 1 reply; 4+ messages in thread
From: gregkh @ 2026-05-01 10:31 UTC (permalink / raw)
To: cassiogabrielcontato, lkp, tiwai; +Cc: stable
The patch below does not apply to the 5.10-stable tree.
If someone wants it applied there, or to any other stable or longterm
tree, then please email the backport, including the original git commit
id to <stable@vger.kernel.org>.
To reproduce the conflict and resubmit, you may use the following commands:
git fetch https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/ linux-5.10.y
git checkout FETCH_HEAD
git cherry-pick -x 5ed060d5491597490fb53ec69da3edc4b1e8c165
# <resolve conflicts, build, test, etc.>
git commit -s
git send-email --to '<stable@vger.kernel.org>' --in-reply-to '2026050153-spookily-fool-bd46@gregkh' --subject-prefix 'PATCH 5.10.y' HEAD^..
Possible dependencies:
thanks,
greg k-h
------------------ original commit in Linus's tree ------------------
From 5ed060d5491597490fb53ec69da3edc4b1e8c165 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?C=C3=A1ssio=20Gabriel?= <cassiogabrielcontato@gmail.com>
Date: Tue, 31 Mar 2026 18:14:04 -0300
Subject: [PATCH] ALSA: aoa: i2sbus: clear stale prepared state
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
The i2sbus PCM code uses pi->active to constrain the sibling stream to
an already prepared duplex format and rate in i2sbus_pcm_open().
That state is set from i2sbus_pcm_prepare(), but the current code only
clears it on close. As a result, the sibling stream can inherit stale
constraints after the prepared state has been torn down.
Clear pi->active when hw_params() or hw_free() tears down the prepared
state, and set it again only after prepare succeeds.
Replace the stale FIXME in the duplex constraint comment with a description
of the current driver behavior: i2sbus still programs a single shared
transport configuration for both directions, so mixed formats are not
supported in duplex mode.
Reported-by: kernel test robot <lkp@intel.com>
Closes: https://lore.kernel.org/oe-kbuild-all/202604010125.AvkWBYKI-lkp@intel.com/
Fixes: f3d9478b2ce4 ("[ALSA] snd-aoa: add snd-aoa")
Cc: stable@vger.kernel.org
Signed-off-by: Cássio Gabriel <cassiogabrielcontato@gmail.com>
Link: https://patch.msgid.link/20260331-aoa-i2sbus-clear-stale-active-v2-1-3764ae2889a1@gmail.com
Signed-off-by: Takashi Iwai <tiwai@suse.de>
diff --git a/sound/aoa/soundbus/i2sbus/pcm.c b/sound/aoa/soundbus/i2sbus/pcm.c
index 97c807e67d56..63004ece94f9 100644
--- a/sound/aoa/soundbus/i2sbus/pcm.c
+++ b/sound/aoa/soundbus/i2sbus/pcm.c
@@ -165,17 +165,16 @@ static int i2sbus_pcm_open(struct i2sbus_dev *i2sdev, int in)
* currently in use (if any). */
hw->rate_min = 5512;
hw->rate_max = 192000;
- /* if the other stream is active, then we can only
- * support what it is currently using.
- * FIXME: I lied. This comment is wrong. We can support
- * anything that works with the same serial format, ie.
- * when recording 24 bit sound we can well play 16 bit
- * sound at the same time iff using the same transfer mode.
+ /* If the other stream is already prepared, keep this stream
+ * on the same duplex format and rate.
+ *
+ * i2sbus_pcm_prepare() still programs one shared transport
+ * configuration for both directions, so mixed duplex formats
+ * are not supported here.
*/
if (other->active) {
- /* FIXME: is this guaranteed by the alsa api? */
hw->formats &= pcm_format_to_bits(i2sdev->format);
- /* see above, restrict rates to the one we already have */
+ /* Restrict rates to the one already in use. */
hw->rate_min = i2sdev->rate;
hw->rate_max = i2sdev->rate;
}
@@ -283,6 +282,23 @@ void i2sbus_wait_for_stop_both(struct i2sbus_dev *i2sdev)
}
#endif
+static void i2sbus_pcm_clear_active(struct i2sbus_dev *i2sdev, int in)
+{
+ struct pcm_info *pi;
+
+ guard(mutex)(&i2sdev->lock);
+
+ get_pcm_info(i2sdev, in, &pi, NULL);
+ pi->active = 0;
+}
+
+static inline int i2sbus_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params, int in)
+{
+ i2sbus_pcm_clear_active(snd_pcm_substream_chip(substream), in);
+ return 0;
+}
+
static inline int i2sbus_hw_free(struct snd_pcm_substream *substream, int in)
{
struct i2sbus_dev *i2sdev = snd_pcm_substream_chip(substream);
@@ -291,14 +307,27 @@ static inline int i2sbus_hw_free(struct snd_pcm_substream *substream, int in)
get_pcm_info(i2sdev, in, &pi, NULL);
if (pi->dbdma_ring.stopping)
i2sbus_wait_for_stop(i2sdev, pi);
+ i2sbus_pcm_clear_active(i2sdev, in);
return 0;
}
+static int i2sbus_playback_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params)
+{
+ return i2sbus_hw_params(substream, params, 0);
+}
+
static int i2sbus_playback_hw_free(struct snd_pcm_substream *substream)
{
return i2sbus_hw_free(substream, 0);
}
+static int i2sbus_record_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params)
+{
+ return i2sbus_hw_params(substream, params, 1);
+}
+
static int i2sbus_record_hw_free(struct snd_pcm_substream *substream)
{
return i2sbus_hw_free(substream, 1);
@@ -335,7 +364,6 @@ static int i2sbus_pcm_prepare(struct i2sbus_dev *i2sdev, int in)
return -EINVAL;
runtime = pi->substream->runtime;
- pi->active = 1;
if (other->active &&
((i2sdev->format != runtime->format)
|| (i2sdev->rate != runtime->rate)))
@@ -444,9 +472,11 @@ static int i2sbus_pcm_prepare(struct i2sbus_dev *i2sdev, int in)
/* early exit if already programmed correctly */
/* not locking these is fine since we touch them only in this function */
- if (in_le32(&i2sdev->intfregs->serial_format) == sfr
- && in_le32(&i2sdev->intfregs->data_word_sizes) == dws)
+ if (in_le32(&i2sdev->intfregs->serial_format) == sfr &&
+ in_le32(&i2sdev->intfregs->data_word_sizes) == dws) {
+ pi->active = 1;
return 0;
+ }
/* let's notify the codecs about clocks going away.
* For now we only do mastering on the i2s cell... */
@@ -484,6 +514,7 @@ static int i2sbus_pcm_prepare(struct i2sbus_dev *i2sdev, int in)
if (cii->codec->switch_clock)
cii->codec->switch_clock(cii, CLOCK_SWITCH_SLAVE);
+ pi->active = 1;
return 0;
}
@@ -728,6 +759,7 @@ static snd_pcm_uframes_t i2sbus_playback_pointer(struct snd_pcm_substream
static const struct snd_pcm_ops i2sbus_playback_ops = {
.open = i2sbus_playback_open,
.close = i2sbus_playback_close,
+ .hw_params = i2sbus_playback_hw_params,
.hw_free = i2sbus_playback_hw_free,
.prepare = i2sbus_playback_prepare,
.trigger = i2sbus_playback_trigger,
@@ -796,6 +828,7 @@ static snd_pcm_uframes_t i2sbus_record_pointer(struct snd_pcm_substream
static const struct snd_pcm_ops i2sbus_record_ops = {
.open = i2sbus_record_open,
.close = i2sbus_record_close,
+ .hw_params = i2sbus_record_hw_params,
.hw_free = i2sbus_record_hw_free,
.prepare = i2sbus_record_prepare,
.trigger = i2sbus_record_trigger,
^ permalink raw reply related [flat|nested] 4+ messages in thread* [PATCH 5.10.y 1/2] ALSA: aoa: Use guard() for mutex locks 2026-05-01 10:31 FAILED: patch "[PATCH] ALSA: aoa: i2sbus: clear stale prepared state" failed to apply to 5.10-stable tree gregkh @ 2026-05-01 17:27 ` Sasha Levin 2026-05-01 17:28 ` [PATCH 5.10.y 2/2] ALSA: aoa: i2sbus: clear stale prepared state Sasha Levin 0 siblings, 1 reply; 4+ messages in thread From: Sasha Levin @ 2026-05-01 17:27 UTC (permalink / raw) To: stable; +Cc: Takashi Iwai, Sasha Levin From: Takashi Iwai <tiwai@suse.de> [ Upstream commit 1cb6ecbb372002ef9e531c5377e5f60122411e40 ] Replace the manual mutex lock/unlock pairs with guard() for code simplification. Only code refactoring, and no behavior change. Signed-off-by: Takashi Iwai <tiwai@suse.de> Link: https://patch.msgid.link/20250829151335.7342-14-tiwai@suse.de Stable-dep-of: 5ed060d54915 ("ALSA: aoa: i2sbus: clear stale prepared state") Signed-off-by: Sasha Levin <sashal@kernel.org> --- sound/aoa/codecs/onyx.c | 104 +++++++++-------------------- sound/aoa/codecs/tas.c | 113 +++++++++++--------------------- sound/aoa/core/gpio-feature.c | 20 ++---- sound/aoa/core/gpio-pmf.c | 26 +++----- sound/aoa/soundbus/i2sbus/pcm.c | 76 +++++++-------------- 5 files changed, 112 insertions(+), 227 deletions(-) diff --git a/sound/aoa/codecs/onyx.c b/sound/aoa/codecs/onyx.c index 12028b3e2eee4..c544bf85d25c8 100644 --- a/sound/aoa/codecs/onyx.c +++ b/sound/aoa/codecs/onyx.c @@ -121,10 +121,9 @@ static int onyx_snd_vol_get(struct snd_kcontrol *kcontrol, struct onyx *onyx = snd_kcontrol_chip(kcontrol); s8 l, r; - mutex_lock(&onyx->mutex); + guard(mutex)(&onyx->mutex); onyx_read_register(onyx, ONYX_REG_DAC_ATTEN_LEFT, &l); onyx_read_register(onyx, ONYX_REG_DAC_ATTEN_RIGHT, &r); - mutex_unlock(&onyx->mutex); ucontrol->value.integer.value[0] = l + VOLUME_RANGE_SHIFT; ucontrol->value.integer.value[1] = r + VOLUME_RANGE_SHIFT; @@ -145,15 +144,13 @@ static int onyx_snd_vol_put(struct snd_kcontrol *kcontrol, ucontrol->value.integer.value[1] > -1 + VOLUME_RANGE_SHIFT) return -EINVAL; - mutex_lock(&onyx->mutex); + guard(mutex)(&onyx->mutex); onyx_read_register(onyx, ONYX_REG_DAC_ATTEN_LEFT, &l); onyx_read_register(onyx, ONYX_REG_DAC_ATTEN_RIGHT, &r); if (l + VOLUME_RANGE_SHIFT == ucontrol->value.integer.value[0] && - r + VOLUME_RANGE_SHIFT == ucontrol->value.integer.value[1]) { - mutex_unlock(&onyx->mutex); + r + VOLUME_RANGE_SHIFT == ucontrol->value.integer.value[1]) return 0; - } onyx_write_register(onyx, ONYX_REG_DAC_ATTEN_LEFT, ucontrol->value.integer.value[0] @@ -161,7 +158,6 @@ static int onyx_snd_vol_put(struct snd_kcontrol *kcontrol, onyx_write_register(onyx, ONYX_REG_DAC_ATTEN_RIGHT, ucontrol->value.integer.value[1] - VOLUME_RANGE_SHIFT); - mutex_unlock(&onyx->mutex); return 1; } @@ -197,9 +193,8 @@ static int onyx_snd_inputgain_get(struct snd_kcontrol *kcontrol, struct onyx *onyx = snd_kcontrol_chip(kcontrol); u8 ig; - mutex_lock(&onyx->mutex); + guard(mutex)(&onyx->mutex); onyx_read_register(onyx, ONYX_REG_ADC_CONTROL, &ig); - mutex_unlock(&onyx->mutex); ucontrol->value.integer.value[0] = (ig & ONYX_ADC_PGA_GAIN_MASK) + INPUTGAIN_RANGE_SHIFT; @@ -216,14 +211,13 @@ static int onyx_snd_inputgain_put(struct snd_kcontrol *kcontrol, if (ucontrol->value.integer.value[0] < 3 + INPUTGAIN_RANGE_SHIFT || ucontrol->value.integer.value[0] > 28 + INPUTGAIN_RANGE_SHIFT) return -EINVAL; - mutex_lock(&onyx->mutex); + guard(mutex)(&onyx->mutex); onyx_read_register(onyx, ONYX_REG_ADC_CONTROL, &v); n = v; n &= ~ONYX_ADC_PGA_GAIN_MASK; n |= (ucontrol->value.integer.value[0] - INPUTGAIN_RANGE_SHIFT) & ONYX_ADC_PGA_GAIN_MASK; onyx_write_register(onyx, ONYX_REG_ADC_CONTROL, n); - mutex_unlock(&onyx->mutex); return n != v; } @@ -251,9 +245,8 @@ static int onyx_snd_capture_source_get(struct snd_kcontrol *kcontrol, struct onyx *onyx = snd_kcontrol_chip(kcontrol); s8 v; - mutex_lock(&onyx->mutex); + guard(mutex)(&onyx->mutex); onyx_read_register(onyx, ONYX_REG_ADC_CONTROL, &v); - mutex_unlock(&onyx->mutex); ucontrol->value.enumerated.item[0] = !!(v&ONYX_ADC_INPUT_MIC); @@ -264,13 +257,12 @@ static void onyx_set_capture_source(struct onyx *onyx, int mic) { s8 v; - mutex_lock(&onyx->mutex); + guard(mutex)(&onyx->mutex); onyx_read_register(onyx, ONYX_REG_ADC_CONTROL, &v); v &= ~ONYX_ADC_INPUT_MIC; if (mic) v |= ONYX_ADC_INPUT_MIC; onyx_write_register(onyx, ONYX_REG_ADC_CONTROL, v); - mutex_unlock(&onyx->mutex); } static int onyx_snd_capture_source_put(struct snd_kcontrol *kcontrol, @@ -311,9 +303,8 @@ static int onyx_snd_mute_get(struct snd_kcontrol *kcontrol, struct onyx *onyx = snd_kcontrol_chip(kcontrol); u8 c; - mutex_lock(&onyx->mutex); + guard(mutex)(&onyx->mutex); onyx_read_register(onyx, ONYX_REG_DAC_CONTROL, &c); - mutex_unlock(&onyx->mutex); ucontrol->value.integer.value[0] = !(c & ONYX_MUTE_LEFT); ucontrol->value.integer.value[1] = !(c & ONYX_MUTE_RIGHT); @@ -328,9 +319,9 @@ static int onyx_snd_mute_put(struct snd_kcontrol *kcontrol, u8 v = 0, c = 0; int err = -EBUSY; - mutex_lock(&onyx->mutex); + guard(mutex)(&onyx->mutex); if (onyx->analog_locked) - goto out_unlock; + return -EBUSY; onyx_read_register(onyx, ONYX_REG_DAC_CONTROL, &v); c = v; @@ -341,9 +332,6 @@ static int onyx_snd_mute_put(struct snd_kcontrol *kcontrol, c |= ONYX_MUTE_RIGHT; err = onyx_write_register(onyx, ONYX_REG_DAC_CONTROL, c); - out_unlock: - mutex_unlock(&onyx->mutex); - return !err ? (v != c) : err; } @@ -372,9 +360,8 @@ static int onyx_snd_single_bit_get(struct snd_kcontrol *kcontrol, u8 address = (pv >> 8) & 0xff; u8 mask = pv & 0xff; - mutex_lock(&onyx->mutex); + guard(mutex)(&onyx->mutex); onyx_read_register(onyx, address, &c); - mutex_unlock(&onyx->mutex); ucontrol->value.integer.value[0] = !!(c & mask) ^ polarity; @@ -393,11 +380,10 @@ static int onyx_snd_single_bit_put(struct snd_kcontrol *kcontrol, u8 address = (pv >> 8) & 0xff; u8 mask = pv & 0xff; - mutex_lock(&onyx->mutex); + guard(mutex)(&onyx->mutex); if (spdiflock && onyx->spdif_locked) { /* even if alsamixer doesn't care.. */ - err = -EBUSY; - goto out_unlock; + return -EBUSY; } onyx_read_register(onyx, address, &v); c = v; @@ -406,9 +392,6 @@ static int onyx_snd_single_bit_put(struct snd_kcontrol *kcontrol, c |= mask; err = onyx_write_register(onyx, address, c); - out_unlock: - mutex_unlock(&onyx->mutex); - return !err ? (v != c) : err; } @@ -489,7 +472,7 @@ static int onyx_spdif_get(struct snd_kcontrol *kcontrol, struct onyx *onyx = snd_kcontrol_chip(kcontrol); u8 v; - mutex_lock(&onyx->mutex); + guard(mutex)(&onyx->mutex); onyx_read_register(onyx, ONYX_REG_DIG_INFO1, &v); ucontrol->value.iec958.status[0] = v & 0x3e; @@ -501,7 +484,6 @@ static int onyx_spdif_get(struct snd_kcontrol *kcontrol, onyx_read_register(onyx, ONYX_REG_DIG_INFO4, &v); ucontrol->value.iec958.status[4] = v & 0x0f; - mutex_unlock(&onyx->mutex); return 0; } @@ -512,7 +494,7 @@ static int onyx_spdif_put(struct snd_kcontrol *kcontrol, struct onyx *onyx = snd_kcontrol_chip(kcontrol); u8 v; - mutex_lock(&onyx->mutex); + guard(mutex)(&onyx->mutex); onyx_read_register(onyx, ONYX_REG_DIG_INFO1, &v); v = (v & ~0x3e) | (ucontrol->value.iec958.status[0] & 0x3e); onyx_write_register(onyx, ONYX_REG_DIG_INFO1, v); @@ -527,7 +509,6 @@ static int onyx_spdif_put(struct snd_kcontrol *kcontrol, onyx_read_register(onyx, ONYX_REG_DIG_INFO4, &v); v = (v & ~0x0f) | (ucontrol->value.iec958.status[4] & 0x0f); onyx_write_register(onyx, ONYX_REG_DIG_INFO4, v); - mutex_unlock(&onyx->mutex); return 1; } @@ -672,14 +653,13 @@ static int onyx_usable(struct codec_info_item *cii, struct onyx *onyx = cii->codec_data; int spdif_enabled, analog_enabled; - mutex_lock(&onyx->mutex); + guard(mutex)(&onyx->mutex); onyx_read_register(onyx, ONYX_REG_DIG_INFO4, &v); spdif_enabled = !!(v & ONYX_SPDIF_ENABLE); onyx_read_register(onyx, ONYX_REG_DAC_CONTROL, &v); analog_enabled = (v & (ONYX_MUTE_RIGHT|ONYX_MUTE_LEFT)) != (ONYX_MUTE_RIGHT|ONYX_MUTE_LEFT); - mutex_unlock(&onyx->mutex); switch (ti->tag) { case 0: return 1; @@ -695,9 +675,8 @@ static int onyx_prepare(struct codec_info_item *cii, { u8 v; struct onyx *onyx = cii->codec_data; - int err = -EBUSY; - mutex_lock(&onyx->mutex); + guard(mutex)(&onyx->mutex); #ifdef SNDRV_PCM_FMTBIT_COMPRESSED_16BE if (substream->runtime->format == SNDRV_PCM_FMTBIT_COMPRESSED_16BE) { @@ -706,10 +685,9 @@ static int onyx_prepare(struct codec_info_item *cii, if (onyx_write_register(onyx, ONYX_REG_DAC_CONTROL, v | ONYX_MUTE_RIGHT | ONYX_MUTE_LEFT)) - goto out_unlock; + return -EBUSY; onyx->analog_locked = 1; - err = 0; - goto out_unlock; + return 0; } #endif switch (substream->runtime->rate) { @@ -719,8 +697,7 @@ static int onyx_prepare(struct codec_info_item *cii, /* these rates are ok for all outputs */ /* FIXME: program spdif channel control bits here so that * userspace doesn't have to if it only plays pcm! */ - err = 0; - goto out_unlock; + return 0; default: /* got some rate that the digital output can't do, * so disable and lock it */ @@ -728,16 +705,12 @@ static int onyx_prepare(struct codec_info_item *cii, if (onyx_write_register(onyx, ONYX_REG_DIG_INFO4, v & ~ONYX_SPDIF_ENABLE)) - goto out_unlock; + return -EBUSY; onyx->spdif_locked = 1; - err = 0; - goto out_unlock; + return 0; } - out_unlock: - mutex_unlock(&onyx->mutex); - - return err; + return -EBUSY; } static int onyx_open(struct codec_info_item *cii, @@ -745,9 +718,8 @@ static int onyx_open(struct codec_info_item *cii, { struct onyx *onyx = cii->codec_data; - mutex_lock(&onyx->mutex); + guard(mutex)(&onyx->mutex); onyx->open_count++; - mutex_unlock(&onyx->mutex); return 0; } @@ -757,11 +729,10 @@ static int onyx_close(struct codec_info_item *cii, { struct onyx *onyx = cii->codec_data; - mutex_lock(&onyx->mutex); + guard(mutex)(&onyx->mutex); onyx->open_count--; if (!onyx->open_count) onyx->spdif_locked = onyx->analog_locked = 0; - mutex_unlock(&onyx->mutex); return 0; } @@ -771,7 +742,7 @@ static int onyx_switch_clock(struct codec_info_item *cii, { struct onyx *onyx = cii->codec_data; - mutex_lock(&onyx->mutex); + guard(mutex)(&onyx->mutex); /* this *MUST* be more elaborate later... */ switch (what) { case CLOCK_SWITCH_PREPARE_SLAVE: @@ -783,7 +754,6 @@ static int onyx_switch_clock(struct codec_info_item *cii, default: /* silence warning */ break; } - mutex_unlock(&onyx->mutex); return 0; } @@ -794,27 +764,21 @@ static int onyx_suspend(struct codec_info_item *cii, pm_message_t state) { struct onyx *onyx = cii->codec_data; u8 v; - int err = -ENXIO; - mutex_lock(&onyx->mutex); + guard(mutex)(&onyx->mutex); if (onyx_read_register(onyx, ONYX_REG_CONTROL, &v)) - goto out_unlock; + return -ENXIO; onyx_write_register(onyx, ONYX_REG_CONTROL, v | ONYX_ADPSV | ONYX_DAPSV); /* Apple does a sleep here but the datasheet says to do it on resume */ - err = 0; - out_unlock: - mutex_unlock(&onyx->mutex); - - return err; + return 0; } static int onyx_resume(struct codec_info_item *cii) { struct onyx *onyx = cii->codec_data; u8 v; - int err = -ENXIO; - mutex_lock(&onyx->mutex); + guard(mutex)(&onyx->mutex); /* reset codec */ onyx->codec.gpio->methods->set_hw_reset(onyx->codec.gpio, 0); @@ -826,17 +790,13 @@ static int onyx_resume(struct codec_info_item *cii) /* take codec out of suspend (if it still is after reset) */ if (onyx_read_register(onyx, ONYX_REG_CONTROL, &v)) - goto out_unlock; + return -ENXIO; onyx_write_register(onyx, ONYX_REG_CONTROL, v & ~(ONYX_ADPSV | ONYX_DAPSV)); /* FIXME: should divide by sample rate, but 8k is the lowest we go */ msleep(2205000/8000); /* reset all values */ onyx_register_init(onyx); - err = 0; - out_unlock: - mutex_unlock(&onyx->mutex); - - return err; + return 0; } #endif /* CONFIG_PM */ diff --git a/sound/aoa/codecs/tas.c b/sound/aoa/codecs/tas.c index d3e37577b5299..04a6635f1eb11 100644 --- a/sound/aoa/codecs/tas.c +++ b/sound/aoa/codecs/tas.c @@ -236,10 +236,9 @@ static int tas_snd_vol_get(struct snd_kcontrol *kcontrol, { struct tas *tas = snd_kcontrol_chip(kcontrol); - mutex_lock(&tas->mtx); + guard(mutex)(&tas->mtx); ucontrol->value.integer.value[0] = tas->cached_volume_l; ucontrol->value.integer.value[1] = tas->cached_volume_r; - mutex_unlock(&tas->mtx); return 0; } @@ -255,18 +254,15 @@ static int tas_snd_vol_put(struct snd_kcontrol *kcontrol, ucontrol->value.integer.value[1] > 177) return -EINVAL; - mutex_lock(&tas->mtx); + guard(mutex)(&tas->mtx); if (tas->cached_volume_l == ucontrol->value.integer.value[0] - && tas->cached_volume_r == ucontrol->value.integer.value[1]) { - mutex_unlock(&tas->mtx); + && tas->cached_volume_r == ucontrol->value.integer.value[1]) return 0; - } tas->cached_volume_l = ucontrol->value.integer.value[0]; tas->cached_volume_r = ucontrol->value.integer.value[1]; if (tas->hw_enabled) tas_set_volume(tas); - mutex_unlock(&tas->mtx); return 1; } @@ -286,10 +282,9 @@ static int tas_snd_mute_get(struct snd_kcontrol *kcontrol, { struct tas *tas = snd_kcontrol_chip(kcontrol); - mutex_lock(&tas->mtx); + guard(mutex)(&tas->mtx); ucontrol->value.integer.value[0] = !tas->mute_l; ucontrol->value.integer.value[1] = !tas->mute_r; - mutex_unlock(&tas->mtx); return 0; } @@ -298,18 +293,15 @@ static int tas_snd_mute_put(struct snd_kcontrol *kcontrol, { struct tas *tas = snd_kcontrol_chip(kcontrol); - mutex_lock(&tas->mtx); + guard(mutex)(&tas->mtx); if (tas->mute_l == !ucontrol->value.integer.value[0] - && tas->mute_r == !ucontrol->value.integer.value[1]) { - mutex_unlock(&tas->mtx); + && tas->mute_r == !ucontrol->value.integer.value[1]) return 0; - } tas->mute_l = !ucontrol->value.integer.value[0]; tas->mute_r = !ucontrol->value.integer.value[1]; if (tas->hw_enabled) tas_set_volume(tas); - mutex_unlock(&tas->mtx); return 1; } @@ -338,10 +330,9 @@ static int tas_snd_mixer_get(struct snd_kcontrol *kcontrol, struct tas *tas = snd_kcontrol_chip(kcontrol); int idx = kcontrol->private_value; - mutex_lock(&tas->mtx); + guard(mutex)(&tas->mtx); ucontrol->value.integer.value[0] = tas->mixer_l[idx]; ucontrol->value.integer.value[1] = tas->mixer_r[idx]; - mutex_unlock(&tas->mtx); return 0; } @@ -352,19 +343,16 @@ static int tas_snd_mixer_put(struct snd_kcontrol *kcontrol, struct tas *tas = snd_kcontrol_chip(kcontrol); int idx = kcontrol->private_value; - mutex_lock(&tas->mtx); + guard(mutex)(&tas->mtx); if (tas->mixer_l[idx] == ucontrol->value.integer.value[0] - && tas->mixer_r[idx] == ucontrol->value.integer.value[1]) { - mutex_unlock(&tas->mtx); + && tas->mixer_r[idx] == ucontrol->value.integer.value[1]) return 0; - } tas->mixer_l[idx] = ucontrol->value.integer.value[0]; tas->mixer_r[idx] = ucontrol->value.integer.value[1]; if (tas->hw_enabled) tas_set_mixer(tas); - mutex_unlock(&tas->mtx); return 1; } @@ -397,9 +385,8 @@ static int tas_snd_drc_range_get(struct snd_kcontrol *kcontrol, { struct tas *tas = snd_kcontrol_chip(kcontrol); - mutex_lock(&tas->mtx); + guard(mutex)(&tas->mtx); ucontrol->value.integer.value[0] = tas->drc_range; - mutex_unlock(&tas->mtx); return 0; } @@ -412,16 +399,13 @@ static int tas_snd_drc_range_put(struct snd_kcontrol *kcontrol, ucontrol->value.integer.value[0] > TAS3004_DRC_MAX) return -EINVAL; - mutex_lock(&tas->mtx); - if (tas->drc_range == ucontrol->value.integer.value[0]) { - mutex_unlock(&tas->mtx); + guard(mutex)(&tas->mtx); + if (tas->drc_range == ucontrol->value.integer.value[0]) return 0; - } tas->drc_range = ucontrol->value.integer.value[0]; if (tas->hw_enabled) tas3004_set_drc(tas); - mutex_unlock(&tas->mtx); return 1; } @@ -441,9 +425,8 @@ static int tas_snd_drc_switch_get(struct snd_kcontrol *kcontrol, { struct tas *tas = snd_kcontrol_chip(kcontrol); - mutex_lock(&tas->mtx); + guard(mutex)(&tas->mtx); ucontrol->value.integer.value[0] = tas->drc_enabled; - mutex_unlock(&tas->mtx); return 0; } @@ -452,16 +435,13 @@ static int tas_snd_drc_switch_put(struct snd_kcontrol *kcontrol, { struct tas *tas = snd_kcontrol_chip(kcontrol); - mutex_lock(&tas->mtx); - if (tas->drc_enabled == ucontrol->value.integer.value[0]) { - mutex_unlock(&tas->mtx); + guard(mutex)(&tas->mtx); + if (tas->drc_enabled == ucontrol->value.integer.value[0]) return 0; - } tas->drc_enabled = !!ucontrol->value.integer.value[0]; if (tas->hw_enabled) tas3004_set_drc(tas); - mutex_unlock(&tas->mtx); return 1; } @@ -487,9 +467,8 @@ static int tas_snd_capture_source_get(struct snd_kcontrol *kcontrol, { struct tas *tas = snd_kcontrol_chip(kcontrol); - mutex_lock(&tas->mtx); + guard(mutex)(&tas->mtx); ucontrol->value.enumerated.item[0] = !!(tas->acr & TAS_ACR_INPUT_B); - mutex_unlock(&tas->mtx); return 0; } @@ -501,7 +480,7 @@ static int tas_snd_capture_source_put(struct snd_kcontrol *kcontrol, if (ucontrol->value.enumerated.item[0] > 1) return -EINVAL; - mutex_lock(&tas->mtx); + guard(mutex)(&tas->mtx); oldacr = tas->acr; /* @@ -513,13 +492,10 @@ static int tas_snd_capture_source_put(struct snd_kcontrol *kcontrol, if (ucontrol->value.enumerated.item[0]) tas->acr |= TAS_ACR_INPUT_B | TAS_ACR_B_MONAUREAL | TAS_ACR_B_MON_SEL_RIGHT; - if (oldacr == tas->acr) { - mutex_unlock(&tas->mtx); + if (oldacr == tas->acr) return 0; - } if (tas->hw_enabled) tas_write_reg(tas, TAS_REG_ACR, 1, &tas->acr); - mutex_unlock(&tas->mtx); return 1; } @@ -558,9 +534,8 @@ static int tas_snd_treble_get(struct snd_kcontrol *kcontrol, { struct tas *tas = snd_kcontrol_chip(kcontrol); - mutex_lock(&tas->mtx); + guard(mutex)(&tas->mtx); ucontrol->value.integer.value[0] = tas->treble; - mutex_unlock(&tas->mtx); return 0; } @@ -572,16 +547,13 @@ static int tas_snd_treble_put(struct snd_kcontrol *kcontrol, if (ucontrol->value.integer.value[0] < TAS3004_TREBLE_MIN || ucontrol->value.integer.value[0] > TAS3004_TREBLE_MAX) return -EINVAL; - mutex_lock(&tas->mtx); - if (tas->treble == ucontrol->value.integer.value[0]) { - mutex_unlock(&tas->mtx); + guard(mutex)(&tas->mtx); + if (tas->treble == ucontrol->value.integer.value[0]) return 0; - } tas->treble = ucontrol->value.integer.value[0]; if (tas->hw_enabled) tas_set_treble(tas); - mutex_unlock(&tas->mtx); return 1; } @@ -609,9 +581,8 @@ static int tas_snd_bass_get(struct snd_kcontrol *kcontrol, { struct tas *tas = snd_kcontrol_chip(kcontrol); - mutex_lock(&tas->mtx); + guard(mutex)(&tas->mtx); ucontrol->value.integer.value[0] = tas->bass; - mutex_unlock(&tas->mtx); return 0; } @@ -623,16 +594,13 @@ static int tas_snd_bass_put(struct snd_kcontrol *kcontrol, if (ucontrol->value.integer.value[0] < TAS3004_BASS_MIN || ucontrol->value.integer.value[0] > TAS3004_BASS_MAX) return -EINVAL; - mutex_lock(&tas->mtx); - if (tas->bass == ucontrol->value.integer.value[0]) { - mutex_unlock(&tas->mtx); + guard(mutex)(&tas->mtx); + if (tas->bass == ucontrol->value.integer.value[0]) return 0; - } tas->bass = ucontrol->value.integer.value[0]; if (tas->hw_enabled) tas_set_bass(tas); - mutex_unlock(&tas->mtx); return 1; } @@ -723,13 +691,13 @@ static int tas_switch_clock(struct codec_info_item *cii, enum clock_switch clock break; case CLOCK_SWITCH_SLAVE: /* Clocks are back, re-init the codec */ - mutex_lock(&tas->mtx); - tas_reset_init(tas); - tas_set_volume(tas); - tas_set_mixer(tas); - tas->hw_enabled = 1; - tas->codec.gpio->methods->all_amps_restore(tas->codec.gpio); - mutex_unlock(&tas->mtx); + scoped_guard(mutex, &tas->mtx) { + tas_reset_init(tas); + tas_set_volume(tas); + tas_set_mixer(tas); + tas->hw_enabled = 1; + tas->codec.gpio->methods->all_amps_restore(tas->codec.gpio); + } break; default: /* doesn't happen as of now */ @@ -744,23 +712,21 @@ static int tas_switch_clock(struct codec_info_item *cii, enum clock_switch clock * our i2c device is suspended, and then take note of that! */ static int tas_suspend(struct tas *tas) { - mutex_lock(&tas->mtx); + guard(mutex)(&tas->mtx); tas->hw_enabled = 0; tas->acr |= TAS_ACR_ANALOG_PDOWN; tas_write_reg(tas, TAS_REG_ACR, 1, &tas->acr); - mutex_unlock(&tas->mtx); return 0; } static int tas_resume(struct tas *tas) { /* reset codec */ - mutex_lock(&tas->mtx); + guard(mutex)(&tas->mtx); tas_reset_init(tas); tas_set_volume(tas); tas_set_mixer(tas); tas->hw_enabled = 1; - mutex_unlock(&tas->mtx); return 0; } @@ -803,14 +769,13 @@ static int tas_init_codec(struct aoa_codec *codec) return -EINVAL; } - mutex_lock(&tas->mtx); - if (tas_reset_init(tas)) { - printk(KERN_ERR PFX "tas failed to initialise\n"); - mutex_unlock(&tas->mtx); - return -ENXIO; + scoped_guard(mutex, &tas->mtx) { + if (tas_reset_init(tas)) { + printk(KERN_ERR PFX "tas failed to initialise\n"); + return -ENXIO; + } + tas->hw_enabled = 1; } - tas->hw_enabled = 1; - mutex_unlock(&tas->mtx); if (tas->codec.soundbus_dev->attach_codec(tas->codec.soundbus_dev, aoa_get_card(), diff --git a/sound/aoa/core/gpio-feature.c b/sound/aoa/core/gpio-feature.c index 39bb409b27f6d..19ed0e6907da3 100644 --- a/sound/aoa/core/gpio-feature.c +++ b/sound/aoa/core/gpio-feature.c @@ -212,10 +212,9 @@ static void ftr_handle_notify(struct work_struct *work) struct gpio_notification *notif = container_of(work, struct gpio_notification, work.work); - mutex_lock(¬if->mutex); + guard(mutex)(¬if->mutex); if (notif->notify) notif->notify(notif->data); - mutex_unlock(¬if->mutex); } static void gpio_enable_dual_edge(int gpio) @@ -341,19 +340,17 @@ static int ftr_set_notify(struct gpio_runtime *rt, if (!irq) return -ENODEV; - mutex_lock(¬if->mutex); + guard(mutex)(¬if->mutex); old = notif->notify; - if (!old && !notify) { - err = 0; - goto out_unlock; - } + if (!old && !notify) + return 0; if (old && notify) { if (old == notify && notif->data == data) err = 0; - goto out_unlock; + return err; } if (old && !notify) @@ -362,16 +359,13 @@ static int ftr_set_notify(struct gpio_runtime *rt, if (!old && notify) { err = request_irq(irq, ftr_handle_notify_irq, 0, name, notif); if (err) - goto out_unlock; + return err; } notif->notify = notify; notif->data = data; - err = 0; - out_unlock: - mutex_unlock(¬if->mutex); - return err; + return 0; } static int ftr_get_detect(struct gpio_runtime *rt, diff --git a/sound/aoa/core/gpio-pmf.c b/sound/aoa/core/gpio-pmf.c index 37866039d1ead..e76bde25e41af 100644 --- a/sound/aoa/core/gpio-pmf.c +++ b/sound/aoa/core/gpio-pmf.c @@ -74,10 +74,9 @@ static void pmf_handle_notify(struct work_struct *work) struct gpio_notification *notif = container_of(work, struct gpio_notification, work.work); - mutex_lock(¬if->mutex); + guard(mutex)(¬if->mutex); if (notif->notify) notif->notify(notif->data); - mutex_unlock(¬if->mutex); } static void pmf_gpio_init(struct gpio_runtime *rt) @@ -154,19 +153,17 @@ static int pmf_set_notify(struct gpio_runtime *rt, return -EINVAL; } - mutex_lock(¬if->mutex); + guard(mutex)(¬if->mutex); old = notif->notify; - if (!old && !notify) { - err = 0; - goto out_unlock; - } + if (!old && !notify) + return 0; if (old && notify) { if (old == notify && notif->data == data) err = 0; - goto out_unlock; + return err; } if (old && !notify) { @@ -178,10 +175,8 @@ static int pmf_set_notify(struct gpio_runtime *rt, if (!old && notify) { irq_client = kzalloc(sizeof(struct pmf_irq_client), GFP_KERNEL); - if (!irq_client) { - err = -ENOMEM; - goto out_unlock; - } + if (!irq_client) + return -ENOMEM; irq_client->data = notif; irq_client->handler = pmf_handle_notify_irq; irq_client->owner = THIS_MODULE; @@ -192,17 +187,14 @@ static int pmf_set_notify(struct gpio_runtime *rt, printk(KERN_ERR "snd-aoa: gpio layer failed to" " register %s irq (%d)\n", name, err); kfree(irq_client); - goto out_unlock; + return err; } notif->gpio_private = irq_client; } notif->notify = notify; notif->data = data; - err = 0; - out_unlock: - mutex_unlock(¬if->mutex); - return err; + return 0; } static int pmf_get_detect(struct gpio_runtime *rt, diff --git a/sound/aoa/soundbus/i2sbus/pcm.c b/sound/aoa/soundbus/i2sbus/pcm.c index 1c8e8131a7162..e95103e5f2fcd 100644 --- a/sound/aoa/soundbus/i2sbus/pcm.c +++ b/sound/aoa/soundbus/i2sbus/pcm.c @@ -79,11 +79,10 @@ static int i2sbus_pcm_open(struct i2sbus_dev *i2sdev, int in) u64 formats = 0; unsigned int rates = 0; struct transfer_info v; - int result = 0; int bus_factor = 0, sysclock_factor = 0; int found_this; - mutex_lock(&i2sdev->lock); + guard(mutex)(&i2sdev->lock); get_pcm_info(i2sdev, in, &pi, &other); @@ -92,8 +91,7 @@ static int i2sbus_pcm_open(struct i2sbus_dev *i2sdev, int in) if (pi->active) { /* alsa messed up */ - result = -EBUSY; - goto out_unlock; + return -EBUSY; } /* we now need to assign the hw */ @@ -117,10 +115,8 @@ static int i2sbus_pcm_open(struct i2sbus_dev *i2sdev, int in) ti++; } } - if (!masks_inited || !bus_factor || !sysclock_factor) { - result = -ENODEV; - goto out_unlock; - } + if (!masks_inited || !bus_factor || !sysclock_factor) + return -ENODEV; /* bus dependent stuff */ hw->info = SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID | SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_RESUME | @@ -194,15 +190,12 @@ static int i2sbus_pcm_open(struct i2sbus_dev *i2sdev, int in) hw->periods_max = MAX_DBDMA_COMMANDS; err = snd_pcm_hw_constraint_integer(pi->substream->runtime, SNDRV_PCM_HW_PARAM_PERIODS); - if (err < 0) { - result = err; - goto out_unlock; - } + if (err < 0) + return err; list_for_each_entry(cii, &sdev->codec_list, list) { if (cii->codec->open) { err = cii->codec->open(cii, pi->substream); if (err) { - result = err; /* unwind */ found_this = 0; list_for_each_entry_reverse(rev, @@ -214,14 +207,12 @@ static int i2sbus_pcm_open(struct i2sbus_dev *i2sdev, int in) if (rev == cii) found_this = 1; } - goto out_unlock; + return err; } } } - out_unlock: - mutex_unlock(&i2sdev->lock); - return result; + return 0; } #undef CHECK_RATE @@ -232,7 +223,7 @@ static int i2sbus_pcm_close(struct i2sbus_dev *i2sdev, int in) struct pcm_info *pi; int err = 0, tmp; - mutex_lock(&i2sdev->lock); + guard(mutex)(&i2sdev->lock); get_pcm_info(i2sdev, in, &pi, NULL); @@ -246,7 +237,6 @@ static int i2sbus_pcm_close(struct i2sbus_dev *i2sdev, int in) pi->substream = NULL; pi->active = 0; - mutex_unlock(&i2sdev->lock); return err; } @@ -330,33 +320,26 @@ static int i2sbus_pcm_prepare(struct i2sbus_dev *i2sdev, int in) int input_16bit; struct pcm_info *pi, *other; int cnt; - int result = 0; unsigned int cmd, stopaddr; - mutex_lock(&i2sdev->lock); + guard(mutex)(&i2sdev->lock); get_pcm_info(i2sdev, in, &pi, &other); - if (pi->dbdma_ring.running) { - result = -EBUSY; - goto out_unlock; - } + if (pi->dbdma_ring.running) + return -EBUSY; if (pi->dbdma_ring.stopping) i2sbus_wait_for_stop(i2sdev, pi); - if (!pi->substream || !pi->substream->runtime) { - result = -EINVAL; - goto out_unlock; - } + if (!pi->substream || !pi->substream->runtime) + return -EINVAL; runtime = pi->substream->runtime; pi->active = 1; if (other->active && ((i2sdev->format != runtime->format) - || (i2sdev->rate != runtime->rate))) { - result = -EINVAL; - goto out_unlock; - } + || (i2sdev->rate != runtime->rate))) + return -EINVAL; i2sdev->format = runtime->format; i2sdev->rate = runtime->rate; @@ -412,10 +395,8 @@ static int i2sbus_pcm_prepare(struct i2sbus_dev *i2sdev, int in) bi.bus_factor = cii->codec->bus_factor; break; } - if (!bi.bus_factor) { - result = -ENODEV; - goto out_unlock; - } + if (!bi.bus_factor) + return -ENODEV; input_16bit = 1; break; case SNDRV_PCM_FORMAT_S32_BE: @@ -426,8 +407,7 @@ static int i2sbus_pcm_prepare(struct i2sbus_dev *i2sdev, int in) input_16bit = 0; break; default: - result = -EINVAL; - goto out_unlock; + return -EINVAL; } /* we assume all sysclocks are the same! */ list_for_each_entry(cii, &i2sdev->sound.codec_list, list) { @@ -438,10 +418,8 @@ static int i2sbus_pcm_prepare(struct i2sbus_dev *i2sdev, int in) if (clock_and_divisors(bi.sysclock_factor, bi.bus_factor, runtime->rate, - &sfr) < 0) { - result = -EINVAL; - goto out_unlock; - } + &sfr) < 0) + return -EINVAL; switch (bi.bus_factor) { case 32: sfr |= I2S_SF_SERIAL_FORMAT_I2S_32X; @@ -457,10 +435,8 @@ static int i2sbus_pcm_prepare(struct i2sbus_dev *i2sdev, int in) int err = 0; if (cii->codec->prepare) err = cii->codec->prepare(cii, &bi, pi->substream); - if (err) { - result = err; - goto out_unlock; - } + if (err) + return err; } /* codecs are fine with it, so set our clocks */ if (input_16bit) @@ -476,7 +452,7 @@ static int i2sbus_pcm_prepare(struct i2sbus_dev *i2sdev, int in) /* not locking these is fine since we touch them only in this function */ if (in_le32(&i2sdev->intfregs->serial_format) == sfr && in_le32(&i2sdev->intfregs->data_word_sizes) == dws) - goto out_unlock; + return 0; /* let's notify the codecs about clocks going away. * For now we only do mastering on the i2s cell... */ @@ -514,9 +490,7 @@ static int i2sbus_pcm_prepare(struct i2sbus_dev *i2sdev, int in) if (cii->codec->switch_clock) cii->codec->switch_clock(cii, CLOCK_SWITCH_SLAVE); - out_unlock: - mutex_unlock(&i2sdev->lock); - return result; + return 0; } #ifdef CONFIG_PM -- 2.53.0 ^ permalink raw reply related [flat|nested] 4+ messages in thread
* [PATCH 5.10.y 2/2] ALSA: aoa: i2sbus: clear stale prepared state 2026-05-01 17:27 ` [PATCH 5.10.y 1/2] ALSA: aoa: Use guard() for mutex locks Sasha Levin @ 2026-05-01 17:28 ` Sasha Levin 0 siblings, 0 replies; 4+ messages in thread From: Sasha Levin @ 2026-05-01 17:28 UTC (permalink / raw) To: stable; +Cc: Cássio Gabriel, kernel test robot, Takashi Iwai, Sasha Levin From: Cássio Gabriel <cassiogabrielcontato@gmail.com> [ Upstream commit 5ed060d5491597490fb53ec69da3edc4b1e8c165 ] The i2sbus PCM code uses pi->active to constrain the sibling stream to an already prepared duplex format and rate in i2sbus_pcm_open(). That state is set from i2sbus_pcm_prepare(), but the current code only clears it on close. As a result, the sibling stream can inherit stale constraints after the prepared state has been torn down. Clear pi->active when hw_params() or hw_free() tears down the prepared state, and set it again only after prepare succeeds. Replace the stale FIXME in the duplex constraint comment with a description of the current driver behavior: i2sbus still programs a single shared transport configuration for both directions, so mixed formats are not supported in duplex mode. Reported-by: kernel test robot <lkp@intel.com> Closes: https://lore.kernel.org/oe-kbuild-all/202604010125.AvkWBYKI-lkp@intel.com/ Fixes: f3d9478b2ce4 ("[ALSA] snd-aoa: add snd-aoa") Cc: stable@vger.kernel.org Signed-off-by: Cássio Gabriel <cassiogabrielcontato@gmail.com> Link: https://patch.msgid.link/20260331-aoa-i2sbus-clear-stale-active-v2-1-3764ae2889a1@gmail.com Signed-off-by: Takashi Iwai <tiwai@suse.de> Signed-off-by: Sasha Levin <sashal@kernel.org> --- sound/aoa/soundbus/i2sbus/pcm.c | 55 ++++++++++++++++++++++++++------- 1 file changed, 44 insertions(+), 11 deletions(-) diff --git a/sound/aoa/soundbus/i2sbus/pcm.c b/sound/aoa/soundbus/i2sbus/pcm.c index e95103e5f2fcd..04afdaa1bc39c 100644 --- a/sound/aoa/soundbus/i2sbus/pcm.c +++ b/sound/aoa/soundbus/i2sbus/pcm.c @@ -165,17 +165,16 @@ static int i2sbus_pcm_open(struct i2sbus_dev *i2sdev, int in) * currently in use (if any). */ hw->rate_min = 5512; hw->rate_max = 192000; - /* if the other stream is active, then we can only - * support what it is currently using. - * FIXME: I lied. This comment is wrong. We can support - * anything that works with the same serial format, ie. - * when recording 24 bit sound we can well play 16 bit - * sound at the same time iff using the same transfer mode. + /* If the other stream is already prepared, keep this stream + * on the same duplex format and rate. + * + * i2sbus_pcm_prepare() still programs one shared transport + * configuration for both directions, so mixed duplex formats + * are not supported here. */ if (other->active) { - /* FIXME: is this guaranteed by the alsa api? */ hw->formats &= pcm_format_to_bits(i2sdev->format); - /* see above, restrict rates to the one we already have */ + /* Restrict rates to the one already in use. */ hw->rate_min = i2sdev->rate; hw->rate_max = i2sdev->rate; } @@ -283,6 +282,23 @@ void i2sbus_wait_for_stop_both(struct i2sbus_dev *i2sdev) } #endif +static void i2sbus_pcm_clear_active(struct i2sbus_dev *i2sdev, int in) +{ + struct pcm_info *pi; + + guard(mutex)(&i2sdev->lock); + + get_pcm_info(i2sdev, in, &pi, NULL); + pi->active = 0; +} + +static inline int i2sbus_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, int in) +{ + i2sbus_pcm_clear_active(snd_pcm_substream_chip(substream), in); + return 0; +} + static inline int i2sbus_hw_free(struct snd_pcm_substream *substream, int in) { struct i2sbus_dev *i2sdev = snd_pcm_substream_chip(substream); @@ -291,14 +307,27 @@ static inline int i2sbus_hw_free(struct snd_pcm_substream *substream, int in) get_pcm_info(i2sdev, in, &pi, NULL); if (pi->dbdma_ring.stopping) i2sbus_wait_for_stop(i2sdev, pi); + i2sbus_pcm_clear_active(i2sdev, in); return 0; } +static int i2sbus_playback_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params) +{ + return i2sbus_hw_params(substream, params, 0); +} + static int i2sbus_playback_hw_free(struct snd_pcm_substream *substream) { return i2sbus_hw_free(substream, 0); } +static int i2sbus_record_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params) +{ + return i2sbus_hw_params(substream, params, 1); +} + static int i2sbus_record_hw_free(struct snd_pcm_substream *substream) { return i2sbus_hw_free(substream, 1); @@ -335,7 +364,6 @@ static int i2sbus_pcm_prepare(struct i2sbus_dev *i2sdev, int in) return -EINVAL; runtime = pi->substream->runtime; - pi->active = 1; if (other->active && ((i2sdev->format != runtime->format) || (i2sdev->rate != runtime->rate))) @@ -450,9 +478,11 @@ static int i2sbus_pcm_prepare(struct i2sbus_dev *i2sdev, int in) /* early exit if already programmed correctly */ /* not locking these is fine since we touch them only in this function */ - if (in_le32(&i2sdev->intfregs->serial_format) == sfr - && in_le32(&i2sdev->intfregs->data_word_sizes) == dws) + if (in_le32(&i2sdev->intfregs->serial_format) == sfr && + in_le32(&i2sdev->intfregs->data_word_sizes) == dws) { + pi->active = 1; return 0; + } /* let's notify the codecs about clocks going away. * For now we only do mastering on the i2s cell... */ @@ -490,6 +520,7 @@ static int i2sbus_pcm_prepare(struct i2sbus_dev *i2sdev, int in) if (cii->codec->switch_clock) cii->codec->switch_clock(cii, CLOCK_SWITCH_SLAVE); + pi->active = 1; return 0; } @@ -746,6 +777,7 @@ static snd_pcm_uframes_t i2sbus_playback_pointer(struct snd_pcm_substream static const struct snd_pcm_ops i2sbus_playback_ops = { .open = i2sbus_playback_open, .close = i2sbus_playback_close, + .hw_params = i2sbus_playback_hw_params, .hw_free = i2sbus_playback_hw_free, .prepare = i2sbus_playback_prepare, .trigger = i2sbus_playback_trigger, @@ -814,6 +846,7 @@ static snd_pcm_uframes_t i2sbus_record_pointer(struct snd_pcm_substream static const struct snd_pcm_ops i2sbus_record_ops = { .open = i2sbus_record_open, .close = i2sbus_record_close, + .hw_params = i2sbus_record_hw_params, .hw_free = i2sbus_record_hw_free, .prepare = i2sbus_record_prepare, .trigger = i2sbus_record_trigger, -- 2.53.0 ^ permalink raw reply related [flat|nested] 4+ messages in thread
* FAILED: patch "[PATCH] ALSA: aoa: Skip devices with no codecs in i2sbus_resume()" failed to apply to 5.10-stable tree
@ 2026-05-01 10:32 gregkh
2026-05-01 18:48 ` [PATCH 5.10.y 1/2] ALSA: aoa: Use guard() for mutex locks Sasha Levin
0 siblings, 1 reply; 4+ messages in thread
From: gregkh @ 2026-05-01 10:32 UTC (permalink / raw)
To: thorsten.blum, tiwai; +Cc: stable
The patch below does not apply to the 5.10-stable tree.
If someone wants it applied there, or to any other stable or longterm
tree, then please email the backport, including the original git commit
id to <stable@vger.kernel.org>.
To reproduce the conflict and resubmit, you may use the following commands:
git fetch https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/ linux-5.10.y
git checkout FETCH_HEAD
git cherry-pick -x fd7df93013c5118812e63a52635dc6c3a805a1de
# <resolve conflicts, build, test, etc.>
git commit -s
git send-email --to '<stable@vger.kernel.org>' --in-reply-to '2026050122-sanitary-moonrise-f13e@gregkh' --subject-prefix 'PATCH 5.10.y' HEAD^..
Possible dependencies:
thanks,
greg k-h
------------------ original commit in Linus's tree ------------------
From fd7df93013c5118812e63a52635dc6c3a805a1de Mon Sep 17 00:00:00 2001
From: Thorsten Blum <thorsten.blum@linux.dev>
Date: Tue, 10 Mar 2026 11:29:20 +0100
Subject: [PATCH] ALSA: aoa: Skip devices with no codecs in i2sbus_resume()
In i2sbus_resume(), skip devices with an empty codec list, which avoids
using an uninitialized 'sysclock_factor' in the 32-bit format path in
i2sbus_pcm_prepare().
In i2sbus_pcm_prepare(), replace two list_for_each_entry() loops with a
single list_first_entry() now that the codec list is guaranteed to be
non-empty by all callers.
Fixes: f3d9478b2ce4 ("[ALSA] snd-aoa: add snd-aoa")
Cc: stable@vger.kernel.org
Signed-off-by: Thorsten Blum <thorsten.blum@linux.dev>
Link: https://patch.msgid.link/20260310102921.210109-3-thorsten.blum@linux.dev
Signed-off-by: Takashi Iwai <tiwai@suse.de>
diff --git a/sound/aoa/soundbus/i2sbus/core.c b/sound/aoa/soundbus/i2sbus/core.c
index f974b96e98cd..22c956267f4e 100644
--- a/sound/aoa/soundbus/i2sbus/core.c
+++ b/sound/aoa/soundbus/i2sbus/core.c
@@ -405,6 +405,9 @@ static int i2sbus_resume(struct macio_dev* dev)
int err, ret = 0;
list_for_each_entry(i2sdev, &control->list, item) {
+ if (list_empty(&i2sdev->sound.codec_list))
+ continue;
+
/* reset i2s bus format etc. */
i2sbus_pcm_prepare_both(i2sdev);
diff --git a/sound/aoa/soundbus/i2sbus/pcm.c b/sound/aoa/soundbus/i2sbus/pcm.c
index aff99003d833..97c807e67d56 100644
--- a/sound/aoa/soundbus/i2sbus/pcm.c
+++ b/sound/aoa/soundbus/i2sbus/pcm.c
@@ -383,6 +383,9 @@ static int i2sbus_pcm_prepare(struct i2sbus_dev *i2sdev, int in)
/* set stop command */
command->command = cpu_to_le16(DBDMA_STOP);
+ cii = list_first_entry(&i2sdev->sound.codec_list,
+ struct codec_info_item, list);
+
/* ok, let's set the serial format and stuff */
switch (runtime->format) {
/* 16 bit formats */
@@ -390,13 +393,7 @@ static int i2sbus_pcm_prepare(struct i2sbus_dev *i2sdev, int in)
case SNDRV_PCM_FORMAT_U16_BE:
/* FIXME: if we add different bus factors we need to
* do more here!! */
- bi.bus_factor = 0;
- list_for_each_entry(cii, &i2sdev->sound.codec_list, list) {
- bi.bus_factor = cii->codec->bus_factor;
- break;
- }
- if (!bi.bus_factor)
- return -ENODEV;
+ bi.bus_factor = cii->codec->bus_factor;
input_16bit = 1;
break;
case SNDRV_PCM_FORMAT_S32_BE:
@@ -410,10 +407,7 @@ static int i2sbus_pcm_prepare(struct i2sbus_dev *i2sdev, int in)
return -EINVAL;
}
/* we assume all sysclocks are the same! */
- list_for_each_entry(cii, &i2sdev->sound.codec_list, list) {
- bi.sysclock_factor = cii->codec->sysclock_factor;
- break;
- }
+ bi.sysclock_factor = cii->codec->sysclock_factor;
if (clock_and_divisors(bi.sysclock_factor,
bi.bus_factor,
^ permalink raw reply related [flat|nested] 4+ messages in thread* [PATCH 5.10.y 1/2] ALSA: aoa: Use guard() for mutex locks 2026-05-01 10:32 FAILED: patch "[PATCH] ALSA: aoa: Skip devices with no codecs in i2sbus_resume()" failed to apply to 5.10-stable tree gregkh @ 2026-05-01 18:48 ` Sasha Levin 0 siblings, 0 replies; 4+ messages in thread From: Sasha Levin @ 2026-05-01 18:48 UTC (permalink / raw) To: stable; +Cc: Takashi Iwai, Sasha Levin From: Takashi Iwai <tiwai@suse.de> [ Upstream commit 1cb6ecbb372002ef9e531c5377e5f60122411e40 ] Replace the manual mutex lock/unlock pairs with guard() for code simplification. Only code refactoring, and no behavior change. Signed-off-by: Takashi Iwai <tiwai@suse.de> Link: https://patch.msgid.link/20250829151335.7342-14-tiwai@suse.de Stable-dep-of: fd7df93013c5 ("ALSA: aoa: Skip devices with no codecs in i2sbus_resume()") Signed-off-by: Sasha Levin <sashal@kernel.org> --- sound/aoa/codecs/onyx.c | 104 +++++++++-------------------- sound/aoa/codecs/tas.c | 113 +++++++++++--------------------- sound/aoa/core/gpio-feature.c | 20 ++---- sound/aoa/core/gpio-pmf.c | 26 +++----- sound/aoa/soundbus/i2sbus/pcm.c | 76 +++++++-------------- 5 files changed, 112 insertions(+), 227 deletions(-) diff --git a/sound/aoa/codecs/onyx.c b/sound/aoa/codecs/onyx.c index 12028b3e2eee4..c544bf85d25c8 100644 --- a/sound/aoa/codecs/onyx.c +++ b/sound/aoa/codecs/onyx.c @@ -121,10 +121,9 @@ static int onyx_snd_vol_get(struct snd_kcontrol *kcontrol, struct onyx *onyx = snd_kcontrol_chip(kcontrol); s8 l, r; - mutex_lock(&onyx->mutex); + guard(mutex)(&onyx->mutex); onyx_read_register(onyx, ONYX_REG_DAC_ATTEN_LEFT, &l); onyx_read_register(onyx, ONYX_REG_DAC_ATTEN_RIGHT, &r); - mutex_unlock(&onyx->mutex); ucontrol->value.integer.value[0] = l + VOLUME_RANGE_SHIFT; ucontrol->value.integer.value[1] = r + VOLUME_RANGE_SHIFT; @@ -145,15 +144,13 @@ static int onyx_snd_vol_put(struct snd_kcontrol *kcontrol, ucontrol->value.integer.value[1] > -1 + VOLUME_RANGE_SHIFT) return -EINVAL; - mutex_lock(&onyx->mutex); + guard(mutex)(&onyx->mutex); onyx_read_register(onyx, ONYX_REG_DAC_ATTEN_LEFT, &l); onyx_read_register(onyx, ONYX_REG_DAC_ATTEN_RIGHT, &r); if (l + VOLUME_RANGE_SHIFT == ucontrol->value.integer.value[0] && - r + VOLUME_RANGE_SHIFT == ucontrol->value.integer.value[1]) { - mutex_unlock(&onyx->mutex); + r + VOLUME_RANGE_SHIFT == ucontrol->value.integer.value[1]) return 0; - } onyx_write_register(onyx, ONYX_REG_DAC_ATTEN_LEFT, ucontrol->value.integer.value[0] @@ -161,7 +158,6 @@ static int onyx_snd_vol_put(struct snd_kcontrol *kcontrol, onyx_write_register(onyx, ONYX_REG_DAC_ATTEN_RIGHT, ucontrol->value.integer.value[1] - VOLUME_RANGE_SHIFT); - mutex_unlock(&onyx->mutex); return 1; } @@ -197,9 +193,8 @@ static int onyx_snd_inputgain_get(struct snd_kcontrol *kcontrol, struct onyx *onyx = snd_kcontrol_chip(kcontrol); u8 ig; - mutex_lock(&onyx->mutex); + guard(mutex)(&onyx->mutex); onyx_read_register(onyx, ONYX_REG_ADC_CONTROL, &ig); - mutex_unlock(&onyx->mutex); ucontrol->value.integer.value[0] = (ig & ONYX_ADC_PGA_GAIN_MASK) + INPUTGAIN_RANGE_SHIFT; @@ -216,14 +211,13 @@ static int onyx_snd_inputgain_put(struct snd_kcontrol *kcontrol, if (ucontrol->value.integer.value[0] < 3 + INPUTGAIN_RANGE_SHIFT || ucontrol->value.integer.value[0] > 28 + INPUTGAIN_RANGE_SHIFT) return -EINVAL; - mutex_lock(&onyx->mutex); + guard(mutex)(&onyx->mutex); onyx_read_register(onyx, ONYX_REG_ADC_CONTROL, &v); n = v; n &= ~ONYX_ADC_PGA_GAIN_MASK; n |= (ucontrol->value.integer.value[0] - INPUTGAIN_RANGE_SHIFT) & ONYX_ADC_PGA_GAIN_MASK; onyx_write_register(onyx, ONYX_REG_ADC_CONTROL, n); - mutex_unlock(&onyx->mutex); return n != v; } @@ -251,9 +245,8 @@ static int onyx_snd_capture_source_get(struct snd_kcontrol *kcontrol, struct onyx *onyx = snd_kcontrol_chip(kcontrol); s8 v; - mutex_lock(&onyx->mutex); + guard(mutex)(&onyx->mutex); onyx_read_register(onyx, ONYX_REG_ADC_CONTROL, &v); - mutex_unlock(&onyx->mutex); ucontrol->value.enumerated.item[0] = !!(v&ONYX_ADC_INPUT_MIC); @@ -264,13 +257,12 @@ static void onyx_set_capture_source(struct onyx *onyx, int mic) { s8 v; - mutex_lock(&onyx->mutex); + guard(mutex)(&onyx->mutex); onyx_read_register(onyx, ONYX_REG_ADC_CONTROL, &v); v &= ~ONYX_ADC_INPUT_MIC; if (mic) v |= ONYX_ADC_INPUT_MIC; onyx_write_register(onyx, ONYX_REG_ADC_CONTROL, v); - mutex_unlock(&onyx->mutex); } static int onyx_snd_capture_source_put(struct snd_kcontrol *kcontrol, @@ -311,9 +303,8 @@ static int onyx_snd_mute_get(struct snd_kcontrol *kcontrol, struct onyx *onyx = snd_kcontrol_chip(kcontrol); u8 c; - mutex_lock(&onyx->mutex); + guard(mutex)(&onyx->mutex); onyx_read_register(onyx, ONYX_REG_DAC_CONTROL, &c); - mutex_unlock(&onyx->mutex); ucontrol->value.integer.value[0] = !(c & ONYX_MUTE_LEFT); ucontrol->value.integer.value[1] = !(c & ONYX_MUTE_RIGHT); @@ -328,9 +319,9 @@ static int onyx_snd_mute_put(struct snd_kcontrol *kcontrol, u8 v = 0, c = 0; int err = -EBUSY; - mutex_lock(&onyx->mutex); + guard(mutex)(&onyx->mutex); if (onyx->analog_locked) - goto out_unlock; + return -EBUSY; onyx_read_register(onyx, ONYX_REG_DAC_CONTROL, &v); c = v; @@ -341,9 +332,6 @@ static int onyx_snd_mute_put(struct snd_kcontrol *kcontrol, c |= ONYX_MUTE_RIGHT; err = onyx_write_register(onyx, ONYX_REG_DAC_CONTROL, c); - out_unlock: - mutex_unlock(&onyx->mutex); - return !err ? (v != c) : err; } @@ -372,9 +360,8 @@ static int onyx_snd_single_bit_get(struct snd_kcontrol *kcontrol, u8 address = (pv >> 8) & 0xff; u8 mask = pv & 0xff; - mutex_lock(&onyx->mutex); + guard(mutex)(&onyx->mutex); onyx_read_register(onyx, address, &c); - mutex_unlock(&onyx->mutex); ucontrol->value.integer.value[0] = !!(c & mask) ^ polarity; @@ -393,11 +380,10 @@ static int onyx_snd_single_bit_put(struct snd_kcontrol *kcontrol, u8 address = (pv >> 8) & 0xff; u8 mask = pv & 0xff; - mutex_lock(&onyx->mutex); + guard(mutex)(&onyx->mutex); if (spdiflock && onyx->spdif_locked) { /* even if alsamixer doesn't care.. */ - err = -EBUSY; - goto out_unlock; + return -EBUSY; } onyx_read_register(onyx, address, &v); c = v; @@ -406,9 +392,6 @@ static int onyx_snd_single_bit_put(struct snd_kcontrol *kcontrol, c |= mask; err = onyx_write_register(onyx, address, c); - out_unlock: - mutex_unlock(&onyx->mutex); - return !err ? (v != c) : err; } @@ -489,7 +472,7 @@ static int onyx_spdif_get(struct snd_kcontrol *kcontrol, struct onyx *onyx = snd_kcontrol_chip(kcontrol); u8 v; - mutex_lock(&onyx->mutex); + guard(mutex)(&onyx->mutex); onyx_read_register(onyx, ONYX_REG_DIG_INFO1, &v); ucontrol->value.iec958.status[0] = v & 0x3e; @@ -501,7 +484,6 @@ static int onyx_spdif_get(struct snd_kcontrol *kcontrol, onyx_read_register(onyx, ONYX_REG_DIG_INFO4, &v); ucontrol->value.iec958.status[4] = v & 0x0f; - mutex_unlock(&onyx->mutex); return 0; } @@ -512,7 +494,7 @@ static int onyx_spdif_put(struct snd_kcontrol *kcontrol, struct onyx *onyx = snd_kcontrol_chip(kcontrol); u8 v; - mutex_lock(&onyx->mutex); + guard(mutex)(&onyx->mutex); onyx_read_register(onyx, ONYX_REG_DIG_INFO1, &v); v = (v & ~0x3e) | (ucontrol->value.iec958.status[0] & 0x3e); onyx_write_register(onyx, ONYX_REG_DIG_INFO1, v); @@ -527,7 +509,6 @@ static int onyx_spdif_put(struct snd_kcontrol *kcontrol, onyx_read_register(onyx, ONYX_REG_DIG_INFO4, &v); v = (v & ~0x0f) | (ucontrol->value.iec958.status[4] & 0x0f); onyx_write_register(onyx, ONYX_REG_DIG_INFO4, v); - mutex_unlock(&onyx->mutex); return 1; } @@ -672,14 +653,13 @@ static int onyx_usable(struct codec_info_item *cii, struct onyx *onyx = cii->codec_data; int spdif_enabled, analog_enabled; - mutex_lock(&onyx->mutex); + guard(mutex)(&onyx->mutex); onyx_read_register(onyx, ONYX_REG_DIG_INFO4, &v); spdif_enabled = !!(v & ONYX_SPDIF_ENABLE); onyx_read_register(onyx, ONYX_REG_DAC_CONTROL, &v); analog_enabled = (v & (ONYX_MUTE_RIGHT|ONYX_MUTE_LEFT)) != (ONYX_MUTE_RIGHT|ONYX_MUTE_LEFT); - mutex_unlock(&onyx->mutex); switch (ti->tag) { case 0: return 1; @@ -695,9 +675,8 @@ static int onyx_prepare(struct codec_info_item *cii, { u8 v; struct onyx *onyx = cii->codec_data; - int err = -EBUSY; - mutex_lock(&onyx->mutex); + guard(mutex)(&onyx->mutex); #ifdef SNDRV_PCM_FMTBIT_COMPRESSED_16BE if (substream->runtime->format == SNDRV_PCM_FMTBIT_COMPRESSED_16BE) { @@ -706,10 +685,9 @@ static int onyx_prepare(struct codec_info_item *cii, if (onyx_write_register(onyx, ONYX_REG_DAC_CONTROL, v | ONYX_MUTE_RIGHT | ONYX_MUTE_LEFT)) - goto out_unlock; + return -EBUSY; onyx->analog_locked = 1; - err = 0; - goto out_unlock; + return 0; } #endif switch (substream->runtime->rate) { @@ -719,8 +697,7 @@ static int onyx_prepare(struct codec_info_item *cii, /* these rates are ok for all outputs */ /* FIXME: program spdif channel control bits here so that * userspace doesn't have to if it only plays pcm! */ - err = 0; - goto out_unlock; + return 0; default: /* got some rate that the digital output can't do, * so disable and lock it */ @@ -728,16 +705,12 @@ static int onyx_prepare(struct codec_info_item *cii, if (onyx_write_register(onyx, ONYX_REG_DIG_INFO4, v & ~ONYX_SPDIF_ENABLE)) - goto out_unlock; + return -EBUSY; onyx->spdif_locked = 1; - err = 0; - goto out_unlock; + return 0; } - out_unlock: - mutex_unlock(&onyx->mutex); - - return err; + return -EBUSY; } static int onyx_open(struct codec_info_item *cii, @@ -745,9 +718,8 @@ static int onyx_open(struct codec_info_item *cii, { struct onyx *onyx = cii->codec_data; - mutex_lock(&onyx->mutex); + guard(mutex)(&onyx->mutex); onyx->open_count++; - mutex_unlock(&onyx->mutex); return 0; } @@ -757,11 +729,10 @@ static int onyx_close(struct codec_info_item *cii, { struct onyx *onyx = cii->codec_data; - mutex_lock(&onyx->mutex); + guard(mutex)(&onyx->mutex); onyx->open_count--; if (!onyx->open_count) onyx->spdif_locked = onyx->analog_locked = 0; - mutex_unlock(&onyx->mutex); return 0; } @@ -771,7 +742,7 @@ static int onyx_switch_clock(struct codec_info_item *cii, { struct onyx *onyx = cii->codec_data; - mutex_lock(&onyx->mutex); + guard(mutex)(&onyx->mutex); /* this *MUST* be more elaborate later... */ switch (what) { case CLOCK_SWITCH_PREPARE_SLAVE: @@ -783,7 +754,6 @@ static int onyx_switch_clock(struct codec_info_item *cii, default: /* silence warning */ break; } - mutex_unlock(&onyx->mutex); return 0; } @@ -794,27 +764,21 @@ static int onyx_suspend(struct codec_info_item *cii, pm_message_t state) { struct onyx *onyx = cii->codec_data; u8 v; - int err = -ENXIO; - mutex_lock(&onyx->mutex); + guard(mutex)(&onyx->mutex); if (onyx_read_register(onyx, ONYX_REG_CONTROL, &v)) - goto out_unlock; + return -ENXIO; onyx_write_register(onyx, ONYX_REG_CONTROL, v | ONYX_ADPSV | ONYX_DAPSV); /* Apple does a sleep here but the datasheet says to do it on resume */ - err = 0; - out_unlock: - mutex_unlock(&onyx->mutex); - - return err; + return 0; } static int onyx_resume(struct codec_info_item *cii) { struct onyx *onyx = cii->codec_data; u8 v; - int err = -ENXIO; - mutex_lock(&onyx->mutex); + guard(mutex)(&onyx->mutex); /* reset codec */ onyx->codec.gpio->methods->set_hw_reset(onyx->codec.gpio, 0); @@ -826,17 +790,13 @@ static int onyx_resume(struct codec_info_item *cii) /* take codec out of suspend (if it still is after reset) */ if (onyx_read_register(onyx, ONYX_REG_CONTROL, &v)) - goto out_unlock; + return -ENXIO; onyx_write_register(onyx, ONYX_REG_CONTROL, v & ~(ONYX_ADPSV | ONYX_DAPSV)); /* FIXME: should divide by sample rate, but 8k is the lowest we go */ msleep(2205000/8000); /* reset all values */ onyx_register_init(onyx); - err = 0; - out_unlock: - mutex_unlock(&onyx->mutex); - - return err; + return 0; } #endif /* CONFIG_PM */ diff --git a/sound/aoa/codecs/tas.c b/sound/aoa/codecs/tas.c index d3e37577b5299..04a6635f1eb11 100644 --- a/sound/aoa/codecs/tas.c +++ b/sound/aoa/codecs/tas.c @@ -236,10 +236,9 @@ static int tas_snd_vol_get(struct snd_kcontrol *kcontrol, { struct tas *tas = snd_kcontrol_chip(kcontrol); - mutex_lock(&tas->mtx); + guard(mutex)(&tas->mtx); ucontrol->value.integer.value[0] = tas->cached_volume_l; ucontrol->value.integer.value[1] = tas->cached_volume_r; - mutex_unlock(&tas->mtx); return 0; } @@ -255,18 +254,15 @@ static int tas_snd_vol_put(struct snd_kcontrol *kcontrol, ucontrol->value.integer.value[1] > 177) return -EINVAL; - mutex_lock(&tas->mtx); + guard(mutex)(&tas->mtx); if (tas->cached_volume_l == ucontrol->value.integer.value[0] - && tas->cached_volume_r == ucontrol->value.integer.value[1]) { - mutex_unlock(&tas->mtx); + && tas->cached_volume_r == ucontrol->value.integer.value[1]) return 0; - } tas->cached_volume_l = ucontrol->value.integer.value[0]; tas->cached_volume_r = ucontrol->value.integer.value[1]; if (tas->hw_enabled) tas_set_volume(tas); - mutex_unlock(&tas->mtx); return 1; } @@ -286,10 +282,9 @@ static int tas_snd_mute_get(struct snd_kcontrol *kcontrol, { struct tas *tas = snd_kcontrol_chip(kcontrol); - mutex_lock(&tas->mtx); + guard(mutex)(&tas->mtx); ucontrol->value.integer.value[0] = !tas->mute_l; ucontrol->value.integer.value[1] = !tas->mute_r; - mutex_unlock(&tas->mtx); return 0; } @@ -298,18 +293,15 @@ static int tas_snd_mute_put(struct snd_kcontrol *kcontrol, { struct tas *tas = snd_kcontrol_chip(kcontrol); - mutex_lock(&tas->mtx); + guard(mutex)(&tas->mtx); if (tas->mute_l == !ucontrol->value.integer.value[0] - && tas->mute_r == !ucontrol->value.integer.value[1]) { - mutex_unlock(&tas->mtx); + && tas->mute_r == !ucontrol->value.integer.value[1]) return 0; - } tas->mute_l = !ucontrol->value.integer.value[0]; tas->mute_r = !ucontrol->value.integer.value[1]; if (tas->hw_enabled) tas_set_volume(tas); - mutex_unlock(&tas->mtx); return 1; } @@ -338,10 +330,9 @@ static int tas_snd_mixer_get(struct snd_kcontrol *kcontrol, struct tas *tas = snd_kcontrol_chip(kcontrol); int idx = kcontrol->private_value; - mutex_lock(&tas->mtx); + guard(mutex)(&tas->mtx); ucontrol->value.integer.value[0] = tas->mixer_l[idx]; ucontrol->value.integer.value[1] = tas->mixer_r[idx]; - mutex_unlock(&tas->mtx); return 0; } @@ -352,19 +343,16 @@ static int tas_snd_mixer_put(struct snd_kcontrol *kcontrol, struct tas *tas = snd_kcontrol_chip(kcontrol); int idx = kcontrol->private_value; - mutex_lock(&tas->mtx); + guard(mutex)(&tas->mtx); if (tas->mixer_l[idx] == ucontrol->value.integer.value[0] - && tas->mixer_r[idx] == ucontrol->value.integer.value[1]) { - mutex_unlock(&tas->mtx); + && tas->mixer_r[idx] == ucontrol->value.integer.value[1]) return 0; - } tas->mixer_l[idx] = ucontrol->value.integer.value[0]; tas->mixer_r[idx] = ucontrol->value.integer.value[1]; if (tas->hw_enabled) tas_set_mixer(tas); - mutex_unlock(&tas->mtx); return 1; } @@ -397,9 +385,8 @@ static int tas_snd_drc_range_get(struct snd_kcontrol *kcontrol, { struct tas *tas = snd_kcontrol_chip(kcontrol); - mutex_lock(&tas->mtx); + guard(mutex)(&tas->mtx); ucontrol->value.integer.value[0] = tas->drc_range; - mutex_unlock(&tas->mtx); return 0; } @@ -412,16 +399,13 @@ static int tas_snd_drc_range_put(struct snd_kcontrol *kcontrol, ucontrol->value.integer.value[0] > TAS3004_DRC_MAX) return -EINVAL; - mutex_lock(&tas->mtx); - if (tas->drc_range == ucontrol->value.integer.value[0]) { - mutex_unlock(&tas->mtx); + guard(mutex)(&tas->mtx); + if (tas->drc_range == ucontrol->value.integer.value[0]) return 0; - } tas->drc_range = ucontrol->value.integer.value[0]; if (tas->hw_enabled) tas3004_set_drc(tas); - mutex_unlock(&tas->mtx); return 1; } @@ -441,9 +425,8 @@ static int tas_snd_drc_switch_get(struct snd_kcontrol *kcontrol, { struct tas *tas = snd_kcontrol_chip(kcontrol); - mutex_lock(&tas->mtx); + guard(mutex)(&tas->mtx); ucontrol->value.integer.value[0] = tas->drc_enabled; - mutex_unlock(&tas->mtx); return 0; } @@ -452,16 +435,13 @@ static int tas_snd_drc_switch_put(struct snd_kcontrol *kcontrol, { struct tas *tas = snd_kcontrol_chip(kcontrol); - mutex_lock(&tas->mtx); - if (tas->drc_enabled == ucontrol->value.integer.value[0]) { - mutex_unlock(&tas->mtx); + guard(mutex)(&tas->mtx); + if (tas->drc_enabled == ucontrol->value.integer.value[0]) return 0; - } tas->drc_enabled = !!ucontrol->value.integer.value[0]; if (tas->hw_enabled) tas3004_set_drc(tas); - mutex_unlock(&tas->mtx); return 1; } @@ -487,9 +467,8 @@ static int tas_snd_capture_source_get(struct snd_kcontrol *kcontrol, { struct tas *tas = snd_kcontrol_chip(kcontrol); - mutex_lock(&tas->mtx); + guard(mutex)(&tas->mtx); ucontrol->value.enumerated.item[0] = !!(tas->acr & TAS_ACR_INPUT_B); - mutex_unlock(&tas->mtx); return 0; } @@ -501,7 +480,7 @@ static int tas_snd_capture_source_put(struct snd_kcontrol *kcontrol, if (ucontrol->value.enumerated.item[0] > 1) return -EINVAL; - mutex_lock(&tas->mtx); + guard(mutex)(&tas->mtx); oldacr = tas->acr; /* @@ -513,13 +492,10 @@ static int tas_snd_capture_source_put(struct snd_kcontrol *kcontrol, if (ucontrol->value.enumerated.item[0]) tas->acr |= TAS_ACR_INPUT_B | TAS_ACR_B_MONAUREAL | TAS_ACR_B_MON_SEL_RIGHT; - if (oldacr == tas->acr) { - mutex_unlock(&tas->mtx); + if (oldacr == tas->acr) return 0; - } if (tas->hw_enabled) tas_write_reg(tas, TAS_REG_ACR, 1, &tas->acr); - mutex_unlock(&tas->mtx); return 1; } @@ -558,9 +534,8 @@ static int tas_snd_treble_get(struct snd_kcontrol *kcontrol, { struct tas *tas = snd_kcontrol_chip(kcontrol); - mutex_lock(&tas->mtx); + guard(mutex)(&tas->mtx); ucontrol->value.integer.value[0] = tas->treble; - mutex_unlock(&tas->mtx); return 0; } @@ -572,16 +547,13 @@ static int tas_snd_treble_put(struct snd_kcontrol *kcontrol, if (ucontrol->value.integer.value[0] < TAS3004_TREBLE_MIN || ucontrol->value.integer.value[0] > TAS3004_TREBLE_MAX) return -EINVAL; - mutex_lock(&tas->mtx); - if (tas->treble == ucontrol->value.integer.value[0]) { - mutex_unlock(&tas->mtx); + guard(mutex)(&tas->mtx); + if (tas->treble == ucontrol->value.integer.value[0]) return 0; - } tas->treble = ucontrol->value.integer.value[0]; if (tas->hw_enabled) tas_set_treble(tas); - mutex_unlock(&tas->mtx); return 1; } @@ -609,9 +581,8 @@ static int tas_snd_bass_get(struct snd_kcontrol *kcontrol, { struct tas *tas = snd_kcontrol_chip(kcontrol); - mutex_lock(&tas->mtx); + guard(mutex)(&tas->mtx); ucontrol->value.integer.value[0] = tas->bass; - mutex_unlock(&tas->mtx); return 0; } @@ -623,16 +594,13 @@ static int tas_snd_bass_put(struct snd_kcontrol *kcontrol, if (ucontrol->value.integer.value[0] < TAS3004_BASS_MIN || ucontrol->value.integer.value[0] > TAS3004_BASS_MAX) return -EINVAL; - mutex_lock(&tas->mtx); - if (tas->bass == ucontrol->value.integer.value[0]) { - mutex_unlock(&tas->mtx); + guard(mutex)(&tas->mtx); + if (tas->bass == ucontrol->value.integer.value[0]) return 0; - } tas->bass = ucontrol->value.integer.value[0]; if (tas->hw_enabled) tas_set_bass(tas); - mutex_unlock(&tas->mtx); return 1; } @@ -723,13 +691,13 @@ static int tas_switch_clock(struct codec_info_item *cii, enum clock_switch clock break; case CLOCK_SWITCH_SLAVE: /* Clocks are back, re-init the codec */ - mutex_lock(&tas->mtx); - tas_reset_init(tas); - tas_set_volume(tas); - tas_set_mixer(tas); - tas->hw_enabled = 1; - tas->codec.gpio->methods->all_amps_restore(tas->codec.gpio); - mutex_unlock(&tas->mtx); + scoped_guard(mutex, &tas->mtx) { + tas_reset_init(tas); + tas_set_volume(tas); + tas_set_mixer(tas); + tas->hw_enabled = 1; + tas->codec.gpio->methods->all_amps_restore(tas->codec.gpio); + } break; default: /* doesn't happen as of now */ @@ -744,23 +712,21 @@ static int tas_switch_clock(struct codec_info_item *cii, enum clock_switch clock * our i2c device is suspended, and then take note of that! */ static int tas_suspend(struct tas *tas) { - mutex_lock(&tas->mtx); + guard(mutex)(&tas->mtx); tas->hw_enabled = 0; tas->acr |= TAS_ACR_ANALOG_PDOWN; tas_write_reg(tas, TAS_REG_ACR, 1, &tas->acr); - mutex_unlock(&tas->mtx); return 0; } static int tas_resume(struct tas *tas) { /* reset codec */ - mutex_lock(&tas->mtx); + guard(mutex)(&tas->mtx); tas_reset_init(tas); tas_set_volume(tas); tas_set_mixer(tas); tas->hw_enabled = 1; - mutex_unlock(&tas->mtx); return 0; } @@ -803,14 +769,13 @@ static int tas_init_codec(struct aoa_codec *codec) return -EINVAL; } - mutex_lock(&tas->mtx); - if (tas_reset_init(tas)) { - printk(KERN_ERR PFX "tas failed to initialise\n"); - mutex_unlock(&tas->mtx); - return -ENXIO; + scoped_guard(mutex, &tas->mtx) { + if (tas_reset_init(tas)) { + printk(KERN_ERR PFX "tas failed to initialise\n"); + return -ENXIO; + } + tas->hw_enabled = 1; } - tas->hw_enabled = 1; - mutex_unlock(&tas->mtx); if (tas->codec.soundbus_dev->attach_codec(tas->codec.soundbus_dev, aoa_get_card(), diff --git a/sound/aoa/core/gpio-feature.c b/sound/aoa/core/gpio-feature.c index 39bb409b27f6d..19ed0e6907da3 100644 --- a/sound/aoa/core/gpio-feature.c +++ b/sound/aoa/core/gpio-feature.c @@ -212,10 +212,9 @@ static void ftr_handle_notify(struct work_struct *work) struct gpio_notification *notif = container_of(work, struct gpio_notification, work.work); - mutex_lock(¬if->mutex); + guard(mutex)(¬if->mutex); if (notif->notify) notif->notify(notif->data); - mutex_unlock(¬if->mutex); } static void gpio_enable_dual_edge(int gpio) @@ -341,19 +340,17 @@ static int ftr_set_notify(struct gpio_runtime *rt, if (!irq) return -ENODEV; - mutex_lock(¬if->mutex); + guard(mutex)(¬if->mutex); old = notif->notify; - if (!old && !notify) { - err = 0; - goto out_unlock; - } + if (!old && !notify) + return 0; if (old && notify) { if (old == notify && notif->data == data) err = 0; - goto out_unlock; + return err; } if (old && !notify) @@ -362,16 +359,13 @@ static int ftr_set_notify(struct gpio_runtime *rt, if (!old && notify) { err = request_irq(irq, ftr_handle_notify_irq, 0, name, notif); if (err) - goto out_unlock; + return err; } notif->notify = notify; notif->data = data; - err = 0; - out_unlock: - mutex_unlock(¬if->mutex); - return err; + return 0; } static int ftr_get_detect(struct gpio_runtime *rt, diff --git a/sound/aoa/core/gpio-pmf.c b/sound/aoa/core/gpio-pmf.c index 37866039d1ead..e76bde25e41af 100644 --- a/sound/aoa/core/gpio-pmf.c +++ b/sound/aoa/core/gpio-pmf.c @@ -74,10 +74,9 @@ static void pmf_handle_notify(struct work_struct *work) struct gpio_notification *notif = container_of(work, struct gpio_notification, work.work); - mutex_lock(¬if->mutex); + guard(mutex)(¬if->mutex); if (notif->notify) notif->notify(notif->data); - mutex_unlock(¬if->mutex); } static void pmf_gpio_init(struct gpio_runtime *rt) @@ -154,19 +153,17 @@ static int pmf_set_notify(struct gpio_runtime *rt, return -EINVAL; } - mutex_lock(¬if->mutex); + guard(mutex)(¬if->mutex); old = notif->notify; - if (!old && !notify) { - err = 0; - goto out_unlock; - } + if (!old && !notify) + return 0; if (old && notify) { if (old == notify && notif->data == data) err = 0; - goto out_unlock; + return err; } if (old && !notify) { @@ -178,10 +175,8 @@ static int pmf_set_notify(struct gpio_runtime *rt, if (!old && notify) { irq_client = kzalloc(sizeof(struct pmf_irq_client), GFP_KERNEL); - if (!irq_client) { - err = -ENOMEM; - goto out_unlock; - } + if (!irq_client) + return -ENOMEM; irq_client->data = notif; irq_client->handler = pmf_handle_notify_irq; irq_client->owner = THIS_MODULE; @@ -192,17 +187,14 @@ static int pmf_set_notify(struct gpio_runtime *rt, printk(KERN_ERR "snd-aoa: gpio layer failed to" " register %s irq (%d)\n", name, err); kfree(irq_client); - goto out_unlock; + return err; } notif->gpio_private = irq_client; } notif->notify = notify; notif->data = data; - err = 0; - out_unlock: - mutex_unlock(¬if->mutex); - return err; + return 0; } static int pmf_get_detect(struct gpio_runtime *rt, diff --git a/sound/aoa/soundbus/i2sbus/pcm.c b/sound/aoa/soundbus/i2sbus/pcm.c index 1c8e8131a7162..e95103e5f2fcd 100644 --- a/sound/aoa/soundbus/i2sbus/pcm.c +++ b/sound/aoa/soundbus/i2sbus/pcm.c @@ -79,11 +79,10 @@ static int i2sbus_pcm_open(struct i2sbus_dev *i2sdev, int in) u64 formats = 0; unsigned int rates = 0; struct transfer_info v; - int result = 0; int bus_factor = 0, sysclock_factor = 0; int found_this; - mutex_lock(&i2sdev->lock); + guard(mutex)(&i2sdev->lock); get_pcm_info(i2sdev, in, &pi, &other); @@ -92,8 +91,7 @@ static int i2sbus_pcm_open(struct i2sbus_dev *i2sdev, int in) if (pi->active) { /* alsa messed up */ - result = -EBUSY; - goto out_unlock; + return -EBUSY; } /* we now need to assign the hw */ @@ -117,10 +115,8 @@ static int i2sbus_pcm_open(struct i2sbus_dev *i2sdev, int in) ti++; } } - if (!masks_inited || !bus_factor || !sysclock_factor) { - result = -ENODEV; - goto out_unlock; - } + if (!masks_inited || !bus_factor || !sysclock_factor) + return -ENODEV; /* bus dependent stuff */ hw->info = SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID | SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_RESUME | @@ -194,15 +190,12 @@ static int i2sbus_pcm_open(struct i2sbus_dev *i2sdev, int in) hw->periods_max = MAX_DBDMA_COMMANDS; err = snd_pcm_hw_constraint_integer(pi->substream->runtime, SNDRV_PCM_HW_PARAM_PERIODS); - if (err < 0) { - result = err; - goto out_unlock; - } + if (err < 0) + return err; list_for_each_entry(cii, &sdev->codec_list, list) { if (cii->codec->open) { err = cii->codec->open(cii, pi->substream); if (err) { - result = err; /* unwind */ found_this = 0; list_for_each_entry_reverse(rev, @@ -214,14 +207,12 @@ static int i2sbus_pcm_open(struct i2sbus_dev *i2sdev, int in) if (rev == cii) found_this = 1; } - goto out_unlock; + return err; } } } - out_unlock: - mutex_unlock(&i2sdev->lock); - return result; + return 0; } #undef CHECK_RATE @@ -232,7 +223,7 @@ static int i2sbus_pcm_close(struct i2sbus_dev *i2sdev, int in) struct pcm_info *pi; int err = 0, tmp; - mutex_lock(&i2sdev->lock); + guard(mutex)(&i2sdev->lock); get_pcm_info(i2sdev, in, &pi, NULL); @@ -246,7 +237,6 @@ static int i2sbus_pcm_close(struct i2sbus_dev *i2sdev, int in) pi->substream = NULL; pi->active = 0; - mutex_unlock(&i2sdev->lock); return err; } @@ -330,33 +320,26 @@ static int i2sbus_pcm_prepare(struct i2sbus_dev *i2sdev, int in) int input_16bit; struct pcm_info *pi, *other; int cnt; - int result = 0; unsigned int cmd, stopaddr; - mutex_lock(&i2sdev->lock); + guard(mutex)(&i2sdev->lock); get_pcm_info(i2sdev, in, &pi, &other); - if (pi->dbdma_ring.running) { - result = -EBUSY; - goto out_unlock; - } + if (pi->dbdma_ring.running) + return -EBUSY; if (pi->dbdma_ring.stopping) i2sbus_wait_for_stop(i2sdev, pi); - if (!pi->substream || !pi->substream->runtime) { - result = -EINVAL; - goto out_unlock; - } + if (!pi->substream || !pi->substream->runtime) + return -EINVAL; runtime = pi->substream->runtime; pi->active = 1; if (other->active && ((i2sdev->format != runtime->format) - || (i2sdev->rate != runtime->rate))) { - result = -EINVAL; - goto out_unlock; - } + || (i2sdev->rate != runtime->rate))) + return -EINVAL; i2sdev->format = runtime->format; i2sdev->rate = runtime->rate; @@ -412,10 +395,8 @@ static int i2sbus_pcm_prepare(struct i2sbus_dev *i2sdev, int in) bi.bus_factor = cii->codec->bus_factor; break; } - if (!bi.bus_factor) { - result = -ENODEV; - goto out_unlock; - } + if (!bi.bus_factor) + return -ENODEV; input_16bit = 1; break; case SNDRV_PCM_FORMAT_S32_BE: @@ -426,8 +407,7 @@ static int i2sbus_pcm_prepare(struct i2sbus_dev *i2sdev, int in) input_16bit = 0; break; default: - result = -EINVAL; - goto out_unlock; + return -EINVAL; } /* we assume all sysclocks are the same! */ list_for_each_entry(cii, &i2sdev->sound.codec_list, list) { @@ -438,10 +418,8 @@ static int i2sbus_pcm_prepare(struct i2sbus_dev *i2sdev, int in) if (clock_and_divisors(bi.sysclock_factor, bi.bus_factor, runtime->rate, - &sfr) < 0) { - result = -EINVAL; - goto out_unlock; - } + &sfr) < 0) + return -EINVAL; switch (bi.bus_factor) { case 32: sfr |= I2S_SF_SERIAL_FORMAT_I2S_32X; @@ -457,10 +435,8 @@ static int i2sbus_pcm_prepare(struct i2sbus_dev *i2sdev, int in) int err = 0; if (cii->codec->prepare) err = cii->codec->prepare(cii, &bi, pi->substream); - if (err) { - result = err; - goto out_unlock; - } + if (err) + return err; } /* codecs are fine with it, so set our clocks */ if (input_16bit) @@ -476,7 +452,7 @@ static int i2sbus_pcm_prepare(struct i2sbus_dev *i2sdev, int in) /* not locking these is fine since we touch them only in this function */ if (in_le32(&i2sdev->intfregs->serial_format) == sfr && in_le32(&i2sdev->intfregs->data_word_sizes) == dws) - goto out_unlock; + return 0; /* let's notify the codecs about clocks going away. * For now we only do mastering on the i2s cell... */ @@ -514,9 +490,7 @@ static int i2sbus_pcm_prepare(struct i2sbus_dev *i2sdev, int in) if (cii->codec->switch_clock) cii->codec->switch_clock(cii, CLOCK_SWITCH_SLAVE); - out_unlock: - mutex_unlock(&i2sdev->lock); - return result; + return 0; } #ifdef CONFIG_PM -- 2.53.0 ^ permalink raw reply related [flat|nested] 4+ messages in thread
end of thread, other threads:[~2026-05-01 18:48 UTC | newest] Thread overview: 4+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2026-05-01 10:31 FAILED: patch "[PATCH] ALSA: aoa: i2sbus: clear stale prepared state" failed to apply to 5.10-stable tree gregkh 2026-05-01 17:27 ` [PATCH 5.10.y 1/2] ALSA: aoa: Use guard() for mutex locks Sasha Levin 2026-05-01 17:28 ` [PATCH 5.10.y 2/2] ALSA: aoa: i2sbus: clear stale prepared state Sasha Levin -- strict thread matches above, loose matches on Subject: below -- 2026-05-01 10:32 FAILED: patch "[PATCH] ALSA: aoa: Skip devices with no codecs in i2sbus_resume()" failed to apply to 5.10-stable tree gregkh 2026-05-01 18:48 ` [PATCH 5.10.y 1/2] ALSA: aoa: Use guard() for mutex locks Sasha Levin
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox