--- /dev/null
+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) {
--- /dev/null
+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
+@@ -2688,16 +2688,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)
--- /dev/null
+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
+@@ -1690,6 +1690,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;
--- /dev/null
+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)
--- /dev/null
+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
+@@ -892,6 +892,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)
--- /dev/null
+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
+@@ -1904,6 +1904,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)
--- /dev/null
+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
+@@ -573,46 +573,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,
--- /dev/null
+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;
--- /dev/null
+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;
+ }
+-
--- /dev/null
+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
+@@ -335,6 +335,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)
+@@ -343,7 +344,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)
+@@ -493,6 +498,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)
+@@ -503,7 +509,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)
+@@ -814,7 +824,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)
+@@ -1163,7 +1177,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;
+
+@@ -1173,7 +1188,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[] = {
+@@ -1331,7 +1350,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;
+@@ -1342,7 +1362,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,
+@@ -2140,13 +2164,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)
--- /dev/null
+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
+@@ -2950,12 +2950,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)
+@@ -3040,11 +3042,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)
--- /dev/null
+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;
+ }
+
iio-temperature-ltc2983-fix-reinit_completion-called-after-conversion-start.patch
alsa-virtio-add-missing-384-khz-pcm-rate-mapping.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-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