Merge tag 'sound-5.3-rc7' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai...
authorLinus Torvalds <torvalds@linux-foundation.org>
Tue, 27 Aug 2019 17:42:03 +0000 (10:42 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Tue, 27 Aug 2019 17:42:03 +0000 (10:42 -0700)
Pull sound fixes from Takashi Iwai:
 "A collection of small fixes as usual:

   - More coverage of USB-audio descriptor sanity checks

   - A fix for mute LED regression on Conexant HD-audio codecs

   - A few device-specific fixes and quirks for USB-audio and HD-audio

   - A fix for (die-hard remaining) possible race in sequencer core

   - FireWire oxfw regression fix that was introduced in 5.3-rc1"

* tag 'sound-5.3-rc7' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound:
  ALSA: oxfw: fix to handle correct stream for PCM playback
  ALSA: seq: Fix potential concurrent access to the deleted pool
  ALSA: usb-audio: Check mixer unit bitmap yet more strictly
  ALSA: line6: Fix memory leak at line6_init_pcm() error path
  ALSA: usb-audio: Fix invalid NULL check in snd_emuusb_set_samplerate()
  ALSA: hda/ca0132 - Add new SBZ quirk
  ALSA: usb-audio: Add implicit fb quirk for Behringer UFX1604
  ALSA: hda - Fixes inverted Conexant GPIO mic mute led

sound/core/seq/seq_clientmgr.c
sound/core/seq/seq_fifo.c
sound/core/seq/seq_fifo.h
sound/firewire/oxfw/oxfw-pcm.c
sound/pci/hda/patch_ca0132.c
sound/pci/hda/patch_conexant.c
sound/usb/line6/pcm.c
sound/usb/mixer.c
sound/usb/mixer_quirks.c
sound/usb/pcm.c

index 7737b2670064dcd1b8c13af1b8b69a0ab5cd7997..6d9592f0ae1d53c42b3d7d59bfdc462f39a34f77 100644 (file)
@@ -1835,8 +1835,7 @@ static int snd_seq_ioctl_get_client_pool(struct snd_seq_client *client,
        if (cptr->type == USER_CLIENT) {
                info->input_pool = cptr->data.user.fifo_pool_size;
                info->input_free = info->input_pool;
-               if (cptr->data.user.fifo)
-                       info->input_free = snd_seq_unused_cells(cptr->data.user.fifo->pool);
+               info->input_free = snd_seq_fifo_unused_cells(cptr->data.user.fifo);
        } else {
                info->input_pool = 0;
                info->input_free = 0;
index ea69261f269aa4be262cffe736d876c6136b2d78..eaaa8b5830bb6471616c2c4e0458ab469e6c4c85 100644 (file)
@@ -263,3 +263,20 @@ int snd_seq_fifo_resize(struct snd_seq_fifo *f, int poolsize)
 
        return 0;
 }
+
+/* get the number of unused cells safely */
+int snd_seq_fifo_unused_cells(struct snd_seq_fifo *f)
+{
+       unsigned long flags;
+       int cells;
+
+       if (!f)
+               return 0;
+
+       snd_use_lock_use(&f->use_lock);
+       spin_lock_irqsave(&f->lock, flags);
+       cells = snd_seq_unused_cells(f->pool);
+       spin_unlock_irqrestore(&f->lock, flags);
+       snd_use_lock_free(&f->use_lock);
+       return cells;
+}
index edc68743943d7249bfc46c2a874c5d4602362644..b56a7b897c9c313f9b91be1069c1a84da2866132 100644 (file)
@@ -53,5 +53,7 @@ int snd_seq_fifo_poll_wait(struct snd_seq_fifo *f, struct file *file, poll_table
 /* resize pool in fifo */
 int snd_seq_fifo_resize(struct snd_seq_fifo *f, int poolsize);
 
+/* get the number of unused cells safely */
+int snd_seq_fifo_unused_cells(struct snd_seq_fifo *f);
 
 #endif
index 9ea39348cdf5623db8c1a8a73fd9a26ecadee095..7c6d1c277d4d9e52a107c8079ff9f5a3254b4ac9 100644 (file)
@@ -248,7 +248,7 @@ static int pcm_playback_hw_params(struct snd_pcm_substream *substream,
                unsigned int channels = params_channels(hw_params);
 
                mutex_lock(&oxfw->mutex);
-               err = snd_oxfw_stream_reserve_duplex(oxfw, &oxfw->tx_stream,
+               err = snd_oxfw_stream_reserve_duplex(oxfw, &oxfw->rx_stream,
                                                     rate, channels);
                if (err >= 0)
                        ++oxfw->substreams_count;
index 0d51823d7270eaf2629eabb15290e14d4839dec2..6d1fb7c11f17ed93b5ca4f2f12e295c3970b6ec4 100644 (file)
@@ -1175,6 +1175,7 @@ static const struct snd_pci_quirk ca0132_quirks[] = {
        SND_PCI_QUIRK(0x1028, 0x0708, "Alienware 15 R2 2016", QUIRK_ALIENWARE),
        SND_PCI_QUIRK(0x1102, 0x0010, "Sound Blaster Z", QUIRK_SBZ),
        SND_PCI_QUIRK(0x1102, 0x0023, "Sound Blaster Z", QUIRK_SBZ),
+       SND_PCI_QUIRK(0x1102, 0x0027, "Sound Blaster Z", QUIRK_SBZ),
        SND_PCI_QUIRK(0x1102, 0x0033, "Sound Blaster ZxR", QUIRK_SBZ),
        SND_PCI_QUIRK(0x1458, 0xA016, "Recon3Di", QUIRK_R3DI),
        SND_PCI_QUIRK(0x1458, 0xA026, "Gigabyte G1.Sniper Z97", QUIRK_R3DI),
index 14298ef45b21bdf71db7dc864542ea8a7213331f..968d3caab6ac3e157f5eb4bee9f0990f30840d16 100644 (file)
@@ -611,18 +611,20 @@ static void cxt_fixup_hp_gate_mic_jack(struct hda_codec *codec,
 
 /* update LED status via GPIO */
 static void cxt_update_gpio_led(struct hda_codec *codec, unsigned int mask,
-                               bool enabled)
+                               bool led_on)
 {
        struct conexant_spec *spec = codec->spec;
        unsigned int oldval = spec->gpio_led;
 
        if (spec->mute_led_polarity)
-               enabled = !enabled;
+               led_on = !led_on;
 
-       if (enabled)
-               spec->gpio_led &= ~mask;
-       else
+       if (led_on)
                spec->gpio_led |= mask;
+       else
+               spec->gpio_led &= ~mask;
+       codec_dbg(codec, "mask:%d enabled:%d gpio_led:%d\n",
+                       mask, led_on, spec->gpio_led);
        if (spec->gpio_led != oldval)
                snd_hda_codec_write(codec, 0x01, 0, AC_VERB_SET_GPIO_DATA,
                                    spec->gpio_led);
@@ -633,8 +635,8 @@ static void cxt_fixup_gpio_mute_hook(void *private_data, int enabled)
 {
        struct hda_codec *codec = private_data;
        struct conexant_spec *spec = codec->spec;
-
-       cxt_update_gpio_led(codec, spec->gpio_mute_led_mask, enabled);
+       /* muted -> LED on */
+       cxt_update_gpio_led(codec, spec->gpio_mute_led_mask, !enabled);
 }
 
 /* turn on/off mic-mute LED via GPIO per capture hook */
@@ -656,7 +658,6 @@ static void cxt_fixup_mute_led_gpio(struct hda_codec *codec,
                { 0x01, AC_VERB_SET_GPIO_DIRECTION, 0x03 },
                {}
        };
-       codec_info(codec, "action: %d gpio_led: %d\n", action, spec->gpio_led);
 
        if (action == HDA_FIXUP_ACT_PRE_PROBE) {
                spec->gen.vmaster_mute.hook = cxt_fixup_gpio_mute_hook;
index 2c03e0f6bf72d661226b73ddee90c087db8f4b6f..f70211e6b174fdc18553a222630c58643a7fed34 100644 (file)
@@ -550,6 +550,15 @@ int line6_init_pcm(struct usb_line6 *line6,
        line6pcm->volume_monitor = 255;
        line6pcm->line6 = line6;
 
+       spin_lock_init(&line6pcm->out.lock);
+       spin_lock_init(&line6pcm->in.lock);
+       line6pcm->impulse_period = LINE6_IMPULSE_DEFAULT_PERIOD;
+
+       line6->line6pcm = line6pcm;
+
+       pcm->private_data = line6pcm;
+       pcm->private_free = line6_cleanup_pcm;
+
        line6pcm->max_packet_size_in =
                usb_maxpacket(line6->usbdev,
                        usb_rcvisocpipe(line6->usbdev, ep_read), 0);
@@ -562,15 +571,6 @@ int line6_init_pcm(struct usb_line6 *line6,
                return -EINVAL;
        }
 
-       spin_lock_init(&line6pcm->out.lock);
-       spin_lock_init(&line6pcm->in.lock);
-       line6pcm->impulse_period = LINE6_IMPULSE_DEFAULT_PERIOD;
-
-       line6->line6pcm = line6pcm;
-
-       pcm->private_data = line6pcm;
-       pcm->private_free = line6_cleanup_pcm;
-
        err = line6_create_audio_out_urbs(line6pcm);
        if (err < 0)
                return err;
index b5927c3d5bc0b0657360ef8aa923c0aa344422bb..eceab19766dbc745e20c9cb09a82320c43c8a72a 100644 (file)
@@ -739,7 +739,6 @@ static int uac_mixer_unit_get_channels(struct mixer_build *state,
                                       struct uac_mixer_unit_descriptor *desc)
 {
        int mu_channels;
-       void *c;
 
        if (desc->bLength < sizeof(*desc))
                return -EINVAL;
@@ -762,13 +761,6 @@ static int uac_mixer_unit_get_channels(struct mixer_build *state,
                break;
        }
 
-       if (!mu_channels)
-               return 0;
-
-       c = uac_mixer_unit_bmControls(desc, state->mixer->protocol);
-       if (c - (void *)desc + (mu_channels - 1) / 8 >= desc->bLength)
-               return 0; /* no bmControls -> skip */
-
        return mu_channels;
 }
 
@@ -2009,6 +2001,31 @@ static int parse_audio_feature_unit(struct mixer_build *state, int unitid,
  * Mixer Unit
  */
 
+/* check whether the given in/out overflows bmMixerControls matrix */
+static bool mixer_bitmap_overflow(struct uac_mixer_unit_descriptor *desc,
+                                 int protocol, int num_ins, int num_outs)
+{
+       u8 *hdr = (u8 *)desc;
+       u8 *c = uac_mixer_unit_bmControls(desc, protocol);
+       size_t rest; /* remaining bytes after bmMixerControls */
+
+       switch (protocol) {
+       case UAC_VERSION_1:
+       default:
+               rest = 1; /* iMixer */
+               break;
+       case UAC_VERSION_2:
+               rest = 2; /* bmControls + iMixer */
+               break;
+       case UAC_VERSION_3:
+               rest = 6; /* bmControls + wMixerDescrStr */
+               break;
+       }
+
+       /* overflow? */
+       return c + (num_ins * num_outs + 7) / 8 + rest > hdr + hdr[0];
+}
+
 /*
  * build a mixer unit control
  *
@@ -2137,6 +2154,9 @@ static int parse_audio_mixer_unit(struct mixer_build *state, int unitid,
                if (err < 0)
                        return err;
                num_ins += iterm.channels;
+               if (mixer_bitmap_overflow(desc, state->mixer->protocol,
+                                         num_ins, num_outs))
+                       break;
                for (; ich < num_ins; ich++) {
                        int och, ich_has_controls = 0;
 
index 199fa157a411e4731fa56e477f0953b2c8fd68ea..27dcb3743690f7c29764fb978823f0f37ad9c977 100644 (file)
@@ -1155,17 +1155,17 @@ void snd_emuusb_set_samplerate(struct snd_usb_audio *chip,
 {
        struct usb_mixer_interface *mixer;
        struct usb_mixer_elem_info *cval;
-       int unitid = 12; /* SamleRate ExtensionUnit ID */
+       int unitid = 12; /* SampleRate ExtensionUnit ID */
 
        list_for_each_entry(mixer, &chip->mixer_list, list) {
-               cval = mixer_elem_list_to_info(mixer->id_elems[unitid]);
-               if (cval) {
+               if (mixer->id_elems[unitid]) {
+                       cval = mixer_elem_list_to_info(mixer->id_elems[unitid]);
                        snd_usb_mixer_set_ctl_value(cval, UAC_SET_CUR,
                                                    cval->control << 8,
                                                    samplerate_id);
                        snd_usb_mixer_notify_id(mixer, unitid);
+                       break;
                }
-               break;
        }
 }
 
index 75b96929f76c5ee73cfb159a7f0ef557326f43fd..e4bbf79de956e1d8958d02ead1c907c5bd7ea2bc 100644 (file)
@@ -339,6 +339,7 @@ static int set_sync_ep_implicit_fb_quirk(struct snd_usb_substream *subs,
                ep = 0x81;
                ifnum = 2;
                goto add_sync_ep_from_ifnum;
+       case USB_ID(0x1397, 0x0001): /* Behringer UFX1604 */
        case USB_ID(0x1397, 0x0002): /* Behringer UFX1204 */
                ep = 0x81;
                ifnum = 1;