Commit 888ea7d5 authored by Takashi Iwai's avatar Takashi Iwai

ALSA: usb-audio: Fix races at disconnection in mixer_quirks.c

Similar like the previous commit, cover with chip->shutdown_rwsem
and chip->shutdown checks.
Reported-by: default avatarMatthieu CASTET <matthieu.castet@parrot.com>
Cc: <stable@vger.kernel.org>
Signed-off-by: default avatarTakashi Iwai <tiwai@suse.de>
parent 34f3c89f
...@@ -283,6 +283,11 @@ static int snd_audigy2nx_led_put(struct snd_kcontrol *kcontrol, struct snd_ctl_e ...@@ -283,6 +283,11 @@ static int snd_audigy2nx_led_put(struct snd_kcontrol *kcontrol, struct snd_ctl_e
if (value > 1) if (value > 1)
return -EINVAL; return -EINVAL;
changed = value != mixer->audigy2nx_leds[index]; changed = value != mixer->audigy2nx_leds[index];
down_read(&mixer->chip->shutdown_rwsem);
if (mixer->chip->shutdown) {
err = -ENODEV;
goto out;
}
if (mixer->chip->usb_id == USB_ID(0x041e, 0x3042)) if (mixer->chip->usb_id == USB_ID(0x041e, 0x3042))
err = snd_usb_ctl_msg(mixer->chip->dev, err = snd_usb_ctl_msg(mixer->chip->dev,
usb_sndctrlpipe(mixer->chip->dev, 0), 0x24, usb_sndctrlpipe(mixer->chip->dev, 0), 0x24,
...@@ -299,6 +304,8 @@ static int snd_audigy2nx_led_put(struct snd_kcontrol *kcontrol, struct snd_ctl_e ...@@ -299,6 +304,8 @@ static int snd_audigy2nx_led_put(struct snd_kcontrol *kcontrol, struct snd_ctl_e
usb_sndctrlpipe(mixer->chip->dev, 0), 0x24, usb_sndctrlpipe(mixer->chip->dev, 0), 0x24,
USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_OTHER, USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_OTHER,
value, index + 2, NULL, 0); value, index + 2, NULL, 0);
out:
up_read(&mixer->chip->shutdown_rwsem);
if (err < 0) if (err < 0)
return err; return err;
mixer->audigy2nx_leds[index] = value; mixer->audigy2nx_leds[index] = value;
...@@ -392,11 +399,16 @@ static void snd_audigy2nx_proc_read(struct snd_info_entry *entry, ...@@ -392,11 +399,16 @@ static void snd_audigy2nx_proc_read(struct snd_info_entry *entry,
for (i = 0; jacks[i].name; ++i) { for (i = 0; jacks[i].name; ++i) {
snd_iprintf(buffer, "%s: ", jacks[i].name); snd_iprintf(buffer, "%s: ", jacks[i].name);
err = snd_usb_ctl_msg(mixer->chip->dev, down_read(&mixer->chip->shutdown_rwsem);
if (mixer->chip->shutdown)
err = 0;
else
err = snd_usb_ctl_msg(mixer->chip->dev,
usb_rcvctrlpipe(mixer->chip->dev, 0), usb_rcvctrlpipe(mixer->chip->dev, 0),
UAC_GET_MEM, USB_DIR_IN | USB_TYPE_CLASS | UAC_GET_MEM, USB_DIR_IN | USB_TYPE_CLASS |
USB_RECIP_INTERFACE, 0, USB_RECIP_INTERFACE, 0,
jacks[i].unitid << 8, buf, 3); jacks[i].unitid << 8, buf, 3);
up_read(&mixer->chip->shutdown_rwsem);
if (err == 3 && (buf[0] == 3 || buf[0] == 6)) if (err == 3 && (buf[0] == 3 || buf[0] == 6))
snd_iprintf(buffer, "%02x %02x\n", buf[1], buf[2]); snd_iprintf(buffer, "%02x %02x\n", buf[1], buf[2]);
else else
...@@ -426,10 +438,15 @@ static int snd_xonar_u1_switch_put(struct snd_kcontrol *kcontrol, ...@@ -426,10 +438,15 @@ static int snd_xonar_u1_switch_put(struct snd_kcontrol *kcontrol,
else else
new_status = old_status & ~0x02; new_status = old_status & ~0x02;
changed = new_status != old_status; changed = new_status != old_status;
err = snd_usb_ctl_msg(mixer->chip->dev, down_read(&mixer->chip->shutdown_rwsem);
if (mixer->chip->shutdown)
err = -ENODEV;
else
err = snd_usb_ctl_msg(mixer->chip->dev,
usb_sndctrlpipe(mixer->chip->dev, 0), 0x08, usb_sndctrlpipe(mixer->chip->dev, 0), 0x08,
USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_OTHER, USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_OTHER,
50, 0, &new_status, 1); 50, 0, &new_status, 1);
up_read(&mixer->chip->shutdown_rwsem);
if (err < 0) if (err < 0)
return err; return err;
mixer->xonar_u1_status = new_status; mixer->xonar_u1_status = new_status;
...@@ -468,11 +485,17 @@ static int snd_nativeinstruments_control_get(struct snd_kcontrol *kcontrol, ...@@ -468,11 +485,17 @@ static int snd_nativeinstruments_control_get(struct snd_kcontrol *kcontrol,
u8 bRequest = (kcontrol->private_value >> 16) & 0xff; u8 bRequest = (kcontrol->private_value >> 16) & 0xff;
u16 wIndex = kcontrol->private_value & 0xffff; u16 wIndex = kcontrol->private_value & 0xffff;
u8 tmp; u8 tmp;
int ret;
int ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), bRequest, down_read(&mixer->chip->shutdown_rwsem);
if (mixer->chip->shutdown)
ret = -ENODEV;
else
ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), bRequest,
USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN,
0, cpu_to_le16(wIndex), 0, cpu_to_le16(wIndex),
&tmp, sizeof(tmp), 1000); &tmp, sizeof(tmp), 1000);
up_read(&mixer->chip->shutdown_rwsem);
if (ret < 0) { if (ret < 0) {
snd_printk(KERN_ERR snd_printk(KERN_ERR
...@@ -493,11 +516,17 @@ static int snd_nativeinstruments_control_put(struct snd_kcontrol *kcontrol, ...@@ -493,11 +516,17 @@ static int snd_nativeinstruments_control_put(struct snd_kcontrol *kcontrol,
u8 bRequest = (kcontrol->private_value >> 16) & 0xff; u8 bRequest = (kcontrol->private_value >> 16) & 0xff;
u16 wIndex = kcontrol->private_value & 0xffff; u16 wIndex = kcontrol->private_value & 0xffff;
u16 wValue = ucontrol->value.integer.value[0]; u16 wValue = ucontrol->value.integer.value[0];
int ret;
int ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), bRequest, down_read(&mixer->chip->shutdown_rwsem);
if (mixer->chip->shutdown)
ret = -ENODEV;
else
ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), bRequest,
USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_OUT, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_OUT,
cpu_to_le16(wValue), cpu_to_le16(wIndex), cpu_to_le16(wValue), cpu_to_le16(wIndex),
NULL, 0, 1000); NULL, 0, 1000);
up_read(&mixer->chip->shutdown_rwsem);
if (ret < 0) { if (ret < 0) {
snd_printk(KERN_ERR snd_printk(KERN_ERR
...@@ -656,11 +685,16 @@ static int snd_ftu_eff_switch_get(struct snd_kcontrol *kctl, ...@@ -656,11 +685,16 @@ static int snd_ftu_eff_switch_get(struct snd_kcontrol *kctl,
return -EINVAL; return -EINVAL;
err = snd_usb_ctl_msg(chip->dev, down_read(&mixer->chip->shutdown_rwsem);
if (mixer->chip->shutdown)
err = -ENODEV;
else
err = snd_usb_ctl_msg(chip->dev,
usb_rcvctrlpipe(chip->dev, 0), UAC_GET_CUR, usb_rcvctrlpipe(chip->dev, 0), UAC_GET_CUR,
USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN, USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN,
validx << 8, snd_usb_ctrl_intf(chip) | (id << 8), validx << 8, snd_usb_ctrl_intf(chip) | (id << 8),
value, val_len); value, val_len);
up_read(&mixer->chip->shutdown_rwsem);
if (err < 0) if (err < 0)
return err; return err;
...@@ -703,11 +737,16 @@ static int snd_ftu_eff_switch_put(struct snd_kcontrol *kctl, ...@@ -703,11 +737,16 @@ static int snd_ftu_eff_switch_put(struct snd_kcontrol *kctl,
if (!pval->is_cached) { if (!pval->is_cached) {
/* Read current value */ /* Read current value */
err = snd_usb_ctl_msg(chip->dev, down_read(&mixer->chip->shutdown_rwsem);
if (mixer->chip->shutdown)
err = -ENODEV;
else
err = snd_usb_ctl_msg(chip->dev,
usb_rcvctrlpipe(chip->dev, 0), UAC_GET_CUR, usb_rcvctrlpipe(chip->dev, 0), UAC_GET_CUR,
USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN, USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN,
validx << 8, snd_usb_ctrl_intf(chip) | (id << 8), validx << 8, snd_usb_ctrl_intf(chip) | (id << 8),
value, val_len); value, val_len);
up_read(&mixer->chip->shutdown_rwsem);
if (err < 0) if (err < 0)
return err; return err;
...@@ -719,11 +758,16 @@ static int snd_ftu_eff_switch_put(struct snd_kcontrol *kctl, ...@@ -719,11 +758,16 @@ static int snd_ftu_eff_switch_put(struct snd_kcontrol *kctl,
if (cur_val != new_val) { if (cur_val != new_val) {
value[0] = new_val; value[0] = new_val;
value[1] = 0; value[1] = 0;
err = snd_usb_ctl_msg(chip->dev, down_read(&mixer->chip->shutdown_rwsem);
if (mixer->chip->shutdown)
err = -ENODEV;
else
err = snd_usb_ctl_msg(chip->dev,
usb_sndctrlpipe(chip->dev, 0), UAC_SET_CUR, usb_sndctrlpipe(chip->dev, 0), UAC_SET_CUR,
USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_OUT, USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_OUT,
validx << 8, snd_usb_ctrl_intf(chip) | (id << 8), validx << 8, snd_usb_ctrl_intf(chip) | (id << 8),
value, val_len); value, val_len);
up_read(&mixer->chip->shutdown_rwsem);
if (err < 0) if (err < 0)
return err; return err;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment