sound fixes for 4.6-rc2
Linus,
please pull sound fixes for v4.6-rc2 from:
git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound.git tags/sound-4.6-rc2
The topmost commit is 4a07083ed613644c96c34a7dd2853dc5d7c70902
----------------------------------------------------------------
sound fixes for 4.6-rc2
A collection of small fixes:
- A fix in ALSA timer core to avoid possible BUG() trigger
- A fix in ALSA timer core 32bit compat layer
- A few HD-audio quirks for ASUS and HP machines
- AMD HD-audio HDMI controller quirks
- Fixes of USB-audio double-free at some error paths
- A fix for memory leak in DICE driver at hotunplug
----------------------------------------------------------------
Bobi Mihalca (3):
ALSA: hda - Asus N750JV external subwoofer fixup
ALSA: hda - Fix white noise on Asus N750JV headphone
ALSA: hda - Apply fix for white noise on Asus N550JV, too
Hui Wang (1):
ALSA: hda - fix front mic problem for a HP desktop
Maruthi Srinivas Bayyavarapu (1):
ALSA: hda: add AMD Polaris-10/11 AZ PCI IDs with proper driver caps
Takashi Iwai (1):
ALSA: timer: Use mod_timer() for rearming the system timer
Takashi Sakamoto (2):
ALSA: timer: fix gparams ioctl compatibility for different architectures
ALSA: dice: fix memory leak when unplugging
Vladis Dronov (1):
ALSA: usb-audio: Fix double-free in error paths after snd_usb_add_audio_stream() call
--- sound/core/timer.c | 24 +++++++++++++++--------- sound/core/timer_compat.c | 30 +++++++++++++++++++++++++++++- sound/firewire/dice/dice-stream.c | 14 ++++---------- sound/pci/hda/hda_intel.c | 4 ++++ sound/pci/hda/patch_realtek.c | 19 ++++++++++++++++++- sound/usb/quirks.c | 4 ++++ sound/usb/stream.c | 6 +++++- 7 files changed, 79 insertions(+), 22 deletions(-)
sound/core/timer.c +15 -9
@@ -1019,8 +1019,8 @@ static int snd_timer_s_start(struct snd_timer * timer) njiff += timer->sticks - priv->correction; priv->correction =0 ; } - priv->last_expires = priv->tlist.expires = njiff; -add_timer (&priv->tlist); + priv->last_expires = njiff; +mod_timer (&priv->tlist, njiff);return 0 ; }
@@ -1502,17 +1502,13 @@ static int snd_timer_user_ginfo(struct file *file,return err; } -static int snd_timer_user_gparams (struct file *file, -struct snd_timer_gparams __user *_gparams) +static int timer_set_gparams (struct snd_timer_gparams *gparams) { -struct snd_timer_gparams gparams;struct snd_timer *t;int err; -if (copy_from_user (&gparams, _gparams,sizeof (gparams))) -return -EFAULT ;mutex_lock (®ister_mutex); - t =snd_timer_find (&gparams.tid); + t =snd_timer_find (&gparams->tid);if (!t) { err = -ENODEV ; goto _error;
@@ -1525,12 +1521,22 @@ static int snd_timer_user_gparams(struct file *file, err = -ENOSYS ; goto _error; } - err = t->hw.set_period (t, gparams.period_num, gparams.period_den); + err = t->hw.set_period (t, gparams->period_num, gparams->period_den); _error:mutex_unlock (®ister_mutex);return err; } +static int snd_timer_user_gparams (struct file *file, +struct snd_timer_gparams __user *_gparams) +{ +struct snd_timer_gparams gparams; + +if (copy_from_user (&gparams, _gparams,sizeof (gparams))) +return -EFAULT ; +return timer_set_gparams (&gparams); +} +static int snd_timer_user_gstatus (struct file *file,struct snd_timer_gstatus __user *_gstatus) {
sound/core/timer_compat.c +29 -1
@@ -22,6 +22,19 @@#include <linux/compat.h> +/* +* ILP32/LP64 has different size for 'long' type. Additionally, the size +* of storage alignment differs depending on architectures. Here, '__packed' +* qualifier is used so that the size of this structure is multiple of 4 and +* it fits to any architectures with 32 bit storage alignment. +*/ +struct snd_timer_gparams32 { +struct snd_timer_id tid; +u32 period_num; +u32 period_den; +unsigned char reserved[32 ]; +} __packed; +struct snd_timer_info32 {u32 flags;s32 card;
@@ -32,6 +45,19 @@ struct snd_timer_info32 {unsigned char reserved[64 ]; }; +static int snd_timer_user_gparams_compat (struct file *file, +struct snd_timer_gparams32 __user *user) +{ +struct snd_timer_gparams gparams; + +if (copy_from_user (&gparams.tid, &user->tid,sizeof (gparams.tid)) || +get_user (gparams.period_num, &user->period_num) || +get_user (gparams.period_den, &user->period_den)) +return -EFAULT ; + +return timer_set_gparams (&gparams); +} +static int snd_timer_user_info_compat (struct file *file,struct snd_timer_info32 __user *_info) {
@@ -99,6 +125,7 @@ static int snd_timer_user_status_compat(struct file *file,*/ enum { + SNDRV_TIMER_IOCTL_GPARAMS32 = _IOW('T', 0x04, struct snd_timer_gparams32), SNDRV_TIMER_IOCTL_INFO32 = _IOR('T', 0x11, struct snd_timer_info32), SNDRV_TIMER_IOCTL_STATUS32 = _IOW('T', 0x14, struct snd_timer_status32),#ifdef CONFIG_X86_X32
@@ -114,7 +141,6 @@ static long snd_timer_user_ioctl_compat(struct file *file, unsigned int cmd, unscase SNDRV_TIMER_IOCTL_PVERSION :case SNDRV_TIMER_IOCTL_TREAD :case SNDRV_TIMER_IOCTL_GINFO : -case SNDRV_TIMER_IOCTL_GPARAMS :case SNDRV_TIMER_IOCTL_GSTATUS :case SNDRV_TIMER_IOCTL_SELECT :case SNDRV_TIMER_IOCTL_PARAMS :
@@ -128,6 +154,8 @@ static long snd_timer_user_ioctl_compat(struct file *file, unsigned int cmd, unscase SNDRV_TIMER_IOCTL_PAUSE_OLD :case SNDRV_TIMER_IOCTL_NEXT_DEVICE :return snd_timer_user_ioctl (file, cmd, (unsigned long )argp); +case SNDRV_TIMER_IOCTL_GPARAMS32 : +return snd_timer_user_gparams_compat (file, argp);case SNDRV_TIMER_IOCTL_INFO32 :return snd_timer_user_info_compat (file, argp);case SNDRV_TIMER_IOCTL_STATUS32 :
sound/firewire/dice/dice-stream.c +4 -10
@@ -446,18 +446,12 @@ end:void snd_dice_stream_destroy_duplex (struct snd_dice *dice) { -struct reg_params tx_params, rx_params; - -snd_dice_transaction_clear_enable (dice); +unsigned int i; -if (get_register_params (dice, &tx_params, &rx_params) ==0 ) { -stop_streams (dice,AMDTP_IN_STREAM , &tx_params); -stop_streams (dice,AMDTP_OUT_STREAM , &rx_params); +for (i =0 ; i <MAX_STREAMS ; i++) { +destroy_stream (dice,AMDTP_IN_STREAM , i); +destroy_stream (dice,AMDTP_OUT_STREAM , i); } - -release_resources (dice); - - dice->substreams_counter =0 ; }void snd_dice_stream_update_duplex (struct snd_dice *dice)
sound/pci/hda/hda_intel.c +4 -0
@@ -2361,6 +2361,10 @@ static const struct pci_device_id azx_ids[] = { .driver_data = AZX_DRIVER_ATIHDMI_NS | AZX_DCAPS_PRESET_ATI_HDMI_NS }, { PCI_DEVICE(0x1002, 0xaae8), .driver_data = AZX_DRIVER_ATIHDMI_NS | AZX_DCAPS_PRESET_ATI_HDMI_NS }, + { PCI_DEVICE(0x1002, 0xaae0), + .driver_data = AZX_DRIVER_ATIHDMI_NS | AZX_DCAPS_PRESET_ATI_HDMI_NS }, + { PCI_DEVICE(0x1002, 0xaaf0), + .driver_data = AZX_DRIVER_ATIHDMI_NS | AZX_DCAPS_PRESET_ATI_HDMI_NS }, /* VIA VT8251/VT8237A */ { PCI_DEVICE(0x1106, 0x3288), .driver_data = AZX_DRIVER_VIA },/* VIA GFX VT7122/VX900 */
sound/pci/hda/patch_realtek.c +18 -1
@@ -4759,6 +4759,7 @@ enum {ALC255_FIXUP_DELL_SPK_NOISE ,ALC225_FIXUP_DELL1_MIC_NO_PRESENCE ,ALC280_FIXUP_HP_HEADSET_MIC , + ALC221_FIXUP_HP_FRONT_MIC, }; static const struct hda_fixup alc269_fixups[] = {
@@ -5401,6 +5402,13 @@ static const struct hda_fixup alc269_fixups[] = { .chained = true, .chain_id = ALC269_FIXUP_HEADSET_MIC, }, + [ALC221_FIXUP_HP_FRONT_MIC] = { + .type = HDA_FIXUP_PINS, + .v.pins = (const struct hda_pintbl []) { + {0x19 ,0x02a19020 },/* Front Mic */ + { } + }, + }, };static const struct snd_pci_quirk alc269_fixup_tbl[] = {
@@ -5506,6 +5514,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {SND_PCI_QUIRK (0x103c ,0x2336 ,"HP" ,ALC269_FIXUP_HP_MUTE_LED_MIC1 ),SND_PCI_QUIRK (0x103c ,0x2337 ,"HP" ,ALC269_FIXUP_HP_MUTE_LED_MIC1 ),SND_PCI_QUIRK (0x103c ,0x221c ,"HP EliteBook 755 G2" ,ALC280_FIXUP_HP_HEADSET_MIC ), +SND_PCI_QUIRK (0x103c ,0x8256 ,"HP" ,ALC221_FIXUP_HP_FRONT_MIC ),SND_PCI_QUIRK (0x1043 ,0x103f ,"ASUS TX300" ,ALC282_FIXUP_ASUS_TX300 ),SND_PCI_QUIRK (0x1043 ,0x106d ,"Asus K53BE" ,ALC269_FIXUP_LIMIT_INT_MIC_BOOST ), SND_PCI_QUIRK(0x1043, 0x115d, "Asus 1015E", ALC269_FIXUP_LIMIT_INT_MIC_BOOST),
@@ -6406,6 +6415,7 @@ enum {ALC668_FIXUP_AUTO_MUTE ,ALC668_FIXUP_DELL_DISABLE_AAMIX ,ALC668_FIXUP_DELL_XPS13 , + ALC662_FIXUP_ASUS_Nx50, }; static const struct hda_fixup alc662_fixups[] = {
@@ -6646,6 +6656,12 @@ static const struct hda_fixup alc662_fixups[] = { .type = HDA_FIXUP_FUNC, .v.func = alc_fixup_bass_chmap, }, + [ALC662_FIXUP_ASUS_Nx50] = { + .type = HDA_FIXUP_FUNC, + .v.func = alc_fixup_auto_mute_via_amp, + .chained = true, + .chain_id =ALC662_FIXUP_BASS_1A + }, };static const struct snd_pci_quirk alc662_fixup_tbl[] = {
@@ -6668,8 +6684,9 @@ static const struct snd_pci_quirk alc662_fixup_tbl[] = {SND_PCI_QUIRK (0x1028 ,0x0698 ,"Dell" ,ALC668_FIXUP_DELL_MIC_NO_PRESENCE ),SND_PCI_QUIRK (0x1028 ,0x069f ,"Dell" ,ALC668_FIXUP_DELL_MIC_NO_PRESENCE ),SND_PCI_QUIRK (0x103c ,0x1632 ,"HP RP5800" ,ALC662_FIXUP_HP_RP5800 ), -SND_PCI_QUIRK (0x1043 ,0x11cd ,"Asus N550" ,ALC662_FIXUP_BASS_1A ), +SND_PCI_QUIRK (0x1043 ,0x11cd ,"Asus N550" , ALC662_FIXUP_ASUS_Nx50),SND_PCI_QUIRK (0x1043 ,0x13df ,"Asus N550JX" ,ALC662_FIXUP_BASS_1A ), +SND_PCI_QUIRK (0x1043 ,0x129d ,"Asus N750" , ALC662_FIXUP_ASUS_Nx50),SND_PCI_QUIRK (0x1043 ,0x1477 ,"ASUS N56VZ" ,ALC662_FIXUP_BASS_MODE4_CHMAP ),SND_PCI_QUIRK (0x1043 ,0x15a7 ,"ASUS UX51VZH" ,ALC662_FIXUP_BASS_16 ), SND_PCI_QUIRK(0x1043, 0x1b73, "ASUS N55SF", ALC662_FIXUP_BASS_16),
sound/usb/quirks.c +4 -0
@@ -150,6 +150,7 @@ static int create_fixed_stream_quirk(struct snd_usb_audio *chip,usb_audio_err (chip,"cannot memdup\n" );return -ENOMEM ; } +INIT_LIST_HEAD (&fp->list);if (fp->nr_rates >MAX_NR_RATES ) {kfree (fp);return -EINVAL ;
@@ -193,6 +194,7 @@ static int create_fixed_stream_quirk(struct snd_usb_audio *chip,return 0 ; error: +list_del (&fp->list);/* unlink for avoiding double-free */ kfree (fp);kfree (rate_table);return err;
@@ -469,6 +471,7 @@ static int create_uaxx_quirk(struct snd_usb_audio *chip, fp->ep_attr =get_endpoint (alts,0 )->bmAttributes; fp->datainterval =0 ; fp->maxpacksize =le16_to_cpu (get_endpoint (alts,0 )->wMaxPacketSize); +INIT_LIST_HEAD (&fp->list);switch (fp->maxpacksize) {case 0x120 :
@@ -492,6 +495,7 @@ static int create_uaxx_quirk(struct snd_usb_audio *chip, ? SNDRV_PCM_STREAM_CAPTURE : SNDRV_PCM_STREAM_PLAYBACK; err =snd_usb_add_audio_stream (chip, stream, fp);if (err <0 ) { +list_del (&fp->list);/* unlink for avoiding double-free */ kfree (fp);return err; }
sound/usb/stream.c +5 -1
@@ -316,7 +316,9 @@ static struct snd_pcm_chmap_elem *convert_chmap(int channels, unsigned int bits,/* * add this endpoint to the chip instance. * if a stream with the same endpoint already exists, append to it. -* if not, create a new pcm stream. +* if not, create a new pcm stream. note, fp is added to the substream +* fmt_list and will be freed on the chip instance release. do not free +* fp or do remove it from the substream fmt_list to avoid double-free. */ int snd_usb_add_audio_stream(struct snd_usb_audio *chip, int stream,
@@ -677,6 +679,7 @@ int snd_usb_parse_audio_interface(struct snd_usb_audio *chip, int iface_no) * (fp->maxpacksize &0x7ff ); fp->attributes =parse_uac_endpoint_attributes (chip, alts, protocol, iface_no); fp->clock = clock; +INIT_LIST_HEAD (&fp->list);/* some quirks for attributes here */
@@ -725,6 +728,7 @@ int snd_usb_parse_audio_interface(struct snd_usb_audio *chip, int iface_no)dev_dbg (&dev->dev,"%u:%d: add audio endpoint %#x\n" , iface_no, altno, fp->endpoint); err =snd_usb_add_audio_stream (chip, stream, fp);if (err <0 ) { +list_del (&fp->list);/* unlink for avoiding double-free */ kfree (fp->rate_table);kfree (fp->chmap);kfree (fp);