mirror of
https://github.com/linux-msm/laptops-kernel.git
synced 2026-08-13 14:19:53 -07:00
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:
+25
-34
@@ -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
File diff suppressed because it is too large
Load Diff
+15
-16
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user