From 862a6244eb9f9f5123fe819454fcfcae0ee1f2f9 Mon Sep 17 00:00:00 2001 From: Clemens Ladisch Date: Sat, 15 Oct 2011 23:19:25 +0200 Subject: ALSA: ua101: fix crash when unplugging If the device is unplugged while running, it is possible for a PCM device to be closed after the disconnect callback has returned. This means that kill_stream_urb() and disable_iso_interface() would try to access already-invalid or freed USB data structures. The function free_usb_related_resources() was intended to prevent this, but forgot to clear the affected variables. Reported-and-tested-by: Olivier Courtay Signed-off-by: Clemens Ladisch Cc: 2.6.33+ Signed-off-by: Takashi Iwai --- sound/usb/misc/ua101.c | 28 +++++++++++++++++++++------- 1 file changed, 21 insertions(+), 7 deletions(-) diff --git a/sound/usb/misc/ua101.c b/sound/usb/misc/ua101.c index 67bec7612442..c0609c210303 100644 --- a/sound/usb/misc/ua101.c +++ b/sound/usb/misc/ua101.c @@ -459,7 +459,8 @@ static void kill_stream_urbs(struct ua101_stream *stream) unsigned int i; for (i = 0; i < stream->queue_length; ++i) - usb_kill_urb(&stream->urbs[i]->urb); + if (stream->urbs[i]) + usb_kill_urb(&stream->urbs[i]->urb); } static int enable_iso_interface(struct ua101 *ua, unsigned int intf_index) @@ -484,6 +485,9 @@ static void disable_iso_interface(struct ua101 *ua, unsigned int intf_index) { struct usb_host_interface *alts; + if (!ua->intf[intf_index]) + return; + alts = ua->intf[intf_index]->cur_altsetting; if (alts->desc.bAlternateSetting != 0) { int err = usb_set_interface(ua->dev, @@ -1144,27 +1148,37 @@ static void free_stream_urbs(struct ua101_stream *stream) { unsigned int i; - for (i = 0; i < stream->queue_length; ++i) + for (i = 0; i < stream->queue_length; ++i) { kfree(stream->urbs[i]); + stream->urbs[i] = NULL; + } } static void free_usb_related_resources(struct ua101 *ua, struct usb_interface *interface) { unsigned int i; + struct usb_interface *intf; + mutex_lock(&ua->mutex); free_stream_urbs(&ua->capture); free_stream_urbs(&ua->playback); + mutex_unlock(&ua->mutex); free_stream_buffers(ua, &ua->capture); free_stream_buffers(ua, &ua->playback); - for (i = 0; i < ARRAY_SIZE(ua->intf); ++i) - if (ua->intf[i]) { - usb_set_intfdata(ua->intf[i], NULL); - if (ua->intf[i] != interface) + for (i = 0; i < ARRAY_SIZE(ua->intf); ++i) { + mutex_lock(&ua->mutex); + intf = ua->intf[i]; + ua->intf[i] = NULL; + mutex_unlock(&ua->mutex); + if (intf) { + usb_set_intfdata(intf, NULL); + if (intf != interface) usb_driver_release_interface(&ua101_driver, - ua->intf[i]); + intf); } + } } static void ua101_card_free(struct snd_card *card) -- cgit v1.2.1 From 447c6f93aba42e6889be55a614d4dddc25f17863 Mon Sep 17 00:00:00 2001 From: Olof Johansson Date: Sat, 5 Nov 2011 22:51:54 +0100 Subject: ALSA: control: remove compilation warning on 32-bit This was introduced by 'ALSA: control: add support for ENUMERATED user space controls' which adds a u64 variable that gets cast to a pointer: sound/core/control.c: In function 'snd_ctl_elem_init_enum_names': sound/core/control.c:1089: warning: cast to pointer from integer of different size Cast to uintptr_t before casting to pointer to avoid the warning. Signed-off-by: Olof Johansson [cl: replace long with uintptr_t] Signed-off-by: Clemens Ladisch Signed-off-by: Takashi Iwai --- sound/core/control.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/core/control.c b/sound/core/control.c index 978fe1a8e9f0..59edb12dd542 100644 --- a/sound/core/control.c +++ b/sound/core/control.c @@ -1081,12 +1081,12 @@ static int snd_ctl_elem_init_enum_names(struct user_element *ue) char *names, *p; size_t buf_len, name_len; unsigned int i; + const uintptr_t user_ptrval = ue->info.value.enumerated.names_ptr; if (ue->info.value.enumerated.names_length > 64 * 1024) return -EINVAL; - names = memdup_user( - (const void __user *)ue->info.value.enumerated.names_ptr, + names = memdup_user((const void __user *)user_ptrval, ue->info.value.enumerated.names_length); if (IS_ERR(names)) return PTR_ERR(names); -- cgit v1.2.1 From 43dea228a3ba5463392281535dfb3d3fe56f4c2c Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Sun, 6 Nov 2011 11:25:34 +0100 Subject: ALSA: hda - Fix silent output regression with ALC861 The 3.1 kernel has a regression for ALC861 codec where no sound output is heard with the default setup. It's because the amps in DACs aren't properly unmuted while the output mixers are assigned only to pins. This patch fixes the missing initialization of DACs when no mixer is assigned to them. Tested-by: Andrea Iob Cc: [v3.1+] Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_realtek.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 80d6add8a620..9693059dec84 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -3329,6 +3329,12 @@ static void alc_auto_set_output_and_unmute(struct hda_codec *codec, if (nid) snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO); + + /* unmute DAC if it's not assigned to a mixer */ + nid = alc_look_for_out_mute_nid(codec, pin, dac); + if (nid == mix && nid_has_mute(codec, dac, HDA_OUTPUT)) + snd_hda_codec_write(codec, dac, 0, AC_VERB_SET_AMP_GAIN_MUTE, + AMP_OUT_ZERO); } static void alc_auto_init_multi_out(struct hda_codec *codec) -- cgit v1.2.1 From 69f9ba9b0cad67bc03f0a096f7f274de795ca844 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Sun, 6 Nov 2011 13:49:13 +0100 Subject: ALSA: hda - Fix a regression for DMA-position check with CA0110 The regression-fix in 3.1 for the check of DMA-position validity caused yet another regression for CA0110. As usual, this hardware seems working only with LPIB properly. Adding the appropriate driver-caps bit to force LPIB fixes the problem. Reported-and-tested-by: Andres Freund Cc: [v3.1] Signed-off-by: Takashi Iwai --- sound/pci/hda/hda_intel.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index bd7fc99af187..096507d2ca9a 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c @@ -3063,12 +3063,12 @@ static DEFINE_PCI_DEVICE_TABLE(azx_ids) = { .class = PCI_CLASS_MULTIMEDIA_HD_AUDIO << 8, .class_mask = 0xffffff, .driver_data = AZX_DRIVER_CTX | AZX_DCAPS_CTX_WORKAROUND | - AZX_DCAPS_RIRB_PRE_DELAY }, + AZX_DCAPS_RIRB_PRE_DELAY | AZX_DCAPS_POSFIX_LPIB }, #else /* this entry seems still valid -- i.e. without emu20kx chip */ { PCI_DEVICE(0x1102, 0x0009), .driver_data = AZX_DRIVER_CTX | AZX_DCAPS_CTX_WORKAROUND | - AZX_DCAPS_RIRB_PRE_DELAY }, + AZX_DCAPS_RIRB_PRE_DELAY | AZX_DCAPS_POSFIX_LPIB }, #endif /* Vortex86MX */ { PCI_DEVICE(0x17f3, 0x3010), .driver_data = AZX_DRIVER_GENERIC }, -- cgit v1.2.1 From f441917256c9727d3573ca2f89f657a75e06a262 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Sun, 6 Nov 2011 14:01:58 +0100 Subject: ALSA: hda - Revert the check of NO_PRESENCE pincfg default bit The implementation on commit [08a1f5eb: ALSA: hda - Check NO_PRESENCE pincfg default bit] seems like a mis-interpretation of specification. The spec gives the reversed bit definition. But, following the spec also causes to change so many existing device configurations, thus we can't change it so easily for now. For 3.2-rc1, it's safer to revert this check (actually this patch comments out the code). We may re-introduced the fixed version once after the wider test-case coverages are done. Signed-off-by: Takashi Iwai --- sound/pci/hda/hda_local.h | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/sound/pci/hda/hda_local.h b/sound/pci/hda/hda_local.h index 79f49e2e8cbc..dcbea0da0fa2 100644 --- a/sound/pci/hda/hda_local.h +++ b/sound/pci/hda/hda_local.h @@ -511,8 +511,11 @@ int snd_hda_jack_detect(struct hda_codec *codec, hda_nid_t nid); static inline bool is_jack_detectable(struct hda_codec *codec, hda_nid_t nid) { return (snd_hda_query_pin_caps(codec, nid) & AC_PINCAP_PRES_DETECT) && - !(get_defcfg_misc(snd_hda_codec_get_pincfg(codec, nid) & - AC_DEFCFG_MISC_NO_PRESENCE)) && + /* disable MISC_NO_PRESENCE check because it may break too + * many devices + */ + /*(get_defcfg_misc(snd_hda_codec_get_pincfg(codec, nid) & + AC_DEFCFG_MISC_NO_PRESENCE)) &&*/ (get_wcaps(codec, nid) & AC_WCAP_UNSOL_CAP); } -- cgit v1.2.1