diff options
| author | Takashi Iwai <tiwai@suse.de> | 2012-10-15 06:40:37 -0400 |
|---|---|---|
| committer | Takashi Iwai <tiwai@suse.de> | 2012-10-30 06:07:05 -0400 |
| commit | 888ea7d5ac6815ba16b3b3a20f665a92c7af6724 (patch) | |
| tree | 0fa4d254cf538ee02236a6d93fae0ff5eb728038 | |
| parent | 34f3c89fda4fba9fe689db22253ca8db2f5e6386 (diff) | |
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: Matthieu CASTET <matthieu.castet@parrot.com>
Cc: <stable@vger.kernel.org>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
| -rw-r--r-- | sound/usb/mixer_quirks.c | 58 |
1 files changed, 51 insertions, 7 deletions
diff --git a/sound/usb/mixer_quirks.c b/sound/usb/mixer_quirks.c index 690000db0ec0..ae2b71435220 100644 --- a/sound/usb/mixer_quirks.c +++ b/sound/usb/mixer_quirks.c | |||
| @@ -283,6 +283,11 @@ static int snd_audigy2nx_led_put(struct snd_kcontrol *kcontrol, struct snd_ctl_e | |||
| 283 | if (value > 1) | 283 | if (value > 1) |
| 284 | return -EINVAL; | 284 | return -EINVAL; |
| 285 | changed = value != mixer->audigy2nx_leds[index]; | 285 | changed = value != mixer->audigy2nx_leds[index]; |
| 286 | down_read(&mixer->chip->shutdown_rwsem); | ||
| 287 | if (mixer->chip->shutdown) { | ||
| 288 | err = -ENODEV; | ||
| 289 | goto out; | ||
| 290 | } | ||
| 286 | if (mixer->chip->usb_id == USB_ID(0x041e, 0x3042)) | 291 | if (mixer->chip->usb_id == USB_ID(0x041e, 0x3042)) |
| 287 | err = snd_usb_ctl_msg(mixer->chip->dev, | 292 | err = snd_usb_ctl_msg(mixer->chip->dev, |
| 288 | usb_sndctrlpipe(mixer->chip->dev, 0), 0x24, | 293 | 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 | usb_sndctrlpipe(mixer->chip->dev, 0), 0x24, | 304 | usb_sndctrlpipe(mixer->chip->dev, 0), 0x24, |
| 300 | USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_OTHER, | 305 | USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_OTHER, |
| 301 | value, index + 2, NULL, 0); | 306 | value, index + 2, NULL, 0); |
| 307 | out: | ||
| 308 | up_read(&mixer->chip->shutdown_rwsem); | ||
| 302 | if (err < 0) | 309 | if (err < 0) |
| 303 | return err; | 310 | return err; |
| 304 | mixer->audigy2nx_leds[index] = value; | 311 | mixer->audigy2nx_leds[index] = value; |
| @@ -392,11 +399,16 @@ static void snd_audigy2nx_proc_read(struct snd_info_entry *entry, | |||
| 392 | 399 | ||
| 393 | for (i = 0; jacks[i].name; ++i) { | 400 | for (i = 0; jacks[i].name; ++i) { |
| 394 | snd_iprintf(buffer, "%s: ", jacks[i].name); | 401 | snd_iprintf(buffer, "%s: ", jacks[i].name); |
| 395 | err = snd_usb_ctl_msg(mixer->chip->dev, | 402 | down_read(&mixer->chip->shutdown_rwsem); |
| 403 | if (mixer->chip->shutdown) | ||
| 404 | err = 0; | ||
| 405 | else | ||
| 406 | err = snd_usb_ctl_msg(mixer->chip->dev, | ||
| 396 | usb_rcvctrlpipe(mixer->chip->dev, 0), | 407 | usb_rcvctrlpipe(mixer->chip->dev, 0), |
| 397 | UAC_GET_MEM, USB_DIR_IN | USB_TYPE_CLASS | | 408 | UAC_GET_MEM, USB_DIR_IN | USB_TYPE_CLASS | |
| 398 | USB_RECIP_INTERFACE, 0, | 409 | USB_RECIP_INTERFACE, 0, |
| 399 | jacks[i].unitid << 8, buf, 3); | 410 | jacks[i].unitid << 8, buf, 3); |
| 411 | up_read(&mixer->chip->shutdown_rwsem); | ||
| 400 | if (err == 3 && (buf[0] == 3 || buf[0] == 6)) | 412 | if (err == 3 && (buf[0] == 3 || buf[0] == 6)) |
| 401 | snd_iprintf(buffer, "%02x %02x\n", buf[1], buf[2]); | 413 | snd_iprintf(buffer, "%02x %02x\n", buf[1], buf[2]); |
| 402 | else | 414 | else |
| @@ -426,10 +438,15 @@ static int snd_xonar_u1_switch_put(struct snd_kcontrol *kcontrol, | |||
| 426 | else | 438 | else |
| 427 | new_status = old_status & ~0x02; | 439 | new_status = old_status & ~0x02; |
| 428 | changed = new_status != old_status; | 440 | changed = new_status != old_status; |
| 429 | err = snd_usb_ctl_msg(mixer->chip->dev, | 441 | down_read(&mixer->chip->shutdown_rwsem); |
| 442 | if (mixer->chip->shutdown) | ||
| 443 | err = -ENODEV; | ||
| 444 | else | ||
| 445 | err = snd_usb_ctl_msg(mixer->chip->dev, | ||
| 430 | usb_sndctrlpipe(mixer->chip->dev, 0), 0x08, | 446 | usb_sndctrlpipe(mixer->chip->dev, 0), 0x08, |
| 431 | USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_OTHER, | 447 | USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_OTHER, |
| 432 | 50, 0, &new_status, 1); | 448 | 50, 0, &new_status, 1); |
| 449 | up_read(&mixer->chip->shutdown_rwsem); | ||
| 433 | if (err < 0) | 450 | if (err < 0) |
| 434 | return err; | 451 | return err; |
| 435 | mixer->xonar_u1_status = new_status; | 452 | mixer->xonar_u1_status = new_status; |
| @@ -468,11 +485,17 @@ static int snd_nativeinstruments_control_get(struct snd_kcontrol *kcontrol, | |||
| 468 | u8 bRequest = (kcontrol->private_value >> 16) & 0xff; | 485 | u8 bRequest = (kcontrol->private_value >> 16) & 0xff; |
| 469 | u16 wIndex = kcontrol->private_value & 0xffff; | 486 | u16 wIndex = kcontrol->private_value & 0xffff; |
| 470 | u8 tmp; | 487 | u8 tmp; |
| 488 | int ret; | ||
| 471 | 489 | ||
| 472 | int ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), bRequest, | 490 | down_read(&mixer->chip->shutdown_rwsem); |
| 491 | if (mixer->chip->shutdown) | ||
| 492 | ret = -ENODEV; | ||
| 493 | else | ||
| 494 | ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), bRequest, | ||
| 473 | USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN, | 495 | USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN, |
| 474 | 0, cpu_to_le16(wIndex), | 496 | 0, cpu_to_le16(wIndex), |
| 475 | &tmp, sizeof(tmp), 1000); | 497 | &tmp, sizeof(tmp), 1000); |
| 498 | up_read(&mixer->chip->shutdown_rwsem); | ||
| 476 | 499 | ||
| 477 | if (ret < 0) { | 500 | if (ret < 0) { |
| 478 | snd_printk(KERN_ERR | 501 | snd_printk(KERN_ERR |
| @@ -493,11 +516,17 @@ static int snd_nativeinstruments_control_put(struct snd_kcontrol *kcontrol, | |||
| 493 | u8 bRequest = (kcontrol->private_value >> 16) & 0xff; | 516 | u8 bRequest = (kcontrol->private_value >> 16) & 0xff; |
| 494 | u16 wIndex = kcontrol->private_value & 0xffff; | 517 | u16 wIndex = kcontrol->private_value & 0xffff; |
| 495 | u16 wValue = ucontrol->value.integer.value[0]; | 518 | u16 wValue = ucontrol->value.integer.value[0]; |
| 519 | int ret; | ||
| 496 | 520 | ||
| 497 | int ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), bRequest, | 521 | down_read(&mixer->chip->shutdown_rwsem); |
| 522 | if (mixer->chip->shutdown) | ||
| 523 | ret = -ENODEV; | ||
| 524 | else | ||
| 525 | ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), bRequest, | ||
| 498 | USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_OUT, | 526 | USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_OUT, |
| 499 | cpu_to_le16(wValue), cpu_to_le16(wIndex), | 527 | cpu_to_le16(wValue), cpu_to_le16(wIndex), |
| 500 | NULL, 0, 1000); | 528 | NULL, 0, 1000); |
| 529 | up_read(&mixer->chip->shutdown_rwsem); | ||
| 501 | 530 | ||
| 502 | if (ret < 0) { | 531 | if (ret < 0) { |
| 503 | snd_printk(KERN_ERR | 532 | snd_printk(KERN_ERR |
| @@ -656,11 +685,16 @@ static int snd_ftu_eff_switch_get(struct snd_kcontrol *kctl, | |||
| 656 | return -EINVAL; | 685 | return -EINVAL; |
| 657 | 686 | ||
| 658 | 687 | ||
| 659 | err = snd_usb_ctl_msg(chip->dev, | 688 | down_read(&mixer->chip->shutdown_rwsem); |
| 689 | if (mixer->chip->shutdown) | ||
| 690 | err = -ENODEV; | ||
| 691 | else | ||
| 692 | err = snd_usb_ctl_msg(chip->dev, | ||
| 660 | usb_rcvctrlpipe(chip->dev, 0), UAC_GET_CUR, | 693 | usb_rcvctrlpipe(chip->dev, 0), UAC_GET_CUR, |
| 661 | USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN, | 694 | USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN, |
| 662 | validx << 8, snd_usb_ctrl_intf(chip) | (id << 8), | 695 | validx << 8, snd_usb_ctrl_intf(chip) | (id << 8), |
| 663 | value, val_len); | 696 | value, val_len); |
| 697 | up_read(&mixer->chip->shutdown_rwsem); | ||
| 664 | if (err < 0) | 698 | if (err < 0) |
| 665 | return err; | 699 | return err; |
| 666 | 700 | ||
| @@ -703,11 +737,16 @@ static int snd_ftu_eff_switch_put(struct snd_kcontrol *kctl, | |||
| 703 | 737 | ||
| 704 | if (!pval->is_cached) { | 738 | if (!pval->is_cached) { |
| 705 | /* Read current value */ | 739 | /* Read current value */ |
| 706 | err = snd_usb_ctl_msg(chip->dev, | 740 | down_read(&mixer->chip->shutdown_rwsem); |
| 741 | if (mixer->chip->shutdown) | ||
| 742 | err = -ENODEV; | ||
| 743 | else | ||
| 744 | err = snd_usb_ctl_msg(chip->dev, | ||
| 707 | usb_rcvctrlpipe(chip->dev, 0), UAC_GET_CUR, | 745 | usb_rcvctrlpipe(chip->dev, 0), UAC_GET_CUR, |
| 708 | USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN, | 746 | USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN, |
| 709 | validx << 8, snd_usb_ctrl_intf(chip) | (id << 8), | 747 | validx << 8, snd_usb_ctrl_intf(chip) | (id << 8), |
| 710 | value, val_len); | 748 | value, val_len); |
| 749 | up_read(&mixer->chip->shutdown_rwsem); | ||
| 711 | if (err < 0) | 750 | if (err < 0) |
| 712 | return err; | 751 | return err; |
| 713 | 752 | ||
| @@ -719,11 +758,16 @@ static int snd_ftu_eff_switch_put(struct snd_kcontrol *kctl, | |||
| 719 | if (cur_val != new_val) { | 758 | if (cur_val != new_val) { |
| 720 | value[0] = new_val; | 759 | value[0] = new_val; |
| 721 | value[1] = 0; | 760 | value[1] = 0; |
| 722 | err = snd_usb_ctl_msg(chip->dev, | 761 | down_read(&mixer->chip->shutdown_rwsem); |
| 762 | if (mixer->chip->shutdown) | ||
| 763 | err = -ENODEV; | ||
| 764 | else | ||
| 765 | err = snd_usb_ctl_msg(chip->dev, | ||
| 723 | usb_sndctrlpipe(chip->dev, 0), UAC_SET_CUR, | 766 | usb_sndctrlpipe(chip->dev, 0), UAC_SET_CUR, |
| 724 | USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_OUT, | 767 | USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_OUT, |
| 725 | validx << 8, snd_usb_ctrl_intf(chip) | (id << 8), | 768 | validx << 8, snd_usb_ctrl_intf(chip) | (id << 8), |
| 726 | value, val_len); | 769 | value, val_len); |
| 770 | up_read(&mixer->chip->shutdown_rwsem); | ||
| 727 | if (err < 0) | 771 | if (err < 0) |
| 728 | return err; | 772 | return err; |
| 729 | 773 | ||
