ALSA: usb-audio: Use auto-cleanup for shutdown locks

Introduce an auto-cleanup macro for the temporary shutdown locks for
USB-audio, and replace the manual lock/unlock pairs with it.

Namely, the former

	err = snd_usb_lock_shutdown(chip);
	if (err < 0)
		return err;
	....
	snd_usb_unlock_shutdown(chip);

is replaced with

	CLASS(snd_usb_lock, pm)(chip);
	if (pm.err < 0)
		return pm.err;
	....

with the automatic unlocking.

Link: https://patch.msgid.link/20250811101647.8637-1-tiwai@suse.de
Signed-off-by: Takashi Iwai <tiwai@suse.de>
This commit is contained in:
Takashi Iwai
2025-08-13 17:39:28 +02:00
parent efea7a5737
commit aff8436ed9
5 changed files with 209 additions and 267 deletions
+25 -34
View File
@@ -313,8 +313,8 @@ static int get_ctl_value_v1(struct usb_mixer_elem_info *cval, int request,
int timeout = 10;
int idx = 0, err;
err = snd_usb_lock_shutdown(chip);
if (err < 0)
CLASS(snd_usb_lock, pm)(chip);
if (pm.err < 0)
return -EIO;
while (timeout-- > 0) {
@@ -324,20 +324,15 @@ static int get_ctl_value_v1(struct usb_mixer_elem_info *cval, int request,
validx, idx, buf, val_len);
if (err >= val_len) {
*value_ret = convert_signed_value(cval, snd_usb_combine_bytes(buf, val_len));
err = 0;
goto out;
return 0;
} else if (err == -ETIMEDOUT) {
goto out;
return err;
}
}
usb_audio_dbg(chip,
"cannot get ctl value: req = %#x, wValue = %#x, wIndex = %#x, type = %d\n",
request, validx, idx, cval->val_type);
err = -EINVAL;
out:
snd_usb_unlock_shutdown(chip);
return err;
return -EINVAL;
}
static int get_ctl_value_v2(struct usb_mixer_elem_info *cval, int request,
@@ -362,14 +357,16 @@ static int get_ctl_value_v2(struct usb_mixer_elem_info *cval, int request,
memset(buf, 0, sizeof(buf));
if (snd_usb_lock_shutdown(chip))
return -EIO;
{
CLASS(snd_usb_lock, pm)(chip);
if (pm.err)
return -EIO;
idx = mixer_ctrl_intf(cval->head.mixer) | (cval->head.id << 8);
ret = snd_usb_ctl_msg(chip->dev, usb_rcvctrlpipe(chip->dev, 0), bRequest,
USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN,
validx, idx, buf, size);
snd_usb_unlock_shutdown(chip);
idx = mixer_ctrl_intf(cval->head.mixer) | (cval->head.id << 8);
ret = snd_usb_ctl_msg(chip->dev, usb_rcvctrlpipe(chip->dev, 0), bRequest,
USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN,
validx, idx, buf, size);
}
if (ret < 0) {
usb_audio_dbg(chip,
@@ -484,8 +481,8 @@ int snd_usb_mixer_set_ctl_value(struct usb_mixer_elem_info *cval,
buf[2] = (value_set >> 16) & 0xff;
buf[3] = (value_set >> 24) & 0xff;
err = snd_usb_lock_shutdown(chip);
if (err < 0)
CLASS(snd_usb_lock, pm)(chip);
if (pm.err < 0)
return -EIO;
while (timeout-- > 0) {
@@ -494,20 +491,14 @@ int snd_usb_mixer_set_ctl_value(struct usb_mixer_elem_info *cval,
usb_sndctrlpipe(chip->dev, 0), request,
USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_OUT,
validx, idx, buf, val_len);
if (err >= 0) {
err = 0;
goto out;
} else if (err == -ETIMEDOUT) {
goto out;
}
if (err >= 0)
return 0;
else if (err == -ETIMEDOUT)
return err;
}
usb_audio_dbg(chip, "cannot set ctl value: req = %#x, wValue = %#x, wIndex = %#x, type = %d, data = %#x/%#x\n",
request, validx, idx, cval->val_type, buf[0], buf[1]);
err = -EINVAL;
out:
snd_usb_unlock_shutdown(chip);
return err;
return -EINVAL;
}
static int set_cur_ctl_value(struct usb_mixer_elem_info *cval,
@@ -1494,9 +1485,11 @@ static int get_connector_value(struct usb_mixer_elem_info *cval,
validx = cval->control << 8 | 0;
ret = snd_usb_lock_shutdown(chip) ? -EIO : 0;
if (ret)
CLASS(snd_usb_lock, pm)(chip);
if (pm.err) {
ret = -EIO;
goto error;
}
idx = mixer_ctrl_intf(cval->head.mixer) | (cval->head.id << 8);
if (cval->head.mixer->protocol == UAC_VERSION_2) {
@@ -1517,8 +1510,6 @@ static int get_connector_value(struct usb_mixer_elem_info *cval,
*val = !!uac3_conn.bmConInserted;
}
snd_usb_unlock_shutdown(chip);
if (ret < 0) {
if (name && strstr(name, "Speaker")) {
if (val)
+140 -208
View File
File diff suppressed because it is too large Load Diff
+15 -16
View File
@@ -614,11 +614,11 @@ int snd_usb_hw_free(struct snd_usb_substream *subs)
scoped_guard(mutex, &chip->mutex) {
subs->cur_audiofmt = NULL;
}
if (!snd_usb_lock_shutdown(chip)) {
CLASS(snd_usb_lock, pm)(chip);
if (!pm.err) {
if (stop_endpoints(subs, false))
sync_pending_stops(subs);
close_endpoints(chip, subs);
snd_usb_unlock_shutdown(chip);
}
return 0;
@@ -675,28 +675,26 @@ static int snd_usb_pcm_prepare(struct snd_pcm_substream *substream)
int retry = 0;
int ret;
ret = snd_usb_lock_shutdown(chip);
if (ret < 0)
return ret;
if (snd_BUG_ON(!subs->data_endpoint)) {
ret = -EIO;
goto unlock;
}
CLASS(snd_usb_lock, pm)(chip);
if (pm.err < 0)
return pm.err;
if (snd_BUG_ON(!subs->data_endpoint))
return -EIO;
ret = snd_usb_pcm_change_state(subs, UAC3_PD_STATE_D0);
if (ret < 0)
goto unlock;
return ret;
again:
if (subs->sync_endpoint) {
ret = snd_usb_endpoint_prepare(chip, subs->sync_endpoint);
if (ret < 0)
goto unlock;
return ret;
}
ret = snd_usb_endpoint_prepare(chip, subs->data_endpoint);
if (ret < 0)
goto unlock;
return ret;
else if (ret > 0)
snd_usb_set_format_quirk(subs, subs->cur_audiofmt);
ret = 0;
@@ -722,8 +720,7 @@ static int snd_usb_pcm_prepare(struct snd_pcm_substream *substream)
goto again;
}
}
unlock:
snd_usb_unlock_shutdown(chip);
return ret;
}
@@ -1296,9 +1293,11 @@ static int snd_usb_pcm_close(struct snd_pcm_substream *substream)
snd_media_stop_pipeline(subs);
if (!snd_usb_lock_shutdown(subs->stream->chip)) {
{
CLASS(snd_usb_lock, pm)(subs->stream->chip);
if (pm.err)
return pm.err;
ret = snd_usb_pcm_change_state(subs, UAC3_PD_STATE_D1);
snd_usb_unlock_shutdown(subs->stream->chip);
if (ret < 0)
return ret;
}
+6 -9
View File
@@ -961,21 +961,21 @@ static int enable_audio_stream(struct snd_usb_substream *subs,
goto put_suspend;
if (!atomic_read(&chip->shutdown)) {
ret = snd_usb_lock_shutdown(chip);
if (ret < 0)
CLASS(snd_usb_lock, pm)(chip);
if (pm.err < 0) {
ret = pm.err;
goto detach_ep;
}
if (subs->sync_endpoint) {
ret = snd_usb_endpoint_prepare(chip, subs->sync_endpoint);
if (ret < 0)
goto unlock;
goto detach_ep;
}
ret = snd_usb_endpoint_prepare(chip, subs->data_endpoint);
if (ret < 0)
goto unlock;
snd_usb_unlock_shutdown(chip);
goto detach_ep;
dev_dbg(uaudio_qdev->data->dev,
"selected %s iface:%d altsetting:%d datainterval:%dus\n",
@@ -989,9 +989,6 @@ static int enable_audio_stream(struct snd_usb_substream *subs,
return 0;
unlock:
snd_usb_unlock_shutdown(chip);
detach_ep:
snd_usb_hw_free(subs);
+23
View File
@@ -139,6 +139,29 @@ struct snd_usb_audio_quirk {
int snd_usb_lock_shutdown(struct snd_usb_audio *chip);
void snd_usb_unlock_shutdown(struct snd_usb_audio *chip);
/* auto-cleanup */
struct __snd_usb_lock {
struct snd_usb_audio *chip;
int err;
};
static inline struct __snd_usb_lock __snd_usb_lock_shutdown(struct snd_usb_audio *chip)
{
struct __snd_usb_lock T = { .chip = chip };
T.err = snd_usb_lock_shutdown(chip);
return T;
}
static inline void __snd_usb_unlock_shutdown(struct __snd_usb_lock *lock)
{
if (!lock->err)
snd_usb_unlock_shutdown(lock->chip);
}
DEFINE_CLASS(snd_usb_lock, struct __snd_usb_lock,
__snd_usb_unlock_shutdown(&(_T)), __snd_usb_lock_shutdown(chip),
struct snd_usb_audio *chip)
extern bool snd_usb_use_vmalloc;
extern bool snd_usb_skip_validation;