diff options
| -rw-r--r-- | sound/core/timer.c | 24 | ||||
| -rw-r--r-- | sound/core/timer_compat.c | 30 | ||||
| -rw-r--r-- | sound/firewire/dice/dice-stream.c | 14 | ||||
| -rw-r--r-- | sound/pci/hda/hda_intel.c | 4 | ||||
| -rw-r--r-- | sound/pci/hda/patch_realtek.c | 19 | ||||
| -rw-r--r-- | sound/usb/quirks.c | 4 | ||||
| -rw-r--r-- | sound/usb/stream.c | 6 |
7 files changed, 79 insertions, 22 deletions
diff --git a/sound/core/timer.c b/sound/core/timer.c index aa1b15c155d1..6469bedda2f3 100644 --- a/sound/core/timer.c +++ b/sound/core/timer.c | |||
| @@ -1019,8 +1019,8 @@ static int snd_timer_s_start(struct snd_timer * timer) | |||
| 1019 | njiff += timer->sticks - priv->correction; | 1019 | njiff += timer->sticks - priv->correction; |
| 1020 | priv->correction = 0; | 1020 | priv->correction = 0; |
| 1021 | } | 1021 | } |
| 1022 | priv->last_expires = priv->tlist.expires = njiff; | 1022 | priv->last_expires = njiff; |
| 1023 | add_timer(&priv->tlist); | 1023 | mod_timer(&priv->tlist, njiff); |
| 1024 | return 0; | 1024 | return 0; |
| 1025 | } | 1025 | } |
| 1026 | 1026 | ||
| @@ -1502,17 +1502,13 @@ static int snd_timer_user_ginfo(struct file *file, | |||
| 1502 | return err; | 1502 | return err; |
| 1503 | } | 1503 | } |
| 1504 | 1504 | ||
| 1505 | static int snd_timer_user_gparams(struct file *file, | 1505 | static int timer_set_gparams(struct snd_timer_gparams *gparams) |
| 1506 | struct snd_timer_gparams __user *_gparams) | ||
| 1507 | { | 1506 | { |
| 1508 | struct snd_timer_gparams gparams; | ||
| 1509 | struct snd_timer *t; | 1507 | struct snd_timer *t; |
| 1510 | int err; | 1508 | int err; |
| 1511 | 1509 | ||
| 1512 | if (copy_from_user(&gparams, _gparams, sizeof(gparams))) | ||
| 1513 | return -EFAULT; | ||
| 1514 | mutex_lock(®ister_mutex); | 1510 | mutex_lock(®ister_mutex); |
| 1515 | t = snd_timer_find(&gparams.tid); | 1511 | t = snd_timer_find(&gparams->tid); |
| 1516 | if (!t) { | 1512 | if (!t) { |
| 1517 | err = -ENODEV; | 1513 | err = -ENODEV; |
| 1518 | goto _error; | 1514 | goto _error; |
| @@ -1525,12 +1521,22 @@ static int snd_timer_user_gparams(struct file *file, | |||
| 1525 | err = -ENOSYS; | 1521 | err = -ENOSYS; |
| 1526 | goto _error; | 1522 | goto _error; |
| 1527 | } | 1523 | } |
| 1528 | err = t->hw.set_period(t, gparams.period_num, gparams.period_den); | 1524 | err = t->hw.set_period(t, gparams->period_num, gparams->period_den); |
| 1529 | _error: | 1525 | _error: |
| 1530 | mutex_unlock(®ister_mutex); | 1526 | mutex_unlock(®ister_mutex); |
| 1531 | return err; | 1527 | return err; |
| 1532 | } | 1528 | } |
| 1533 | 1529 | ||
| 1530 | static int snd_timer_user_gparams(struct file *file, | ||
| 1531 | struct snd_timer_gparams __user *_gparams) | ||
| 1532 | { | ||
| 1533 | struct snd_timer_gparams gparams; | ||
| 1534 | |||
| 1535 | if (copy_from_user(&gparams, _gparams, sizeof(gparams))) | ||
| 1536 | return -EFAULT; | ||
| 1537 | return timer_set_gparams(&gparams); | ||
| 1538 | } | ||
| 1539 | |||
| 1534 | static int snd_timer_user_gstatus(struct file *file, | 1540 | static int snd_timer_user_gstatus(struct file *file, |
| 1535 | struct snd_timer_gstatus __user *_gstatus) | 1541 | struct snd_timer_gstatus __user *_gstatus) |
| 1536 | { | 1542 | { |
diff --git a/sound/core/timer_compat.c b/sound/core/timer_compat.c index 2e908225d754..6a437eb66115 100644 --- a/sound/core/timer_compat.c +++ b/sound/core/timer_compat.c | |||
| @@ -22,6 +22,19 @@ | |||
| 22 | 22 | ||
| 23 | #include <linux/compat.h> | 23 | #include <linux/compat.h> |
| 24 | 24 | ||
| 25 | /* | ||
| 26 | * ILP32/LP64 has different size for 'long' type. Additionally, the size | ||
| 27 | * of storage alignment differs depending on architectures. Here, '__packed' | ||
| 28 | * qualifier is used so that the size of this structure is multiple of 4 and | ||
| 29 | * it fits to any architectures with 32 bit storage alignment. | ||
| 30 | */ | ||
| 31 | struct snd_timer_gparams32 { | ||
| 32 | struct snd_timer_id tid; | ||
| 33 | u32 period_num; | ||
| 34 | u32 period_den; | ||
| 35 | unsigned char reserved[32]; | ||
| 36 | } __packed; | ||
| 37 | |||
| 25 | struct snd_timer_info32 { | 38 | struct snd_timer_info32 { |
| 26 | u32 flags; | 39 | u32 flags; |
| 27 | s32 card; | 40 | s32 card; |
| @@ -32,6 +45,19 @@ struct snd_timer_info32 { | |||
| 32 | unsigned char reserved[64]; | 45 | unsigned char reserved[64]; |
| 33 | }; | 46 | }; |
| 34 | 47 | ||
| 48 | static int snd_timer_user_gparams_compat(struct file *file, | ||
| 49 | struct snd_timer_gparams32 __user *user) | ||
| 50 | { | ||
| 51 | struct snd_timer_gparams gparams; | ||
| 52 | |||
| 53 | if (copy_from_user(&gparams.tid, &user->tid, sizeof(gparams.tid)) || | ||
| 54 | get_user(gparams.period_num, &user->period_num) || | ||
| 55 | get_user(gparams.period_den, &user->period_den)) | ||
| 56 | return -EFAULT; | ||
| 57 | |||
| 58 | return timer_set_gparams(&gparams); | ||
| 59 | } | ||
| 60 | |||
| 35 | static int snd_timer_user_info_compat(struct file *file, | 61 | static int snd_timer_user_info_compat(struct file *file, |
| 36 | struct snd_timer_info32 __user *_info) | 62 | struct snd_timer_info32 __user *_info) |
| 37 | { | 63 | { |
| @@ -99,6 +125,7 @@ static int snd_timer_user_status_compat(struct file *file, | |||
| 99 | */ | 125 | */ |
| 100 | 126 | ||
| 101 | enum { | 127 | enum { |
| 128 | SNDRV_TIMER_IOCTL_GPARAMS32 = _IOW('T', 0x04, struct snd_timer_gparams32), | ||
| 102 | SNDRV_TIMER_IOCTL_INFO32 = _IOR('T', 0x11, struct snd_timer_info32), | 129 | SNDRV_TIMER_IOCTL_INFO32 = _IOR('T', 0x11, struct snd_timer_info32), |
| 103 | SNDRV_TIMER_IOCTL_STATUS32 = _IOW('T', 0x14, struct snd_timer_status32), | 130 | SNDRV_TIMER_IOCTL_STATUS32 = _IOW('T', 0x14, struct snd_timer_status32), |
| 104 | #ifdef CONFIG_X86_X32 | 131 | #ifdef CONFIG_X86_X32 |
| @@ -114,7 +141,6 @@ static long snd_timer_user_ioctl_compat(struct file *file, unsigned int cmd, uns | |||
| 114 | case SNDRV_TIMER_IOCTL_PVERSION: | 141 | case SNDRV_TIMER_IOCTL_PVERSION: |
| 115 | case SNDRV_TIMER_IOCTL_TREAD: | 142 | case SNDRV_TIMER_IOCTL_TREAD: |
| 116 | case SNDRV_TIMER_IOCTL_GINFO: | 143 | case SNDRV_TIMER_IOCTL_GINFO: |
| 117 | case SNDRV_TIMER_IOCTL_GPARAMS: | ||
| 118 | case SNDRV_TIMER_IOCTL_GSTATUS: | 144 | case SNDRV_TIMER_IOCTL_GSTATUS: |
| 119 | case SNDRV_TIMER_IOCTL_SELECT: | 145 | case SNDRV_TIMER_IOCTL_SELECT: |
| 120 | case SNDRV_TIMER_IOCTL_PARAMS: | 146 | case SNDRV_TIMER_IOCTL_PARAMS: |
| @@ -128,6 +154,8 @@ static long snd_timer_user_ioctl_compat(struct file *file, unsigned int cmd, uns | |||
| 128 | case SNDRV_TIMER_IOCTL_PAUSE_OLD: | 154 | case SNDRV_TIMER_IOCTL_PAUSE_OLD: |
| 129 | case SNDRV_TIMER_IOCTL_NEXT_DEVICE: | 155 | case SNDRV_TIMER_IOCTL_NEXT_DEVICE: |
| 130 | return snd_timer_user_ioctl(file, cmd, (unsigned long)argp); | 156 | return snd_timer_user_ioctl(file, cmd, (unsigned long)argp); |
| 157 | case SNDRV_TIMER_IOCTL_GPARAMS32: | ||
| 158 | return snd_timer_user_gparams_compat(file, argp); | ||
| 131 | case SNDRV_TIMER_IOCTL_INFO32: | 159 | case SNDRV_TIMER_IOCTL_INFO32: |
| 132 | return snd_timer_user_info_compat(file, argp); | 160 | return snd_timer_user_info_compat(file, argp); |
| 133 | case SNDRV_TIMER_IOCTL_STATUS32: | 161 | case SNDRV_TIMER_IOCTL_STATUS32: |
diff --git a/sound/firewire/dice/dice-stream.c b/sound/firewire/dice/dice-stream.c index 845d5e5884a4..ec4db3a514fc 100644 --- a/sound/firewire/dice/dice-stream.c +++ b/sound/firewire/dice/dice-stream.c | |||
| @@ -446,18 +446,12 @@ end: | |||
| 446 | 446 | ||
| 447 | void snd_dice_stream_destroy_duplex(struct snd_dice *dice) | 447 | void snd_dice_stream_destroy_duplex(struct snd_dice *dice) |
| 448 | { | 448 | { |
| 449 | struct reg_params tx_params, rx_params; | 449 | unsigned int i; |
| 450 | |||
| 451 | snd_dice_transaction_clear_enable(dice); | ||
| 452 | 450 | ||
| 453 | if (get_register_params(dice, &tx_params, &rx_params) == 0) { | 451 | for (i = 0; i < MAX_STREAMS; i++) { |
| 454 | stop_streams(dice, AMDTP_IN_STREAM, &tx_params); | 452 | destroy_stream(dice, AMDTP_IN_STREAM, i); |
| 455 | stop_streams(dice, AMDTP_OUT_STREAM, &rx_params); | 453 | destroy_stream(dice, AMDTP_OUT_STREAM, i); |
| 456 | } | 454 | } |
| 457 | |||
| 458 | release_resources(dice); | ||
| 459 | |||
| 460 | dice->substreams_counter = 0; | ||
| 461 | } | 455 | } |
| 462 | 456 | ||
| 463 | void snd_dice_stream_update_duplex(struct snd_dice *dice) | 457 | void snd_dice_stream_update_duplex(struct snd_dice *dice) |
diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index 2624cfe98884..b680be0e937d 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c | |||
| @@ -2361,6 +2361,10 @@ static const struct pci_device_id azx_ids[] = { | |||
| 2361 | .driver_data = AZX_DRIVER_ATIHDMI_NS | AZX_DCAPS_PRESET_ATI_HDMI_NS }, | 2361 | .driver_data = AZX_DRIVER_ATIHDMI_NS | AZX_DCAPS_PRESET_ATI_HDMI_NS }, |
| 2362 | { PCI_DEVICE(0x1002, 0xaae8), | 2362 | { PCI_DEVICE(0x1002, 0xaae8), |
| 2363 | .driver_data = AZX_DRIVER_ATIHDMI_NS | AZX_DCAPS_PRESET_ATI_HDMI_NS }, | 2363 | .driver_data = AZX_DRIVER_ATIHDMI_NS | AZX_DCAPS_PRESET_ATI_HDMI_NS }, |
| 2364 | { PCI_DEVICE(0x1002, 0xaae0), | ||
| 2365 | .driver_data = AZX_DRIVER_ATIHDMI_NS | AZX_DCAPS_PRESET_ATI_HDMI_NS }, | ||
| 2366 | { PCI_DEVICE(0x1002, 0xaaf0), | ||
| 2367 | .driver_data = AZX_DRIVER_ATIHDMI_NS | AZX_DCAPS_PRESET_ATI_HDMI_NS }, | ||
| 2364 | /* VIA VT8251/VT8237A */ | 2368 | /* VIA VT8251/VT8237A */ |
| 2365 | { PCI_DEVICE(0x1106, 0x3288), .driver_data = AZX_DRIVER_VIA }, | 2369 | { PCI_DEVICE(0x1106, 0x3288), .driver_data = AZX_DRIVER_VIA }, |
| 2366 | /* VIA GFX VT7122/VX900 */ | 2370 | /* VIA GFX VT7122/VX900 */ |
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 4f5ca0b9ce27..fefe83f2beab 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c | |||
| @@ -4759,6 +4759,7 @@ enum { | |||
| 4759 | ALC255_FIXUP_DELL_SPK_NOISE, | 4759 | ALC255_FIXUP_DELL_SPK_NOISE, |
| 4760 | ALC225_FIXUP_DELL1_MIC_NO_PRESENCE, | 4760 | ALC225_FIXUP_DELL1_MIC_NO_PRESENCE, |
| 4761 | ALC280_FIXUP_HP_HEADSET_MIC, | 4761 | ALC280_FIXUP_HP_HEADSET_MIC, |
| 4762 | ALC221_FIXUP_HP_FRONT_MIC, | ||
| 4762 | }; | 4763 | }; |
| 4763 | 4764 | ||
| 4764 | static const struct hda_fixup alc269_fixups[] = { | 4765 | static const struct hda_fixup alc269_fixups[] = { |
| @@ -5401,6 +5402,13 @@ static const struct hda_fixup alc269_fixups[] = { | |||
| 5401 | .chained = true, | 5402 | .chained = true, |
| 5402 | .chain_id = ALC269_FIXUP_HEADSET_MIC, | 5403 | .chain_id = ALC269_FIXUP_HEADSET_MIC, |
| 5403 | }, | 5404 | }, |
| 5405 | [ALC221_FIXUP_HP_FRONT_MIC] = { | ||
| 5406 | .type = HDA_FIXUP_PINS, | ||
| 5407 | .v.pins = (const struct hda_pintbl[]) { | ||
| 5408 | { 0x19, 0x02a19020 }, /* Front Mic */ | ||
| 5409 | { } | ||
| 5410 | }, | ||
| 5411 | }, | ||
| 5404 | }; | 5412 | }; |
| 5405 | 5413 | ||
| 5406 | static const struct snd_pci_quirk alc269_fixup_tbl[] = { | 5414 | static const struct snd_pci_quirk alc269_fixup_tbl[] = { |
| @@ -5506,6 +5514,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { | |||
| 5506 | SND_PCI_QUIRK(0x103c, 0x2336, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), | 5514 | SND_PCI_QUIRK(0x103c, 0x2336, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), |
| 5507 | SND_PCI_QUIRK(0x103c, 0x2337, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), | 5515 | SND_PCI_QUIRK(0x103c, 0x2337, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1), |
| 5508 | SND_PCI_QUIRK(0x103c, 0x221c, "HP EliteBook 755 G2", ALC280_FIXUP_HP_HEADSET_MIC), | 5516 | SND_PCI_QUIRK(0x103c, 0x221c, "HP EliteBook 755 G2", ALC280_FIXUP_HP_HEADSET_MIC), |
| 5517 | SND_PCI_QUIRK(0x103c, 0x8256, "HP", ALC221_FIXUP_HP_FRONT_MIC), | ||
| 5509 | SND_PCI_QUIRK(0x1043, 0x103f, "ASUS TX300", ALC282_FIXUP_ASUS_TX300), | 5518 | SND_PCI_QUIRK(0x1043, 0x103f, "ASUS TX300", ALC282_FIXUP_ASUS_TX300), |
| 5510 | SND_PCI_QUIRK(0x1043, 0x106d, "Asus K53BE", ALC269_FIXUP_LIMIT_INT_MIC_BOOST), | 5519 | SND_PCI_QUIRK(0x1043, 0x106d, "Asus K53BE", ALC269_FIXUP_LIMIT_INT_MIC_BOOST), |
| 5511 | SND_PCI_QUIRK(0x1043, 0x115d, "Asus 1015E", ALC269_FIXUP_LIMIT_INT_MIC_BOOST), | 5520 | SND_PCI_QUIRK(0x1043, 0x115d, "Asus 1015E", ALC269_FIXUP_LIMIT_INT_MIC_BOOST), |
| @@ -6406,6 +6415,7 @@ enum { | |||
| 6406 | ALC668_FIXUP_AUTO_MUTE, | 6415 | ALC668_FIXUP_AUTO_MUTE, |
| 6407 | ALC668_FIXUP_DELL_DISABLE_AAMIX, | 6416 | ALC668_FIXUP_DELL_DISABLE_AAMIX, |
| 6408 | ALC668_FIXUP_DELL_XPS13, | 6417 | ALC668_FIXUP_DELL_XPS13, |
| 6418 | ALC662_FIXUP_ASUS_Nx50, | ||
| 6409 | }; | 6419 | }; |
| 6410 | 6420 | ||
| 6411 | static const struct hda_fixup alc662_fixups[] = { | 6421 | static const struct hda_fixup alc662_fixups[] = { |
| @@ -6646,6 +6656,12 @@ static const struct hda_fixup alc662_fixups[] = { | |||
| 6646 | .type = HDA_FIXUP_FUNC, | 6656 | .type = HDA_FIXUP_FUNC, |
| 6647 | .v.func = alc_fixup_bass_chmap, | 6657 | .v.func = alc_fixup_bass_chmap, |
| 6648 | }, | 6658 | }, |
| 6659 | [ALC662_FIXUP_ASUS_Nx50] = { | ||
| 6660 | .type = HDA_FIXUP_FUNC, | ||
| 6661 | .v.func = alc_fixup_auto_mute_via_amp, | ||
| 6662 | .chained = true, | ||
| 6663 | .chain_id = ALC662_FIXUP_BASS_1A | ||
| 6664 | }, | ||
| 6649 | }; | 6665 | }; |
| 6650 | 6666 | ||
| 6651 | static const struct snd_pci_quirk alc662_fixup_tbl[] = { | 6667 | static const struct snd_pci_quirk alc662_fixup_tbl[] = { |
| @@ -6668,8 +6684,9 @@ static const struct snd_pci_quirk alc662_fixup_tbl[] = { | |||
| 6668 | SND_PCI_QUIRK(0x1028, 0x0698, "Dell", ALC668_FIXUP_DELL_MIC_NO_PRESENCE), | 6684 | SND_PCI_QUIRK(0x1028, 0x0698, "Dell", ALC668_FIXUP_DELL_MIC_NO_PRESENCE), |
| 6669 | SND_PCI_QUIRK(0x1028, 0x069f, "Dell", ALC668_FIXUP_DELL_MIC_NO_PRESENCE), | 6685 | SND_PCI_QUIRK(0x1028, 0x069f, "Dell", ALC668_FIXUP_DELL_MIC_NO_PRESENCE), |
| 6670 | SND_PCI_QUIRK(0x103c, 0x1632, "HP RP5800", ALC662_FIXUP_HP_RP5800), | 6686 | SND_PCI_QUIRK(0x103c, 0x1632, "HP RP5800", ALC662_FIXUP_HP_RP5800), |
| 6671 | SND_PCI_QUIRK(0x1043, 0x11cd, "Asus N550", ALC662_FIXUP_BASS_1A), | 6687 | SND_PCI_QUIRK(0x1043, 0x11cd, "Asus N550", ALC662_FIXUP_ASUS_Nx50), |
| 6672 | SND_PCI_QUIRK(0x1043, 0x13df, "Asus N550JX", ALC662_FIXUP_BASS_1A), | 6688 | SND_PCI_QUIRK(0x1043, 0x13df, "Asus N550JX", ALC662_FIXUP_BASS_1A), |
| 6689 | SND_PCI_QUIRK(0x1043, 0x129d, "Asus N750", ALC662_FIXUP_ASUS_Nx50), | ||
| 6673 | SND_PCI_QUIRK(0x1043, 0x1477, "ASUS N56VZ", ALC662_FIXUP_BASS_MODE4_CHMAP), | 6690 | SND_PCI_QUIRK(0x1043, 0x1477, "ASUS N56VZ", ALC662_FIXUP_BASS_MODE4_CHMAP), |
| 6674 | SND_PCI_QUIRK(0x1043, 0x15a7, "ASUS UX51VZH", ALC662_FIXUP_BASS_16), | 6691 | SND_PCI_QUIRK(0x1043, 0x15a7, "ASUS UX51VZH", ALC662_FIXUP_BASS_16), |
| 6675 | SND_PCI_QUIRK(0x1043, 0x1b73, "ASUS N55SF", ALC662_FIXUP_BASS_16), | 6692 | SND_PCI_QUIRK(0x1043, 0x1b73, "ASUS N55SF", ALC662_FIXUP_BASS_16), |
diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c index fb62bce2435c..6178bb5d0731 100644 --- a/sound/usb/quirks.c +++ b/sound/usb/quirks.c | |||
| @@ -150,6 +150,7 @@ static int create_fixed_stream_quirk(struct snd_usb_audio *chip, | |||
| 150 | usb_audio_err(chip, "cannot memdup\n"); | 150 | usb_audio_err(chip, "cannot memdup\n"); |
| 151 | return -ENOMEM; | 151 | return -ENOMEM; |
| 152 | } | 152 | } |
| 153 | INIT_LIST_HEAD(&fp->list); | ||
| 153 | if (fp->nr_rates > MAX_NR_RATES) { | 154 | if (fp->nr_rates > MAX_NR_RATES) { |
| 154 | kfree(fp); | 155 | kfree(fp); |
| 155 | return -EINVAL; | 156 | return -EINVAL; |
| @@ -193,6 +194,7 @@ static int create_fixed_stream_quirk(struct snd_usb_audio *chip, | |||
| 193 | return 0; | 194 | return 0; |
| 194 | 195 | ||
| 195 | error: | 196 | error: |
| 197 | list_del(&fp->list); /* unlink for avoiding double-free */ | ||
| 196 | kfree(fp); | 198 | kfree(fp); |
| 197 | kfree(rate_table); | 199 | kfree(rate_table); |
| 198 | return err; | 200 | return err; |
| @@ -469,6 +471,7 @@ static int create_uaxx_quirk(struct snd_usb_audio *chip, | |||
| 469 | fp->ep_attr = get_endpoint(alts, 0)->bmAttributes; | 471 | fp->ep_attr = get_endpoint(alts, 0)->bmAttributes; |
| 470 | fp->datainterval = 0; | 472 | fp->datainterval = 0; |
| 471 | fp->maxpacksize = le16_to_cpu(get_endpoint(alts, 0)->wMaxPacketSize); | 473 | fp->maxpacksize = le16_to_cpu(get_endpoint(alts, 0)->wMaxPacketSize); |
| 474 | INIT_LIST_HEAD(&fp->list); | ||
| 472 | 475 | ||
| 473 | switch (fp->maxpacksize) { | 476 | switch (fp->maxpacksize) { |
| 474 | case 0x120: | 477 | case 0x120: |
| @@ -492,6 +495,7 @@ static int create_uaxx_quirk(struct snd_usb_audio *chip, | |||
| 492 | ? SNDRV_PCM_STREAM_CAPTURE : SNDRV_PCM_STREAM_PLAYBACK; | 495 | ? SNDRV_PCM_STREAM_CAPTURE : SNDRV_PCM_STREAM_PLAYBACK; |
| 493 | err = snd_usb_add_audio_stream(chip, stream, fp); | 496 | err = snd_usb_add_audio_stream(chip, stream, fp); |
| 494 | if (err < 0) { | 497 | if (err < 0) { |
| 498 | list_del(&fp->list); /* unlink for avoiding double-free */ | ||
| 495 | kfree(fp); | 499 | kfree(fp); |
| 496 | return err; | 500 | return err; |
| 497 | } | 501 | } |
diff --git a/sound/usb/stream.c b/sound/usb/stream.c index 51258a15f653..6fe7f210bd4e 100644 --- a/sound/usb/stream.c +++ b/sound/usb/stream.c | |||
| @@ -316,7 +316,9 @@ static struct snd_pcm_chmap_elem *convert_chmap(int channels, unsigned int bits, | |||
| 316 | /* | 316 | /* |
| 317 | * add this endpoint to the chip instance. | 317 | * add this endpoint to the chip instance. |
| 318 | * if a stream with the same endpoint already exists, append to it. | 318 | * if a stream with the same endpoint already exists, append to it. |
| 319 | * if not, create a new pcm stream. | 319 | * if not, create a new pcm stream. note, fp is added to the substream |
| 320 | * fmt_list and will be freed on the chip instance release. do not free | ||
| 321 | * fp or do remove it from the substream fmt_list to avoid double-free. | ||
| 320 | */ | 322 | */ |
| 321 | int snd_usb_add_audio_stream(struct snd_usb_audio *chip, | 323 | int snd_usb_add_audio_stream(struct snd_usb_audio *chip, |
| 322 | int stream, | 324 | int stream, |
| @@ -677,6 +679,7 @@ int snd_usb_parse_audio_interface(struct snd_usb_audio *chip, int iface_no) | |||
| 677 | * (fp->maxpacksize & 0x7ff); | 679 | * (fp->maxpacksize & 0x7ff); |
| 678 | fp->attributes = parse_uac_endpoint_attributes(chip, alts, protocol, iface_no); | 680 | fp->attributes = parse_uac_endpoint_attributes(chip, alts, protocol, iface_no); |
| 679 | fp->clock = clock; | 681 | fp->clock = clock; |
| 682 | INIT_LIST_HEAD(&fp->list); | ||
| 680 | 683 | ||
| 681 | /* some quirks for attributes here */ | 684 | /* some quirks for attributes here */ |
| 682 | 685 | ||
| @@ -725,6 +728,7 @@ int snd_usb_parse_audio_interface(struct snd_usb_audio *chip, int iface_no) | |||
| 725 | dev_dbg(&dev->dev, "%u:%d: add audio endpoint %#x\n", iface_no, altno, fp->endpoint); | 728 | dev_dbg(&dev->dev, "%u:%d: add audio endpoint %#x\n", iface_no, altno, fp->endpoint); |
| 726 | err = snd_usb_add_audio_stream(chip, stream, fp); | 729 | err = snd_usb_add_audio_stream(chip, stream, fp); |
| 727 | if (err < 0) { | 730 | if (err < 0) { |
| 731 | list_del(&fp->list); /* unlink for avoiding double-free */ | ||
| 728 | kfree(fp->rate_table); | 732 | kfree(fp->rate_table); |
| 729 | kfree(fp->chmap); | 733 | kfree(fp->chmap); |
| 730 | kfree(fp); | 734 | kfree(fp); |
