Commit 0f380715 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'sound-4.14-rc4' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound

Pull sound fixes from Takashi Iwai:
 "A collection of small fixes, mostly with stable ones:

 - X32 ABI fix for PCM; likely not so many people suffer from it, but
   still better to fix

 - Two minor kernel warning fixes on USB audio devices spotted by
   syzkaller

 - Regression fix of echoaudio due to its inconsistent dimension

 - Fix for HBR support on Intel DP audio, on some recent chips

 - USB-audio quirk for yet another Plantronics devices

 - Fix for potential double-fetch in ASIHPI FIFO queue"

* tag 'sound-4.14-rc4' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound:
  ALSA: usx2y: Suppress kernel warning at page allocation failures
  Revert "ALSA: echoaudio: purge contradictions between dimension matrix members and total number of members"
  ALSA: usb-audio: Check out-of-bounds access by corrupted buffer descriptor
  ALSA: pcm: Fix structure definition for X32 ABI
  ALSA: usb-audio: Add sample rate quirk for Plantronics C310/C520-M
  ALSA: hda - program ICT bits to support HBR audio
  ALSA: asihpi: fix a potential double-fetch bug when copying puhm
  ALSA: compress: Remove unused variable
parents 77ede3a0 7682e399
...@@ -95,6 +95,7 @@ enum { ...@@ -95,6 +95,7 @@ enum {
#define AC_VERB_SET_EAPD_BTLENABLE 0x70c #define AC_VERB_SET_EAPD_BTLENABLE 0x70c
#define AC_VERB_SET_DIGI_CONVERT_1 0x70d #define AC_VERB_SET_DIGI_CONVERT_1 0x70d
#define AC_VERB_SET_DIGI_CONVERT_2 0x70e #define AC_VERB_SET_DIGI_CONVERT_2 0x70e
#define AC_VERB_SET_DIGI_CONVERT_3 0x73e
#define AC_VERB_SET_VOLUME_KNOB_CONTROL 0x70f #define AC_VERB_SET_VOLUME_KNOB_CONTROL 0x70f
#define AC_VERB_SET_GPIO_DATA 0x715 #define AC_VERB_SET_GPIO_DATA 0x715
#define AC_VERB_SET_GPIO_MASK 0x716 #define AC_VERB_SET_GPIO_MASK 0x716
......
...@@ -948,14 +948,13 @@ static const struct file_operations snd_compr_file_ops = { ...@@ -948,14 +948,13 @@ static const struct file_operations snd_compr_file_ops = {
static int snd_compress_dev_register(struct snd_device *device) static int snd_compress_dev_register(struct snd_device *device)
{ {
int ret = -EINVAL; int ret = -EINVAL;
char str[16];
struct snd_compr *compr; struct snd_compr *compr;
if (snd_BUG_ON(!device || !device->device_data)) if (snd_BUG_ON(!device || !device->device_data))
return -EBADFD; return -EBADFD;
compr = device->device_data; compr = device->device_data;
pr_debug("reg %s for device %s, direction %d\n", str, compr->name, pr_debug("reg device %s, direction %d\n", compr->name,
compr->direction); compr->direction);
/* register compressed device */ /* register compressed device */
ret = snd_register_device(SNDRV_DEVICE_TYPE_COMPRESS, ret = snd_register_device(SNDRV_DEVICE_TYPE_COMPRESS,
......
...@@ -547,6 +547,7 @@ struct snd_pcm_mmap_status_x32 { ...@@ -547,6 +547,7 @@ struct snd_pcm_mmap_status_x32 {
u32 pad2; /* alignment */ u32 pad2; /* alignment */
struct timespec tstamp; struct timespec tstamp;
s32 suspended_state; s32 suspended_state;
s32 pad3;
struct timespec audio_tstamp; struct timespec audio_tstamp;
} __packed; } __packed;
......
...@@ -103,6 +103,7 @@ long asihpi_hpi_ioctl(struct file *file, unsigned int cmd, unsigned long arg) ...@@ -103,6 +103,7 @@ long asihpi_hpi_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
void __user *puhr; void __user *puhr;
union hpi_message_buffer_v1 *hm; union hpi_message_buffer_v1 *hm;
union hpi_response_buffer_v1 *hr; union hpi_response_buffer_v1 *hr;
u16 msg_size;
u16 res_max_size; u16 res_max_size;
u32 uncopied_bytes; u32 uncopied_bytes;
int err = 0; int err = 0;
...@@ -127,22 +128,25 @@ long asihpi_hpi_ioctl(struct file *file, unsigned int cmd, unsigned long arg) ...@@ -127,22 +128,25 @@ long asihpi_hpi_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
} }
/* Now read the message size and data from user space. */ /* Now read the message size and data from user space. */
if (get_user(hm->h.size, (u16 __user *)puhm)) { if (get_user(msg_size, (u16 __user *)puhm)) {
err = -EFAULT; err = -EFAULT;
goto out; goto out;
} }
if (hm->h.size > sizeof(*hm)) if (msg_size > sizeof(*hm))
hm->h.size = sizeof(*hm); msg_size = sizeof(*hm);
/* printk(KERN_INFO "message size %d\n", hm->h.wSize); */ /* printk(KERN_INFO "message size %d\n", hm->h.wSize); */
uncopied_bytes = copy_from_user(hm, puhm, hm->h.size); uncopied_bytes = copy_from_user(hm, puhm, msg_size);
if (uncopied_bytes) { if (uncopied_bytes) {
HPI_DEBUG_LOG(ERROR, "uncopied bytes %d\n", uncopied_bytes); HPI_DEBUG_LOG(ERROR, "uncopied bytes %d\n", uncopied_bytes);
err = -EFAULT; err = -EFAULT;
goto out; goto out;
} }
/* Override h.size in case it is changed between two userspace fetches */
hm->h.size = msg_size;
if (get_user(res_max_size, (u16 __user *)puhr)) { if (get_user(res_max_size, (u16 __user *)puhr)) {
err = -EFAULT; err = -EFAULT;
goto out; goto out;
......
...@@ -1272,11 +1272,11 @@ static int snd_echo_mixer_info(struct snd_kcontrol *kcontrol, ...@@ -1272,11 +1272,11 @@ static int snd_echo_mixer_info(struct snd_kcontrol *kcontrol,
chip = snd_kcontrol_chip(kcontrol); chip = snd_kcontrol_chip(kcontrol);
uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
uinfo->count = 1;
uinfo->value.integer.min = ECHOGAIN_MINOUT; uinfo->value.integer.min = ECHOGAIN_MINOUT;
uinfo->value.integer.max = ECHOGAIN_MAXOUT; uinfo->value.integer.max = ECHOGAIN_MAXOUT;
uinfo->dimen.d[0] = num_busses_out(chip); uinfo->dimen.d[0] = num_busses_out(chip);
uinfo->dimen.d[1] = num_busses_in(chip); uinfo->dimen.d[1] = num_busses_in(chip);
uinfo->count = uinfo->dimen.d[0] * uinfo->dimen.d[1];
return 0; return 0;
} }
...@@ -1344,11 +1344,11 @@ static int snd_echo_vmixer_info(struct snd_kcontrol *kcontrol, ...@@ -1344,11 +1344,11 @@ static int snd_echo_vmixer_info(struct snd_kcontrol *kcontrol,
chip = snd_kcontrol_chip(kcontrol); chip = snd_kcontrol_chip(kcontrol);
uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
uinfo->count = 1;
uinfo->value.integer.min = ECHOGAIN_MINOUT; uinfo->value.integer.min = ECHOGAIN_MINOUT;
uinfo->value.integer.max = ECHOGAIN_MAXOUT; uinfo->value.integer.max = ECHOGAIN_MAXOUT;
uinfo->dimen.d[0] = num_busses_out(chip); uinfo->dimen.d[0] = num_busses_out(chip);
uinfo->dimen.d[1] = num_pipes_out(chip); uinfo->dimen.d[1] = num_pipes_out(chip);
uinfo->count = uinfo->dimen.d[0] * uinfo->dimen.d[1];
return 0; return 0;
} }
...@@ -1728,6 +1728,7 @@ static int snd_echo_vumeters_info(struct snd_kcontrol *kcontrol, ...@@ -1728,6 +1728,7 @@ static int snd_echo_vumeters_info(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_info *uinfo) struct snd_ctl_elem_info *uinfo)
{ {
uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
uinfo->count = 96;
uinfo->value.integer.min = ECHOGAIN_MINOUT; uinfo->value.integer.min = ECHOGAIN_MINOUT;
uinfo->value.integer.max = 0; uinfo->value.integer.max = 0;
#ifdef ECHOCARD_HAS_VMIXER #ifdef ECHOCARD_HAS_VMIXER
...@@ -1737,7 +1738,6 @@ static int snd_echo_vumeters_info(struct snd_kcontrol *kcontrol, ...@@ -1737,7 +1738,6 @@ static int snd_echo_vumeters_info(struct snd_kcontrol *kcontrol,
#endif #endif
uinfo->dimen.d[1] = 16; /* 16 channels */ uinfo->dimen.d[1] = 16; /* 16 channels */
uinfo->dimen.d[2] = 2; /* 0=level, 1=peak */ uinfo->dimen.d[2] = 2; /* 0=level, 1=peak */
uinfo->count = uinfo->dimen.d[0] * uinfo->dimen.d[1] * uinfo->dimen.d[2];
return 0; return 0;
} }
......
...@@ -906,6 +906,7 @@ static int hdmi_setup_stream(struct hda_codec *codec, hda_nid_t cvt_nid, ...@@ -906,6 +906,7 @@ static int hdmi_setup_stream(struct hda_codec *codec, hda_nid_t cvt_nid,
hda_nid_t pin_nid, u32 stream_tag, int format) hda_nid_t pin_nid, u32 stream_tag, int format)
{ {
struct hdmi_spec *spec = codec->spec; struct hdmi_spec *spec = codec->spec;
unsigned int param;
int err; int err;
err = spec->ops.pin_hbr_setup(codec, pin_nid, is_hbr_format(format)); err = spec->ops.pin_hbr_setup(codec, pin_nid, is_hbr_format(format));
...@@ -915,6 +916,26 @@ static int hdmi_setup_stream(struct hda_codec *codec, hda_nid_t cvt_nid, ...@@ -915,6 +916,26 @@ static int hdmi_setup_stream(struct hda_codec *codec, hda_nid_t cvt_nid,
return err; return err;
} }
if (is_haswell_plus(codec)) {
/*
* on recent platforms IEC Coding Type is required for HBR
* support, read current Digital Converter settings and set
* ICT bitfield if needed.
*/
param = snd_hda_codec_read(codec, cvt_nid, 0,
AC_VERB_GET_DIGI_CONVERT_1, 0);
param = (param >> 16) & ~(AC_DIG3_ICT);
/* on recent platforms ICT mode is required for HBR support */
if (is_hbr_format(format))
param |= 0x1;
snd_hda_codec_write(codec, cvt_nid, 0,
AC_VERB_SET_DIGI_CONVERT_3, param);
}
snd_hda_codec_setup_stream(codec, cvt_nid, stream_tag, 0, format); snd_hda_codec_setup_stream(codec, cvt_nid, stream_tag, 0, format);
return 0; return 0;
} }
......
...@@ -221,6 +221,7 @@ static int snd_usb_create_streams(struct snd_usb_audio *chip, int ctrlif) ...@@ -221,6 +221,7 @@ static int snd_usb_create_streams(struct snd_usb_audio *chip, int ctrlif)
struct usb_interface_descriptor *altsd; struct usb_interface_descriptor *altsd;
void *control_header; void *control_header;
int i, protocol; int i, protocol;
int rest_bytes;
/* find audiocontrol interface */ /* find audiocontrol interface */
host_iface = &usb_ifnum_to_if(dev, ctrlif)->altsetting[0]; host_iface = &usb_ifnum_to_if(dev, ctrlif)->altsetting[0];
...@@ -235,6 +236,15 @@ static int snd_usb_create_streams(struct snd_usb_audio *chip, int ctrlif) ...@@ -235,6 +236,15 @@ static int snd_usb_create_streams(struct snd_usb_audio *chip, int ctrlif)
return -EINVAL; return -EINVAL;
} }
rest_bytes = (void *)(host_iface->extra + host_iface->extralen) -
control_header;
/* just to be sure -- this shouldn't hit at all */
if (rest_bytes <= 0) {
dev_err(&dev->dev, "invalid control header\n");
return -EINVAL;
}
switch (protocol) { switch (protocol) {
default: default:
dev_warn(&dev->dev, dev_warn(&dev->dev,
...@@ -245,11 +255,21 @@ static int snd_usb_create_streams(struct snd_usb_audio *chip, int ctrlif) ...@@ -245,11 +255,21 @@ static int snd_usb_create_streams(struct snd_usb_audio *chip, int ctrlif)
case UAC_VERSION_1: { case UAC_VERSION_1: {
struct uac1_ac_header_descriptor *h1 = control_header; struct uac1_ac_header_descriptor *h1 = control_header;
if (rest_bytes < sizeof(*h1)) {
dev_err(&dev->dev, "too short v1 buffer descriptor\n");
return -EINVAL;
}
if (!h1->bInCollection) { if (!h1->bInCollection) {
dev_info(&dev->dev, "skipping empty audio interface (v1)\n"); dev_info(&dev->dev, "skipping empty audio interface (v1)\n");
return -EINVAL; return -EINVAL;
} }
if (rest_bytes < h1->bLength) {
dev_err(&dev->dev, "invalid buffer length (v1)\n");
return -EINVAL;
}
if (h1->bLength < sizeof(*h1) + h1->bInCollection) { if (h1->bLength < sizeof(*h1) + h1->bInCollection) {
dev_err(&dev->dev, "invalid UAC_HEADER (v1)\n"); dev_err(&dev->dev, "invalid UAC_HEADER (v1)\n");
return -EINVAL; return -EINVAL;
......
...@@ -1137,6 +1137,8 @@ bool snd_usb_get_sample_rate_quirk(struct snd_usb_audio *chip) ...@@ -1137,6 +1137,8 @@ bool snd_usb_get_sample_rate_quirk(struct snd_usb_audio *chip)
case USB_ID(0x047F, 0x02F7): /* Plantronics BT-600 */ case USB_ID(0x047F, 0x02F7): /* Plantronics BT-600 */
case USB_ID(0x047F, 0x0415): /* Plantronics BT-300 */ case USB_ID(0x047F, 0x0415): /* Plantronics BT-300 */
case USB_ID(0x047F, 0xAA05): /* Plantronics DA45 */ case USB_ID(0x047F, 0xAA05): /* Plantronics DA45 */
case USB_ID(0x047F, 0xC022): /* Plantronics C310 */
case USB_ID(0x047F, 0xC036): /* Plantronics C520-M */
case USB_ID(0x04D8, 0xFEEA): /* Benchmark DAC1 Pre */ case USB_ID(0x04D8, 0xFEEA): /* Benchmark DAC1 Pre */
case USB_ID(0x0556, 0x0014): /* Phoenix Audio TMX320VC */ case USB_ID(0x0556, 0x0014): /* Phoenix Audio TMX320VC */
case USB_ID(0x05A3, 0x9420): /* ELP HD USB Camera */ case USB_ID(0x05A3, 0x9420): /* ELP HD USB Camera */
......
...@@ -191,7 +191,8 @@ struct usb_stream *usb_stream_new(struct usb_stream_kernel *sk, ...@@ -191,7 +191,8 @@ struct usb_stream *usb_stream_new(struct usb_stream_kernel *sk,
} }
pg = get_order(read_size); pg = get_order(read_size);
sk->s = (void *) __get_free_pages(GFP_KERNEL|__GFP_COMP|__GFP_ZERO, pg); sk->s = (void *) __get_free_pages(GFP_KERNEL|__GFP_COMP|__GFP_ZERO|
__GFP_NOWARN, pg);
if (!sk->s) { if (!sk->s) {
snd_printk(KERN_WARNING "couldn't __get_free_pages()\n"); snd_printk(KERN_WARNING "couldn't __get_free_pages()\n");
goto out; goto out;
...@@ -211,7 +212,8 @@ struct usb_stream *usb_stream_new(struct usb_stream_kernel *sk, ...@@ -211,7 +212,8 @@ struct usb_stream *usb_stream_new(struct usb_stream_kernel *sk,
pg = get_order(write_size); pg = get_order(write_size);
sk->write_page = sk->write_page =
(void *)__get_free_pages(GFP_KERNEL|__GFP_COMP|__GFP_ZERO, pg); (void *)__get_free_pages(GFP_KERNEL|__GFP_COMP|__GFP_ZERO|
__GFP_NOWARN, pg);
if (!sk->write_page) { if (!sk->write_page) {
snd_printk(KERN_WARNING "couldn't __get_free_pages()\n"); snd_printk(KERN_WARNING "couldn't __get_free_pages()\n");
usb_stream_free(sk); usb_stream_free(sk);
......
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