]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
6.12-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 13 Jul 2026 13:02:53 +0000 (15:02 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 13 Jul 2026 13:02:53 +0000 (15:02 +0200)
added patches:
alsa-caiaq-fix-out-of-bounds-read-in-the-traktor-kontrol-s4-input-parser.patch
alsa-cmipci-check-snd_ctl_new1-return-value.patch
alsa-es1938-check-snd_ctl_new1-return-value.patch
alsa-firewire-isight-bound-the-sample-count-to-the-packet-payload.patch
alsa-gus-check-snd_ctl_new1-return-value.patch
alsa-ice1712-check-snd_ctl_new1-return-value.patch
alsa-seq-fix-uninitialised-heap-leak-in-snd_seq_event_dup.patch
alsa-usb-audio-avoid-kobject-path-lookup-in-dualsense-match.patch
alsa-usb-audio-propagate-errors-in-scarlett_ctl_enum_put.patch
alsa-usb-audio-propagate-us-16x08-write-errors-in-route-mix-eq-switch-put-callbacks.patch
alsa-usb-audio-roll-back-quirk-control-caches-on-write-errors.patch
alsa-usb-audio-update-babyface-pro-control-caches-only-after-successful-writes.patch
alsa-usb-audio-update-us-16x08-eq-comp-shadow-state-after-successful-writes.patch

14 files changed:
queue-6.12/alsa-caiaq-fix-out-of-bounds-read-in-the-traktor-kontrol-s4-input-parser.patch [new file with mode: 0644]
queue-6.12/alsa-cmipci-check-snd_ctl_new1-return-value.patch [new file with mode: 0644]
queue-6.12/alsa-es1938-check-snd_ctl_new1-return-value.patch [new file with mode: 0644]
queue-6.12/alsa-firewire-isight-bound-the-sample-count-to-the-packet-payload.patch [new file with mode: 0644]
queue-6.12/alsa-gus-check-snd_ctl_new1-return-value.patch [new file with mode: 0644]
queue-6.12/alsa-ice1712-check-snd_ctl_new1-return-value.patch [new file with mode: 0644]
queue-6.12/alsa-seq-fix-uninitialised-heap-leak-in-snd_seq_event_dup.patch [new file with mode: 0644]
queue-6.12/alsa-usb-audio-avoid-kobject-path-lookup-in-dualsense-match.patch [new file with mode: 0644]
queue-6.12/alsa-usb-audio-propagate-errors-in-scarlett_ctl_enum_put.patch [new file with mode: 0644]
queue-6.12/alsa-usb-audio-propagate-us-16x08-write-errors-in-route-mix-eq-switch-put-callbacks.patch [new file with mode: 0644]
queue-6.12/alsa-usb-audio-roll-back-quirk-control-caches-on-write-errors.patch [new file with mode: 0644]
queue-6.12/alsa-usb-audio-update-babyface-pro-control-caches-only-after-successful-writes.patch [new file with mode: 0644]
queue-6.12/alsa-usb-audio-update-us-16x08-eq-comp-shadow-state-after-successful-writes.patch [new file with mode: 0644]
queue-6.12/series

diff --git a/queue-6.12/alsa-caiaq-fix-out-of-bounds-read-in-the-traktor-kontrol-s4-input-parser.patch b/queue-6.12/alsa-caiaq-fix-out-of-bounds-read-in-the-traktor-kontrol-s4-input-parser.patch
new file mode 100644 (file)
index 0000000..fa4d6de
--- /dev/null
@@ -0,0 +1,51 @@
+From f7f3f9fd81e7adbaa12c2e62ee07f0e094a543fd Mon Sep 17 00:00:00 2001
+From: Maoyi Xie <maoyixie.tju@gmail.com>
+Date: Thu, 18 Jun 2026 14:03:15 +0800
+Subject: ALSA: caiaq: fix out-of-bounds read in the Traktor Kontrol S4 input parser
+
+From: Maoyi Xie <maoyixie.tju@gmail.com>
+
+commit f7f3f9fd81e7adbaa12c2e62ee07f0e094a543fd upstream.
+
+snd_usb_caiaq_tks4_dispatch() decodes the Traktor Kontrol S4 input
+stream in fixed 16-byte (TKS4_MSGBLOCK_SIZE) message blocks. On every
+iteration it advances buf and subtracts the block size while looping on
+"while (len)".
+
+len is urb->actual_length. That value is supplied by the device and is
+not guaranteed to be a multiple of 16. When a final short block leaves
+len between 1 and 15, the loop runs once more, reads up to buf[15], and
+then does "len -= TKS4_MSGBLOCK_SIZE". As len is unsigned this underflows
+to a huge value. The loop then keeps iterating and walking buf far past
+the end of the 512-byte ep4_in_buf, reading out of bounds until a bogus
+block id happens to be hit.
+
+Iterate only while a full message block is available. This stops the
+unsigned underflow and silently drops any trailing partial block, which
+carries no complete control value anyway.
+
+The sibling endpoint-4 parsers are not affected. The Traktor Kontrol X1
+and Maschine arms in snd_usb_caiaq_ep4_reply_dispatch() floor
+urb->actual_length before dispatching.
+
+Fixes: 15c5ab607045 ("ALSA: snd-usb-caiaq: Add support for Traktor Kontrol S4")
+Cc: stable@vger.kernel.org
+Signed-off-by: Maoyi Xie <maoyixie.tju@gmail.com>
+Link: https://patch.msgid.link/178176259547.3343534.2724779296835237429@maoyixie.com
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ sound/usb/caiaq/input.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/sound/usb/caiaq/input.c
++++ b/sound/usb/caiaq/input.c
+@@ -330,7 +330,7 @@ static void snd_usb_caiaq_tks4_dispatch(
+ {
+       struct device *dev = caiaqdev_to_dev(cdev);
+-      while (len) {
++      while (len >= TKS4_MSGBLOCK_SIZE) {
+               unsigned int i, block_id = (buf[0] << 8) | buf[1];
+               switch (block_id) {
diff --git a/queue-6.12/alsa-cmipci-check-snd_ctl_new1-return-value.patch b/queue-6.12/alsa-cmipci-check-snd_ctl_new1-return-value.patch
new file mode 100644 (file)
index 0000000..9abecc0
--- /dev/null
@@ -0,0 +1,53 @@
+From c205bd1b28fb7e5f1061a4e78813fad7d315cb3e Mon Sep 17 00:00:00 2001
+From: Zhao Dongdong <zhaodongdong@kylinos.cn>
+Date: Wed, 27 May 2026 20:09:13 +0800
+Subject: ALSA: cmipci: check snd_ctl_new1() return value
+
+From: Zhao Dongdong <zhaodongdong@kylinos.cn>
+
+commit c205bd1b28fb7e5f1061a4e78813fad7d315cb3e upstream.
+
+snd_ctl_new1() can return NULL when memory allocation fails.
+snd_cmipci_spdif_controls() does not check the return value before
+dereferencing kctl->id.device, which can lead to a NULL pointer
+dereference.
+
+Add NULL checks after snd_ctl_new1() calls and return -ENOMEM if any
+fails.
+
+Assisted-by: Opencode:DeepSeek-V4-Flash
+Cc: stable@vger.kernel.org
+Fixes: f2f312ad88c6 ("ALSA: cmipci: Fix kctl->id initialization")
+Signed-off-by: Zhao Dongdong <zhaodongdong@kylinos.cn>
+Link: https://patch.msgid.link/tencent_964433DCD132125D5EDA79EE068A2D6EFA09@qq.com
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ sound/pci/cmipci.c |    6 ++++++
+ 1 file changed, 6 insertions(+)
+
+--- a/sound/pci/cmipci.c
++++ b/sound/pci/cmipci.c
+@@ -2672,16 +2672,22 @@ static int snd_cmipci_mixer_new(struct c
+               }
+               if (cm->can_ac3_hw) {
+                       kctl = snd_ctl_new1(&snd_cmipci_spdif_default, cm);
++                      if (!kctl)
++                              return -ENOMEM;
+                       kctl->id.device = pcm_spdif_device;
+                       err = snd_ctl_add(card, kctl);
+                       if (err < 0)
+                               return err;
+                       kctl = snd_ctl_new1(&snd_cmipci_spdif_mask, cm);
++                      if (!kctl)
++                              return -ENOMEM;
+                       kctl->id.device = pcm_spdif_device;
+                       err = snd_ctl_add(card, kctl);
+                       if (err < 0)
+                               return err;
+                       kctl = snd_ctl_new1(&snd_cmipci_spdif_stream, cm);
++                      if (!kctl)
++                              return -ENOMEM;
+                       kctl->id.device = pcm_spdif_device;
+                       err = snd_ctl_add(card, kctl);
+                       if (err < 0)
diff --git a/queue-6.12/alsa-es1938-check-snd_ctl_new1-return-value.patch b/queue-6.12/alsa-es1938-check-snd_ctl_new1-return-value.patch
new file mode 100644 (file)
index 0000000..10a3e25
--- /dev/null
@@ -0,0 +1,37 @@
+From 1edd1f02dddd20aeb6066ded41017615766ea42f Mon Sep 17 00:00:00 2001
+From: Zhao Dongdong <zhaodongdong@kylinos.cn>
+Date: Wed, 27 May 2026 20:09:09 +0800
+Subject: ALSA: es1938: check snd_ctl_new1() return value
+
+From: Zhao Dongdong <zhaodongdong@kylinos.cn>
+
+commit 1edd1f02dddd20aeb6066ded41017615766ea42f upstream.
+
+snd_ctl_new1() can return NULL when memory allocation fails.
+snd_es1938_mixer() does not check the return value before dereferencing
+the pointer, which can lead to a NULL pointer dereference.
+
+Add a NULL check after snd_ctl_new1() and return -ENOMEM if it fails.
+
+Assisted-by: Opencode:DeepSeek-V4-Flash
+Cc: stable@vger.kernel.org
+Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
+Signed-off-by: Zhao Dongdong <zhaodongdong@kylinos.cn>
+Link: https://patch.msgid.link/tencent_E0DC65165FDF2C8982BAFB6794B854B53B0A@qq.com
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ sound/pci/es1938.c |    2 ++
+ 1 file changed, 2 insertions(+)
+
+--- a/sound/pci/es1938.c
++++ b/sound/pci/es1938.c
+@@ -1663,6 +1663,8 @@ static int snd_es1938_mixer(struct es193
+       for (idx = 0; idx < ARRAY_SIZE(snd_es1938_controls); idx++) {
+               struct snd_kcontrol *kctl;
+               kctl = snd_ctl_new1(&snd_es1938_controls[idx], chip);
++              if (!kctl)
++                      return -ENOMEM;
+               switch (idx) {
+                       case 0:
+                               chip->master_volume = kctl;
diff --git a/queue-6.12/alsa-firewire-isight-bound-the-sample-count-to-the-packet-payload.patch b/queue-6.12/alsa-firewire-isight-bound-the-sample-count-to-the-packet-payload.patch
new file mode 100644 (file)
index 0000000..de79d6c
--- /dev/null
@@ -0,0 +1,55 @@
+From 29b9667982e4df2ed7744f86b1144f8bb58eb698 Mon Sep 17 00:00:00 2001
+From: Maoyi Xie <maoyixie.tju@gmail.com>
+Date: Sun, 21 Jun 2026 23:09:07 +0800
+Subject: ALSA: firewire: isight: bound the sample count to the packet payload
+
+From: Maoyi Xie <maoyixie.tju@gmail.com>
+
+commit 29b9667982e4df2ed7744f86b1144f8bb58eb698 upstream.
+
+isight_packet() takes the frame count from the device iso packet and
+checks it only against the device claimed iso length.
+
+       count = be32_to_cpu(payload->sample_count);
+       if (likely(count <= (length - 16) / 4))
+               isight_samples(isight, payload->samples, count);
+
+length is the iso header data_length. It can be up to 0xffff. So the
+gate allows a count up to about 16379. isight_samples() then copies
+count frames out of payload->samples into the PCM DMA buffer.
+
+payload->samples holds only 2 * MAX_FRAMES_PER_PACKET values. The
+device multiplexes two samples per frame. A count past
+MAX_FRAMES_PER_PACKET reads past the payload. A count past the buffer
+size writes past runtime->dma_area. The smallest PCM buffer is larger
+than MAX_FRAMES_PER_PACKET. Bounding the count to MAX_FRAMES_PER_PACKET
+keeps both the read and the write in range.
+
+A malicious or faulty Apple iSight on the FireWire bus reaches this
+during a normal capture.
+
+Add the MAX_FRAMES_PER_PACKET bound to the gate.
+
+Fixes: 3a691b28a0ca ("ALSA: add Apple iSight microphone driver")
+Suggested-by: Takashi Sakamoto <o-takashi@sakamocchi.jp>
+Cc: stable@vger.kernel.org
+Signed-off-by: Maoyi Xie <maoyixie.tju@gmail.com>
+Link: https://patch.msgid.link/178205454729.1900991.7807310178296762772@maoyixie.com
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ sound/firewire/isight.c |    3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+--- a/sound/firewire/isight.c
++++ b/sound/firewire/isight.c
+@@ -179,7 +179,8 @@ static void isight_packet(struct fw_iso_
+       if (likely(length >= 16 &&
+                  payload->signature == cpu_to_be32(0x73676874/*"sght"*/))) {
+               count = be32_to_cpu(payload->sample_count);
+-              if (likely(count <= (length - 16) / 4)) {
++              if (likely(count <= (length - 16) / 4 &&
++                         count <= MAX_FRAMES_PER_PACKET)) {
+                       total = be32_to_cpu(payload->sample_total);
+                       if (unlikely(total != isight->total_samples)) {
+                               if (!isight->first_packet)
diff --git a/queue-6.12/alsa-gus-check-snd_ctl_new1-return-value.patch b/queue-6.12/alsa-gus-check-snd_ctl_new1-return-value.patch
new file mode 100644 (file)
index 0000000..07abebd
--- /dev/null
@@ -0,0 +1,38 @@
+From c7fa99d30c7a166a5e5db5a585ce7501ff68326b Mon Sep 17 00:00:00 2001
+From: Zhao Dongdong <zhaodongdong@kylinos.cn>
+Date: Wed, 27 May 2026 20:09:10 +0800
+Subject: ALSA: gus: check snd_ctl_new1() return value
+
+From: Zhao Dongdong <zhaodongdong@kylinos.cn>
+
+commit c7fa99d30c7a166a5e5db5a585ce7501ff68326b upstream.
+
+snd_ctl_new1() can return NULL when memory allocation fails.
+snd_gf1_pcm_volume_control() does not check the return value before
+dereferencing kctl->id.index, which can lead to a NULL pointer
+dereference.
+
+Add a NULL check after snd_ctl_new1() and return -ENOMEM if it fails.
+
+Assisted-by: Opencode:DeepSeek-V4-Flash
+Cc: stable@vger.kernel.org
+Fixes: c5ae57b1bb99 ("ALSA: gus: Fix kctl->id initialization")
+Signed-off-by: Zhao Dongdong <zhaodongdong@kylinos.cn>
+Link: https://patch.msgid.link/tencent_F644A3DCAD32945D62DB2FEEBE8A996F6809@qq.com
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ sound/isa/gus/gus_pcm.c |    2 ++
+ 1 file changed, 2 insertions(+)
+
+--- a/sound/isa/gus/gus_pcm.c
++++ b/sound/isa/gus/gus_pcm.c
+@@ -862,6 +862,8 @@ int snd_gf1_pcm_new(struct snd_gus_card
+               kctl = snd_ctl_new1(&snd_gf1_pcm_volume_control1, gus);
+       else
+               kctl = snd_ctl_new1(&snd_gf1_pcm_volume_control, gus);
++      if (!kctl)
++              return -ENOMEM;
+       kctl->id.index = control_index;
+       err = snd_ctl_add(card, kctl);
+       if (err < 0)
diff --git a/queue-6.12/alsa-ice1712-check-snd_ctl_new1-return-value.patch b/queue-6.12/alsa-ice1712-check-snd_ctl_new1-return-value.patch
new file mode 100644 (file)
index 0000000..c64783e
--- /dev/null
@@ -0,0 +1,98 @@
+From 2b929b91b0f3bc6de8a844370049cd99ee8e31ff Mon Sep 17 00:00:00 2001
+From: Zhao Dongdong <zhaodongdong@kylinos.cn>
+Date: Wed, 27 May 2026 20:09:11 +0800
+Subject: ALSA: ice1712: check snd_ctl_new1() return value
+
+From: Zhao Dongdong <zhaodongdong@kylinos.cn>
+
+commit 2b929b91b0f3bc6de8a844370049cd99ee8e31ff upstream.
+
+snd_ctl_new1() can return NULL when memory allocation fails. The
+ice1712 driver calls snd_ctl_new1() without checking the return value
+before dereferencing the pointer in multiple places (ice1712.c,
+ice1724.c, aureon.c), which can lead to NULL pointer dereferences.
+
+Add NULL checks after snd_ctl_new1() calls and return -ENOMEM if any
+fails.
+
+Assisted-by: Opencode:DeepSeek-V4-Flash
+Cc: stable@vger.kernel.org
+Fixes: b9a4efd61b6b ("ALSA: ice1712,ice1724: fix the kcontrol->id initialization")
+Signed-off-by: Zhao Dongdong <zhaodongdong@kylinos.cn>
+Link: https://patch.msgid.link/tencent_42E5E2AB1B6A5101F7EE8C2117F1F687BB07@qq.com
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ sound/pci/ice1712/aureon.c  |    2 ++
+ sound/pci/ice1712/ice1712.c |    8 ++++++++
+ sound/pci/ice1712/ice1724.c |    6 ++++++
+ 3 files changed, 16 insertions(+)
+
+--- a/sound/pci/ice1712/aureon.c
++++ b/sound/pci/ice1712/aureon.c
+@@ -1900,6 +1900,8 @@ static int aureon_add_controls(struct sn
+                       for (i = 0; i < ARRAY_SIZE(cs8415_controls); i++) {
+                               struct snd_kcontrol *kctl;
+                               kctl = snd_ctl_new1(&cs8415_controls[i], ice);
++                              if (!kctl)
++                                      return -ENOMEM;
+                               if (i > 1)
+                                       kctl->id.device = ice->pcm->device;
+                               err = snd_ctl_add(ice->card, kctl);
+--- a/sound/pci/ice1712/ice1712.c
++++ b/sound/pci/ice1712/ice1712.c
+@@ -2372,21 +2372,29 @@ int snd_ice1712_spdif_build_controls(str
+       if (snd_BUG_ON(!ice->pcm_pro))
+               return -EIO;
+       kctl = snd_ctl_new1(&snd_ice1712_spdif_default, ice);
++      if (!kctl)
++              return -ENOMEM;
+       kctl->id.device = ice->pcm_pro->device;
+       err = snd_ctl_add(ice->card, kctl);
+       if (err < 0)
+               return err;
+       kctl = snd_ctl_new1(&snd_ice1712_spdif_maskc, ice);
++      if (!kctl)
++              return -ENOMEM;
+       kctl->id.device = ice->pcm_pro->device;
+       err = snd_ctl_add(ice->card, kctl);
+       if (err < 0)
+               return err;
+       kctl = snd_ctl_new1(&snd_ice1712_spdif_maskp, ice);
++      if (!kctl)
++              return -ENOMEM;
+       kctl->id.device = ice->pcm_pro->device;
+       err = snd_ctl_add(ice->card, kctl);
+       if (err < 0)
+               return err;
+       kctl = snd_ctl_new1(&snd_ice1712_spdif_stream, ice);
++      if (!kctl)
++              return -ENOMEM;
+       kctl->id.device = ice->pcm_pro->device;
+       err = snd_ctl_add(ice->card, kctl);
+       if (err < 0)
+--- a/sound/pci/ice1712/ice1724.c
++++ b/sound/pci/ice1712/ice1724.c
+@@ -2393,16 +2393,22 @@ static int snd_vt1724_spdif_build_contro
+               return err;
+       kctl = snd_ctl_new1(&snd_vt1724_spdif_default, ice);
++      if (!kctl)
++              return -ENOMEM;
+       kctl->id.device = ice->pcm->device;
+       err = snd_ctl_add(ice->card, kctl);
+       if (err < 0)
+               return err;
+       kctl = snd_ctl_new1(&snd_vt1724_spdif_maskc, ice);
++      if (!kctl)
++              return -ENOMEM;
+       kctl->id.device = ice->pcm->device;
+       err = snd_ctl_add(ice->card, kctl);
+       if (err < 0)
+               return err;
+       kctl = snd_ctl_new1(&snd_vt1724_spdif_maskp, ice);
++      if (!kctl)
++              return -ENOMEM;
+       kctl->id.device = ice->pcm->device;
+       err = snd_ctl_add(ice->card, kctl);
+       if (err < 0)
diff --git a/queue-6.12/alsa-seq-fix-uninitialised-heap-leak-in-snd_seq_event_dup.patch b/queue-6.12/alsa-seq-fix-uninitialised-heap-leak-in-snd_seq_event_dup.patch
new file mode 100644 (file)
index 0000000..d0a8316
--- /dev/null
@@ -0,0 +1,55 @@
+From 435990e25bf1f4af3e6df12a6fbfd1f7ba4a97d4 Mon Sep 17 00:00:00 2001
+From: HyeongJun An <sammiee5311@gmail.com>
+Date: Wed, 24 Jun 2026 08:38:40 +0900
+Subject: ALSA: seq: Fix uninitialised heap leak in snd_seq_event_dup()
+
+From: HyeongJun An <sammiee5311@gmail.com>
+
+commit 435990e25bf1f4af3e6df12a6fbfd1f7ba4a97d4 upstream.
+
+snd_seq_event_dup() copies an incoming event into a pool cell and, in
+the UMP-enabled build, clears the trailing cell->ump.raw.extra word that
+the memcpy() did not cover.  The guard deciding whether to clear it
+compares the copied size against sizeof(cell->event):
+
+       memcpy(&cell->ump, event, size);
+       if (size < sizeof(cell->event))
+               cell->ump.raw.extra = 0;
+
+For a legacy (non-UMP) event, size == sizeof(struct snd_seq_event) ==
+sizeof(cell->event), so the condition is false and the extra word keeps
+stale data.  The cell pool is allocated with kvmalloc() (not zeroed) and
+cells are reused via a free list, so that word holds uninitialised heap
+or leftover event data.
+
+When such a cell is delivered to a UMP client (client->midi_version > 0)
+that set SNDRV_SEQ_FILTER_NO_CONVERT -- so the legacy event reaches it
+unconverted -- snd_seq_read() reads it out as the larger struct
+snd_seq_ump_event and copies the stale word to user space, a 4-byte
+kernel heap infoleak to an unprivileged /dev/snd/seq client.
+
+Compare against sizeof(cell->ump) instead, so the trailing word is zeroed
+for every event shorter than the UMP cell.
+
+Fixes: 46397622a3fa ("ALSA: seq: Add UMP support")
+Cc: stable@vger.kernel.org
+Assisted-by: Claude:claude-opus-4-8
+Signed-off-by: HyeongJun An <sammiee5311@gmail.com>
+Link: https://patch.msgid.link/20260623233841.853326-1-sammiee5311@gmail.com
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ sound/core/seq/seq_memory.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/sound/core/seq/seq_memory.c
++++ b/sound/core/seq/seq_memory.c
+@@ -364,7 +364,7 @@ int snd_seq_event_dup(struct snd_seq_poo
+       size = snd_seq_event_packet_size(event);
+       memcpy(&cell->ump, event, size);
+ #if IS_ENABLED(CONFIG_SND_SEQ_UMP)
+-      if (size < sizeof(cell->event))
++      if (size < sizeof(cell->ump))
+               cell->ump.raw.extra = 0;
+ #endif
diff --git a/queue-6.12/alsa-usb-audio-avoid-kobject-path-lookup-in-dualsense-match.patch b/queue-6.12/alsa-usb-audio-avoid-kobject-path-lookup-in-dualsense-match.patch
new file mode 100644 (file)
index 0000000..4674882
--- /dev/null
@@ -0,0 +1,106 @@
+From 7693c0cc415f3a16a7a3355f245474a5e661be4e Mon Sep 17 00:00:00 2001
+From: Darvell Long <contact@darvell.me>
+Date: Wed, 24 Jun 2026 07:37:23 -0700
+Subject: ALSA: usb-audio: avoid kobject path lookup in DualSense match
+
+From: Darvell Long <contact@darvell.me>
+
+commit 7693c0cc415f3a16a7a3355f245474a5e661be4e upstream.
+
+The DualSense jack-detection input handler verifies that a matching input
+device belongs to the same physical controller by building kobject path
+strings for both the input device and the USB audio device, then comparing
+the path prefix.
+
+This was observed when a weak physical connection caused the controller
+to rapidly disconnect and reconnect. During that repeated hotplug,
+snd_dualsense_ih_match() can run while the controller's USB device is
+being disconnected. kobject_get_path() walks ancestor kobjects and
+dereferences their names; if the USB device kobject name is no longer
+valid, this can fault in strlen():
+
+  RIP: 0010:strlen+0x10/0x30
+  Call Trace:
+   kobject_get_path+0x34/0x150
+   snd_dualsense_ih_match+0x49/0xd0 [snd_usb_audio]
+   input_register_device+0x566/0x6a0
+   ps_probe+0xb89/0x1590 [hid_playstation]
+
+The same ownership check can be done without building kobject path
+strings. The input device is parented below the HID device, USB interface
+and USB device, so walking the input device parent chain and comparing
+against the mixer USB device preserves the check without dereferencing
+kobject names during disconnect.
+
+Fixes: 79d561c4ec04 ("ALSA: usb-audio: Add mixer quirk for Sony DualSense PS5")
+Cc: <stable@vger.kernel.org>
+Assisted-by: Cute:gpt-5.5
+Signed-off-by: Darvell Long <contact@darvell.me>
+Link: https://patch.msgid.link/20260624143723.2986353-1-contact@darvell.me
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ sound/usb/mixer_quirks.c |   40 ++++++++++++----------------------------
+ 1 file changed, 12 insertions(+), 28 deletions(-)
+
+--- a/sound/usb/mixer_quirks.c
++++ b/sound/usb/mixer_quirks.c
+@@ -571,46 +571,30 @@ static bool snd_dualsense_ih_match(struc
+ {
+       struct dualsense_mixer_elem_info *mei;
+       struct usb_device *snd_dev;
+-      char *input_dev_path, *usb_dev_path;
+-      size_t usb_dev_path_len;
+-      bool match = false;
++      struct device *parent;
+       mei = container_of(handler, struct dualsense_mixer_elem_info, ih);
+       snd_dev = mei->info.head.mixer->chip->dev;
+-      input_dev_path = kobject_get_path(&dev->dev.kobj, GFP_KERNEL);
+-      if (!input_dev_path) {
+-              dev_warn(&snd_dev->dev, "Failed to get input dev path\n");
+-              return false;
+-      }
+-
+-      usb_dev_path = kobject_get_path(&snd_dev->dev.kobj, GFP_KERNEL);
+-      if (!usb_dev_path) {
+-              dev_warn(&snd_dev->dev, "Failed to get USB dev path\n");
+-              goto free_paths;
+-      }
+-
+       /*
+        * Ensure the VID:PID matched input device supposedly owned by the
+        * hid-playstation driver belongs to the actual hardware handled by
+-       * the current USB audio device, which implies input_dev_path being
+-       * a subpath of usb_dev_path.
++       * the current USB audio device.
+        *
+        * This verification is necessary when there is more than one identical
+        * controller attached to the host system.
++       *
++       * The input device is registered below the HID device, USB interface and
++       * USB device, so compare the parent chain directly instead of building
++       * kobject path strings. This avoids dereferencing kobject names while the
++       * USB device hierarchy is being torn down during disconnect.
+        */
+-      usb_dev_path_len = strlen(usb_dev_path);
+-      if (usb_dev_path_len >= strlen(input_dev_path))
+-              goto free_paths;
+-
+-      usb_dev_path[usb_dev_path_len] = '/';
+-      match = !memcmp(input_dev_path, usb_dev_path, usb_dev_path_len + 1);
+-
+-free_paths:
+-      kfree(input_dev_path);
+-      kfree(usb_dev_path);
++      for (parent = dev->dev.parent; parent; parent = parent->parent) {
++              if (parent == &snd_dev->dev)
++                      return true;
++      }
+-      return match;
++      return false;
+ }
+ static int snd_dualsense_ih_connect(struct input_handler *handler,
diff --git a/queue-6.12/alsa-usb-audio-propagate-errors-in-scarlett_ctl_enum_put.patch b/queue-6.12/alsa-usb-audio-propagate-errors-in-scarlett_ctl_enum_put.patch
new file mode 100644 (file)
index 0000000..776cbfe
--- /dev/null
@@ -0,0 +1,42 @@
+From 0f25cf1f02e3dba626791d949c759a48c0a44996 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?C=C3=A1ssio=20Gabriel?= <cassiogabrielcontato@gmail.com>
+Date: Sun, 19 Apr 2026 17:30:30 -0300
+Subject: ALSA: usb-audio: Propagate errors in scarlett_ctl_enum_put()
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Cássio Gabriel <cassiogabrielcontato@gmail.com>
+
+commit 0f25cf1f02e3dba626791d949c759a48c0a44996 upstream.
+
+scarlett_ctl_enum_put() ignores the return value from
+snd_usb_set_cur_mix_value() and reports success whenever the
+requested enum value differs from the current one.
+
+If the SET_CUR request fails, the callback still returns success even
+though neither the hardware state nor the cached mixer value changed.
+
+Fixes: 76b188c4b370 ("ALSA: usb-audio: Scarlett mixer interface for 6i6, 18i6, 18i8 and 18i20")
+Cc: stable@vger.kernel.org
+Signed-off-by: Cássio Gabriel <cassiogabrielcontato@gmail.com>
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Link: https://patch.msgid.link/20260419-usb-write-error-propagation-v1-2-5a3bd4a673ae@gmail.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ sound/usb/mixer_scarlett.c |    4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+--- a/sound/usb/mixer_scarlett.c
++++ b/sound/usb/mixer_scarlett.c
+@@ -438,7 +438,9 @@ static int scarlett_ctl_enum_put(struct
+       val = ucontrol->value.integer.value[0];
+       val = val + opt->start;
+       if (val != oval) {
+-              snd_usb_set_cur_mix_value(elem, 0, 0, val);
++              err = snd_usb_set_cur_mix_value(elem, 0, 0, val);
++              if (err < 0)
++                      return err;
+               return 1;
+       }
+       return 0;
diff --git a/queue-6.12/alsa-usb-audio-propagate-us-16x08-write-errors-in-route-mix-eq-switch-put-callbacks.patch b/queue-6.12/alsa-usb-audio-propagate-us-16x08-write-errors-in-route-mix-eq-switch-put-callbacks.patch
new file mode 100644 (file)
index 0000000..b06f1ca
--- /dev/null
@@ -0,0 +1,134 @@
+From 3c06aec8abda6ba068b58a8b7119cdb2a48456b1 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?C=C3=A1ssio=20Gabriel?= <cassiogabrielcontato@gmail.com>
+Date: Sun, 19 Apr 2026 17:30:31 -0300
+Subject: ALSA: usb-audio: Propagate US-16x08 write errors in route/mix EQ-switch put callbacks
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Cássio Gabriel <cassiogabrielcontato@gmail.com>
+
+commit 3c06aec8abda6ba068b58a8b7119cdb2a48456b1 upstream.
+
+Several US-16x08 mixer put callbacks log failed control URBs but
+still return success to userspace. That hides device write failures
+even though the requested value was not applied.
+
+Return the negative write error instead in the route, master, bus,
+channel, and EQ switch put callbacks.
+
+Fixes: d2bb390a2081 ("ALSA: usb-audio: Tascam US-16x08 DSP mixer quirk")
+Cc: stable@vger.kernel.org
+Signed-off-by: Cássio Gabriel <cassiogabrielcontato@gmail.com>
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Link: https://patch.msgid.link/20260419-usb-write-error-propagation-v1-3-5a3bd4a673ae@gmail.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ sound/usb/mixer_us16x08.c |   49 ++++++++++++++++++++++------------------------
+ 1 file changed, 24 insertions(+), 25 deletions(-)
+
+--- a/sound/usb/mixer_us16x08.c
++++ b/sound/usb/mixer_us16x08.c
+@@ -225,14 +225,14 @@ static int snd_us16x08_route_put(struct
+       err = snd_us16x08_send_urb(chip, buf, sizeof(route_msg));
+-      if (err > 0) {
+-              elem->cached |= 1 << index;
+-              elem->cache_val[index] = val;
+-      } else {
++      if (err < 0) {
+               usb_audio_dbg(chip, "Failed to set routing, err:%d\n", err);
++              return err;
+       }
+-      return err > 0 ? 1 : 0;
++      elem->cached |= 1 << index;
++      elem->cache_val[index] = val;
++      return 1;
+ }
+ static int snd_us16x08_master_info(struct snd_kcontrol *kcontrol,
+@@ -284,14 +284,14 @@ static int snd_us16x08_master_put(struct
+       buf[5] = index + 1;
+       err = snd_us16x08_send_urb(chip, buf, sizeof(mix_msg_out));
+-      if (err > 0) {
+-              elem->cached |= 1 << index;
+-              elem->cache_val[index] = val;
+-      } else {
++      if (err < 0) {
+               usb_audio_dbg(chip, "Failed to set master, err:%d\n", err);
++              return err;
+       }
+-      return err > 0 ? 1 : 0;
++      elem->cached |= 1 << index;
++      elem->cache_val[index] = val;
++      return 1;
+ }
+ static int snd_us16x08_bus_put(struct snd_kcontrol *kcontrol,
+@@ -325,14 +325,14 @@ static int snd_us16x08_bus_put(struct sn
+               break;
+       }
+-      if (err > 0) {
+-              elem->cached |= 1;
+-              elem->cache_val[0] = val;
+-      } else {
++      if (err < 0) {
+               usb_audio_dbg(chip, "Failed to set bus parameter, err:%d\n", err);
++              return err;
+       }
+-      return err > 0 ? 1 : 0;
++      elem->cached |= 1;
++      elem->cache_val[0] = val;
++      return 1;
+ }
+ static int snd_us16x08_bus_get(struct snd_kcontrol *kcontrol,
+@@ -393,14 +393,14 @@ static int snd_us16x08_channel_put(struc
+       err = snd_us16x08_send_urb(chip, buf, sizeof(mix_msg_in));
+-      if (err > 0) {
+-              elem->cached |= 1 << index;
+-              elem->cache_val[index] = val;
+-      } else {
++      if (err < 0) {
+               usb_audio_dbg(chip, "Failed to set channel, err:%d\n", err);
++              return err;
+       }
+-      return err > 0 ? 1 : 0;
++      elem->cached |= 1 << index;
++      elem->cache_val[index] = val;
++      return 1;
+ }
+ static int snd_us16x08_mix_info(struct snd_kcontrol *kcontrol,
+@@ -530,13 +530,13 @@ static int snd_us16x08_eqswitch_put(stru
+               msleep(15);
+       }
+-      if (err > 0) {
+-              elem->cached |= 1 << index;
+-              elem->cache_val[index] = val;
+-      } else {
++      if (err < 0) {
+               usb_audio_dbg(chip, "Failed to set eq switch, err:%d\n", err);
++              return err;
+       }
++      elem->cached |= 1 << index;
++      elem->cache_val[index] = val;
+       return 1;
+ }
+@@ -1419,4 +1419,3 @@ int snd_us16x08_controls_create(struct u
+       return 0;
+ }
+-
diff --git a/queue-6.12/alsa-usb-audio-roll-back-quirk-control-caches-on-write-errors.patch b/queue-6.12/alsa-usb-audio-roll-back-quirk-control-caches-on-write-errors.patch
new file mode 100644 (file)
index 0000000..ff3c90e
--- /dev/null
@@ -0,0 +1,165 @@
+From 6380957fa24251856a532e48a46a4dc3d1ae26b6 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?C=C3=A1ssio=20Gabriel?= <cassiogabrielcontato@gmail.com>
+Date: Wed, 29 Apr 2026 10:20:01 -0300
+Subject: ALSA: usb-audio: Roll back quirk control caches on write errors
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Cássio Gabriel <cassiogabrielcontato@gmail.com>
+
+commit 6380957fa24251856a532e48a46a4dc3d1ae26b6 upstream.
+
+Several mixer quirk callbacks cache the requested
+control value in kcontrol->private_value before
+issuing a single vendor or class write.
+
+Their paired get and resume paths consume that cache
+directly, so a failed write currently leaves software
+state changed even though the update did not succeed.
+That can make later reads report a value the device
+never accepted and can replay the stale cache on resume.
+
+Restore the previous cached value on failure in
+the Audigy2NX LED, Emu0204 channel switch,
+Xonar U1 output switch, Native Instruments controls,
+FTU effect program switch, and Sound Blaster E1 input source switch.
+
+Fixes: 9cf3689bfe07 ("ALSA: usb-audio: Add audigy2nx resume support")
+Fixes: 5f503ee9e270 ("ALSA: usb-audio: Add Emu0204 channel switch resume support")
+Fixes: 2bfb14c3b8fb ("ALSA: usb-audio: Add Xonar U1 resume support")
+Fixes: da6d276957ea ("ALSA: usb-audio: Add resume support for Native Instruments controls")
+Fixes: 0b4e9cfcef05 ("ALSA: usb-audio: Add resume support for FTU controls")
+Fixes: 388fdb8f882a ("ALSA: usb-audio: Support changing input on Sound Blaster E1")
+Cc: stable@vger.kernel.org
+Signed-off-by: Cássio Gabriel <cassiogabrielcontato@gmail.com>
+Link: https://patch.msgid.link/20260429-alsa-usb-quirks-cache-rollback-v1-1-01b35c688b80@gmail.com
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ sound/usb/mixer_quirks.c |   45 +++++++++++++++++++++++++++++++++++++--------
+ 1 file changed, 37 insertions(+), 8 deletions(-)
+
+--- a/sound/usb/mixer_quirks.c
++++ b/sound/usb/mixer_quirks.c
+@@ -333,6 +333,7 @@ static int snd_audigy2nx_led_put(struct
+       int index = kcontrol->private_value & 0xff;
+       unsigned int value = ucontrol->value.integer.value[0];
+       int old_value = kcontrol->private_value >> 8;
++      unsigned long old_pval = kcontrol->private_value;
+       int err;
+       if (value > 1)
+@@ -341,7 +342,11 @@ static int snd_audigy2nx_led_put(struct
+               return 0;
+       kcontrol->private_value = (value << 8) | index;
+       err = snd_audigy2nx_led_update(mixer, value, index);
+-      return err < 0 ? err : 1;
++      if (err < 0) {
++              kcontrol->private_value = old_pval;
++              return err;
++      }
++      return 1;
+ }
+ static int snd_audigy2nx_led_resume(struct usb_mixer_elem_list *list)
+@@ -491,6 +496,7 @@ static int snd_emu0204_ch_switch_put(str
+       struct usb_mixer_elem_list *list = snd_kcontrol_chip(kcontrol);
+       struct usb_mixer_interface *mixer = list->mixer;
+       unsigned int value = ucontrol->value.enumerated.item[0];
++      unsigned long old_pval = kcontrol->private_value;
+       int err;
+       if (value > 1)
+@@ -501,7 +507,11 @@ static int snd_emu0204_ch_switch_put(str
+       kcontrol->private_value = value;
+       err = snd_emu0204_ch_switch_update(mixer, value);
+-      return err < 0 ? err : 1;
++      if (err < 0) {
++              kcontrol->private_value = old_pval;
++              return err;
++      }
++      return 1;
+ }
+ static int snd_emu0204_ch_switch_resume(struct usb_mixer_elem_list *list)
+@@ -812,7 +822,11 @@ static int snd_xonar_u1_switch_put(struc
+       kcontrol->private_value = new_status;
+       err = snd_xonar_u1_switch_update(list->mixer, new_status);
+-      return err < 0 ? err : 1;
++      if (err < 0) {
++              kcontrol->private_value = old_status;
++              return err;
++      }
++      return 1;
+ }
+ static int snd_xonar_u1_switch_resume(struct usb_mixer_elem_list *list)
+@@ -1161,7 +1175,8 @@ static int snd_nativeinstruments_control
+                                            struct snd_ctl_elem_value *ucontrol)
+ {
+       struct usb_mixer_elem_list *list = snd_kcontrol_chip(kcontrol);
+-      u8 oldval = (kcontrol->private_value >> 24) & 0xff;
++      unsigned long old_pval = kcontrol->private_value;
++      u8 oldval = (old_pval >> 24) & 0xff;
+       u8 newval = ucontrol->value.integer.value[0];
+       int err;
+@@ -1171,7 +1186,11 @@ static int snd_nativeinstruments_control
+       kcontrol->private_value &= ~(0xff << 24);
+       kcontrol->private_value |= (unsigned int)newval << 24;
+       err = snd_ni_update_cur_val(list);
+-      return err < 0 ? err : 1;
++      if (err < 0) {
++              kcontrol->private_value = old_pval;
++              return err;
++      }
++      return 1;
+ }
+ static const struct snd_kcontrol_new snd_nativeinstruments_ta6_mixers[] = {
+@@ -1329,7 +1348,8 @@ static int snd_ftu_eff_switch_put(struct
+                                 struct snd_ctl_elem_value *ucontrol)
+ {
+       struct usb_mixer_elem_list *list = snd_kcontrol_chip(kctl);
+-      unsigned int pval = list->kctl->private_value;
++      unsigned long old_pval = list->kctl->private_value;
++      unsigned int pval = old_pval;
+       int cur_val, err, new_val;
+       cur_val = pval >> 24;
+@@ -1340,7 +1360,11 @@ static int snd_ftu_eff_switch_put(struct
+       kctl->private_value &= ~(0xff << 24);
+       kctl->private_value |= new_val << 24;
+       err = snd_ftu_eff_switch_update(list);
+-      return err < 0 ? err : 1;
++      if (err < 0) {
++              kctl->private_value = old_pval;
++              return err;
++      }
++      return 1;
+ }
+ static int snd_ftu_create_effect_switch(struct usb_mixer_interface *mixer,
+@@ -2138,13 +2162,18 @@ static int snd_soundblaster_e1_switch_pu
+ {
+       struct usb_mixer_elem_list *list = snd_kcontrol_chip(kcontrol);
+       unsigned char value = !!ucontrol->value.integer.value[0];
++      unsigned long old_pval = kcontrol->private_value;
+       int err;
+       if (kcontrol->private_value == value)
+               return 0;
+       kcontrol->private_value = value;
+       err = snd_soundblaster_e1_switch_update(list->mixer, value);
+-      return err < 0 ? err : 1;
++      if (err < 0) {
++              kcontrol->private_value = old_pval;
++              return err;
++      }
++      return 1;
+ }
+ static int snd_soundblaster_e1_switch_resume(struct usb_mixer_elem_list *list)
diff --git a/queue-6.12/alsa-usb-audio-update-babyface-pro-control-caches-only-after-successful-writes.patch b/queue-6.12/alsa-usb-audio-update-babyface-pro-control-caches-only-after-successful-writes.patch
new file mode 100644 (file)
index 0000000..4b492f1
--- /dev/null
@@ -0,0 +1,69 @@
+From d8f802ccf1fdbeb89d62748d6a0d0fbd442c8127 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?C=C3=A1ssio=20Gabriel?= <cassiogabrielcontato@gmail.com>
+Date: Wed, 29 Apr 2026 10:20:02 -0300
+Subject: ALSA: usb-audio: Update Babyface Pro control caches only after successful writes
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Cássio Gabriel <cassiogabrielcontato@gmail.com>
+
+commit d8f802ccf1fdbeb89d62748d6a0d0fbd442c8127 upstream.
+
+snd_bbfpro_ctl_put() and snd_bbfpro_vol_put()
+cache the requested packed control state in
+kcontrol->private_value before issuing the USB write.
+
+Their get and resume paths use that cached value directly,
+so a failed write can leave the driver reporting and later
+replaying a setting the hardware never accepted.
+
+Update the cached state only after a successful USB write.
+
+Fixes: 3e8f3bd04716 ("ALSA: usb-audio: RME Babyface Pro mixer patch")
+Cc: stable@vger.kernel.org
+Signed-off-by: Cássio Gabriel <cassiogabrielcontato@gmail.com>
+Link: https://patch.msgid.link/20260429-alsa-usb-quirks-cache-rollback-v1-2-01b35c688b80@gmail.com
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ sound/usb/mixer_quirks.c |   16 ++++++++++------
+ 1 file changed, 10 insertions(+), 6 deletions(-)
+
+--- a/sound/usb/mixer_quirks.c
++++ b/sound/usb/mixer_quirks.c
+@@ -2958,12 +2958,14 @@ static int snd_bbfpro_ctl_put(struct snd
+       if (val == old_value)
+               return 0;
++      err = snd_bbfpro_ctl_update(mixer, reg, idx, val);
++      if (err < 0)
++              return err;
++
+       kcontrol->private_value = reg
+               | ((idx & SND_BBFPRO_CTL_IDX_MASK) << SND_BBFPRO_CTL_IDX_SHIFT)
+               | ((val & SND_BBFPRO_CTL_VAL_MASK) << SND_BBFPRO_CTL_VAL_SHIFT);
+-
+-      err = snd_bbfpro_ctl_update(mixer, reg, idx, val);
+-      return err < 0 ? err : 1;
++      return 1;
+ }
+ static int snd_bbfpro_ctl_resume(struct usb_mixer_elem_list *list)
+@@ -3156,11 +3158,13 @@ static int snd_bbfpro_vol_put(struct snd
+       new_val = uvalue & SND_BBFPRO_MIXER_VAL_MASK;
++      err = snd_bbfpro_vol_update(mixer, idx, new_val);
++      if (err < 0)
++              return err;
++
+       kcontrol->private_value = idx
+               | (new_val << SND_BBFPRO_MIXER_VAL_SHIFT);
+-
+-      err = snd_bbfpro_vol_update(mixer, idx, new_val);
+-      return err < 0 ? err : 1;
++      return 1;
+ }
+ static int snd_bbfpro_vol_resume(struct usb_mixer_elem_list *list)
diff --git a/queue-6.12/alsa-usb-audio-update-us-16x08-eq-comp-shadow-state-after-successful-writes.patch b/queue-6.12/alsa-usb-audio-update-us-16x08-eq-comp-shadow-state-after-successful-writes.patch
new file mode 100644 (file)
index 0000000..c45791f
--- /dev/null
@@ -0,0 +1,156 @@
+From a440c17869ecd71da0f295b62868fc742d09a8ba Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?C=C3=A1ssio=20Gabriel?= <cassiogabrielcontato@gmail.com>
+Date: Sun, 19 Apr 2026 17:30:32 -0300
+Subject: ALSA: usb-audio: Update US-16x08 EQ/comp shadow state after successful writes
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Cássio Gabriel <cassiogabrielcontato@gmail.com>
+
+commit a440c17869ecd71da0f295b62868fc742d09a8ba upstream.
+
+snd_us16x08_comp_put() and snd_us16x08_eq_put() update their
+software stores before sending the USB write. If the transfer
+fails, later get callbacks report a value the hardware never
+accepted.
+
+Build the outgoing message from the current store plus the
+pending value, then commit the store only after a successful
+write.
+
+Fixes: d2bb390a2081 ("ALSA: usb-audio: Tascam US-16x08 DSP mixer quirk")
+Cc: stable@vger.kernel.org
+Signed-off-by: Cássio Gabriel <cassiogabrielcontato@gmail.com>
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Link: https://patch.msgid.link/20260419-usb-write-error-propagation-v1-4-5a3bd4a673ae@gmail.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ sound/usb/mixer_us16x08.c |   78 ++++++++++++++++++++++++++++++----------------
+ 1 file changed, 52 insertions(+), 26 deletions(-)
+
+--- a/sound/usb/mixer_us16x08.c
++++ b/sound/usb/mixer_us16x08.c
+@@ -436,6 +436,7 @@ static int snd_us16x08_comp_put(struct s
+       int index = ucontrol->id.index;
+       char buf[sizeof(comp_msg)];
+       int val_idx, val;
++      int threshold, ratio, attack, release, gain, switch_on;
+       int err;
+       val = ucontrol->value.integer.value[0];
+@@ -448,36 +449,61 @@ static int snd_us16x08_comp_put(struct s
+       /* new control value incl. bias*/
+       val_idx = elem->head.id - SND_US16X08_ID_COMP_BASE;
+-      store->val[val_idx][index] = ucontrol->value.integer.value[0];
++      threshold = store->val[COMP_STORE_IDX(SND_US16X08_ID_COMP_THRESHOLD)]
++              [index];
++      ratio = store->val[COMP_STORE_IDX(SND_US16X08_ID_COMP_RATIO)][index];
++      attack = store->val[COMP_STORE_IDX(SND_US16X08_ID_COMP_ATTACK)][index];
++      release = store->val[COMP_STORE_IDX(SND_US16X08_ID_COMP_RELEASE)]
++              [index];
++      gain = store->val[COMP_STORE_IDX(SND_US16X08_ID_COMP_GAIN)][index];
++      switch_on = store->val[COMP_STORE_IDX(SND_US16X08_ID_COMP_SWITCH)]
++              [index];
++
++      switch (val_idx) {
++      case COMP_STORE_IDX(SND_US16X08_ID_COMP_THRESHOLD):
++              threshold = val;
++              break;
++      case COMP_STORE_IDX(SND_US16X08_ID_COMP_RATIO):
++              ratio = val;
++              break;
++      case COMP_STORE_IDX(SND_US16X08_ID_COMP_ATTACK):
++              attack = val;
++              break;
++      case COMP_STORE_IDX(SND_US16X08_ID_COMP_RELEASE):
++              release = val;
++              break;
++      case COMP_STORE_IDX(SND_US16X08_ID_COMP_GAIN):
++              gain = val;
++              break;
++      case COMP_STORE_IDX(SND_US16X08_ID_COMP_SWITCH):
++              switch_on = val;
++              break;
++      }
+       /* prepare compressor URB message from template  */
+       memcpy(buf, comp_msg, sizeof(comp_msg));
+       /* place comp values in message buffer watch bias! */
+-      buf[8] = store->val[
+-              COMP_STORE_IDX(SND_US16X08_ID_COMP_THRESHOLD)][index]
+-              - SND_US16X08_COMP_THRESHOLD_BIAS;
+-      buf[11] = ratio_map[store->val[
+-              COMP_STORE_IDX(SND_US16X08_ID_COMP_RATIO)][index]];
+-      buf[14] = store->val[COMP_STORE_IDX(SND_US16X08_ID_COMP_ATTACK)][index]
+-              + SND_US16X08_COMP_ATTACK_BIAS;
+-      buf[17] = store->val[COMP_STORE_IDX(SND_US16X08_ID_COMP_RELEASE)][index]
+-              + SND_US16X08_COMP_RELEASE_BIAS;
+-      buf[20] = store->val[COMP_STORE_IDX(SND_US16X08_ID_COMP_GAIN)][index];
+-      buf[26] = store->val[COMP_STORE_IDX(SND_US16X08_ID_COMP_SWITCH)][index];
++      buf[8] = threshold - SND_US16X08_COMP_THRESHOLD_BIAS;
++      buf[11] = ratio_map[ratio];
++      buf[14] = attack + SND_US16X08_COMP_ATTACK_BIAS;
++      buf[17] = release + SND_US16X08_COMP_RELEASE_BIAS;
++      buf[20] = gain;
++      buf[26] = switch_on;
+       /* place channel selector in message buffer */
+       buf[5] = index + 1;
+       err = snd_us16x08_send_urb(chip, buf, sizeof(comp_msg));
+-      if (err > 0) {
+-              elem->cached |= 1 << index;
+-              elem->cache_val[index] = val;
+-      } else {
++      if (err < 0) {
+               usb_audio_dbg(chip, "Failed to set compressor, err:%d\n", err);
++              return err;
+       }
++      store->val[val_idx][index] = val;
++      elem->cached |= 1 << index;
++      elem->cache_val[index] = val;
+       return 1;
+ }
+@@ -579,11 +605,10 @@ static int snd_us16x08_eq_put(struct snd
+       /* copy URB buffer from EQ template */
+       memcpy(buf, eqs_msq, sizeof(eqs_msq));
+-      store->val[b_idx][p_idx][index] = val;
+-      buf[20] = store->val[b_idx][3][index];
+-      buf[17] = store->val[b_idx][2][index];
+-      buf[14] = store->val[b_idx][1][index];
+-      buf[11] = store->val[b_idx][0][index];
++      buf[20] = p_idx == 3 ? val : store->val[b_idx][3][index];
++      buf[17] = p_idx == 2 ? val : store->val[b_idx][2][index];
++      buf[14] = p_idx == 1 ? val : store->val[b_idx][1][index];
++      buf[11] = p_idx == 0 ? val : store->val[b_idx][0][index];
+       /* place channel index in URB buffer */
+       buf[5] = index + 1;
+@@ -593,14 +618,15 @@ static int snd_us16x08_eq_put(struct snd
+       err = snd_us16x08_send_urb(chip, buf, sizeof(eqs_msq));
+-      if (err > 0) {
+-              /* store new value in EQ band cache */
+-              elem->cached |= 1 << index;
+-              elem->cache_val[index] = val;
+-      } else {
++      if (err < 0) {
+               usb_audio_dbg(chip, "Failed to set eq param, err:%d\n", err);
++              return err;
+       }
++      store->val[b_idx][p_idx][index] = val;
++      /* store new value in EQ band cache */
++      elem->cached |= 1 << index;
++      elem->cache_val[index] = val;
+       return 1;
+ }
index 0ee01d131249e4ea3b8583a5e118fe3d07872c19..9a032afe4df70265e3c8254fb00969931e29267a 100644 (file)
@@ -71,3 +71,16 @@ iio-temperature-ltc2983-fix-reinit_completion-called-after-conversion-start.patc
 alsa-virtio-add-missing-384-khz-pcm-rate-mapping.patch
 alsa-virtio-validate-control-metadata-from-the-device.patch
 alsa-ymfpci-check-snd_ctl_new1-return-value.patch
+alsa-caiaq-fix-out-of-bounds-read-in-the-traktor-kontrol-s4-input-parser.patch
+alsa-cmipci-check-snd_ctl_new1-return-value.patch
+alsa-es1938-check-snd_ctl_new1-return-value.patch
+alsa-firewire-isight-bound-the-sample-count-to-the-packet-payload.patch
+alsa-gus-check-snd_ctl_new1-return-value.patch
+alsa-ice1712-check-snd_ctl_new1-return-value.patch
+alsa-seq-fix-uninitialised-heap-leak-in-snd_seq_event_dup.patch
+alsa-usb-audio-avoid-kobject-path-lookup-in-dualsense-match.patch
+alsa-usb-audio-propagate-errors-in-scarlett_ctl_enum_put.patch
+alsa-usb-audio-propagate-us-16x08-write-errors-in-route-mix-eq-switch-put-callbacks.patch
+alsa-usb-audio-roll-back-quirk-control-caches-on-write-errors.patch
+alsa-usb-audio-update-babyface-pro-control-caches-only-after-successful-writes.patch
+alsa-usb-audio-update-us-16x08-eq-comp-shadow-state-after-successful-writes.patch