]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
6.6-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 8 Jan 2026 10:40:45 +0000 (11:40 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 8 Jan 2026 10:40:45 +0000 (11:40 +0100)
added patches:
alsa-hda-cs35l41-fix-null-pointer-dereference-in-cs35l41_hda_read_acpi.patch
alsa-wavefront-clear-substream-pointers-on-close.patch
alsa-wavefront-fix-integer-overflow-in-sample-size-validation.patch
alsa-wavefront-use-guard-for-spin-locks.patch
alsa-wavefront-use-standard-print-api.patch
arm-dts-microchip-sama7g5-fix-uart-fifo-size-to-32.patch
btrfs-don-t-rewrite-ret-from-inode_permission.patch
drm-amd-display-fix-null-pointer-deref-in-dcn20_resource.c.patch
drm-amdgpu-forward-vmid-reservation-errors.patch
drm-mediatek-fix-probe-memory-leak.patch
drm-mediatek-fix-probe-resource-leaks.patch
drm-tilcdc-fix-removal-actions-in-case-of-failed-probe.patch
drm-tilcdc-request-and-mapp-iomem-with-devres.patch
ext4-fix-string-copying-in-parse_apply_sb_mount_options.patch
f2fs-fix-to-avoid-potential-deadlock.patch
f2fs-use-f2fs_err_ratelimited-to-avoid-redundant-logs.patch
fuse-fix-readahead-reclaim-deadlock.patch
gfs2-fix-freeze-error-handling.patch
gpiolib-acpi-add-quirk-for-dell-precision-7780.patch
jbd2-fix-the-inconsistency-between-checksum-and-data-in-memory-for-journal-sb.patch
lockd-fix-vfs_test_lock-calls.patch
loongarch-refactor-register-restoration-in-ftrace_common_return.patch
mm-consider-non-anon-swap-cache-folios-in-folio_expected_ref_count.patch
mm-ksm-fix-exec-fork-inheritance-support-for-prctl.patch
mm-simplify-folio_expected_ref_count.patch
mptcp-ensure-context-reset-on-disconnect.patch
mptcp-fallback-earlier-on-simult-connection.patch
mptcp-initialise-rcv_mss-before-calling-tcp_send_active_reset-in-mptcp_do_fastclose.patch
mptcp-pm-ignore-unknown-endpoint-flags.patch
net-phy-mediatek-fix-nvmem-cell-reference-leak-in-mt798x_phy_calibration.patch
net-remove-rtnl-dance-for-siocbraddif-and-siocbrdelif.patch
nfsd-clear-seclabel-in-the-suppattr_exclcreat-bitmap.patch
pci-brcmstb-fix-disabling-l0s-capability.patch
pmdomain-imx-fix-reference-count-leak-in-imx_gpc_probe.patch
pmdomain-use-device_get_match_data.patch
scsi-ufs-core-add-ufshcd_update_evt_hist-for-ufs-suspend-error.patch
svcrdma-bound-check-rq_pages-index-in-inline-path.patch
tty-introduce-and-use-tty_port_tty_vhangup-helper.patch
usb-ohci-nxp-fix-device-leak-on-probe-failure.patch
usb-ohci-nxp-use-helper-function-devm_clk_get_enabled.patch
usb-xhci-apply-the-link-chain-quirk-on-nec-isoc-endpoints.patch
usb-xhci-move-link-chain-bit-quirk-checks-into-one-helper-function.patch
wifi-mac80211-discard-beacon-frames-to-non-broadcast-address.patch
wifi-mt76-fix-dts-power-limits-on-little-endian-systems.patch
xhci-dbgtty-fix-device-unregister-fixup.patch

46 files changed:
queue-6.6/alsa-hda-cs35l41-fix-null-pointer-dereference-in-cs35l41_hda_read_acpi.patch [new file with mode: 0644]
queue-6.6/alsa-wavefront-clear-substream-pointers-on-close.patch [new file with mode: 0644]
queue-6.6/alsa-wavefront-fix-integer-overflow-in-sample-size-validation.patch [new file with mode: 0644]
queue-6.6/alsa-wavefront-use-guard-for-spin-locks.patch [new file with mode: 0644]
queue-6.6/alsa-wavefront-use-standard-print-api.patch [new file with mode: 0644]
queue-6.6/arm-dts-microchip-sama7g5-fix-uart-fifo-size-to-32.patch [new file with mode: 0644]
queue-6.6/btrfs-don-t-rewrite-ret-from-inode_permission.patch [new file with mode: 0644]
queue-6.6/drm-amd-display-fix-null-pointer-deref-in-dcn20_resource.c.patch [new file with mode: 0644]
queue-6.6/drm-amdgpu-forward-vmid-reservation-errors.patch [new file with mode: 0644]
queue-6.6/drm-mediatek-fix-probe-memory-leak.patch [new file with mode: 0644]
queue-6.6/drm-mediatek-fix-probe-resource-leaks.patch [new file with mode: 0644]
queue-6.6/drm-tilcdc-fix-removal-actions-in-case-of-failed-probe.patch [new file with mode: 0644]
queue-6.6/drm-tilcdc-request-and-mapp-iomem-with-devres.patch [new file with mode: 0644]
queue-6.6/ext4-fix-string-copying-in-parse_apply_sb_mount_options.patch [new file with mode: 0644]
queue-6.6/f2fs-fix-to-avoid-potential-deadlock.patch [new file with mode: 0644]
queue-6.6/f2fs-use-f2fs_err_ratelimited-to-avoid-redundant-logs.patch [new file with mode: 0644]
queue-6.6/fuse-fix-readahead-reclaim-deadlock.patch [new file with mode: 0644]
queue-6.6/gfs2-fix-freeze-error-handling.patch [new file with mode: 0644]
queue-6.6/gpiolib-acpi-add-quirk-for-dell-precision-7780.patch [new file with mode: 0644]
queue-6.6/jbd2-fix-the-inconsistency-between-checksum-and-data-in-memory-for-journal-sb.patch [new file with mode: 0644]
queue-6.6/lockd-fix-vfs_test_lock-calls.patch [new file with mode: 0644]
queue-6.6/loongarch-refactor-register-restoration-in-ftrace_common_return.patch [new file with mode: 0644]
queue-6.6/mm-consider-non-anon-swap-cache-folios-in-folio_expected_ref_count.patch [new file with mode: 0644]
queue-6.6/mm-ksm-fix-exec-fork-inheritance-support-for-prctl.patch [new file with mode: 0644]
queue-6.6/mm-simplify-folio_expected_ref_count.patch [new file with mode: 0644]
queue-6.6/mptcp-ensure-context-reset-on-disconnect.patch [new file with mode: 0644]
queue-6.6/mptcp-fallback-earlier-on-simult-connection.patch [new file with mode: 0644]
queue-6.6/mptcp-initialise-rcv_mss-before-calling-tcp_send_active_reset-in-mptcp_do_fastclose.patch [new file with mode: 0644]
queue-6.6/mptcp-pm-ignore-unknown-endpoint-flags.patch [new file with mode: 0644]
queue-6.6/net-phy-mediatek-fix-nvmem-cell-reference-leak-in-mt798x_phy_calibration.patch [new file with mode: 0644]
queue-6.6/net-remove-rtnl-dance-for-siocbraddif-and-siocbrdelif.patch [new file with mode: 0644]
queue-6.6/nfsd-clear-seclabel-in-the-suppattr_exclcreat-bitmap.patch [new file with mode: 0644]
queue-6.6/pci-brcmstb-fix-disabling-l0s-capability.patch [new file with mode: 0644]
queue-6.6/pmdomain-imx-fix-reference-count-leak-in-imx_gpc_probe.patch [new file with mode: 0644]
queue-6.6/pmdomain-use-device_get_match_data.patch [new file with mode: 0644]
queue-6.6/scsi-ufs-core-add-ufshcd_update_evt_hist-for-ufs-suspend-error.patch [new file with mode: 0644]
queue-6.6/series
queue-6.6/svcrdma-bound-check-rq_pages-index-in-inline-path.patch [new file with mode: 0644]
queue-6.6/tty-introduce-and-use-tty_port_tty_vhangup-helper.patch [new file with mode: 0644]
queue-6.6/usb-ohci-nxp-fix-device-leak-on-probe-failure.patch [new file with mode: 0644]
queue-6.6/usb-ohci-nxp-use-helper-function-devm_clk_get_enabled.patch [new file with mode: 0644]
queue-6.6/usb-xhci-apply-the-link-chain-quirk-on-nec-isoc-endpoints.patch [new file with mode: 0644]
queue-6.6/usb-xhci-move-link-chain-bit-quirk-checks-into-one-helper-function.patch [new file with mode: 0644]
queue-6.6/wifi-mac80211-discard-beacon-frames-to-non-broadcast-address.patch [new file with mode: 0644]
queue-6.6/wifi-mt76-fix-dts-power-limits-on-little-endian-systems.patch [new file with mode: 0644]
queue-6.6/xhci-dbgtty-fix-device-unregister-fixup.patch [new file with mode: 0644]

diff --git a/queue-6.6/alsa-hda-cs35l41-fix-null-pointer-dereference-in-cs35l41_hda_read_acpi.patch b/queue-6.6/alsa-hda-cs35l41-fix-null-pointer-dereference-in-cs35l41_hda_read_acpi.patch
new file mode 100644 (file)
index 0000000..cf40556
--- /dev/null
@@ -0,0 +1,42 @@
+From stable+bounces-201658-greg=kroah.com@vger.kernel.org Tue Dec 16 12:42:46 2025
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 16 Dec 2025 06:42:26 -0500
+Subject: ALSA: hda: cs35l41: Fix NULL pointer dereference in cs35l41_hda_read_acpi()
+To: stable@vger.kernel.org
+Cc: Denis Arefev <arefev@swemel.ru>, Richard Fitzgerald <rf@opensource.cirrus.com>, Takashi Iwai <tiwai@suse.de>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20251216114226.2766048-1-sashal@kernel.org>
+
+From: Denis Arefev <arefev@swemel.ru>
+
+[ Upstream commit c34b04cc6178f33c08331568c7fd25c5b9a39f66 ]
+
+The acpi_get_first_physical_node() function can return NULL, in which
+case the get_device() function also returns NULL, but this value is
+then dereferenced without checking,so add a check to prevent a crash.
+
+Found by Linux Verification Center (linuxtesting.org) with SVACE.
+
+Fixes: 7b2f3eb492da ("ALSA: hda: cs35l41: Add support for CS35L41 in HDA systems")
+Cc: stable@vger.kernel.org
+Signed-off-by: Denis Arefev <arefev@swemel.ru>
+Reviewed-by: Richard Fitzgerald <rf@opensource.cirrus.com>
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Link: https://patch.msgid.link/20251202101338.11437-1-arefev@swemel.ru
+[ NULL check right after acpi_dev_put(adev) cleanup call ]
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ sound/pci/hda/cs35l41_hda.c |    2 ++
+ 1 file changed, 2 insertions(+)
+
+--- a/sound/pci/hda/cs35l41_hda.c
++++ b/sound/pci/hda/cs35l41_hda.c
+@@ -1432,6 +1432,8 @@ static int cs35l41_hda_read_acpi(struct
+       physdev = get_device(acpi_get_first_physical_node(adev));
+       acpi_dev_put(adev);
++      if (!physdev)
++              return -ENODEV;
+       sub = acpi_get_subsystem_id(ACPI_HANDLE(physdev));
+       if (IS_ERR(sub))
diff --git a/queue-6.6/alsa-wavefront-clear-substream-pointers-on-close.patch b/queue-6.6/alsa-wavefront-clear-substream-pointers-on-close.patch
new file mode 100644 (file)
index 0000000..0c7adfe
--- /dev/null
@@ -0,0 +1,47 @@
+From stable+bounces-201184-greg=kroah.com@vger.kernel.org Tue Dec 16 12:13:26 2025
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 16 Dec 2025 06:06:30 -0500
+Subject: ALSA: wavefront: Clear substream pointers on close
+To: stable@vger.kernel.org
+Cc: Junrui Luo <moonafterrain@outlook.com>, Yuhao Jiang <danisjiang@gmail.com>, Takashi Iwai <tiwai@suse.de>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20251216110630.2754006-2-sashal@kernel.org>
+
+From: Junrui Luo <moonafterrain@outlook.com>
+
+[ Upstream commit e11c5c13ce0ab2325d38fe63500be1dd88b81e38 ]
+
+Clear substream pointers in close functions to avoid leaving dangling
+pointers, helping to improve code safety and
+prevents potential issues.
+
+Reported-by: Yuhao Jiang <danisjiang@gmail.com>
+Reported-by: Junrui Luo <moonafterrain@outlook.com>
+Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
+Cc: stable@vger.kernel.org
+Signed-off-by: Junrui Luo <moonafterrain@outlook.com>
+Link: https://patch.msgid.link/SYBPR01MB7881DF762CAB45EE42F6D812AFC2A@SYBPR01MB7881.ausprd01.prod.outlook.com
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ sound/isa/wavefront/wavefront_midi.c |    2 ++
+ 1 file changed, 2 insertions(+)
+
+--- a/sound/isa/wavefront/wavefront_midi.c
++++ b/sound/isa/wavefront/wavefront_midi.c
+@@ -278,6 +278,7 @@ static int snd_wavefront_midi_input_clos
+               return -EIO;
+       guard(spinlock_irqsave)(&midi->open);
++      midi->substream_input[mpu] = NULL;
+       midi->mode[mpu] &= ~MPU401_MODE_INPUT;
+       return 0;
+@@ -300,6 +301,7 @@ static int snd_wavefront_midi_output_clo
+               return -EIO;
+       guard(spinlock_irqsave)(&midi->open);
++      midi->substream_output[mpu] = NULL;
+       midi->mode[mpu] &= ~MPU401_MODE_OUTPUT;
+       return 0;
+ }
diff --git a/queue-6.6/alsa-wavefront-fix-integer-overflow-in-sample-size-validation.patch b/queue-6.6/alsa-wavefront-fix-integer-overflow-in-sample-size-validation.patch
new file mode 100644 (file)
index 0000000..17bc8c3
--- /dev/null
@@ -0,0 +1,43 @@
+From stable+bounces-201177-greg=kroah.com@vger.kernel.org Tue Dec 16 11:54:53 2025
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 16 Dec 2025 05:54:28 -0500
+Subject: ALSA: wavefront: Fix integer overflow in sample size validation
+To: stable@vger.kernel.org
+Cc: Junrui Luo <moonafterrain@outlook.com>, Takashi Iwai <tiwai@suse.de>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20251216105428.2749611-2-sashal@kernel.org>
+
+From: Junrui Luo <moonafterrain@outlook.com>
+
+[ Upstream commit 0c4a13ba88594fd4a27292853e736c6b4349823d ]
+
+The wavefront_send_sample() function has an integer overflow issue
+when validating sample size. The header->size field is u32 but gets
+cast to int for comparison with dev->freemem
+
+Fix by using unsigned comparison to avoid integer overflow.
+
+Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
+Cc: stable@vger.kernel.org
+Signed-off-by: Junrui Luo <moonafterrain@outlook.com>
+Link: https://patch.msgid.link/SYBPR01MB7881B47789D1B060CE8BF4C3AFC2A@SYBPR01MB7881.ausprd01.prod.outlook.com
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ sound/isa/wavefront/wavefront_synth.c |    4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+--- a/sound/isa/wavefront/wavefront_synth.c
++++ b/sound/isa/wavefront/wavefront_synth.c
+@@ -950,9 +950,9 @@ wavefront_send_sample (snd_wavefront_t *
+       if (header->size) {
+               dev->freemem = wavefront_freemem (dev);
+-              if (dev->freemem < (int)header->size) {
++              if (dev->freemem < 0 || dev->freemem < header->size) {
+                       dev_err(dev->card->dev,
+-                              "insufficient memory to load %d byte sample.\n",
++                              "insufficient memory to load %u byte sample.\n",
+                               header->size);
+                       return -ENOMEM;
+               }
diff --git a/queue-6.6/alsa-wavefront-use-guard-for-spin-locks.patch b/queue-6.6/alsa-wavefront-use-guard-for-spin-locks.patch
new file mode 100644 (file)
index 0000000..ce38bf0
--- /dev/null
@@ -0,0 +1,367 @@
+From stable+bounces-201183-greg=kroah.com@vger.kernel.org Tue Dec 16 12:14:04 2025
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 16 Dec 2025 06:06:29 -0500
+Subject: ALSA: wavefront: Use guard() for spin locks
+To: stable@vger.kernel.org
+Cc: Takashi Iwai <tiwai@suse.de>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20251216110630.2754006-1-sashal@kernel.org>
+
+From: Takashi Iwai <tiwai@suse.de>
+
+[ Upstream commit 4b97f8e614ba46a50bd181d40b5a1424411a211a ]
+
+Clean up the code using guard() for spin locks.
+
+Merely code refactoring, and no behavior change.
+
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Link: https://patch.msgid.link/20250829145300.5460-19-tiwai@suse.de
+Stable-dep-of: e11c5c13ce0a ("ALSA: wavefront: Clear substream pointers on close")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ sound/isa/wavefront/wavefront_midi.c  |  127 +++++++++++++---------------------
+ sound/isa/wavefront/wavefront_synth.c |   18 ++--
+ 2 files changed, 59 insertions(+), 86 deletions(-)
+
+--- a/sound/isa/wavefront/wavefront_midi.c
++++ b/sound/isa/wavefront/wavefront_midi.c
+@@ -113,7 +113,6 @@ static void snd_wavefront_midi_output_wr
+ {
+       snd_wavefront_midi_t *midi = &card->wavefront.midi;
+       snd_wavefront_mpu_id  mpu;
+-      unsigned long flags;
+       unsigned char midi_byte;
+       int max = 256, mask = 1;
+       int timeout;
+@@ -142,11 +141,9 @@ static void snd_wavefront_midi_output_wr
+                               break;
+               }
+       
+-              spin_lock_irqsave (&midi->virtual, flags);
+-              if ((midi->mode[midi->output_mpu] & MPU401_MODE_OUTPUT) == 0) {
+-                      spin_unlock_irqrestore (&midi->virtual, flags);
++              guard(spinlock_irqsave)(&midi->virtual);
++              if ((midi->mode[midi->output_mpu] & MPU401_MODE_OUTPUT) == 0)
+                       goto __second;
+-              }
+               if (output_ready (midi)) {
+                       if (snd_rawmidi_transmit(midi->substream_output[midi->output_mpu], &midi_byte, 1) == 1) {
+                               if (!midi->isvirtual ||
+@@ -160,14 +157,11 @@ static void snd_wavefront_midi_output_wr
+                                               del_timer(&midi->timer);
+                               }
+                               midi->mode[midi->output_mpu] &= ~MPU401_MODE_OUTPUT_TRIGGER;
+-                              spin_unlock_irqrestore (&midi->virtual, flags);
+                               goto __second;
+                       }
+               } else {
+-                      spin_unlock_irqrestore (&midi->virtual, flags);
+                       return;
+               }
+-              spin_unlock_irqrestore (&midi->virtual, flags);
+       }
+       __second:
+@@ -185,15 +179,13 @@ static void snd_wavefront_midi_output_wr
+                               break;
+               }
+       
+-              spin_lock_irqsave (&midi->virtual, flags);
++              guard(spinlock_irqsave)(&midi->virtual);
+               if (!midi->isvirtual)
+                       mask = 0;
+               mpu = midi->output_mpu ^ mask;
+               mask = 0;       /* don't invert the value from now */
+-              if ((midi->mode[mpu] & MPU401_MODE_OUTPUT) == 0) {
+-                      spin_unlock_irqrestore (&midi->virtual, flags);
++              if ((midi->mode[mpu] & MPU401_MODE_OUTPUT) == 0)
+                       return;
+-              }
+               if (snd_rawmidi_transmit_empty(midi->substream_output[mpu]))
+                       goto __timer;
+               if (output_ready (midi)) {
+@@ -215,20 +207,16 @@ static void snd_wavefront_midi_output_wr
+                                               del_timer(&midi->timer);
+                               }
+                               midi->mode[mpu] &= ~MPU401_MODE_OUTPUT_TRIGGER;
+-                              spin_unlock_irqrestore (&midi->virtual, flags);
+                               return;
+                       }
+               } else {
+-                      spin_unlock_irqrestore (&midi->virtual, flags);
+                       return;
+               }
+-              spin_unlock_irqrestore (&midi->virtual, flags);
+       }
+ }
+ static int snd_wavefront_midi_input_open(struct snd_rawmidi_substream *substream)
+ {
+-      unsigned long flags;
+       snd_wavefront_midi_t *midi;
+       snd_wavefront_mpu_id mpu;
+@@ -243,17 +231,15 @@ static int snd_wavefront_midi_input_open
+       if (!midi)
+               return -EIO;
+-      spin_lock_irqsave (&midi->open, flags);
++      guard(spinlock_irqsave)(&midi->open);
+       midi->mode[mpu] |= MPU401_MODE_INPUT;
+       midi->substream_input[mpu] = substream;
+-      spin_unlock_irqrestore (&midi->open, flags);
+       return 0;
+ }
+ static int snd_wavefront_midi_output_open(struct snd_rawmidi_substream *substream)
+ {
+-      unsigned long flags;
+       snd_wavefront_midi_t *midi;
+       snd_wavefront_mpu_id mpu;
+@@ -268,17 +254,15 @@ static int snd_wavefront_midi_output_ope
+       if (!midi)
+               return -EIO;
+-      spin_lock_irqsave (&midi->open, flags);
++      guard(spinlock_irqsave)(&midi->open);
+       midi->mode[mpu] |= MPU401_MODE_OUTPUT;
+       midi->substream_output[mpu] = substream;
+-      spin_unlock_irqrestore (&midi->open, flags);
+       return 0;
+ }
+ static int snd_wavefront_midi_input_close(struct snd_rawmidi_substream *substream)
+ {
+-      unsigned long flags;
+       snd_wavefront_midi_t *midi;
+       snd_wavefront_mpu_id mpu;
+@@ -293,16 +277,14 @@ static int snd_wavefront_midi_input_clos
+       if (!midi)
+               return -EIO;
+-      spin_lock_irqsave (&midi->open, flags);
++      guard(spinlock_irqsave)(&midi->open);
+       midi->mode[mpu] &= ~MPU401_MODE_INPUT;
+-      spin_unlock_irqrestore (&midi->open, flags);
+       return 0;
+ }
+ static int snd_wavefront_midi_output_close(struct snd_rawmidi_substream *substream)
+ {
+-      unsigned long flags;
+       snd_wavefront_midi_t *midi;
+       snd_wavefront_mpu_id mpu;
+@@ -317,15 +299,13 @@ static int snd_wavefront_midi_output_clo
+       if (!midi)
+               return -EIO;
+-      spin_lock_irqsave (&midi->open, flags);
++      guard(spinlock_irqsave)(&midi->open);
+       midi->mode[mpu] &= ~MPU401_MODE_OUTPUT;
+-      spin_unlock_irqrestore (&midi->open, flags);
+       return 0;
+ }
+ static void snd_wavefront_midi_input_trigger(struct snd_rawmidi_substream *substream, int up)
+ {
+-      unsigned long flags;
+       snd_wavefront_midi_t *midi;
+       snd_wavefront_mpu_id mpu;
+@@ -341,30 +321,27 @@ static void snd_wavefront_midi_input_tri
+       if (!midi)
+               return;
+-      spin_lock_irqsave (&midi->virtual, flags);
++      guard(spinlock_irqsave)(&midi->virtual);
+       if (up) {
+               midi->mode[mpu] |= MPU401_MODE_INPUT_TRIGGER;
+       } else {
+               midi->mode[mpu] &= ~MPU401_MODE_INPUT_TRIGGER;
+       }
+-      spin_unlock_irqrestore (&midi->virtual, flags);
+ }
+ static void snd_wavefront_midi_output_timer(struct timer_list *t)
+ {
+       snd_wavefront_midi_t *midi = from_timer(midi, t, timer);
+       snd_wavefront_card_t *card = midi->timer_card;
+-      unsigned long flags;
+       
+-      spin_lock_irqsave (&midi->virtual, flags);
+-      mod_timer(&midi->timer, 1 + jiffies);
+-      spin_unlock_irqrestore (&midi->virtual, flags);
++      scoped_guard(spinlock_irqsave, &midi->virtual) {
++              mod_timer(&midi->timer, 1 + jiffies);
++      }
+       snd_wavefront_midi_output_write(card);
+ }
+ static void snd_wavefront_midi_output_trigger(struct snd_rawmidi_substream *substream, int up)
+ {
+-      unsigned long flags;
+       snd_wavefront_midi_t *midi;
+       snd_wavefront_mpu_id mpu;
+@@ -380,22 +357,22 @@ static void snd_wavefront_midi_output_tr
+       if (!midi)
+               return;
+-      spin_lock_irqsave (&midi->virtual, flags);
+-      if (up) {
+-              if ((midi->mode[mpu] & MPU401_MODE_OUTPUT_TRIGGER) == 0) {
+-                      if (!midi->istimer) {
+-                              timer_setup(&midi->timer,
+-                                          snd_wavefront_midi_output_timer,
+-                                          0);
+-                              mod_timer(&midi->timer, 1 + jiffies);
++      scoped_guard(spinlock_irqsave, &midi->virtual) {
++              if (up) {
++                      if ((midi->mode[mpu] & MPU401_MODE_OUTPUT_TRIGGER) == 0) {
++                              if (!midi->istimer) {
++                                      timer_setup(&midi->timer,
++                                                  snd_wavefront_midi_output_timer,
++                                                  0);
++                                      mod_timer(&midi->timer, 1 + jiffies);
++                              }
++                              midi->istimer++;
++                              midi->mode[mpu] |= MPU401_MODE_OUTPUT_TRIGGER;
+                       }
+-                      midi->istimer++;
+-                      midi->mode[mpu] |= MPU401_MODE_OUTPUT_TRIGGER;
++              } else {
++                      midi->mode[mpu] &= ~MPU401_MODE_OUTPUT_TRIGGER;
+               }
+-      } else {
+-              midi->mode[mpu] &= ~MPU401_MODE_OUTPUT_TRIGGER;
+       }
+-      spin_unlock_irqrestore (&midi->virtual, flags);
+       if (up)
+               snd_wavefront_midi_output_write((snd_wavefront_card_t *)substream->rmidi->card->private_data);
+@@ -405,7 +382,6 @@ void
+ snd_wavefront_midi_interrupt (snd_wavefront_card_t *card)
+ {
+-      unsigned long flags;
+       snd_wavefront_midi_t *midi;
+       static struct snd_rawmidi_substream *substream = NULL;
+       static int mpu = external_mpu; 
+@@ -419,37 +395,37 @@ snd_wavefront_midi_interrupt (snd_wavefr
+               return;
+       }
+-      spin_lock_irqsave (&midi->virtual, flags);
+-      while (--max) {
++      scoped_guard(spinlock_irqsave, &midi->virtual) {
++              while (--max) {
+-              if (input_avail (midi)) {
+-                      byte = read_data (midi);
++                      if (input_avail(midi)) {
++                              byte = read_data(midi);
+-                      if (midi->isvirtual) {                          
+-                              if (byte == WF_EXTERNAL_SWITCH) {
+-                                      substream = midi->substream_input[external_mpu];
+-                                      mpu = external_mpu;
+-                              } else if (byte == WF_INTERNAL_SWITCH) { 
+-                                      substream = midi->substream_output[internal_mpu];
++                              if (midi->isvirtual) {
++                                      if (byte == WF_EXTERNAL_SWITCH) {
++                                              substream = midi->substream_input[external_mpu];
++                                              mpu = external_mpu;
++                                      } else if (byte == WF_INTERNAL_SWITCH) {
++                                              substream = midi->substream_output[internal_mpu];
++                                              mpu = internal_mpu;
++                                      } /* else just leave it as it is */
++                              } else {
++                                      substream = midi->substream_input[internal_mpu];
+                                       mpu = internal_mpu;
+-                              } /* else just leave it as it is */
+-                      } else {
+-                              substream = midi->substream_input[internal_mpu];
+-                              mpu = internal_mpu;
+-                      }
++                              }
+-                      if (substream == NULL) {
+-                              continue;
+-                      }
++                              if (substream == NULL) {
++                                      continue;
++                              }
+-                      if (midi->mode[mpu] & MPU401_MODE_INPUT_TRIGGER) {
+-                              snd_rawmidi_receive(substream, &byte, 1);
++                              if (midi->mode[mpu] & MPU401_MODE_INPUT_TRIGGER) {
++                                      snd_rawmidi_receive(substream, &byte, 1);
++                              }
++                      } else {
++                              break;
+                       }
+-              } else {
+-                      break;
+               }
+-      } 
+-      spin_unlock_irqrestore (&midi->virtual, flags);
++      }
+       snd_wavefront_midi_output_write(card);
+ }
+@@ -471,13 +447,10 @@ void
+ snd_wavefront_midi_disable_virtual (snd_wavefront_card_t *card)
+ {
+-      unsigned long flags;
+-
+-      spin_lock_irqsave (&card->wavefront.midi.virtual, flags);
++      guard(spinlock_irqsave)(&card->wavefront.midi.virtual);
+       // snd_wavefront_midi_input_close (card->ics2115_external_rmidi);
+       // snd_wavefront_midi_output_close (card->ics2115_external_rmidi);
+       card->wavefront.midi.isvirtual = 0;
+-      spin_unlock_irqrestore (&card->wavefront.midi.virtual, flags);
+ }
+ int
+--- a/sound/isa/wavefront/wavefront_synth.c
++++ b/sound/isa/wavefront/wavefront_synth.c
+@@ -1741,10 +1741,10 @@ snd_wavefront_internal_interrupt (snd_wa
+               return;
+       }
+-      spin_lock(&dev->irq_lock);
+-      dev->irq_ok = 1;
+-      dev->irq_cnt++;
+-      spin_unlock(&dev->irq_lock);
++      scoped_guard(spinlock, &dev->irq_lock) {
++              dev->irq_ok = 1;
++              dev->irq_cnt++;
++      }
+       wake_up(&dev->interrupt_sleeper);
+ }
+@@ -1796,11 +1796,11 @@ wavefront_should_cause_interrupt (snd_wa
+       wait_queue_entry_t wait;
+       init_waitqueue_entry(&wait, current);
+-      spin_lock_irq(&dev->irq_lock);
+-      add_wait_queue(&dev->interrupt_sleeper, &wait);
+-      dev->irq_ok = 0;
+-      outb (val,port);
+-      spin_unlock_irq(&dev->irq_lock);
++      scoped_guard(spinlock_irq, &dev->irq_lock) {
++              add_wait_queue(&dev->interrupt_sleeper, &wait);
++              dev->irq_ok = 0;
++              outb(val, port);
++      }
+       while (!dev->irq_ok && time_before(jiffies, timeout)) {
+               schedule_timeout_uninterruptible(1);
+               barrier();
diff --git a/queue-6.6/alsa-wavefront-use-standard-print-api.patch b/queue-6.6/alsa-wavefront-use-standard-print-api.patch
new file mode 100644 (file)
index 0000000..fc50d51
--- /dev/null
@@ -0,0 +1,1000 @@
+From stable+bounces-201176-greg=kroah.com@vger.kernel.org Tue Dec 16 11:55:12 2025
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 16 Dec 2025 05:54:27 -0500
+Subject: ALSA: wavefront: Use standard print API
+To: stable@vger.kernel.org
+Cc: Takashi Iwai <tiwai@suse.de>, Jaroslav Kysela <perex@perex.cz>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20251216105428.2749611-1-sashal@kernel.org>
+
+From: Takashi Iwai <tiwai@suse.de>
+
+[ Upstream commit 8b4ac5429938dd5f1fbf2eea0687f08cbcccb6be ]
+
+Use the standard print API with dev_*() instead of the old house-baked
+one.  It gives better information and allows dynamically control of
+debug prints.
+
+Reviewed-by: Jaroslav Kysela <perex@perex.cz>
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Link: https://patch.msgid.link/20240807133452.9424-36-tiwai@suse.de
+Stable-dep-of: 0c4a13ba8859 ("ALSA: wavefront: Fix integer overflow in sample size validation")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ include/sound/snd_wavefront.h         |    4 
+ sound/isa/wavefront/wavefront.c       |   61 +++++-----
+ sound/isa/wavefront/wavefront_fx.c    |   36 +++---
+ sound/isa/wavefront/wavefront_midi.c  |   15 +-
+ sound/isa/wavefront/wavefront_synth.c |  196 +++++++++++++++++-----------------
+ 5 files changed, 158 insertions(+), 154 deletions(-)
+
+--- a/include/sound/snd_wavefront.h
++++ b/include/sound/snd_wavefront.h
+@@ -137,8 +137,4 @@ extern int  snd_wavefront_fx_ioctl  (str
+ extern int snd_wavefront_fx_open    (struct snd_hwdep *, struct file *);
+ extern int snd_wavefront_fx_release (struct snd_hwdep *, struct file *);
+-/* prefix in all snd_printk() delivered messages */
+-
+-#define LOGNAME "WaveFront: "
+-
+ #endif  /* __SOUND_SND_WAVEFRONT_H__ */
+--- a/sound/isa/wavefront/wavefront.c
++++ b/sound/isa/wavefront/wavefront.c
+@@ -140,7 +140,7 @@ snd_wavefront_pnp (int dev, snd_wavefron
+       err = pnp_activate_dev(pdev);
+       if (err < 0) {
+-              snd_printk(KERN_ERR "PnP WSS pnp configure failure\n");
++              dev_err(&pdev->dev, "PnP WSS pnp configure failure\n");
+               return err;
+       }
+@@ -156,7 +156,7 @@ snd_wavefront_pnp (int dev, snd_wavefron
+       
+       err = pnp_activate_dev(pdev);
+       if (err < 0) {
+-              snd_printk(KERN_ERR "PnP ICS2115 pnp configure failure\n");
++              dev_err(&pdev->dev, "PnP ICS2115 pnp configure failure\n");
+               return err;
+       }
+@@ -174,26 +174,27 @@ snd_wavefront_pnp (int dev, snd_wavefron
+               err = pnp_activate_dev(pdev);
+               if (err < 0) {
+-                      snd_printk(KERN_ERR "PnP MPU401 pnp configure failure\n");
++                      dev_err(&pdev->dev, "PnP MPU401 pnp configure failure\n");
+                       cs4232_mpu_port[dev] = SNDRV_AUTO_PORT;
+               } else {
+                       cs4232_mpu_port[dev] = pnp_port_start(pdev, 0);
+                       cs4232_mpu_irq[dev] = pnp_irq(pdev, 0);
+               }
+-              snd_printk (KERN_INFO "CS4232 MPU: port=0x%lx, irq=%i\n", 
+-                          cs4232_mpu_port[dev], 
+-                          cs4232_mpu_irq[dev]);
++              dev_info(&pdev->dev, "CS4232 MPU: port=0x%lx, irq=%i\n",
++                       cs4232_mpu_port[dev],
++                       cs4232_mpu_irq[dev]);
+       }
+-      snd_printdd ("CS4232: pcm port=0x%lx, fm port=0x%lx, dma1=%i, dma2=%i, irq=%i\nICS2115: port=0x%lx, irq=%i\n", 
+-                  cs4232_pcm_port[dev], 
+-                  fm_port[dev],
+-                  dma1[dev], 
+-                  dma2[dev], 
+-                  cs4232_pcm_irq[dev],
+-                  ics2115_port[dev], 
+-                  ics2115_irq[dev]);
++      dev_dbg(&pdev->dev,
++              "CS4232: pcm port=0x%lx, fm port=0x%lx, dma1=%i, dma2=%i, irq=%i\nICS2115: port=0x%lx, irq=%i\n",
++              cs4232_pcm_port[dev],
++              fm_port[dev],
++              dma1[dev],
++              dma2[dev],
++              cs4232_pcm_irq[dev],
++              ics2115_port[dev],
++              ics2115_irq[dev]);
+       
+       return 0;
+ }
+@@ -251,7 +252,7 @@ static struct snd_hwdep *snd_wavefront_n
+       struct snd_hwdep *fx_processor;
+       if (snd_wavefront_fx_start (&acard->wavefront)) {
+-              snd_printk (KERN_ERR "cannot initialize YSS225 FX processor");
++              dev_err(card->dev, "cannot initialize YSS225 FX processor");
+               return NULL;
+       }
+@@ -282,7 +283,7 @@ static struct snd_rawmidi *snd_wavefront
+               first = 0;
+               acard->wavefront.midi.base = port;
+               if (snd_wavefront_midi_start (acard)) {
+-                      snd_printk (KERN_ERR "cannot initialize MIDI interface\n");
++                      dev_err(card->dev, "cannot initialize MIDI interface\n");
+                       return NULL;
+               }
+       }
+@@ -349,7 +350,7 @@ snd_wavefront_probe (struct snd_card *ca
+                            cs4232_pcm_irq[dev], dma1[dev], dma2[dev],
+                            WSS_HW_DETECT, 0, &chip);
+       if (err < 0) {
+-              snd_printk(KERN_ERR "can't allocate WSS device\n");
++              dev_err(card->dev, "can't allocate WSS device\n");
+               return err;
+       }
+@@ -369,7 +370,7 @@ snd_wavefront_probe (struct snd_card *ca
+               err = snd_opl3_create(card, fm_port[dev], fm_port[dev] + 2,
+                                     OPL3_HW_OPL3_CS, 0, &opl3);
+               if (err < 0) {
+-                      snd_printk (KERN_ERR "can't allocate or detect OPL3 synth\n");
++                      dev_err(card->dev, "can't allocate or detect OPL3 synth\n");
+                       return err;
+               }
+@@ -385,14 +386,14 @@ snd_wavefront_probe (struct snd_card *ca
+               devm_request_region(card->dev, ics2115_port[dev], 16,
+                                   "ICS2115");
+       if (acard->wavefront.res_base == NULL) {
+-              snd_printk(KERN_ERR "unable to grab ICS2115 i/o region 0x%lx-0x%lx\n",
+-                         ics2115_port[dev], ics2115_port[dev] + 16 - 1);
++              dev_err(card->dev, "unable to grab ICS2115 i/o region 0x%lx-0x%lx\n",
++                      ics2115_port[dev], ics2115_port[dev] + 16 - 1);
+               return -EBUSY;
+       }
+       if (devm_request_irq(card->dev, ics2115_irq[dev],
+                            snd_wavefront_ics2115_interrupt,
+                            0, "ICS2115", acard)) {
+-              snd_printk(KERN_ERR "unable to use ICS2115 IRQ %d\n", ics2115_irq[dev]);
++              dev_err(card->dev, "unable to use ICS2115 IRQ %d\n", ics2115_irq[dev]);
+               return -EBUSY;
+       }
+       
+@@ -402,7 +403,7 @@ snd_wavefront_probe (struct snd_card *ca
+       wavefront_synth = snd_wavefront_new_synth(card, hw_dev, acard);
+       if (wavefront_synth == NULL) {
+-              snd_printk (KERN_ERR "can't create WaveFront synth device\n");
++              dev_err(card->dev, "can't create WaveFront synth device\n");
+               return -ENOMEM;
+       }
+@@ -414,7 +415,7 @@ snd_wavefront_probe (struct snd_card *ca
+       err = snd_wss_mixer(chip);
+       if (err < 0) {
+-              snd_printk (KERN_ERR "can't allocate mixer device\n");
++              dev_err(card->dev, "can't allocate mixer device\n");
+               return err;
+       }
+@@ -425,7 +426,7 @@ snd_wavefront_probe (struct snd_card *ca
+                                         cs4232_mpu_port[dev], 0,
+                                         cs4232_mpu_irq[dev], NULL);
+               if (err < 0) {
+-                      snd_printk (KERN_ERR "can't allocate CS4232 MPU-401 device\n");
++                      dev_err(card->dev, "can't allocate CS4232 MPU-401 device\n");
+                       return err;
+               }
+               midi_dev++;
+@@ -441,7 +442,7 @@ snd_wavefront_probe (struct snd_card *ca
+                                               ics2115_port[dev],
+                                               internal_mpu);
+               if (ics2115_internal_rmidi == NULL) {
+-                      snd_printk (KERN_ERR "can't setup ICS2115 internal MIDI device\n");
++                      dev_err(card->dev, "can't setup ICS2115 internal MIDI device\n");
+                       return -ENOMEM;
+               }
+               midi_dev++;
+@@ -457,7 +458,7 @@ snd_wavefront_probe (struct snd_card *ca
+                                               ics2115_port[dev],
+                                               external_mpu);
+               if (ics2115_external_rmidi == NULL) {
+-                      snd_printk (KERN_ERR "can't setup ICS2115 external MIDI device\n");
++                      dev_err(card->dev, "can't setup ICS2115 external MIDI device\n");
+                       return -ENOMEM;
+               }
+               midi_dev++;
+@@ -471,7 +472,7 @@ snd_wavefront_probe (struct snd_card *ca
+                                                    acard,
+                                                    ics2115_port[dev]);
+               if (fx_processor == NULL) {
+-                      snd_printk (KERN_ERR "can't setup FX device\n");
++                      dev_err(card->dev, "can't setup FX device\n");
+                       return -ENOMEM;
+               }
+@@ -525,11 +526,11 @@ static int snd_wavefront_isa_match(struc
+               return 0;
+ #endif
+       if (cs4232_pcm_port[dev] == SNDRV_AUTO_PORT) {
+-              snd_printk(KERN_ERR "specify CS4232 port\n");
++              dev_err(pdev, "specify CS4232 port\n");
+               return 0;
+       }
+       if (ics2115_port[dev] == SNDRV_AUTO_PORT) {
+-              snd_printk(KERN_ERR "specify ICS2115 port\n");
++              dev_err(pdev, "specify ICS2115 port\n");
+               return 0;
+       }
+       return 1;
+@@ -585,7 +586,7 @@ static int snd_wavefront_pnp_detect(stru
+       if (snd_wavefront_pnp (dev, card->private_data, pcard, pid) < 0) {
+               if (cs4232_pcm_port[dev] == SNDRV_AUTO_PORT) {
+-                      snd_printk (KERN_ERR "isapnp detection failed\n");
++                      dev_err(card->dev, "isapnp detection failed\n");
+                       return -ENODEV;
+               }
+       }
+--- a/sound/isa/wavefront/wavefront_fx.c
++++ b/sound/isa/wavefront/wavefront_fx.c
+@@ -38,7 +38,7 @@ wavefront_fx_idle (snd_wavefront_t *dev)
+       }
+       if (x & 0x80) {
+-              snd_printk ("FX device never idle.\n");
++              dev_err(dev->card->dev, "FX device never idle.\n");
+               return 0;
+       }
+@@ -64,14 +64,14 @@ wavefront_fx_memset (snd_wavefront_t *de
+                    unsigned short *data)
+ {
+       if (page < 0 || page > 7) {
+-              snd_printk ("FX memset: "
+-                      "page must be >= 0 and <= 7\n");
++              dev_err(dev->card->dev,
++                      "FX memset: page must be >= 0 and <= 7\n");
+               return -EINVAL;
+       }
+       if (addr < 0 || addr > 0x7f) {
+-              snd_printk ("FX memset: "
+-                      "addr must be >= 0 and <= 7f\n");
++              dev_err(dev->card->dev,
++                      "FX memset: addr must be >= 0 and <= 7f\n");
+               return -EINVAL;
+       }
+@@ -83,7 +83,7 @@ wavefront_fx_memset (snd_wavefront_t *de
+               outb ((data[0] >> 8), dev->fx_dsp_msb);
+               outb ((data[0] & 0xff), dev->fx_dsp_lsb);
+-              snd_printk ("FX: addr %d:%x set to 0x%x\n",
++              dev_err(dev->card->dev, "FX: addr %d:%x set to 0x%x\n",
+                       page, addr, data[0]);
+       } else {
+@@ -102,9 +102,9 @@ wavefront_fx_memset (snd_wavefront_t *de
+               }
+               if (i != cnt) {
+-                      snd_printk ("FX memset "
+-                                  "(0x%x, 0x%x, 0x%lx, %d) incomplete\n",
+-                                  page, addr, (unsigned long) data, cnt);
++                      dev_err(dev->card->dev,
++                              "FX memset (0x%x, 0x%x, 0x%lx, %d) incomplete\n",
++                              page, addr, (unsigned long) data, cnt);
+                       return -EIO;
+               }
+       }
+@@ -123,7 +123,7 @@ snd_wavefront_fx_detect (snd_wavefront_t
+       */
+       if (inb (dev->fx_status) & 0x80) {
+-              snd_printk ("Hmm, probably a Maui or Tropez.\n");
++              dev_err(dev->card->dev, "Hmm, probably a Maui or Tropez.\n");
+               return -1;
+       }
+@@ -180,15 +180,15 @@ snd_wavefront_fx_ioctl (struct snd_hwdep
+       case WFFX_MEMSET:
+               if (r.data[2] <= 0) {
+-                      snd_printk ("cannot write "
+-                              "<= 0 bytes to FX\n");
++                      dev_err(dev->card->dev,
++                              "cannot write <= 0 bytes to FX\n");
+                       return -EIO;
+               } else if (r.data[2] == 1) {
+                       pd = (unsigned short *) &r.data[3];
+               } else {
+                       if (r.data[2] > 256) {
+-                              snd_printk ("cannot write "
+-                                          "> 512 bytes to FX\n");
++                              dev_err(dev->card->dev,
++                                      "cannot write > 512 bytes to FX\n");
+                               return -EIO;
+                       }
+                       page_data = memdup_user((unsigned char __user *)
+@@ -208,8 +208,8 @@ snd_wavefront_fx_ioctl (struct snd_hwdep
+               break;
+       default:
+-              snd_printk ("FX: ioctl %d not yet supported\n",
+-                          r.request);
++              dev_err(dev->card->dev, "FX: ioctl %d not yet supported\n",
++                      r.request);
+               return -ENOTTY;
+       }
+       return err;
+@@ -254,8 +254,8 @@ snd_wavefront_fx_start (snd_wavefront_t
+                               goto out;
+                       }
+               } else {
+-                      snd_printk(KERN_ERR "invalid address"
+-                                 " in register data\n");
++                      dev_err(dev->card->dev,
++                              "invalid address in register data\n");
+                       err = -1;
+                       goto out;
+               }
+--- a/sound/isa/wavefront/wavefront_midi.c
++++ b/sound/isa/wavefront/wavefront_midi.c
+@@ -501,7 +501,8 @@ snd_wavefront_midi_start (snd_wavefront_
+       for (i = 0; i < 30000 && !output_ready (midi); i++);
+       if (!output_ready (midi)) {
+-              snd_printk ("MIDI interface not ready for command\n");
++              dev_err(card->wavefront.card->dev,
++                      "MIDI interface not ready for command\n");
+               return -1;
+       }
+@@ -523,7 +524,8 @@ snd_wavefront_midi_start (snd_wavefront_
+       }
+       if (!ok) {
+-              snd_printk ("cannot set UART mode for MIDI interface");
++              dev_err(card->wavefront.card->dev,
++                      "cannot set UART mode for MIDI interface");
+               dev->interrupts_are_midi = 0;
+               return -1;
+       }
+@@ -531,7 +533,8 @@ snd_wavefront_midi_start (snd_wavefront_
+       /* Route external MIDI to WaveFront synth (by default) */
+     
+       if (snd_wavefront_cmd (dev, WFC_MISYNTH_ON, rbuf, wbuf)) {
+-              snd_printk ("can't enable MIDI-IN-2-synth routing.\n");
++              dev_warn(card->wavefront.card->dev,
++                       "can't enable MIDI-IN-2-synth routing.\n");
+               /* XXX error ? */
+       }
+@@ -547,14 +550,16 @@ snd_wavefront_midi_start (snd_wavefront_
+       */
+       if (snd_wavefront_cmd (dev, WFC_VMIDI_OFF, rbuf, wbuf)) { 
+-              snd_printk ("virtual MIDI mode not disabled\n");
++              dev_warn(card->wavefront.card->dev,
++                       "virtual MIDI mode not disabled\n");
+               return 0; /* We're OK, but missing the external MIDI dev */
+       }
+       snd_wavefront_midi_enable_virtual (card);
+       if (snd_wavefront_cmd (dev, WFC_VMIDI_ON, rbuf, wbuf)) {
+-              snd_printk ("cannot enable virtual MIDI mode.\n");
++              dev_warn(card->wavefront.card->dev,
++                       "cannot enable virtual MIDI mode.\n");
+               snd_wavefront_midi_disable_virtual (card);
+       } 
+       return 0;
+--- a/sound/isa/wavefront/wavefront_synth.c
++++ b/sound/isa/wavefront/wavefront_synth.c
+@@ -116,7 +116,7 @@ MODULE_PARM_DESC(osrun_time, "how many s
+ #define DPRINT(cond, ...) \
+        if ((dev->debug & (cond)) == (cond)) { \
+-           snd_printk (__VA_ARGS__); \
++           pr_debug(__VA_ARGS__); \
+        }
+ #else
+ #define DPRINT(cond, args...)
+@@ -341,7 +341,7 @@ snd_wavefront_cmd (snd_wavefront_t *dev,
+       wfcmd = wavefront_get_command(cmd);
+       if (!wfcmd) {
+-              snd_printk ("command 0x%x not supported.\n",
++              dev_err(dev->card->dev, "command 0x%x not supported.\n",
+                       cmd);
+               return 1;
+       }
+@@ -623,7 +623,7 @@ wavefront_get_sample_status (snd_wavefro
+       /* check sample status */
+     
+       if (snd_wavefront_cmd (dev, WFC_GET_NSAMPLES, rbuf, wbuf)) {
+-              snd_printk ("cannot request sample count.\n");
++              dev_err(dev->card->dev, "cannot request sample count.\n");
+               return -1;
+       } 
+     
+@@ -635,8 +635,8 @@ wavefront_get_sample_status (snd_wavefro
+               wbuf[1] = i >> 7;
+               if (snd_wavefront_cmd (dev, WFC_IDENTIFY_SAMPLE_TYPE, rbuf, wbuf)) {
+-                      snd_printk(KERN_WARNING "cannot identify sample "
+-                                 "type of slot %d\n", i);
++                      dev_warn(dev->card->dev,
++                               "cannot identify sample type of slot %d\n", i);
+                       dev->sample_status[i] = WF_ST_EMPTY;
+                       continue;
+               }
+@@ -661,9 +661,9 @@ wavefront_get_sample_status (snd_wavefro
+                       break;
+               default:
+-                      snd_printk ("unknown sample type for "
+-                                  "slot %d (0x%x)\n", 
+-                                  i, rbuf[0]);
++                      dev_err(dev->card->dev,
++                              "unknown sample type for slot %d (0x%x)\n",
++                              i, rbuf[0]);
+               }
+               if (rbuf[0] != WF_ST_EMPTY) {
+@@ -671,9 +671,10 @@ wavefront_get_sample_status (snd_wavefro
+               } 
+       }
+-      snd_printk ("%d samples used (%d real, %d aliases, %d multi), "
+-                  "%d empty\n", dev->samples_used, sc_real, sc_alias, sc_multi,
+-                  WF_MAX_SAMPLE - dev->samples_used);
++      dev_info(dev->card->dev,
++               "%d samples used (%d real, %d aliases, %d multi), %d empty\n",
++               dev->samples_used, sc_real, sc_alias, sc_multi,
++               WF_MAX_SAMPLE - dev->samples_used);
+       return (0);
+@@ -706,8 +707,8 @@ wavefront_get_patch_status (snd_wavefron
+               } else if (x == 3) { /* Bad patch number */
+                       dev->patch_status[i] = 0;
+               } else {
+-                      snd_printk ("upload patch "
+-                                  "error 0x%x\n", x);
++                      dev_err(dev->card->dev,
++                              "upload patch error 0x%x\n", x);
+                       dev->patch_status[i] = 0;
+                       return 1;
+               }
+@@ -724,7 +725,8 @@ wavefront_get_patch_status (snd_wavefron
+               }
+       
+       }
+-      snd_printk ("%d patch slots filled, %d in use\n", cnt, cnt2);
++      dev_info(dev->card->dev, "%d patch slots filled, %d in use\n",
++               cnt, cnt2);
+       return (0);
+ }
+@@ -760,8 +762,8 @@ wavefront_get_program_status (snd_wavefr
+               } else if (x == 1) { /* Bad program number */
+                       dev->prog_status[i] = 0;
+               } else {
+-                      snd_printk ("upload program "
+-                                  "error 0x%x\n", x);
++                      dev_err(dev->card->dev,
++                              "upload program error 0x%x\n", x);
+                       dev->prog_status[i] = 0;
+               }
+       }
+@@ -772,7 +774,7 @@ wavefront_get_program_status (snd_wavefr
+               }
+       }
+-      snd_printk ("%d programs slots in use\n", cnt);
++      dev_info(dev->card->dev, "%d programs slots in use\n", cnt);
+       return (0);
+ }
+@@ -796,7 +798,7 @@ wavefront_send_patch (snd_wavefront_t *d
+       munge_buf ((unsigned char *)&header->hdr.p, bptr, WF_PATCH_BYTES);
+     
+       if (snd_wavefront_cmd (dev, WFC_DOWNLOAD_PATCH, NULL, buf)) {
+-              snd_printk ("download patch failed\n");
++              dev_err(dev->card->dev, "download patch failed\n");
+               return -EIO;
+       }
+@@ -837,7 +839,7 @@ wavefront_send_program (snd_wavefront_t
+       munge_buf ((unsigned char *)&header->hdr.pr, &buf[1], WF_PROGRAM_BYTES);
+     
+       if (snd_wavefront_cmd (dev, WFC_DOWNLOAD_PROGRAM, NULL, buf)) {
+-              snd_printk ("download patch failed\n"); 
++              dev_err(dev->card->dev, "download patch failed\n");
+               return -EIO;
+       }
+@@ -851,7 +853,7 @@ wavefront_freemem (snd_wavefront_t *dev)
+       char rbuf[8];
+       if (snd_wavefront_cmd (dev, WFC_REPORT_FREE_MEMORY, rbuf, NULL)) {
+-              snd_printk ("can't get memory stats.\n");
++              dev_err(dev->card->dev, "can't get memory stats.\n");
+               return -1;
+       } else {
+               return demunge_int32 (rbuf, 4);
+@@ -901,7 +903,7 @@ wavefront_send_sample (snd_wavefront_t *
+               x = wavefront_find_free_sample(dev);
+               if (x < 0)
+                       return -ENOMEM;
+-              snd_printk ("unspecified sample => %d\n", x);
++              dev_info(dev->card->dev, "unspecified sample => %d\n", x);
+               header->number = x;
+       }
+@@ -935,9 +937,9 @@ wavefront_send_sample (snd_wavefront_t *
+               if (dev->rom_samples_rdonly) {
+                       if (dev->sample_status[header->number] & WF_SLOT_ROM) {
+-                              snd_printk ("sample slot %d "
+-                                          "write protected\n",
+-                                          header->number);
++                              dev_err(dev->card->dev,
++                                      "sample slot %d write protected\n",
++                                      header->number);
+                               return -EACCES;
+                       }
+               }
+@@ -949,9 +951,9 @@ wavefront_send_sample (snd_wavefront_t *
+               dev->freemem = wavefront_freemem (dev);
+               if (dev->freemem < (int)header->size) {
+-                      snd_printk ("insufficient memory to "
+-                                  "load %d byte sample.\n",
+-                                  header->size);
++                      dev_err(dev->card->dev,
++                              "insufficient memory to load %d byte sample.\n",
++                              header->size);
+                       return -ENOMEM;
+               }
+       
+@@ -960,8 +962,8 @@ wavefront_send_sample (snd_wavefront_t *
+       skip = WF_GET_CHANNEL(&header->hdr.s);
+       if (skip > 0 && header->hdr.s.SampleResolution != LINEAR_16BIT) {
+-              snd_printk ("channel selection only "
+-                          "possible on 16-bit samples");
++              dev_err(dev->card->dev,
++                      "channel selection only possible on 16-bit samples");
+               return -EINVAL;
+       }
+@@ -1057,8 +1059,8 @@ wavefront_send_sample (snd_wavefront_t *
+                          header->size ?
+                          WFC_DOWNLOAD_SAMPLE : WFC_DOWNLOAD_SAMPLE_HEADER,
+                          NULL, sample_hdr)) {
+-              snd_printk ("sample %sdownload refused.\n",
+-                          header->size ? "" : "header ");
++              dev_err(dev->card->dev, "sample %sdownload refused.\n",
++                      header->size ? "" : "header ");
+               return -EIO;
+       }
+@@ -1083,8 +1085,8 @@ wavefront_send_sample (snd_wavefront_t *
+               }
+               if (snd_wavefront_cmd (dev, WFC_DOWNLOAD_BLOCK, NULL, NULL)) {
+-                      snd_printk ("download block "
+-                                  "request refused.\n");
++                      dev_err(dev->card->dev,
++                              "download block request refused.\n");
+                       return -EIO;
+               }
+@@ -1145,13 +1147,13 @@ wavefront_send_sample (snd_wavefront_t *
+               dma_ack = wavefront_read(dev);
+               if (dma_ack != WF_DMA_ACK) {
+                       if (dma_ack == -1) {
+-                              snd_printk ("upload sample "
+-                                          "DMA ack timeout\n");
++                              dev_err(dev->card->dev,
++                                      "upload sample DMA ack timeout\n");
+                               return -EIO;
+                       } else {
+-                              snd_printk ("upload sample "
+-                                          "DMA ack error 0x%x\n",
+-                                          dma_ack);
++                              dev_err(dev->card->dev,
++                                      "upload sample DMA ack error 0x%x\n",
++                                      dma_ack);
+                               return -EIO;
+                       }
+               }
+@@ -1195,7 +1197,7 @@ wavefront_send_alias (snd_wavefront_t *d
+       munge_int32 (*(&header->hdr.a.FrequencyBias+1), &alias_hdr[23], 2);
+       if (snd_wavefront_cmd (dev, WFC_DOWNLOAD_SAMPLE_ALIAS, NULL, alias_hdr)) {
+-              snd_printk ("download alias failed.\n");
++              dev_err(dev->card->dev, "download alias failed.\n");
+               return -EIO;
+       }
+@@ -1248,7 +1250,7 @@ wavefront_send_multisample (snd_wavefron
+       if (snd_wavefront_cmd (dev, WFC_DOWNLOAD_MULTISAMPLE, 
+                          (unsigned char *) (long) ((num_samples*2)+3),
+                          msample_hdr)) {
+-              snd_printk ("download of multisample failed.\n");
++              dev_err(dev->card->dev, "download of multisample failed.\n");
+               kfree(msample_hdr);
+               return -EIO;
+       }
+@@ -1271,7 +1273,7 @@ wavefront_fetch_multisample (snd_wavefro
+       munge_int32 (header->number, number, 2);
+     
+       if (snd_wavefront_cmd (dev, WFC_UPLOAD_MULTISAMPLE, log_ns, number)) {
+-              snd_printk ("upload multisample failed.\n");
++              dev_err(dev->card->dev, "upload multisample failed.\n");
+               return -EIO;
+       }
+     
+@@ -1290,16 +1292,16 @@ wavefront_fetch_multisample (snd_wavefro
+       
+               val = wavefront_read(dev);
+               if (val == -1) {
+-                      snd_printk ("upload multisample failed "
+-                                  "during sample loop.\n");
++                      dev_err(dev->card->dev,
++                              "upload multisample failed during sample loop.\n");
+                       return -EIO;
+               }
+               d[0] = val;
+               val = wavefront_read(dev);
+               if (val == -1) {
+-                      snd_printk ("upload multisample failed "
+-                                  "during sample loop.\n");
++                      dev_err(dev->card->dev,
++                              "upload multisample failed during sample loop.\n");
+                       return -EIO;
+               }
+               d[1] = val;
+@@ -1334,7 +1336,7 @@ wavefront_send_drum (snd_wavefront_t *de
+       }
+       if (snd_wavefront_cmd (dev, WFC_DOWNLOAD_EDRUM_PROGRAM, NULL, drumbuf)) {
+-              snd_printk ("download drum failed.\n");
++              dev_err(dev->card->dev, "download drum failed.\n");
+               return -EIO;
+       }
+@@ -1352,7 +1354,7 @@ wavefront_find_free_sample (snd_wavefron
+                       return i;
+               }
+       }
+-      snd_printk ("no free sample slots!\n");
++      dev_err(dev->card->dev, "no free sample slots!\n");
+       return -1;
+ }
+@@ -1368,7 +1370,7 @@ wavefront_find_free_patch (snd_wavefront
+                       return i;
+               }
+       }
+-      snd_printk ("no free patch slots!\n");
++      dev_err(dev->card->dev, "no free patch slots!\n");
+       return -1;
+ }
+ #endif
+@@ -1385,7 +1387,7 @@ wavefront_load_patch (snd_wavefront_t *d
+       if (copy_from_user (header, addr, sizeof(wavefront_patch_info) -
+                           sizeof(wavefront_any))) {
+-              snd_printk ("bad address for load patch.\n");
++              dev_err(dev->card->dev, "bad address for load patch.\n");
+               err = -EFAULT;
+               goto __error;
+       }
+@@ -1463,8 +1465,8 @@ wavefront_load_patch (snd_wavefront_t *d
+               break;
+       default:
+-              snd_printk ("unknown patch type %d.\n",
+-                          header->subkey);
++              dev_err(dev->card->dev, "unknown patch type %d.\n",
++                      header->subkey);
+               err = -EINVAL;
+               break;
+       }
+@@ -1527,13 +1529,13 @@ wavefront_synth_control (snd_wavefront_c
+       switch (wc->cmd) {
+               
+       case WFC_DISABLE_INTERRUPTS:
+-              snd_printk ("interrupts disabled.\n");
++              dev_dbg(dev->card->dev, "interrupts disabled.\n");
+               outb (0x80|0x20, dev->control_port);
+               dev->interrupts_are_midi = 1;
+               return 0;
+       case WFC_ENABLE_INTERRUPTS:
+-              snd_printk ("interrupts enabled.\n");
++              dev_dbg(dev->card->dev, "interrupts enabled.\n");
+               outb (0x80|0x40|0x20, dev->control_port);
+               dev->interrupts_are_midi = 1;
+               return 0;
+@@ -1550,7 +1552,7 @@ wavefront_synth_control (snd_wavefront_c
+       case WFC_IDENTIFY_SLOT_TYPE:
+               i = wc->wbuf[0] | (wc->wbuf[1] << 7);
+               if (i <0 || i >= WF_MAX_SAMPLE) {
+-                      snd_printk ("invalid slot ID %d\n",
++                      dev_err(dev->card->dev, "invalid slot ID %d\n",
+                               i);
+                       wc->status = EINVAL;
+                       return -EINVAL;
+@@ -1561,7 +1563,7 @@ wavefront_synth_control (snd_wavefront_c
+       case WFC_DEBUG_DRIVER:
+               dev->debug = wc->wbuf[0];
+-              snd_printk ("debug = 0x%x\n", dev->debug);
++              dev_dbg(dev->card->dev, "debug = 0x%x\n", dev->debug);
+               return 0;
+       case WFC_UPLOAD_PATCH:
+@@ -1578,8 +1580,8 @@ wavefront_synth_control (snd_wavefront_c
+               return 0;
+       case WFC_UPLOAD_SAMPLE_ALIAS:
+-              snd_printk ("support for sample alias upload "
+-                      "being considered.\n");
++              dev_err(dev->card->dev,
++                      "support for sample alias upload being considered.\n");
+               wc->status = EINVAL;
+               return -EINVAL;
+       }
+@@ -1620,9 +1622,8 @@ wavefront_synth_control (snd_wavefront_c
+                       break;
+               case WFC_UPLOAD_SAMPLE_ALIAS:
+-                      snd_printk ("support for "
+-                                  "sample aliases still "
+-                                  "being considered.\n");
++                      dev_err(dev->card->dev,
++                              "support for sample aliases still being considered.\n");
+                       break;
+               case WFC_VMIDI_OFF:
+@@ -1760,7 +1761,7 @@ snd_wavefront_internal_interrupt (snd_wa
+ */
+ static int
+-snd_wavefront_interrupt_bits (int irq)
++snd_wavefront_interrupt_bits(snd_wavefront_t *dev, int irq)
+ {
+       int bits;
+@@ -1780,7 +1781,7 @@ snd_wavefront_interrupt_bits (int irq)
+               break;
+       
+       default:
+-              snd_printk ("invalid IRQ %d\n", irq);
++              dev_err(dev->card->dev, "invalid IRQ %d\n", irq);
+               bits = -1;
+       }
+@@ -1815,7 +1816,7 @@ wavefront_reset_to_cleanliness (snd_wave
+       /* IRQ already checked */
+-      bits = snd_wavefront_interrupt_bits (dev->irq);
++      bits = snd_wavefront_interrupt_bits(dev, dev->irq);
+       /* try reset of port */
+@@ -1885,7 +1886,7 @@ wavefront_reset_to_cleanliness (snd_wave
+        */
+       if (!dev->irq_ok) {
+-              snd_printk ("intr not received after h/w un-reset.\n");
++              dev_err(dev->card->dev, "intr not received after h/w un-reset.\n");
+               goto gone_bad;
+       } 
+@@ -1909,18 +1910,18 @@ wavefront_reset_to_cleanliness (snd_wave
+                                        dev->data_port, ramcheck_time*HZ);
+       if (!dev->irq_ok) {
+-              snd_printk ("post-RAM-check interrupt not received.\n");
++              dev_err(dev->card->dev, "post-RAM-check interrupt not received.\n");
+               goto gone_bad;
+       } 
+       if (!wavefront_wait (dev, STAT_CAN_READ)) {
+-              snd_printk ("no response to HW version cmd.\n");
++              dev_err(dev->card->dev, "no response to HW version cmd.\n");
+               goto gone_bad;
+       }
+       
+       hwv[0] = wavefront_read(dev);
+       if (hwv[0] == -1) {
+-              snd_printk ("board not responding correctly.\n");
++              dev_err(dev->card->dev, "board not responding correctly.\n");
+               goto gone_bad;
+       }
+@@ -1932,11 +1933,11 @@ wavefront_reset_to_cleanliness (snd_wave
+               
+               hwv[0] = wavefront_read(dev);
+               if (hwv[0] == -1) {
+-                      snd_printk ("on-board RAM test failed "
+-                                  "(bad error code).\n");
++                      dev_err(dev->card->dev,
++                              "on-board RAM test failed (bad error code).\n");
+               } else {
+-                      snd_printk ("on-board RAM test failed "
+-                                  "(error code: 0x%x).\n",
++                      dev_err(dev->card->dev,
++                              "on-board RAM test failed (error code: 0x%x).\n",
+                               hwv[0]);
+               }
+               goto gone_bad;
+@@ -1946,12 +1947,12 @@ wavefront_reset_to_cleanliness (snd_wave
+       hwv[1] = wavefront_read(dev);
+       if (hwv[1] == -1) {
+-              snd_printk ("incorrect h/w response.\n");
++              dev_err(dev->card->dev, "incorrect h/w response.\n");
+               goto gone_bad;
+       }
+-      snd_printk ("hardware version %d.%d\n",
+-                  hwv[0], hwv[1]);
++      dev_info(dev->card->dev, "hardware version %d.%d\n",
++               hwv[0], hwv[1]);
+       return 0;
+@@ -1971,7 +1972,7 @@ wavefront_download_firmware (snd_wavefro
+       err = request_firmware(&firmware, path, dev->card->dev);
+       if (err < 0) {
+-              snd_printk(KERN_ERR "firmware (%s) download failed!!!\n", path);
++              dev_err(dev->card->dev, "firmware (%s) download failed!!!\n", path);
+               return 1;
+       }
+@@ -1982,16 +1983,16 @@ wavefront_download_firmware (snd_wavefro
+               if (section_length == 0)
+                       break;
+               if (section_length < 0 || section_length > WF_SECTION_MAX) {
+-                      snd_printk(KERN_ERR
+-                                 "invalid firmware section length %d\n",
+-                                 section_length);
++                      dev_err(dev->card->dev,
++                              "invalid firmware section length %d\n",
++                              section_length);
+                       goto failure;
+               }
+               buf++;
+               len++;
+               if (firmware->size < len + section_length) {
+-                      snd_printk(KERN_ERR "firmware section read error.\n");
++                      dev_err(dev->card->dev, "firmware section read error.\n");
+                       goto failure;
+               }
+@@ -2008,15 +2009,14 @@ wavefront_download_firmware (snd_wavefro
+       
+               /* get ACK */
+               if (!wavefront_wait(dev, STAT_CAN_READ)) {
+-                      snd_printk(KERN_ERR "time out for firmware ACK.\n");
++                      dev_err(dev->card->dev, "time out for firmware ACK.\n");
+                       goto failure;
+               }
+               err = inb(dev->data_port);
+               if (err != WF_ACK) {
+-                      snd_printk(KERN_ERR
+-                                 "download of section #%d not "
+-                                 "acknowledged, ack = 0x%x\n",
+-                                 section_cnt_downloaded + 1, err);
++                      dev_err(dev->card->dev,
++                              "download of section #%d not acknowledged, ack = 0x%x\n",
++                              section_cnt_downloaded + 1, err);
+                       goto failure;
+               }
+@@ -2028,7 +2028,7 @@ wavefront_download_firmware (snd_wavefro
+  failure:
+       release_firmware(firmware);
+-      snd_printk(KERN_ERR "firmware download failed!!!\n");
++      dev_err(dev->card->dev, "firmware download failed!!!\n");
+       return 1;
+ }
+@@ -2040,7 +2040,7 @@ wavefront_do_reset (snd_wavefront_t *dev
+       char voices[1];
+       if (wavefront_reset_to_cleanliness (dev)) {
+-              snd_printk ("hw reset failed.\n");
++              dev_err(dev->card->dev, "hw reset failed.\n");
+               goto gone_bad;
+       }
+@@ -2064,7 +2064,7 @@ wavefront_do_reset (snd_wavefront_t *dev
+                                                 (osrun_time*HZ));
+               if (!dev->irq_ok) {
+-                      snd_printk ("no post-OS interrupt.\n");
++                      dev_err(dev->card->dev, "no post-OS interrupt.\n");
+                       goto gone_bad;
+               }
+               
+@@ -2074,7 +2074,7 @@ wavefront_do_reset (snd_wavefront_t *dev
+                                                 dev->data_port, (10*HZ));
+               
+               if (!dev->irq_ok) {
+-                      snd_printk ("no post-OS interrupt(2).\n");
++                      dev_err(dev->card->dev, "no post-OS interrupt(2).\n");
+                       goto gone_bad;
+               }
+@@ -2094,20 +2094,20 @@ wavefront_do_reset (snd_wavefront_t *dev
+       if (dev->freemem < 0)
+               goto gone_bad;
+               
+-      snd_printk ("available DRAM %dk\n", dev->freemem / 1024);
++      dev_info(dev->card->dev, "available DRAM %dk\n", dev->freemem / 1024);
+       if (wavefront_write (dev, 0xf0) ||
+           wavefront_write (dev, 1) ||
+           (wavefront_read (dev) < 0)) {
+               dev->debug = 0;
+-              snd_printk ("MPU emulation mode not set.\n");
++              dev_err(dev->card->dev, "MPU emulation mode not set.\n");
+               goto gone_bad;
+       }
+       voices[0] = 32;
+       if (snd_wavefront_cmd (dev, WFC_SET_NVOICES, NULL, voices)) {
+-              snd_printk ("cannot set number of voices to 32.\n");
++              dev_err(dev->card->dev, "cannot set number of voices to 32.\n");
+               goto gone_bad;
+       }
+@@ -2187,8 +2187,8 @@ snd_wavefront_detect (snd_wavefront_card
+               dev->fw_version[0] = rbuf[0];
+               dev->fw_version[1] = rbuf[1];
+-              snd_printk ("firmware %d.%d already loaded.\n",
+-                          rbuf[0], rbuf[1]);
++              dev_info(dev->card->dev, "firmware %d.%d already loaded.\n",
++                       rbuf[0], rbuf[1]);
+               /* check that a command actually works */
+       
+@@ -2197,22 +2197,24 @@ snd_wavefront_detect (snd_wavefront_card
+                       dev->hw_version[0] = rbuf[0];
+                       dev->hw_version[1] = rbuf[1];
+               } else {
+-                      snd_printk ("not raw, but no "
+-                                  "hardware version!\n");
++                      dev_err(dev->card->dev,
++                              "not raw, but no hardware version!\n");
+                       return -1;
+               }
+               if (!wf_raw) {
+                       return 0;
+               } else {
+-                      snd_printk ("reloading firmware as you requested.\n");
++                      dev_info(dev->card->dev,
++                               "reloading firmware as you requested.\n");
+                       dev->israw = 1;
+               }
+       } else {
+               dev->israw = 1;
+-              snd_printk ("no response to firmware probe, assume raw.\n");
++              dev_info(dev->card->dev,
++                       "no response to firmware probe, assume raw.\n");
+       }
diff --git a/queue-6.6/arm-dts-microchip-sama7g5-fix-uart-fifo-size-to-32.patch b/queue-6.6/arm-dts-microchip-sama7g5-fix-uart-fifo-size-to-32.patch
new file mode 100644 (file)
index 0000000..b7bb96b
--- /dev/null
@@ -0,0 +1,46 @@
+From stable+bounces-204390-greg=kroah.com@vger.kernel.org Wed Dec 31 22:20:43 2025
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 31 Dec 2025 16:20:37 -0500
+Subject: ARM: dts: microchip: sama7g5: fix uart fifo size to 32
+To: stable@vger.kernel.org
+Cc: Nicolas Ferre <nicolas.ferre@microchip.com>, Claudiu Beznea <claudiu.beznea@tuxon.dev>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20251231212037.3504979-1-sashal@kernel.org>
+
+From: Nicolas Ferre <nicolas.ferre@microchip.com>
+
+[ Upstream commit 5654889a94b0de5ad6ceae3793e7f5e0b61b50b6 ]
+
+On some flexcom nodes related to uart, the fifo sizes were wrong: fix
+them to 32 data.
+
+Fixes: 7540629e2fc7 ("ARM: dts: at91: add sama7g5 SoC DT and sama7g5-ek")
+Cc: stable@vger.kernel.org # 5.15+
+Signed-off-by: Nicolas Ferre <nicolas.ferre@microchip.com>
+Link: https://lore.kernel.org/r/20251114103313.20220-2-nicolas.ferre@microchip.com
+Signed-off-by: Claudiu Beznea <claudiu.beznea@tuxon.dev>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/arm/boot/dts/microchip/sama7g5.dtsi |    4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+--- a/arch/arm/boot/dts/microchip/sama7g5.dtsi
++++ b/arch/arm/boot/dts/microchip/sama7g5.dtsi
+@@ -811,7 +811,7 @@
+                               dma-names = "tx", "rx";
+                               atmel,use-dma-rx;
+                               atmel,use-dma-tx;
+-                              atmel,fifo-size = <16>;
++                              atmel,fifo-size = <32>;
+                               status = "disabled";
+                       };
+               };
+@@ -837,7 +837,7 @@
+                               dma-names = "tx", "rx";
+                               atmel,use-dma-rx;
+                               atmel,use-dma-tx;
+-                              atmel,fifo-size = <16>;
++                              atmel,fifo-size = <32>;
+                               status = "disabled";
+                       };
+               };
diff --git a/queue-6.6/btrfs-don-t-rewrite-ret-from-inode_permission.patch b/queue-6.6/btrfs-don-t-rewrite-ret-from-inode_permission.patch
new file mode 100644 (file)
index 0000000..7e60a05
--- /dev/null
@@ -0,0 +1,51 @@
+From stable+bounces-204139-greg=kroah.com@vger.kernel.org Mon Dec 29 22:51:55 2025
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 29 Dec 2025 16:51:49 -0500
+Subject: btrfs: don't rewrite ret from inode_permission
+To: stable@vger.kernel.org
+Cc: Josef Bacik <josef@toxicpanda.com>, Johannes Thumshirn <johannes.thumshirn@wdc.com>, Daniel Vacek <neelx@suse.com>, David Sterba <dsterba@suse.com>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20251229215149.1729676-1-sashal@kernel.org>
+
+From: Josef Bacik <josef@toxicpanda.com>
+
+[ Upstream commit 0185c2292c600993199bc6b1f342ad47a9e8c678 ]
+
+In our user safe ino resolve ioctl we'll just turn any ret into -EACCES
+from inode_permission().  This is redundant, and could potentially be
+wrong if we had an ENOMEM in the security layer or some such other
+error, so simply return the actual return value.
+
+Note: The patch was taken from v5 of fscrypt patchset
+(https://lore.kernel.org/linux-btrfs/cover.1706116485.git.josef@toxicpanda.com/)
+which was handled over time by various people: Omar Sandoval, Sweet Tea
+Dorminy, Josef Bacik.
+
+Fixes: 23d0b79dfaed ("btrfs: Add unprivileged version of ino_lookup ioctl")
+CC: stable@vger.kernel.org # 5.4+
+Reviewed-by: Johannes Thumshirn <johannes.thumshirn@wdc.com>
+Signed-off-by: Josef Bacik <josef@toxicpanda.com>
+Signed-off-by: Daniel Vacek <neelx@suse.com>
+Reviewed-by: David Sterba <dsterba@suse.com>
+[ add note ]
+Signed-off-by: David Sterba <dsterba@suse.com>
+[ Adjust context ]
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/btrfs/ioctl.c |    4 +---
+ 1 file changed, 1 insertion(+), 3 deletions(-)
+
+--- a/fs/btrfs/ioctl.c
++++ b/fs/btrfs/ioctl.c
+@@ -2006,10 +2006,8 @@ static int btrfs_search_path_in_tree_use
+                       ret = inode_permission(idmap, temp_inode,
+                                              MAY_READ | MAY_EXEC);
+                       iput(temp_inode);
+-                      if (ret) {
+-                              ret = -EACCES;
++                      if (ret)
+                               goto out_put;
+-                      }
+                       if (key.offset == upper_limit.objectid)
+                               break;
diff --git a/queue-6.6/drm-amd-display-fix-null-pointer-deref-in-dcn20_resource.c.patch b/queue-6.6/drm-amd-display-fix-null-pointer-deref-in-dcn20_resource.c.patch
new file mode 100644 (file)
index 0000000..9ee5be7
--- /dev/null
@@ -0,0 +1,82 @@
+From david.nystrom@est.tech Wed Jan  7 11:15:51 2026
+From: "David Nyström" <david.nystrom@est.tech>
+Date: Wed, 07 Jan 2026 11:15:26 +0100
+Subject: drm/amd/display: Fix null pointer deref in dcn20_resource.c
+To: stable@vger.kernel.org
+Cc: "Aurabindo Pillai" <aurabindo.pillai@amd.com>, "Sasha Levin" <sashal@kernel.org>, "Greg Kroah-Hartman" <gregkh@linuxfoundation.org>, "Alex Deucher" <alexander.deucher@amd.com>, "Rodrigo Siqueira" <Rodrigo.Siqueira@amd.com>, "David Nyström" <david.nystrom@est.tech>
+Message-ID: <20260107-null_pointer-v1-1-7443ed011f10@est.tech>
+
+From: Aurabindo Pillai <aurabindo.pillai@amd.com>
+
+[ Upstream commit ecbf60782662f0a388493685b85a645a0ba1613c ]
+
+Fixes a hang thats triggered when MPV is run on a DCN401 dGPU:
+
+mpv --hwdec=vaapi --vo=gpu --hwdec-codecs=all
+
+and then enabling fullscreen playback (double click on the video)
+
+The following calltrace will be seen:
+
+[  181.843989] BUG: kernel NULL pointer dereference, address: 0000000000000000
+[  181.843997] #PF: supervisor instruction fetch in kernel mode
+[  181.844003] #PF: error_code(0x0010) - not-present page
+[  181.844009] PGD 0 P4D 0
+[  181.844020] Oops: 0010 [#1] PREEMPT SMP NOPTI
+[  181.844028] CPU: 6 PID: 1892 Comm: gnome-shell Tainted: G        W  OE      6.5.0-41-generic #41~22.04.2-Ubuntu
+[  181.844038] Hardware name: System manufacturer System Product Name/CROSSHAIR VI HERO, BIOS 6302 10/23/2018
+[  181.844044] RIP: 0010:0x0
+[  181.844079] Code: Unable to access opcode bytes at 0xffffffffffffffd6.
+[  181.844084] RSP: 0018:ffffb593c2b8f7b0 EFLAGS: 00010246
+[  181.844093] RAX: 0000000000000000 RBX: 0000000000000000 RCX: 0000000000000004
+[  181.844099] RDX: ffffb593c2b8f804 RSI: ffffb593c2b8f7e0 RDI: ffff9e3c8e758400
+[  181.844105] RBP: ffffb593c2b8f7b8 R08: ffffb593c2b8f9c8 R09: ffffb593c2b8f96c
+[  181.844110] R10: 0000000000000000 R11: 0000000000000000 R12: ffffb593c2b8f9c8
+[  181.844115] R13: 0000000000000001 R14: ffff9e3c88000000 R15: 0000000000000005
+[  181.844121] FS:  00007c6e323bb5c0(0000) GS:ffff9e3f85f80000(0000) knlGS:0000000000000000
+[  181.844128] CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
+[  181.844134] CR2: ffffffffffffffd6 CR3: 0000000140fbe000 CR4: 00000000003506e0
+[  181.844141] Call Trace:
+[  181.844146]  <TASK>
+[  181.844153]  ? show_regs+0x6d/0x80
+[  181.844167]  ? __die+0x24/0x80
+[  181.844179]  ? page_fault_oops+0x99/0x1b0
+[  181.844192]  ? do_user_addr_fault+0x31d/0x6b0
+[  181.844204]  ? exc_page_fault+0x83/0x1b0
+[  181.844216]  ? asm_exc_page_fault+0x27/0x30
+[  181.844237]  dcn20_get_dcc_compression_cap+0x23/0x30 [amdgpu]
+[  181.845115]  amdgpu_dm_plane_validate_dcc.constprop.0+0xe5/0x180 [amdgpu]
+[  181.845985]  amdgpu_dm_plane_fill_plane_buffer_attributes+0x300/0x580 [amdgpu]
+[  181.846848]  fill_dc_plane_info_and_addr+0x258/0x350 [amdgpu]
+[  181.847734]  fill_dc_plane_attributes+0x162/0x350 [amdgpu]
+[  181.848748]  dm_update_plane_state.constprop.0+0x4e3/0x6b0 [amdgpu]
+[  181.849791]  ? dm_update_plane_state.constprop.0+0x4e3/0x6b0 [amdgpu]
+[  181.850840]  amdgpu_dm_atomic_check+0xdfe/0x1760 [amdgpu]
+
+Signed-off-by: Aurabindo Pillai <aurabindo.pillai@amd.com>
+Reviewed-by: Rodrigo Siqueira <Rodrigo.Siqueira@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: David Nyström <david.nystrom@est.tech>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c |    9 +++++----
+ 1 file changed, 5 insertions(+), 4 deletions(-)
+
+--- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c
++++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c
+@@ -2179,10 +2179,11 @@ bool dcn20_get_dcc_compression_cap(const
+               const struct dc_dcc_surface_param *input,
+               struct dc_surface_dcc_cap *output)
+ {
+-      return dc->res_pool->hubbub->funcs->get_dcc_compression_cap(
+-                      dc->res_pool->hubbub,
+-                      input,
+-                      output);
++      if (dc->res_pool->hubbub->funcs->get_dcc_compression_cap)
++              return dc->res_pool->hubbub->funcs->get_dcc_compression_cap(
++                      dc->res_pool->hubbub, input, output);
++
++      return false;
+ }
+ static void dcn20_destroy_resource_pool(struct resource_pool **pool)
diff --git a/queue-6.6/drm-amdgpu-forward-vmid-reservation-errors.patch b/queue-6.6/drm-amdgpu-forward-vmid-reservation-errors.patch
new file mode 100644 (file)
index 0000000..8462169
--- /dev/null
@@ -0,0 +1,45 @@
+From stable+bounces-206132-greg=kroah.com@vger.kernel.org Wed Jan  7 13:00:07 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed,  7 Jan 2026 06:54:14 -0500
+Subject: drm/amdgpu: Forward VMID reservation errors
+To: stable@vger.kernel.org
+Cc: "Natalie Vock" <natalie.vock@gmx.de>, "Christian König" <christian.koenig@amd.com>, "Alex Deucher" <alexander.deucher@amd.com>, "Sasha Levin" <sashal@kernel.org>
+Message-ID: <20260107115414.3985195-1-sashal@kernel.org>
+
+From: Natalie Vock <natalie.vock@gmx.de>
+
+[ Upstream commit 8defb4f081a5feccc3ea8372d0c7af3522124e1f ]
+
+Otherwise userspace may be fooled into believing it has a reserved VMID
+when in reality it doesn't, ultimately leading to GPU hangs when SPM is
+used.
+
+Fixes: 80e709ee6ecc ("drm/amdgpu: add option params to enforce process isolation between graphics and compute")
+Cc: stable@vger.kernel.org
+Reviewed-by: Christian König <christian.koenig@amd.com>
+Signed-off-by: Natalie Vock <natalie.vock@gmx.de>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+[ adapted 3-argument amdgpu_vmid_alloc_reserved(adev, vm, vmhub) call to 2-argument version and added separate error check to preserve reserved_vmid tracking logic. ]
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c |    6 ++++--
+ 1 file changed, 4 insertions(+), 2 deletions(-)
+
+--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
+@@ -2496,10 +2496,12 @@ int amdgpu_vm_ioctl(struct drm_device *d
+       case AMDGPU_VM_OP_RESERVE_VMID:
+               /* We only have requirement to reserve vmid from gfxhub */
+               if (!fpriv->vm.reserved_vmid[AMDGPU_GFXHUB(0)]) {
+-                      amdgpu_vmid_alloc_reserved(adev, AMDGPU_GFXHUB(0));
++                      int r = amdgpu_vmid_alloc_reserved(adev, AMDGPU_GFXHUB(0));
++
++                      if (r)
++                              return r;
+                       fpriv->vm.reserved_vmid[AMDGPU_GFXHUB(0)] = true;
+               }
+-
+               break;
+       case AMDGPU_VM_OP_UNRESERVE_VMID:
+               if (fpriv->vm.reserved_vmid[AMDGPU_GFXHUB(0)]) {
diff --git a/queue-6.6/drm-mediatek-fix-probe-memory-leak.patch b/queue-6.6/drm-mediatek-fix-probe-memory-leak.patch
new file mode 100644 (file)
index 0000000..db26c76
--- /dev/null
@@ -0,0 +1,44 @@
+From stable+bounces-206138-greg=kroah.com@vger.kernel.org Wed Jan  7 13:07:19 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed,  7 Jan 2026 07:07:09 -0500
+Subject: drm/mediatek: Fix probe memory leak
+To: stable@vger.kernel.org
+Cc: Johan Hovold <johan@kernel.org>, CK Hu <ck.hu@mediatek.com>, AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>, Chun-Kuang Hu <chunkuang.hu@kernel.org>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260107120710.3990944-1-sashal@kernel.org>
+
+From: Johan Hovold <johan@kernel.org>
+
+[ Upstream commit 5e49200593f331cd0629b5376fab9192f698e8ef ]
+
+The Mediatek DRM driver allocates private data for components without a
+platform driver but as the lifetime is tied to each component device,
+the memory is never freed.
+
+Tie the allocation lifetime to the DRM platform device so that the
+memory is released on probe failure (e.g. probe deferral) and when the
+driver is unbound.
+
+Fixes: c0d36de868a6 ("drm/mediatek: Move clk info from struct mtk_ddp_comp to sub driver private data")
+Cc: stable@vger.kernel.org     # 5.12
+Cc: CK Hu <ck.hu@mediatek.com>
+Signed-off-by: Johan Hovold <johan@kernel.org>
+Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
+Link: https://patchwork.kernel.org/project/dri-devel/patch/20250923152340.18234-3-johan@kernel.org/
+Signed-off-by: Chun-Kuang Hu <chunkuang.hu@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c
++++ b/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c
+@@ -588,7 +588,7 @@ int mtk_ddp_comp_init(struct device_node
+           type == MTK_DSI)
+               return 0;
+-      priv = devm_kzalloc(comp->dev, sizeof(*priv), GFP_KERNEL);
++      priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+       if (!priv)
+               return -ENOMEM;
diff --git a/queue-6.6/drm-mediatek-fix-probe-resource-leaks.patch b/queue-6.6/drm-mediatek-fix-probe-resource-leaks.patch
new file mode 100644 (file)
index 0000000..1db1572
--- /dev/null
@@ -0,0 +1,110 @@
+From stable+bounces-206158-greg=kroah.com@vger.kernel.org Wed Jan  7 17:10:32 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed,  7 Jan 2026 10:47:23 -0500
+Subject: drm/mediatek: Fix probe resource leaks
+To: stable@vger.kernel.org
+Cc: Johan Hovold <johan@kernel.org>, CK Hu <ck.hu@mediatek.com>, AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>, Chun-Kuang Hu <chunkuang.hu@kernel.org>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260107154724.4055170-1-sashal@kernel.org>
+
+From: Johan Hovold <johan@kernel.org>
+
+[ Upstream commit 07c7c640a8eb9e196f357d15d88a59602a947197 ]
+
+Make sure to unmap and release the component iomap and clock on probe
+failure (e.g. probe deferral) and on driver unbind.
+
+Note that unlike of_iomap(), devm_of_iomap() also checks whether the
+region is already mapped.
+
+Fixes: 119f5173628a ("drm/mediatek: Add DRM Driver for Mediatek SoC MT8173.")
+Cc: stable@vger.kernel.org     # 4.7
+Cc: CK Hu <ck.hu@mediatek.com>
+Signed-off-by: Johan Hovold <johan@kernel.org>
+Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
+Link: https://patchwork.kernel.org/project/dri-devel/patch/20250923152340.18234-2-johan@kernel.org/
+Signed-off-by: Chun-Kuang Hu <chunkuang.hu@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c |   20 ++++++++++++++++----
+ drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.h |    2 +-
+ drivers/gpu/drm/mediatek/mtk_drm_drv.c      |    4 ++--
+ 3 files changed, 19 insertions(+), 7 deletions(-)
+
+--- a/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c
++++ b/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c
+@@ -543,15 +543,20 @@ unsigned int mtk_drm_find_possible_crtc_
+       return ret;
+ }
+-int mtk_ddp_comp_init(struct device_node *node, struct mtk_ddp_comp *comp,
++static void mtk_ddp_comp_clk_put(void *_clk)
++{
++      struct clk *clk = _clk;
++
++      clk_put(clk);
++}
++
++int mtk_ddp_comp_init(struct device *dev, struct device_node *node, struct mtk_ddp_comp *comp,
+                     unsigned int comp_id)
+ {
+       struct platform_device *comp_pdev;
+       enum mtk_ddp_comp_type type;
+       struct mtk_ddp_comp_dev *priv;
+-#if IS_REACHABLE(CONFIG_MTK_CMDQ)
+       int ret;
+-#endif
+       if (comp_id >= DDP_COMPONENT_DRM_ID_MAX)
+               return -EINVAL;
+@@ -592,11 +597,18 @@ int mtk_ddp_comp_init(struct device_node
+       if (!priv)
+               return -ENOMEM;
+-      priv->regs = of_iomap(node, 0);
++      priv->regs = devm_of_iomap(dev, node, 0, NULL);
++      if (IS_ERR(priv->regs))
++              return PTR_ERR(priv->regs);
++
+       priv->clk = of_clk_get(node, 0);
+       if (IS_ERR(priv->clk))
+               return PTR_ERR(priv->clk);
++      ret = devm_add_action_or_reset(dev, mtk_ddp_comp_clk_put, priv->clk);
++      if (ret)
++              return ret;
++
+ #if IS_REACHABLE(CONFIG_MTK_CMDQ)
+       ret = cmdq_dev_get_client_reg(comp->dev, &priv->cmdq_reg, 0);
+       if (ret)
+--- a/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.h
++++ b/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.h
+@@ -279,7 +279,7 @@ int mtk_ddp_comp_get_id(struct device_no
+                       enum mtk_ddp_comp_type comp_type);
+ unsigned int mtk_drm_find_possible_crtc_by_comp(struct drm_device *drm,
+                                               struct device *dev);
+-int mtk_ddp_comp_init(struct device_node *comp_node, struct mtk_ddp_comp *comp,
++int mtk_ddp_comp_init(struct device *dev, struct device_node *comp_node, struct mtk_ddp_comp *comp,
+                     unsigned int comp_id);
+ enum mtk_ddp_comp_type mtk_ddp_comp_get_type(unsigned int comp_id);
+ void mtk_ddp_write(struct cmdq_pkt *cmdq_pkt, unsigned int value,
+--- a/drivers/gpu/drm/mediatek/mtk_drm_drv.c
++++ b/drivers/gpu/drm/mediatek/mtk_drm_drv.c
+@@ -841,7 +841,7 @@ static int mtk_drm_probe(struct platform
+                                                           (void *)private->mmsys_dev,
+                                                           sizeof(*private->mmsys_dev));
+               private->ddp_comp[DDP_COMPONENT_DRM_OVL_ADAPTOR].dev = &ovl_adaptor->dev;
+-              mtk_ddp_comp_init(NULL, &private->ddp_comp[DDP_COMPONENT_DRM_OVL_ADAPTOR],
++              mtk_ddp_comp_init(dev, NULL, &private->ddp_comp[DDP_COMPONENT_DRM_OVL_ADAPTOR],
+                                 DDP_COMPONENT_DRM_OVL_ADAPTOR);
+               component_match_add(dev, &match, compare_dev, &ovl_adaptor->dev);
+       }
+@@ -910,7 +910,7 @@ static int mtk_drm_probe(struct platform
+                                                  node);
+               }
+-              ret = mtk_ddp_comp_init(node, &private->ddp_comp[comp_id], comp_id);
++              ret = mtk_ddp_comp_init(dev, node, &private->ddp_comp[comp_id], comp_id);
+               if (ret) {
+                       of_node_put(node);
+                       goto err_node;
diff --git a/queue-6.6/drm-tilcdc-fix-removal-actions-in-case-of-failed-probe.patch b/queue-6.6/drm-tilcdc-fix-removal-actions-in-case-of-failed-probe.patch
new file mode 100644 (file)
index 0000000..7cf4ece
--- /dev/null
@@ -0,0 +1,213 @@
+From stable+bounces-206180-greg=kroah.com@vger.kernel.org Wed Jan  7 18:13:19 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed,  7 Jan 2026 11:14:08 -0500
+Subject: drm/tilcdc: Fix removal actions in case of failed probe
+To: stable@vger.kernel.org
+Cc: "Kory Maincent (TI.com)" <kory.maincent@bootlin.com>, Douglas Anderson <dianders@chromium.org>, Luca Ceresoli <luca.ceresoli@bootlin.com>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260107161408.4074126-2-sashal@kernel.org>
+
+From: "Kory Maincent (TI.com)" <kory.maincent@bootlin.com>
+
+[ Upstream commit a585c7ef9cabda58088916baedc6573e9a5cd2a7 ]
+
+The drm_kms_helper_poll_fini() and drm_atomic_helper_shutdown() helpers
+should only be called when the device has been successfully registered.
+Currently, these functions are called unconditionally in tilcdc_fini(),
+which causes warnings during probe deferral scenarios.
+
+[    7.972317] WARNING: CPU: 0 PID: 23 at drivers/gpu/drm/drm_atomic_state_helper.c:175 drm_atomic_helper_crtc_duplicate_state+0x60/0x68
+...
+[    8.005820]  drm_atomic_helper_crtc_duplicate_state from drm_atomic_get_crtc_state+0x68/0x108
+[    8.005858]  drm_atomic_get_crtc_state from drm_atomic_helper_disable_all+0x90/0x1c8
+[    8.005885]  drm_atomic_helper_disable_all from drm_atomic_helper_shutdown+0x90/0x144
+[    8.005911]  drm_atomic_helper_shutdown from tilcdc_fini+0x68/0xf8 [tilcdc]
+[    8.005957]  tilcdc_fini [tilcdc] from tilcdc_pdev_probe+0xb0/0x6d4 [tilcdc]
+
+Fix this by rewriting the failed probe cleanup path using the standard
+goto error handling pattern, which ensures that cleanup functions are
+only called on successfully initialized resources. Additionally, remove
+the now-unnecessary is_registered flag.
+
+Cc: stable@vger.kernel.org
+Fixes: 3c4babae3c4a ("drm: Call drm_atomic_helper_shutdown() at shutdown/remove time for misc drivers")
+Signed-off-by: Kory Maincent (TI.com) <kory.maincent@bootlin.com>
+Reviewed-by: Douglas Anderson <dianders@chromium.org>
+Reviewed-by: Luca Ceresoli <luca.ceresoli@bootlin.com>
+Signed-off-by: Douglas Anderson <dianders@chromium.org>
+Link: https://patch.msgid.link/20251125090546.137193-1-kory.maincent@bootlin.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/gpu/drm/tilcdc/tilcdc_crtc.c |    2 -
+ drivers/gpu/drm/tilcdc/tilcdc_drv.c  |   53 +++++++++++++++++++++++------------
+ drivers/gpu/drm/tilcdc/tilcdc_drv.h  |    2 -
+ 3 files changed, 37 insertions(+), 20 deletions(-)
+
+--- a/drivers/gpu/drm/tilcdc/tilcdc_crtc.c
++++ b/drivers/gpu/drm/tilcdc/tilcdc_crtc.c
+@@ -586,7 +586,7 @@ out:
+       drm_modeset_unlock(&crtc->mutex);
+ }
+-static void tilcdc_crtc_destroy(struct drm_crtc *crtc)
++void tilcdc_crtc_destroy(struct drm_crtc *crtc)
+ {
+       struct tilcdc_drm_private *priv = crtc->dev->dev_private;
+--- a/drivers/gpu/drm/tilcdc/tilcdc_drv.c
++++ b/drivers/gpu/drm/tilcdc/tilcdc_drv.c
+@@ -171,8 +171,7 @@ static void tilcdc_fini(struct drm_devic
+       if (priv->crtc)
+               tilcdc_crtc_shutdown(priv->crtc);
+-      if (priv->is_registered)
+-              drm_dev_unregister(dev);
++      drm_dev_unregister(dev);
+       drm_kms_helper_poll_fini(dev);
+       drm_atomic_helper_shutdown(dev);
+@@ -219,21 +218,21 @@ static int tilcdc_init(const struct drm_
+       priv->wq = alloc_ordered_workqueue("tilcdc", 0);
+       if (!priv->wq) {
+               ret = -ENOMEM;
+-              goto init_failed;
++              goto put_drm;
+       }
+       priv->mmio = devm_platform_ioremap_resource(pdev, 0);
+       if (IS_ERR(priv->mmio)) {
+               dev_err(dev, "failed to request / ioremap\n");
+               ret = PTR_ERR(priv->mmio);
+-              goto init_failed;
++              goto free_wq;
+       }
+       priv->clk = clk_get(dev, "fck");
+       if (IS_ERR(priv->clk)) {
+               dev_err(dev, "failed to get functional clock\n");
+               ret = -ENODEV;
+-              goto init_failed;
++              goto free_wq;
+       }
+       pm_runtime_enable(dev);
+@@ -312,7 +311,7 @@ static int tilcdc_init(const struct drm_
+       ret = tilcdc_crtc_create(ddev);
+       if (ret < 0) {
+               dev_err(dev, "failed to create crtc\n");
+-              goto init_failed;
++              goto disable_pm;
+       }
+       modeset_init(ddev);
+@@ -323,46 +322,46 @@ static int tilcdc_init(const struct drm_
+       if (ret) {
+               dev_err(dev, "failed to register cpufreq notifier\n");
+               priv->freq_transition.notifier_call = NULL;
+-              goto init_failed;
++              goto destroy_crtc;
+       }
+ #endif
+       if (priv->is_componentized) {
+               ret = component_bind_all(dev, ddev);
+               if (ret < 0)
+-                      goto init_failed;
++                      goto unregister_cpufreq_notif;
+               ret = tilcdc_add_component_encoder(ddev);
+               if (ret < 0)
+-                      goto init_failed;
++                      goto unbind_component;
+       } else {
+               ret = tilcdc_attach_external_device(ddev);
+               if (ret)
+-                      goto init_failed;
++                      goto unregister_cpufreq_notif;
+       }
+       if (!priv->external_connector &&
+           ((priv->num_encoders == 0) || (priv->num_connectors == 0))) {
+               dev_err(dev, "no encoders/connectors found\n");
+               ret = -EPROBE_DEFER;
+-              goto init_failed;
++              goto unbind_component;
+       }
+       ret = drm_vblank_init(ddev, 1);
+       if (ret < 0) {
+               dev_err(dev, "failed to initialize vblank\n");
+-              goto init_failed;
++              goto unbind_component;
+       }
+       ret = platform_get_irq(pdev, 0);
+       if (ret < 0)
+-              goto init_failed;
++              goto unbind_component;
+       priv->irq = ret;
+       ret = tilcdc_irq_install(ddev, priv->irq);
+       if (ret < 0) {
+               dev_err(dev, "failed to install IRQ handler\n");
+-              goto init_failed;
++              goto unbind_component;
+       }
+       drm_mode_config_reset(ddev);
+@@ -371,15 +370,33 @@ static int tilcdc_init(const struct drm_
+       ret = drm_dev_register(ddev, 0);
+       if (ret)
+-              goto init_failed;
+-      priv->is_registered = true;
++              goto stop_poll;
+       drm_fbdev_dma_setup(ddev, bpp);
+       return 0;
+-init_failed:
+-      tilcdc_fini(ddev);
++stop_poll:
++      drm_kms_helper_poll_fini(ddev);
++      tilcdc_irq_uninstall(ddev);
++unbind_component:
++      if (priv->is_componentized)
++              component_unbind_all(dev, ddev);
++unregister_cpufreq_notif:
++#ifdef CONFIG_CPU_FREQ
++      cpufreq_unregister_notifier(&priv->freq_transition,
++                                  CPUFREQ_TRANSITION_NOTIFIER);
++destroy_crtc:
++#endif
++      tilcdc_crtc_destroy(priv->crtc);
++disable_pm:
++      pm_runtime_disable(dev);
++      clk_put(priv->clk);
++free_wq:
++      destroy_workqueue(priv->wq);
++put_drm:
+       platform_set_drvdata(pdev, NULL);
++      ddev->dev_private = NULL;
++      drm_dev_put(ddev);
+       return ret;
+ }
+--- a/drivers/gpu/drm/tilcdc/tilcdc_drv.h
++++ b/drivers/gpu/drm/tilcdc/tilcdc_drv.h
+@@ -82,7 +82,6 @@ struct tilcdc_drm_private {
+       struct drm_encoder *external_encoder;
+       struct drm_connector *external_connector;
+-      bool is_registered;
+       bool is_componentized;
+       bool irq_enabled;
+ };
+@@ -164,6 +163,7 @@ void tilcdc_crtc_set_panel_info(struct d
+ void tilcdc_crtc_set_simulate_vesa_sync(struct drm_crtc *crtc,
+                                       bool simulate_vesa_sync);
+ void tilcdc_crtc_shutdown(struct drm_crtc *crtc);
++void tilcdc_crtc_destroy(struct drm_crtc *crtc);
+ int tilcdc_crtc_update_fb(struct drm_crtc *crtc,
+               struct drm_framebuffer *fb,
+               struct drm_pending_vblank_event *event);
diff --git a/queue-6.6/drm-tilcdc-request-and-mapp-iomem-with-devres.patch b/queue-6.6/drm-tilcdc-request-and-mapp-iomem-with-devres.patch
new file mode 100644 (file)
index 0000000..322e1cb
--- /dev/null
@@ -0,0 +1,73 @@
+From stable+bounces-206181-greg=kroah.com@vger.kernel.org Wed Jan  7 18:13:19 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed,  7 Jan 2026 11:14:07 -0500
+Subject: drm/tilcdc: request and mapp iomem with devres
+To: stable@vger.kernel.org
+Cc: Philipp Stanner <pstanner@redhat.com>, Thomas Zimmermann <tzimmermann@suse.de>, Jyri Sarha <jyri.sarha@iki.fi>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260107161408.4074126-1-sashal@kernel.org>
+
+From: Philipp Stanner <pstanner@redhat.com>
+
+[ Upstream commit a196a5166e0812db267281c32fa0724fc5be6582 ]
+
+tilcdc currently just ioremaps its iomem, without doing the (a bit more
+robust) request on the memory first. The devm_ functions provide a handy
+way to both request and ioremap the memory with automatic cleanup.
+
+Replace the manual ioremap with the devm_ version.
+
+Suggested-by: Thomas Zimmermann <tzimmermann@suse.de>
+Signed-off-by: Philipp Stanner <pstanner@redhat.com>
+Reviewed-by: Jyri Sarha <jyri.sarha@iki.fi>
+Tested-by: Jyri Sarha <jyri.sarha@iki.fi>
+Signed-off-by: Jyri Sarha <jyri.sarha@iki.fi>
+Link: https://patchwork.freedesktop.org/patch/msgid/20231222115216.19218-2-pstanner@redhat.com
+Stable-dep-of: a585c7ef9cab ("drm/tilcdc: Fix removal actions in case of failed probe")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/gpu/drm/tilcdc/tilcdc_drv.c |   19 ++++---------------
+ 1 file changed, 4 insertions(+), 15 deletions(-)
+
+--- a/drivers/gpu/drm/tilcdc/tilcdc_drv.c
++++ b/drivers/gpu/drm/tilcdc/tilcdc_drv.c
+@@ -182,9 +182,6 @@ static void tilcdc_fini(struct drm_devic
+       if (priv->clk)
+               clk_put(priv->clk);
+-      if (priv->mmio)
+-              iounmap(priv->mmio);
+-
+       if (priv->wq)
+               destroy_workqueue(priv->wq);
+@@ -201,7 +198,6 @@ static int tilcdc_init(const struct drm_
+       struct platform_device *pdev = to_platform_device(dev);
+       struct device_node *node = dev->of_node;
+       struct tilcdc_drm_private *priv;
+-      struct resource *res;
+       u32 bpp = 0;
+       int ret;
+@@ -226,17 +222,10 @@ static int tilcdc_init(const struct drm_
+               goto init_failed;
+       }
+-      res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+-      if (!res) {
+-              dev_err(dev, "failed to get memory resource\n");
+-              ret = -EINVAL;
+-              goto init_failed;
+-      }
+-
+-      priv->mmio = ioremap(res->start, resource_size(res));
+-      if (!priv->mmio) {
+-              dev_err(dev, "failed to ioremap\n");
+-              ret = -ENOMEM;
++      priv->mmio = devm_platform_ioremap_resource(pdev, 0);
++      if (IS_ERR(priv->mmio)) {
++              dev_err(dev, "failed to request / ioremap\n");
++              ret = PTR_ERR(priv->mmio);
+               goto init_failed;
+       }
diff --git a/queue-6.6/ext4-fix-string-copying-in-parse_apply_sb_mount_options.patch b/queue-6.6/ext4-fix-string-copying-in-parse_apply_sb_mount_options.patch
new file mode 100644 (file)
index 0000000..bd3b66b
--- /dev/null
@@ -0,0 +1,86 @@
+From stable+bounces-204160-greg=kroah.com@vger.kernel.org Tue Dec 30 01:47:33 2025
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 29 Dec 2025 19:47:24 -0500
+Subject: ext4: fix string copying in parse_apply_sb_mount_options()
+To: stable@vger.kernel.org
+Cc: Fedor Pchelkin <pchelkin@ispras.ru>, Baokun Li <libaokun1@huawei.com>, Jan Kara <jack@suse.cz>, Theodore Ts'o <tytso@mit.edu>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20251230004724.1896388-1-sashal@kernel.org>
+
+From: Fedor Pchelkin <pchelkin@ispras.ru>
+
+[ Upstream commit ee5a977b4e771cc181f39d504426dbd31ed701cc ]
+
+strscpy_pad() can't be used to copy a non-NUL-term string into a NUL-term
+string of possibly bigger size.  Commit 0efc5990bca5 ("string.h: Introduce
+memtostr() and memtostr_pad()") provides additional information in that
+regard.  So if this happens, the following warning is observed:
+
+strnlen: detected buffer overflow: 65 byte read of buffer size 64
+WARNING: CPU: 0 PID: 28655 at lib/string_helpers.c:1032 __fortify_report+0x96/0xc0 lib/string_helpers.c:1032
+Modules linked in:
+CPU: 0 UID: 0 PID: 28655 Comm: syz-executor.3 Not tainted 6.12.54-syzkaller-00144-g5f0270f1ba00 #0
+Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.16.3-debian-1.16.3-2 04/01/2014
+RIP: 0010:__fortify_report+0x96/0xc0 lib/string_helpers.c:1032
+Call Trace:
+ <TASK>
+ __fortify_panic+0x1f/0x30 lib/string_helpers.c:1039
+ strnlen include/linux/fortify-string.h:235 [inline]
+ sized_strscpy include/linux/fortify-string.h:309 [inline]
+ parse_apply_sb_mount_options fs/ext4/super.c:2504 [inline]
+ __ext4_fill_super fs/ext4/super.c:5261 [inline]
+ ext4_fill_super+0x3c35/0xad00 fs/ext4/super.c:5706
+ get_tree_bdev_flags+0x387/0x620 fs/super.c:1636
+ vfs_get_tree+0x93/0x380 fs/super.c:1814
+ do_new_mount fs/namespace.c:3553 [inline]
+ path_mount+0x6ae/0x1f70 fs/namespace.c:3880
+ do_mount fs/namespace.c:3893 [inline]
+ __do_sys_mount fs/namespace.c:4103 [inline]
+ __se_sys_mount fs/namespace.c:4080 [inline]
+ __x64_sys_mount+0x280/0x300 fs/namespace.c:4080
+ do_syscall_x64 arch/x86/entry/common.c:52 [inline]
+ do_syscall_64+0x64/0x140 arch/x86/entry/common.c:83
+ entry_SYSCALL_64_after_hwframe+0x76/0x7e
+
+Since userspace is expected to provide s_mount_opts field to be at most 63
+characters long with the ending byte being NUL-term, use a 64-byte buffer
+which matches the size of s_mount_opts, so that strscpy_pad() does its job
+properly.  Return with error if the user still managed to provide a
+non-NUL-term string here.
+
+Found by Linux Verification Center (linuxtesting.org) with Syzkaller.
+
+Fixes: 8ecb790ea8c3 ("ext4: avoid potential buffer over-read in parse_apply_sb_mount_options()")
+Cc: stable@vger.kernel.org
+Signed-off-by: Fedor Pchelkin <pchelkin@ispras.ru>
+Reviewed-by: Baokun Li <libaokun1@huawei.com>
+Reviewed-by: Jan Kara <jack@suse.cz>
+Message-ID: <20251101160430.222297-1-pchelkin@ispras.ru>
+Signed-off-by: Theodore Ts'o <tytso@mit.edu>
+[ adapted 2-argument strscpy_pad() call to 3-argument form with explicit sizeof() ]
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/ext4/super.c |    5 +++--
+ 1 file changed, 3 insertions(+), 2 deletions(-)
+
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -2507,7 +2507,7 @@ static int parse_apply_sb_mount_options(
+                                       struct ext4_fs_context *m_ctx)
+ {
+       struct ext4_sb_info *sbi = EXT4_SB(sb);
+-      char s_mount_opts[65];
++      char s_mount_opts[64];
+       struct ext4_fs_context *s_ctx = NULL;
+       struct fs_context *fc = NULL;
+       int ret = -ENOMEM;
+@@ -2515,7 +2515,8 @@ static int parse_apply_sb_mount_options(
+       if (!sbi->s_es->s_mount_opts[0])
+               return 0;
+-      strscpy_pad(s_mount_opts, sbi->s_es->s_mount_opts, sizeof(s_mount_opts));
++      if (strscpy_pad(s_mount_opts, sbi->s_es->s_mount_opts, sizeof(s_mount_opts)) < 0)
++              return -E2BIG;
+       fc = kzalloc(sizeof(struct fs_context), GFP_KERNEL);
+       if (!fc)
diff --git a/queue-6.6/f2fs-fix-to-avoid-potential-deadlock.patch b/queue-6.6/f2fs-fix-to-avoid-potential-deadlock.patch
new file mode 100644 (file)
index 0000000..23f3c17
--- /dev/null
@@ -0,0 +1,221 @@
+From stable+bounces-204244-greg=kroah.com@vger.kernel.org Tue Dec 30 17:15:46 2025
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 30 Dec 2025 11:15:39 -0500
+Subject: f2fs: fix to avoid potential deadlock
+To: stable@vger.kernel.org
+Cc: Chao Yu <chao@kernel.org>, stable@kernel.org, syzbot+14b90e1156b9f6fc1266@syzkaller.appspotmail.com, Jiaming Zhang <r772577952@gmail.com>, Jaegeuk Kim <jaegeuk@kernel.org>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20251230161539.2301172-2-sashal@kernel.org>
+
+From: Chao Yu <chao@kernel.org>
+
+[ Upstream commit ca8b201f28547e28343a6f00a6e91fa8c09572fe ]
+
+As Jiaming Zhang and syzbot reported, there is potential deadlock in
+f2fs as below:
+
+Chain exists of:
+  &sbi->cp_rwsem --> fs_reclaim --> sb_internal#2
+
+ Possible unsafe locking scenario:
+
+       CPU0                    CPU1
+       ----                    ----
+  rlock(sb_internal#2);
+                               lock(fs_reclaim);
+                               lock(sb_internal#2);
+  rlock(&sbi->cp_rwsem);
+
+ *** DEADLOCK ***
+
+3 locks held by kswapd0/73:
+ #0: ffffffff8e247a40 (fs_reclaim){+.+.}-{0:0}, at: balance_pgdat mm/vmscan.c:7015 [inline]
+ #0: ffffffff8e247a40 (fs_reclaim){+.+.}-{0:0}, at: kswapd+0x951/0x2800 mm/vmscan.c:7389
+ #1: ffff8880118400e0 (&type->s_umount_key#50){.+.+}-{4:4}, at: super_trylock_shared fs/super.c:562 [inline]
+ #1: ffff8880118400e0 (&type->s_umount_key#50){.+.+}-{4:4}, at: super_cache_scan+0x91/0x4b0 fs/super.c:197
+ #2: ffff888011840610 (sb_internal#2){.+.+}-{0:0}, at: f2fs_evict_inode+0x8d9/0x1b60 fs/f2fs/inode.c:890
+
+stack backtrace:
+CPU: 0 UID: 0 PID: 73 Comm: kswapd0 Not tainted syzkaller #0 PREEMPT(full)
+Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 1.16.3-debian-1.16.3-2~bpo12+1 04/01/2014
+Call Trace:
+ <TASK>
+ dump_stack_lvl+0x189/0x250 lib/dump_stack.c:120
+ print_circular_bug+0x2ee/0x310 kernel/locking/lockdep.c:2043
+ check_noncircular+0x134/0x160 kernel/locking/lockdep.c:2175
+ check_prev_add kernel/locking/lockdep.c:3165 [inline]
+ check_prevs_add kernel/locking/lockdep.c:3284 [inline]
+ validate_chain+0xb9b/0x2140 kernel/locking/lockdep.c:3908
+ __lock_acquire+0xab9/0xd20 kernel/locking/lockdep.c:5237
+ lock_acquire+0x120/0x360 kernel/locking/lockdep.c:5868
+ down_read+0x46/0x2e0 kernel/locking/rwsem.c:1537
+ f2fs_down_read fs/f2fs/f2fs.h:2278 [inline]
+ f2fs_lock_op fs/f2fs/f2fs.h:2357 [inline]
+ f2fs_do_truncate_blocks+0x21c/0x10c0 fs/f2fs/file.c:791
+ f2fs_truncate_blocks+0x10a/0x300 fs/f2fs/file.c:867
+ f2fs_truncate+0x489/0x7c0 fs/f2fs/file.c:925
+ f2fs_evict_inode+0x9f2/0x1b60 fs/f2fs/inode.c:897
+ evict+0x504/0x9c0 fs/inode.c:810
+ f2fs_evict_inode+0x1dc/0x1b60 fs/f2fs/inode.c:853
+ evict+0x504/0x9c0 fs/inode.c:810
+ dispose_list fs/inode.c:852 [inline]
+ prune_icache_sb+0x21b/0x2c0 fs/inode.c:1000
+ super_cache_scan+0x39b/0x4b0 fs/super.c:224
+ do_shrink_slab+0x6ef/0x1110 mm/shrinker.c:437
+ shrink_slab_memcg mm/shrinker.c:550 [inline]
+ shrink_slab+0x7ef/0x10d0 mm/shrinker.c:628
+ shrink_one+0x28a/0x7c0 mm/vmscan.c:4955
+ shrink_many mm/vmscan.c:5016 [inline]
+ lru_gen_shrink_node mm/vmscan.c:5094 [inline]
+ shrink_node+0x315d/0x3780 mm/vmscan.c:6081
+ kswapd_shrink_node mm/vmscan.c:6941 [inline]
+ balance_pgdat mm/vmscan.c:7124 [inline]
+ kswapd+0x147c/0x2800 mm/vmscan.c:7389
+ kthread+0x70e/0x8a0 kernel/kthread.c:463
+ ret_from_fork+0x4bc/0x870 arch/x86/kernel/process.c:158
+ ret_from_fork_asm+0x1a/0x30 arch/x86/entry/entry_64.S:245
+ </TASK>
+
+The root cause is deadlock among four locks as below:
+
+kswapd
+- fs_reclaim                           --- Lock A
+ - shrink_one
+  - evict
+   - f2fs_evict_inode
+    - sb_start_intwrite                        --- Lock B
+
+- iput
+ - evict
+  - f2fs_evict_inode
+   - sb_start_intwrite                 --- Lock B
+   - f2fs_truncate
+    - f2fs_truncate_blocks
+     - f2fs_do_truncate_blocks
+      - f2fs_lock_op                   --- Lock C
+
+ioctl
+- f2fs_ioc_commit_atomic_write
+ - f2fs_lock_op                                --- Lock C
+  - __f2fs_commit_atomic_write
+   - __replace_atomic_write_block
+    - f2fs_get_dnode_of_data
+     - __get_node_folio
+      - f2fs_check_nid_range
+       - f2fs_handle_error
+        - f2fs_record_errors
+         - f2fs_down_write             --- Lock D
+
+open
+- do_open
+ - do_truncate
+  - security_inode_need_killpriv
+   - f2fs_getxattr
+    - lookup_all_xattrs
+     - f2fs_handle_error
+      - f2fs_record_errors
+       - f2fs_down_write               --- Lock D
+        - f2fs_commit_super
+         - read_mapping_folio
+          - filemap_alloc_folio_noprof
+           - prepare_alloc_pages
+            - fs_reclaim_acquire       --- Lock A
+
+In order to avoid such deadlock, we need to avoid grabbing sb_lock in
+f2fs_handle_error(), so, let's use asynchronous method instead:
+- remove f2fs_handle_error() implementation
+- rename f2fs_handle_error_async() to f2fs_handle_error()
+- spread f2fs_handle_error()
+
+Fixes: 95fa90c9e5a7 ("f2fs: support recording errors into superblock")
+Cc: stable@kernel.org
+Reported-by: syzbot+14b90e1156b9f6fc1266@syzkaller.appspotmail.com
+Closes: https://lore.kernel.org/linux-f2fs-devel/68eae49b.050a0220.ac43.0001.GAE@google.com
+Reported-by: Jiaming Zhang <r772577952@gmail.com>
+Closes: https://lore.kernel.org/lkml/CANypQFa-Gy9sD-N35o3PC+FystOWkNuN8pv6S75HLT0ga-Tzgw@mail.gmail.com
+Signed-off-by: Chao Yu <chao@kernel.org>
+Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/f2fs/compress.c |    5 +----
+ fs/f2fs/f2fs.h     |    1 -
+ fs/f2fs/super.c    |   41 -----------------------------------------
+ 3 files changed, 1 insertion(+), 46 deletions(-)
+
+--- a/fs/f2fs/compress.c
++++ b/fs/f2fs/compress.c
+@@ -754,10 +754,7 @@ void f2fs_decompress_cluster(struct deco
+               ret = -EFSCORRUPTED;
+               /* Avoid f2fs_commit_super in irq context */
+-              if (!in_task)
+-                      f2fs_handle_error_async(sbi, ERROR_FAIL_DECOMPRESSION);
+-              else
+-                      f2fs_handle_error(sbi, ERROR_FAIL_DECOMPRESSION);
++              f2fs_handle_error(sbi, ERROR_FAIL_DECOMPRESSION);
+               goto out_release;
+       }
+--- a/fs/f2fs/f2fs.h
++++ b/fs/f2fs/f2fs.h
+@@ -3638,7 +3638,6 @@ void f2fs_quota_off_umount(struct super_
+ void f2fs_save_errors(struct f2fs_sb_info *sbi, unsigned char flag);
+ void f2fs_handle_critical_error(struct f2fs_sb_info *sbi, unsigned char reason);
+ void f2fs_handle_error(struct f2fs_sb_info *sbi, unsigned char error);
+-void f2fs_handle_error_async(struct f2fs_sb_info *sbi, unsigned char error);
+ int f2fs_commit_super(struct f2fs_sb_info *sbi, bool recover);
+ int f2fs_sync_fs(struct super_block *sb, int sync);
+ int f2fs_sanity_check_ckpt(struct f2fs_sb_info *sbi);
+--- a/fs/f2fs/super.c
++++ b/fs/f2fs/super.c
+@@ -4071,50 +4071,9 @@ void f2fs_save_errors(struct f2fs_sb_inf
+       spin_unlock_irqrestore(&sbi->error_lock, flags);
+ }
+-static bool f2fs_update_errors(struct f2fs_sb_info *sbi)
+-{
+-      unsigned long flags;
+-      bool need_update = false;
+-
+-      spin_lock_irqsave(&sbi->error_lock, flags);
+-      if (sbi->error_dirty) {
+-              memcpy(F2FS_RAW_SUPER(sbi)->s_errors, sbi->errors,
+-                                                      MAX_F2FS_ERRORS);
+-              sbi->error_dirty = false;
+-              need_update = true;
+-      }
+-      spin_unlock_irqrestore(&sbi->error_lock, flags);
+-
+-      return need_update;
+-}
+-
+-static void f2fs_record_errors(struct f2fs_sb_info *sbi, unsigned char error)
+-{
+-      int err;
+-
+-      f2fs_down_write(&sbi->sb_lock);
+-
+-      if (!f2fs_update_errors(sbi))
+-              goto out_unlock;
+-
+-      err = f2fs_commit_super(sbi, false);
+-      if (err)
+-              f2fs_err_ratelimited(sbi,
+-                      "f2fs_commit_super fails to record errors:%u, err:%d",
+-                      error, err);
+-out_unlock:
+-      f2fs_up_write(&sbi->sb_lock);
+-}
+-
+ void f2fs_handle_error(struct f2fs_sb_info *sbi, unsigned char error)
+ {
+       f2fs_save_errors(sbi, error);
+-      f2fs_record_errors(sbi, error);
+-}
+-
+-void f2fs_handle_error_async(struct f2fs_sb_info *sbi, unsigned char error)
+-{
+-      f2fs_save_errors(sbi, error);
+       if (!sbi->error_dirty)
+               return;
diff --git a/queue-6.6/f2fs-use-f2fs_err_ratelimited-to-avoid-redundant-logs.patch b/queue-6.6/f2fs-use-f2fs_err_ratelimited-to-avoid-redundant-logs.patch
new file mode 100644 (file)
index 0000000..086a68a
--- /dev/null
@@ -0,0 +1,50 @@
+From stable+bounces-204243-greg=kroah.com@vger.kernel.org Tue Dec 30 17:15:44 2025
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 30 Dec 2025 11:15:38 -0500
+Subject: f2fs: use f2fs_err_ratelimited() to avoid redundant logs
+To: stable@vger.kernel.org
+Cc: Chao Yu <chao@kernel.org>, Jaegeuk Kim <jaegeuk@kernel.org>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20251230161539.2301172-1-sashal@kernel.org>
+
+From: Chao Yu <chao@kernel.org>
+
+[ Upstream commit 0b8eb814e05885cde53c1d56ee012a029b8413e6 ]
+
+Use f2fs_err_ratelimited() to instead f2fs_err() in
+f2fs_record_stop_reason() and f2fs_record_errors() to
+avoid redundant logs.
+
+Signed-off-by: Chao Yu <chao@kernel.org>
+Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
+Stable-dep-of: ca8b201f2854 ("f2fs: fix to avoid potential deadlock")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/f2fs/super.c |    9 ++++++---
+ 1 file changed, 6 insertions(+), 3 deletions(-)
+
+--- a/fs/f2fs/super.c
++++ b/fs/f2fs/super.c
+@@ -4054,7 +4054,9 @@ static void f2fs_record_stop_reason(stru
+       f2fs_up_write(&sbi->sb_lock);
+       if (err)
+-              f2fs_err(sbi, "f2fs_commit_super fails to record err:%d", err);
++              f2fs_err_ratelimited(sbi,
++                      "f2fs_commit_super fails to record stop_reason, err:%d",
++                      err);
+ }
+ void f2fs_save_errors(struct f2fs_sb_info *sbi, unsigned char flag)
+@@ -4097,8 +4099,9 @@ static void f2fs_record_errors(struct f2
+       err = f2fs_commit_super(sbi, false);
+       if (err)
+-              f2fs_err(sbi, "f2fs_commit_super fails to record errors:%u, err:%d",
+-                                                              error, err);
++              f2fs_err_ratelimited(sbi,
++                      "f2fs_commit_super fails to record errors:%u, err:%d",
++                      error, err);
+ out_unlock:
+       f2fs_up_write(&sbi->sb_lock);
+ }
diff --git a/queue-6.6/fuse-fix-readahead-reclaim-deadlock.patch b/queue-6.6/fuse-fix-readahead-reclaim-deadlock.patch
new file mode 100644 (file)
index 0000000..cad613a
--- /dev/null
@@ -0,0 +1,120 @@
+From stable+bounces-204415-greg=kroah.com@vger.kernel.org Thu Jan  1 15:13:49 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu,  1 Jan 2026 09:13:41 -0500
+Subject: fuse: fix readahead reclaim deadlock
+To: stable@vger.kernel.org
+Cc: Joanne Koong <joannelkoong@gmail.com>, Omar Sandoval <osandov@fb.com>, Miklos Szeredi <mszeredi@redhat.com>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260101141342.4003826-1-sashal@kernel.org>
+
+From: Joanne Koong <joannelkoong@gmail.com>
+
+[ Upstream commit bd5603eaae0aabf527bfb3ce1bb07e979ce5bd50 ]
+
+Commit e26ee4efbc79 ("fuse: allocate ff->release_args only if release is
+needed") skips allocating ff->release_args if the server does not
+implement open. However in doing so, fuse_prepare_release() now skips
+grabbing the reference on the inode, which makes it possible for an
+inode to be evicted from the dcache while there are inflight readahead
+requests. This causes a deadlock if the server triggers reclaim while
+servicing the readahead request and reclaim attempts to evict the inode
+of the file being read ahead. Since the folio is locked during
+readahead, when reclaim evicts the fuse inode and fuse_evict_inode()
+attempts to remove all folios associated with the inode from the page
+cache (truncate_inode_pages_range()), reclaim will block forever waiting
+for the lock since readahead cannot relinquish the lock because it is
+itself blocked in reclaim:
+
+>>> stack_trace(1504735)
+ folio_wait_bit_common (mm/filemap.c:1308:4)
+ folio_lock (./include/linux/pagemap.h:1052:3)
+ truncate_inode_pages_range (mm/truncate.c:336:10)
+ fuse_evict_inode (fs/fuse/inode.c:161:2)
+ evict (fs/inode.c:704:3)
+ dentry_unlink_inode (fs/dcache.c:412:3)
+ __dentry_kill (fs/dcache.c:615:3)
+ shrink_kill (fs/dcache.c:1060:12)
+ shrink_dentry_list (fs/dcache.c:1087:3)
+ prune_dcache_sb (fs/dcache.c:1168:2)
+ super_cache_scan (fs/super.c:221:10)
+ do_shrink_slab (mm/shrinker.c:435:9)
+ shrink_slab (mm/shrinker.c:626:10)
+ shrink_node (mm/vmscan.c:5951:2)
+ shrink_zones (mm/vmscan.c:6195:3)
+ do_try_to_free_pages (mm/vmscan.c:6257:3)
+ do_swap_page (mm/memory.c:4136:11)
+ handle_pte_fault (mm/memory.c:5562:10)
+ handle_mm_fault (mm/memory.c:5870:9)
+ do_user_addr_fault (arch/x86/mm/fault.c:1338:10)
+ handle_page_fault (arch/x86/mm/fault.c:1481:3)
+ exc_page_fault (arch/x86/mm/fault.c:1539:2)
+ asm_exc_page_fault+0x22/0x27
+
+Fix this deadlock by allocating ff->release_args and grabbing the
+reference on the inode when preparing the file for release even if the
+server does not implement open. The inode reference will be dropped when
+the last reference on the fuse file is dropped (see fuse_file_put() ->
+fuse_release_end()).
+
+Fixes: e26ee4efbc79 ("fuse: allocate ff->release_args only if release is needed")
+Cc: stable@vger.kernel.org
+Signed-off-by: Joanne Koong <joannelkoong@gmail.com>
+Reported-by: Omar Sandoval <osandov@fb.com>
+Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/fuse/file.c |   26 +++++++++++++++++++-------
+ 1 file changed, 19 insertions(+), 7 deletions(-)
+
+--- a/fs/fuse/file.c
++++ b/fs/fuse/file.c
+@@ -113,7 +113,9 @@ static void fuse_file_put(struct fuse_fi
+               struct fuse_args *args = (ra ? &ra->args : NULL);
+               if (!args) {
+-                      /* Do nothing when server does not implement 'open' */
++                      /* Do nothing when server does not implement 'opendir' */
++              } else if (args->opcode == FUSE_RELEASE && ff->fm->fc->no_open) {
++                      fuse_release_end(ff->fm, args, 0);
+               } else if (sync) {
+                       fuse_simple_request(ff->fm, args);
+                       fuse_release_end(ff->fm, args, 0);
+@@ -134,8 +136,17 @@ struct fuse_file *fuse_file_open(struct
+       struct fuse_file *ff;
+       int opcode = isdir ? FUSE_OPENDIR : FUSE_OPEN;
+       bool open = isdir ? !fc->no_opendir : !fc->no_open;
++      bool release = !isdir || open;
+-      ff = fuse_file_alloc(fm, open);
++      /*
++       * ff->args->release_args still needs to be allocated (so we can hold an
++       * inode reference while there are pending inflight file operations when
++       * ->release() is called, see fuse_prepare_release()) even if
++       * fc->no_open is set else it becomes possible for reclaim to deadlock
++       * if while servicing the readahead request the server triggers reclaim
++       * and reclaim evicts the inode of the file being read ahead.
++       */
++      ff = fuse_file_alloc(fm, release);
+       if (!ff)
+               return ERR_PTR(-ENOMEM);
+@@ -154,13 +165,14 @@ struct fuse_file *fuse_file_open(struct
+                       fuse_file_free(ff);
+                       return ERR_PTR(err);
+               } else {
+-                      /* No release needed */
+-                      kfree(ff->release_args);
+-                      ff->release_args = NULL;
+-                      if (isdir)
++                      if (isdir) {
++                              /* No release needed */
++                              kfree(ff->release_args);
++                              ff->release_args = NULL;
+                               fc->no_opendir = 1;
+-                      else
++                      } else {
+                               fc->no_open = 1;
++                      }
+               }
+       }
diff --git a/queue-6.6/gfs2-fix-freeze-error-handling.patch b/queue-6.6/gfs2-fix-freeze-error-handling.patch
new file mode 100644 (file)
index 0000000..e5485f7
--- /dev/null
@@ -0,0 +1,47 @@
+From stable+bounces-204149-greg=kroah.com@vger.kernel.org Tue Dec 30 00:16:02 2025
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 29 Dec 2025 18:15:51 -0500
+Subject: gfs2: fix freeze error handling
+To: stable@vger.kernel.org
+Cc: Alexey Velichayshiy <a.velichayshiy@ispras.ru>, Andreas Gruenbacher <agruenba@redhat.com>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20251229231551.1812844-1-sashal@kernel.org>
+
+From: Alexey Velichayshiy <a.velichayshiy@ispras.ru>
+
+[ Upstream commit 4cfc7d5a4a01d2133b278cdbb1371fba1b419174 ]
+
+After commit b77b4a4815a9 ("gfs2: Rework freeze / thaw logic"),
+the freeze error handling is broken because gfs2_do_thaw()
+overwrites the 'error' variable, causing incorrect processing
+of the original freeze error.
+
+Fix this by calling gfs2_do_thaw() when gfs2_lock_fs_check_clean()
+fails but ignoring its return value to preserve the original
+freeze error for proper reporting.
+
+Found by Linux Verification Center (linuxtesting.org) with SVACE.
+
+Fixes: b77b4a4815a9 ("gfs2: Rework freeze / thaw logic")
+Cc: stable@vger.kernel.org # v6.5+
+Signed-off-by: Alexey Velichayshiy <a.velichayshiy@ispras.ru>
+Signed-off-by: Andreas Gruenbacher <agruenba@redhat.com>
+[ gfs2_do_thaw() only takes one param ]
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/gfs2/super.c |    4 +---
+ 1 file changed, 1 insertion(+), 3 deletions(-)
+
+--- a/fs/gfs2/super.c
++++ b/fs/gfs2/super.c
+@@ -776,9 +776,7 @@ static int gfs2_freeze_super(struct supe
+               if (!error)
+                       break;  /* success */
+-              error = gfs2_do_thaw(sdp);
+-              if (error)
+-                      goto out;
++              (void)gfs2_do_thaw(sdp);
+               if (error == -EBUSY)
+                       fs_err(sdp, "waiting for recovery before freeze\n");
diff --git a/queue-6.6/gpiolib-acpi-add-quirk-for-dell-precision-7780.patch b/queue-6.6/gpiolib-acpi-add-quirk-for-dell-precision-7780.patch
new file mode 100644 (file)
index 0000000..60af4a4
--- /dev/null
@@ -0,0 +1,61 @@
+From stable+bounces-204361-greg=kroah.com@vger.kernel.org Wed Dec 31 16:01:06 2025
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 31 Dec 2025 10:00:59 -0500
+Subject: gpiolib: acpi: Add quirk for Dell Precision 7780
+To: stable@vger.kernel.org
+Cc: Askar Safin <safinaskar@gmail.com>, Andy Shevchenko <andriy.shevchenko@linux.intel.com>, Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20251231150059.3101892-1-sashal@kernel.org>
+
+From: Askar Safin <safinaskar@gmail.com>
+
+[ Upstream commit 2d967310c49ed93ac11cef408a55ddf15c3dd52e ]
+
+Dell Precision 7780 often wakes up on its own from suspend. Sometimes
+wake up happens immediately (i. e. within 7 seconds), sometimes it happens
+after, say, 30 minutes.
+
+Fixes: 1796f808e4bb ("HID: i2c-hid: acpi: Stop setting wakeup_capable")
+Link: https://lore.kernel.org/linux-i2c/197ae95ffd8.dc819e60457077.7692120488609091556@zohomail.com/
+Cc: stable@vger.kernel.org
+Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
+Signed-off-by: Askar Safin <safinaskar@gmail.com>
+Link: https://lore.kernel.org/r/20251206180414.3183334-2-safinaskar@gmail.com
+Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
+[ adapted quirk entry location from gpiolib-acpi-quirks.c to gpiolib-acpi.c ]
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/gpio/gpiolib-acpi.c |   22 ++++++++++++++++++++++
+ 1 file changed, 22 insertions(+)
+
+--- a/drivers/gpio/gpiolib-acpi.c
++++ b/drivers/gpio/gpiolib-acpi.c
+@@ -1720,6 +1720,28 @@ static const struct dmi_system_id gpioli
+                       .ignore_interrupt = "AMDI0030:00@11",
+               },
+       },
++      {
++              /*
++               * Spurious wakeups, likely from touchpad controller
++               * Dell Precision 7780
++               * Found in BIOS 1.24.1
++               *
++               * Found in touchpad firmware, installed by Dell Touchpad Firmware Update Utility version 1160.4196.9, A01
++               * ( Dell-Touchpad-Firmware-Update-Utility_VYGNN_WIN64_1160.4196.9_A00.EXE ),
++               * released on 11 Jul 2024
++               *
++               * https://lore.kernel.org/linux-i2c/197ae95ffd8.dc819e60457077.7692120488609091556@zohomail.com/
++               */
++              .matches = {
++                      DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
++                      DMI_MATCH(DMI_PRODUCT_FAMILY, "Precision"),
++                      DMI_MATCH(DMI_PRODUCT_NAME, "Precision 7780"),
++                      DMI_MATCH(DMI_BOARD_NAME, "0C6JVW"),
++              },
++              .driver_data = &(struct acpi_gpiolib_dmi_quirk) {
++                      .ignore_wake = "VEN_0488:00@355",
++              },
++      },
+       {} /* Terminating entry */
+ };
diff --git a/queue-6.6/jbd2-fix-the-inconsistency-between-checksum-and-data-in-memory-for-journal-sb.patch b/queue-6.6/jbd2-fix-the-inconsistency-between-checksum-and-data-in-memory-for-journal-sb.patch
new file mode 100644 (file)
index 0000000..53761c2
--- /dev/null
@@ -0,0 +1,94 @@
+From stable+bounces-204155-greg=kroah.com@vger.kernel.org Tue Dec 30 00:41:07 2025
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 29 Dec 2025 18:40:57 -0500
+Subject: jbd2: fix the inconsistency between checksum and data in memory for journal sb
+To: stable@vger.kernel.org
+Cc: Ye Bin <yebin10@huawei.com>, Baokun Li <libaokun1@huawei.com>, "Darrick J. Wong" <djwong@kernel.org>, Jan Kara <jack@suse.cz>, Theodore Ts'o <tytso@mit.edu>, stable@kernel.org, Sasha Levin <sashal@kernel.org>
+Message-ID: <20251229234057.1852171-1-sashal@kernel.org>
+
+From: Ye Bin <yebin10@huawei.com>
+
+[ Upstream commit 6abfe107894af7e8ce3a2e120c619d81ee764ad5 ]
+
+Copying the file system while it is mounted as read-only results in
+a mount failure:
+[~]# mkfs.ext4 -F /dev/sdc
+[~]# mount /dev/sdc -o ro /mnt/test
+[~]# dd if=/dev/sdc of=/dev/sda bs=1M
+[~]# mount /dev/sda /mnt/test1
+[ 1094.849826] JBD2: journal checksum error
+[ 1094.850927] EXT4-fs (sda): Could not load journal inode
+mount: mount /dev/sda on /mnt/test1 failed: Bad message
+
+The process described above is just an abstracted way I came up with to
+reproduce the issue. In the actual scenario, the file system was mounted
+read-only and then copied while it was still mounted. It was found that
+the mount operation failed. The user intended to verify the data or use
+it as a backup, and this action was performed during a version upgrade.
+Above issue may happen as follows:
+ext4_fill_super
+ set_journal_csum_feature_set(sb)
+  if (ext4_has_metadata_csum(sb))
+   incompat = JBD2_FEATURE_INCOMPAT_CSUM_V3;
+  if (test_opt(sb, JOURNAL_CHECKSUM)
+   jbd2_journal_set_features(sbi->s_journal, compat, 0, incompat);
+    lock_buffer(journal->j_sb_buffer);
+    sb->s_feature_incompat  |= cpu_to_be32(incompat);
+    //The data in the journal sb was modified, but the checksum was not
+      updated, so the data remaining in memory has a mismatch between the
+      data and the checksum.
+    unlock_buffer(journal->j_sb_buffer);
+
+In this case, the journal sb copied over is in a state where the checksum
+and data are inconsistent, so mounting fails.
+To solve the above issue, update the checksum in memory after modifying
+the journal sb.
+
+Fixes: 4fd5ea43bc11 ("jbd2: checksum journal superblock")
+Signed-off-by: Ye Bin <yebin10@huawei.com>
+Reviewed-by: Baokun Li <libaokun1@huawei.com>
+Reviewed-by: Darrick J. Wong <djwong@kernel.org>
+Reviewed-by: Jan Kara <jack@suse.cz>
+Message-ID: <20251103010123.3753631-1-yebin@huaweicloud.com>
+Signed-off-by: Theodore Ts'o <tytso@mit.edu>
+Cc: stable@kernel.org
+[ jbd2_superblock_csum() also takes a journal param ]
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/jbd2/journal.c |   14 ++++++++++++++
+ 1 file changed, 14 insertions(+)
+
+--- a/fs/jbd2/journal.c
++++ b/fs/jbd2/journal.c
+@@ -2405,6 +2405,12 @@ int jbd2_journal_set_features(journal_t
+       sb->s_feature_compat    |= cpu_to_be32(compat);
+       sb->s_feature_ro_compat |= cpu_to_be32(ro);
+       sb->s_feature_incompat  |= cpu_to_be32(incompat);
++      /*
++       * Update the checksum now so that it is valid even for read-only
++       * filesystems where jbd2_write_superblock() doesn't get called.
++       */
++      if (jbd2_journal_has_csum_v2or3(journal))
++              sb->s_checksum = jbd2_superblock_csum(journal, sb);
+       unlock_buffer(journal->j_sb_buffer);
+       jbd2_journal_init_transaction_limits(journal);
+@@ -2434,9 +2440,17 @@ void jbd2_journal_clear_features(journal
+       sb = journal->j_superblock;
++      lock_buffer(journal->j_sb_buffer);
+       sb->s_feature_compat    &= ~cpu_to_be32(compat);
+       sb->s_feature_ro_compat &= ~cpu_to_be32(ro);
+       sb->s_feature_incompat  &= ~cpu_to_be32(incompat);
++      /*
++       * Update the checksum now so that it is valid even for read-only
++       * filesystems where jbd2_write_superblock() doesn't get called.
++       */
++      if (jbd2_journal_has_csum_v2or3(journal))
++              sb->s_checksum = jbd2_superblock_csum(journal, sb);
++      unlock_buffer(journal->j_sb_buffer);
+       jbd2_journal_init_transaction_limits(journal);
+ }
+ EXPORT_SYMBOL(jbd2_journal_clear_features);
diff --git a/queue-6.6/lockd-fix-vfs_test_lock-calls.patch b/queue-6.6/lockd-fix-vfs_test_lock-calls.patch
new file mode 100644 (file)
index 0000000..644d3dd
--- /dev/null
@@ -0,0 +1,181 @@
+From stable+bounces-206038-greg=kroah.com@vger.kernel.org Tue Jan  6 21:47:26 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue,  6 Jan 2026 15:34:33 -0500
+Subject: lockd: fix vfs_test_lock() calls
+To: stable@vger.kernel.org
+Cc: NeilBrown <neil@brown.name>, Olga Kornievskaia <okorniev@redhat.com>, Jeff Layton <jlayton@kernel.org>, Chuck Lever <chuck.lever@oracle.com>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260106203433.3165546-1-sashal@kernel.org>
+
+From: NeilBrown <neil@brown.name>
+
+[ Upstream commit a49a2a1baa0c553c3548a1c414b6a3c005a8deba ]
+
+Usage of vfs_test_lock() is somewhat confused.  Documentation suggests
+it is given a "lock" but this is not the case.  It is given a struct
+file_lock which contains some details of the sort of lock it should be
+looking for.
+
+In particular passing a "file_lock" containing fl_lmops or fl_ops is
+meaningless and possibly confusing.
+
+This is particularly problematic in lockd.  nlmsvc_testlock() receives
+an initialised "file_lock" from xdr-decode, including manager ops and an
+owner.  It then mistakenly passes this to vfs_test_lock() which might
+replace the owner and the ops.  This can lead to confusion when freeing
+the lock.
+
+The primary role of the 'struct file_lock' passed to vfs_test_lock() is
+to report a conflicting lock that was found, so it makes more sense for
+nlmsvc_testlock() to pass "conflock", which it uses for returning the
+conflicting lock.
+
+With this change, freeing of the lock is not confused and code in
+__nlm4svc_proc_test() and __nlmsvc_proc_test() can be simplified.
+
+Documentation for vfs_test_lock() is improved to reflect its real
+purpose, and a WARN_ON_ONCE() is added to avoid a similar problem in the
+future.
+
+Reported-by: Olga Kornievskaia <okorniev@redhat.com>
+Closes: https://lore.kernel.org/all/20251021130506.45065-1-okorniev@redhat.com
+Signed-off-by: NeilBrown <neil@brown.name>
+Fixes: 20fa19027286 ("nfs: add export operations")
+Cc: stable@vger.kernel.org
+Reviewed-by: Jeff Layton <jlayton@kernel.org>
+Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
+[ adapted fl->c.flc_* field references to flat fl->fl_* naming convention ]
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/lockd/svc4proc.c |    4 +---
+ fs/lockd/svclock.c  |   21 ++++++++++++---------
+ fs/lockd/svcproc.c  |    5 +----
+ fs/locks.c          |   12 ++++++++++--
+ 4 files changed, 24 insertions(+), 18 deletions(-)
+
+--- a/fs/lockd/svc4proc.c
++++ b/fs/lockd/svc4proc.c
+@@ -96,7 +96,6 @@ __nlm4svc_proc_test(struct svc_rqst *rqs
+       struct nlm_args *argp = rqstp->rq_argp;
+       struct nlm_host *host;
+       struct nlm_file *file;
+-      struct nlm_lockowner *test_owner;
+       __be32 rc = rpc_success;
+       dprintk("lockd: TEST4        called\n");
+@@ -106,7 +105,6 @@ __nlm4svc_proc_test(struct svc_rqst *rqs
+       if ((resp->status = nlm4svc_retrieve_args(rqstp, argp, &host, &file)))
+               return resp->status == nlm_drop_reply ? rpc_drop_reply :rpc_success;
+-      test_owner = argp->lock.fl.fl_owner;
+       /* Now check for conflicting locks */
+       resp->status = nlmsvc_testlock(rqstp, file, host, &argp->lock, &resp->lock, &resp->cookie);
+       if (resp->status == nlm_drop_reply)
+@@ -114,7 +112,7 @@ __nlm4svc_proc_test(struct svc_rqst *rqs
+       else
+               dprintk("lockd: TEST4        status %d\n", ntohl(resp->status));
+-      nlmsvc_put_lockowner(test_owner);
++      nlmsvc_release_lockowner(&argp->lock);
+       nlmsvc_release_host(host);
+       nlm_release_file(file);
+       return rc;
+--- a/fs/lockd/svclock.c
++++ b/fs/lockd/svclock.c
+@@ -615,7 +615,13 @@ nlmsvc_testlock(struct svc_rqst *rqstp,
+       }
+       mode = lock_to_openmode(&lock->fl);
+-      error = vfs_test_lock(file->f_file[mode], &lock->fl);
++      locks_init_lock(&conflock->fl);
++      /* vfs_test_lock only uses start, end, and owner, but tests fl_file */
++      conflock->fl.fl_file = lock->fl.fl_file;
++      conflock->fl.fl_start = lock->fl.fl_start;
++      conflock->fl.fl_end = lock->fl.fl_end;
++      conflock->fl.fl_owner = lock->fl.fl_owner;
++      error = vfs_test_lock(file->f_file[mode], &conflock->fl);
+       if (error) {
+               /* We can't currently deal with deferred test requests */
+               if (error == FILE_LOCK_DEFERRED)
+@@ -625,22 +631,19 @@ nlmsvc_testlock(struct svc_rqst *rqstp,
+               goto out;
+       }
+-      if (lock->fl.fl_type == F_UNLCK) {
++      if (conflock->fl.fl_type == F_UNLCK) {
+               ret = nlm_granted;
+               goto out;
+       }
+       dprintk("lockd: conflicting lock(ty=%d, %Ld-%Ld)\n",
+-              lock->fl.fl_type, (long long)lock->fl.fl_start,
+-              (long long)lock->fl.fl_end);
++              conflock->fl.fl_type, (long long)conflock->fl.fl_start,
++              (long long)conflock->fl.fl_end);
+       conflock->caller = "somehost";  /* FIXME */
+       conflock->len = strlen(conflock->caller);
+       conflock->oh.len = 0;           /* don't return OH info */
+-      conflock->svid = lock->fl.fl_pid;
+-      conflock->fl.fl_type = lock->fl.fl_type;
+-      conflock->fl.fl_start = lock->fl.fl_start;
+-      conflock->fl.fl_end = lock->fl.fl_end;
+-      locks_release_private(&lock->fl);
++      conflock->svid = conflock->fl.fl_pid;
++      locks_release_private(&conflock->fl);
+       ret = nlm_lck_denied;
+ out:
+--- a/fs/lockd/svcproc.c
++++ b/fs/lockd/svcproc.c
+@@ -117,7 +117,6 @@ __nlmsvc_proc_test(struct svc_rqst *rqst
+       struct nlm_args *argp = rqstp->rq_argp;
+       struct nlm_host *host;
+       struct nlm_file *file;
+-      struct nlm_lockowner *test_owner;
+       __be32 rc = rpc_success;
+       dprintk("lockd: TEST          called\n");
+@@ -127,8 +126,6 @@ __nlmsvc_proc_test(struct svc_rqst *rqst
+       if ((resp->status = nlmsvc_retrieve_args(rqstp, argp, &host, &file)))
+               return resp->status == nlm_drop_reply ? rpc_drop_reply :rpc_success;
+-      test_owner = argp->lock.fl.fl_owner;
+-
+       /* Now check for conflicting locks */
+       resp->status = cast_status(nlmsvc_testlock(rqstp, file, host, &argp->lock, &resp->lock, &resp->cookie));
+       if (resp->status == nlm_drop_reply)
+@@ -137,7 +134,7 @@ __nlmsvc_proc_test(struct svc_rqst *rqst
+               dprintk("lockd: TEST          status %d vers %d\n",
+                       ntohl(resp->status), rqstp->rq_vers);
+-      nlmsvc_put_lockowner(test_owner);
++      nlmsvc_release_lockowner(&argp->lock);
+       nlmsvc_release_host(host);
+       nlm_release_file(file);
+       return rc;
+--- a/fs/locks.c
++++ b/fs/locks.c
+@@ -2124,13 +2124,21 @@ SYSCALL_DEFINE2(flock, unsigned int, fd,
+ /**
+  * vfs_test_lock - test file byte range lock
+  * @filp: The file to test lock for
+- * @fl: The lock to test; also used to hold result
++ * @fl: The byte-range in the file to test; also used to hold result
+  *
++ * On entry, @fl does not contain a lock, but identifies a range (fl_start, fl_end)
++ * in the file (c.flc_file), and an owner (c.flc_owner) for whom existing locks
++ * should be ignored.  c.flc_type and c.flc_flags are ignored.
++ * Both fl_lmops and fl_ops in @fl must be NULL.
+  * Returns -ERRNO on failure.  Indicates presence of conflicting lock by
+- * setting conf->fl_type to something other than F_UNLCK.
++ * setting fl->fl_type to something other than F_UNLCK.
++ *
++ * If vfs_test_lock() does find a lock and return it, the caller must
++ * use locks_free_lock() or locks_release_private() on the returned lock.
+  */
+ int vfs_test_lock(struct file *filp, struct file_lock *fl)
+ {
++      WARN_ON_ONCE(fl->fl_ops || fl->fl_lmops);
+       WARN_ON_ONCE(filp != fl->fl_file);
+       if (filp->f_op->lock)
+               return filp->f_op->lock(filp, F_GETLK, fl);
diff --git a/queue-6.6/loongarch-refactor-register-restoration-in-ftrace_common_return.patch b/queue-6.6/loongarch-refactor-register-restoration-in-ftrace_common_return.patch
new file mode 100644 (file)
index 0000000..66eaef8
--- /dev/null
@@ -0,0 +1,78 @@
+From stable+bounces-205031-greg=kroah.com@vger.kernel.org Tue Jan  6 04:16:59 2026
+From: Huacai Chen <chenhuacai@loongson.cn>
+Date: Tue,  6 Jan 2026 11:13:00 +0800
+Subject: LoongArch: Refactor register restoration in ftrace_common_return
+To: Greg Kroah-Hartman <gregkh@linuxfoundation.org>, Sasha Levin <sashal@kernel.org>, Huacai Chen <chenhuacai@kernel.org>
+Cc: Xuerui Wang <kernel@xen0n.name>, stable@vger.kernel.org, linux-kernel@vger.kernel.org, loongarch@lists.linux.dev, Chenghao Duan <duanchenghao@kylinos.cn>, Huacai Chen <chenhuacai@loongson.cn>
+Message-ID: <20260106031300.961198-1-chenhuacai@loongson.cn>
+
+From: Chenghao Duan <duanchenghao@kylinos.cn>
+
+commit 45cb47c628dfbd1994c619f3eac271a780602826 upstream.
+
+Refactor the register restoration sequence in the ftrace_common_return
+function to clearly distinguish between the logic of normal returns and
+direct call returns in function tracing scenarios. The logic is as
+follows:
+
+1. In the case of a normal return, the execution flow returns to the
+traced function, and ftrace must ensure that the register data is
+consistent with the state when the function was entered.
+
+ra = parent return address; t0 = traced function return address.
+
+2. In the case of a direct call return, the execution flow jumps to the
+custom trampoline function, and ftrace must ensure that the register
+data is consistent with the state when ftrace was entered.
+
+ra = traced function return address; t0 = parent return address.
+
+Cc: stable@vger.kernel.org
+Fixes: 9cdc3b6a299c ("LoongArch: ftrace: Add direct call support")
+Signed-off-by: Chenghao Duan <duanchenghao@kylinos.cn>
+Signed-off-by: Huacai Chen <chenhuacai@loongson.cn>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/loongarch/kernel/mcount_dyn.S |   14 ++++++++++----
+ 1 file changed, 10 insertions(+), 4 deletions(-)
+
+--- a/arch/loongarch/kernel/mcount_dyn.S
++++ b/arch/loongarch/kernel/mcount_dyn.S
+@@ -93,7 +93,6 @@ SYM_INNER_LABEL(ftrace_graph_call, SYM_L
+  * at the callsite, so there is no need to restore the T series regs.
+  */
+ ftrace_common_return:
+-      PTR_L           ra, sp, PT_R1
+       PTR_L           a0, sp, PT_R4
+       PTR_L           a1, sp, PT_R5
+       PTR_L           a2, sp, PT_R6
+@@ -103,12 +102,17 @@ ftrace_common_return:
+       PTR_L           a6, sp, PT_R10
+       PTR_L           a7, sp, PT_R11
+       PTR_L           fp, sp, PT_R22
+-      PTR_L           t0, sp, PT_ERA
+       PTR_L           t1, sp, PT_R13
+-      PTR_ADDI        sp, sp, PT_SIZE
+       bnez            t1, .Ldirect
++
++      PTR_L           ra, sp, PT_R1
++      PTR_L           t0, sp, PT_ERA
++      PTR_ADDI        sp, sp, PT_SIZE
+       jr              t0
+ .Ldirect:
++      PTR_L           t0, sp, PT_R1
++      PTR_L           ra, sp, PT_ERA
++      PTR_ADDI        sp, sp, PT_SIZE
+       jr              t1
+ SYM_CODE_END(ftrace_common)
+@@ -155,6 +159,8 @@ SYM_CODE_END(return_to_handler)
+ #ifdef CONFIG_DYNAMIC_FTRACE_WITH_DIRECT_CALLS
+ SYM_CODE_START(ftrace_stub_direct_tramp)
+-      jr              t0
++      move            t1, ra
++      move            ra, t0
++      jr              t1
+ SYM_CODE_END(ftrace_stub_direct_tramp)
+ #endif /* CONFIG_DYNAMIC_FTRACE_WITH_DIRECT_CALLS */
diff --git a/queue-6.6/mm-consider-non-anon-swap-cache-folios-in-folio_expected_ref_count.patch b/queue-6.6/mm-consider-non-anon-swap-cache-folios-in-folio_expected_ref_count.patch
new file mode 100644 (file)
index 0000000..4857777
--- /dev/null
@@ -0,0 +1,120 @@
+From stable+bounces-206060-greg=kroah.com@vger.kernel.org Wed Jan  7 00:58:27 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue,  6 Jan 2026 18:58:14 -0500
+Subject: mm: consider non-anon swap cache folios in folio_expected_ref_count()
+To: stable@vger.kernel.org
+Cc: Bijan Tabatabai <bijan311@gmail.com>, "David Hildenbrand (Red Hat)" <david@kernel.org>, Zi Yan <ziy@nvidia.com>, Baolin Wang <baolin.wang@linux.alibaba.com>, Liam Howlett <liam.howlett@oracle.com>, Lorenzo Stoakes <lorenzo.stoakes@oracle.com>, Michal Hocko <mhocko@suse.com>, Mike Rapoport <rppt@kernel.org>, Shivank Garg <shivankg@amd.com>, Suren Baghdasaryan <surenb@google.com>, Vlastimil Babka <vbabka@suse.cz>, Kairui Song <ryncsn@gmail.com>, Andrew Morton <akpm@linux-foundation.org>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260106235814.3462036-2-sashal@kernel.org>
+
+From: Bijan Tabatabai <bijan311@gmail.com>
+
+[ Upstream commit f183663901f21fe0fba8bd31ae894bc529709ee0 ]
+
+Currently, folio_expected_ref_count() only adds references for the swap
+cache if the folio is anonymous.  However, according to the comment above
+the definition of PG_swapcache in enum pageflags, shmem folios can also
+have PG_swapcache set.  This patch makes sure references for the swap
+cache are added if folio_test_swapcache(folio) is true.
+
+This issue was found when trying to hot-unplug memory in a QEMU/KVM
+virtual machine.  When initiating hot-unplug when most of the guest memory
+is allocated, hot-unplug hangs partway through removal due to migration
+failures.  The following message would be printed several times, and would
+be printed again about every five seconds:
+
+[   49.641309] migrating pfn b12f25 failed ret:7
+[   49.641310] page: refcount:2 mapcount:0 mapping:0000000033bd8fe2 index:0x7f404d925 pfn:0xb12f25
+[   49.641311] aops:swap_aops
+[   49.641313] flags: 0x300000000030508(uptodate|active|owner_priv_1|reclaim|swapbacked|node=0|zone=3)
+[   49.641314] raw: 0300000000030508 ffffed312c4bc908 ffffed312c4bc9c8 0000000000000000
+[   49.641315] raw: 00000007f404d925 00000000000c823b 00000002ffffffff 0000000000000000
+[   49.641315] page dumped because: migration failure
+
+When debugging this, I found that these migration failures were due to
+__migrate_folio() returning -EAGAIN for a small set of folios because the
+expected reference count it calculates via folio_expected_ref_count() is
+one less than the actual reference count of the folios.  Furthermore, all
+of the affected folios were not anonymous, but had the PG_swapcache flag
+set, inspiring this patch.  After applying this patch, the memory
+hot-unplug behaves as expected.
+
+I tested this on a machine running Ubuntu 24.04 with kernel version
+6.8.0-90-generic and 64GB of memory.  The guest VM is managed by libvirt
+and runs Ubuntu 24.04 with kernel version 6.18 (though the head of the
+mm-unstable branch as a Dec 16, 2025 was also tested and behaves the same)
+and 48GB of memory.  The libvirt XML definition for the VM can be found at
+[1].  CONFIG_MHP_DEFAULT_ONLINE_TYPE_ONLINE_MOVABLE is set in the guest
+kernel so the hot-pluggable memory is automatically onlined.
+
+Below are the steps to reproduce this behavior:
+
+1) Define and start and virtual machine
+  host$ virsh -c qemu:///system define ./test_vm.xml # test_vm.xml from [1]
+  host$ virsh -c qemu:///system start test_vm
+
+2) Setup swap in the guest
+  guest$ sudo fallocate -l 32G /swapfile
+  guest$ sudo chmod 0600 /swapfile
+  guest$ sudo mkswap /swapfile
+  guest$ sudo swapon /swapfile
+
+3) Use alloc_data [2] to allocate most of the remaining guest memory
+  guest$ ./alloc_data 45
+
+4) In a separate guest terminal, monitor the amount of used memory
+  guest$ watch -n1 free -h
+
+5) When alloc_data has finished allocating, initiate the memory
+hot-unplug using the provided xml file [3]
+  host$ virsh -c qemu:///system detach-device test_vm ./remove.xml --live
+
+After initiating the memory hot-unplug, you should see the amount of
+available memory in the guest decrease, and the amount of used swap data
+increase.  If everything works as expected, when all of the memory is
+unplugged, there should be around 8.5-9GB of data in swap.  If the
+unplugging is unsuccessful, the amount of used swap data will settle below
+that.  If that happens, you should be able to see log messages in dmesg
+similar to the one posted above.
+
+Link: https://lkml.kernel.org/r/20251216200727.2360228-1-bijan311@gmail.com
+Link: https://github.com/BijanT/linux_patch_files/blob/main/test_vm.xml [1]
+Link: https://github.com/BijanT/linux_patch_files/blob/main/alloc_data.c [2]
+Link: https://github.com/BijanT/linux_patch_files/blob/main/remove.xml [3]
+Fixes: 86ebd50224c0 ("mm: add folio_expected_ref_count() for reference count calculation")
+Signed-off-by: Bijan Tabatabai <bijan311@gmail.com>
+Acked-by: David Hildenbrand (Red Hat) <david@kernel.org>
+Acked-by: Zi Yan <ziy@nvidia.com>
+Reviewed-by: Baolin Wang <baolin.wang@linux.alibaba.com>
+Cc: Liam Howlett <liam.howlett@oracle.com>
+Cc: Lorenzo Stoakes <lorenzo.stoakes@oracle.com>
+Cc: Michal Hocko <mhocko@suse.com>
+Cc: Mike Rapoport <rppt@kernel.org>
+Cc: Shivank Garg <shivankg@amd.com>
+Cc: Suren Baghdasaryan <surenb@google.com>
+Cc: Vlastimil Babka <vbabka@suse.cz>
+Cc: Kairui Song <ryncsn@gmail.com>
+Cc: <stable@vger.kernel.org>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ include/linux/mm.h |    8 ++++----
+ 1 file changed, 4 insertions(+), 4 deletions(-)
+
+--- a/include/linux/mm.h
++++ b/include/linux/mm.h
+@@ -2197,10 +2197,10 @@ static inline int folio_expected_ref_cou
+       if (WARN_ON_ONCE(page_has_type(&folio->page) && !folio_test_hugetlb(folio)))
+               return 0;
+-      if (folio_test_anon(folio)) {
+-              /* One reference per page from the swapcache. */
+-              ref_count += folio_test_swapcache(folio) << order;
+-      } else {
++      /* One reference per page from the swapcache. */
++      ref_count += folio_test_swapcache(folio) << order;
++
++      if (!folio_test_anon(folio)) {
+               /* One reference per page from the pagecache. */
+               ref_count += !!folio->mapping << order;
+               /* One reference from PG_private. */
diff --git a/queue-6.6/mm-ksm-fix-exec-fork-inheritance-support-for-prctl.patch b/queue-6.6/mm-ksm-fix-exec-fork-inheritance-support-for-prctl.patch
new file mode 100644 (file)
index 0000000..0c6e889
--- /dev/null
@@ -0,0 +1,121 @@
+From stable+bounces-204178-greg=kroah.com@vger.kernel.org Tue Dec 30 03:54:51 2025
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 29 Dec 2025 21:54:43 -0500
+Subject: mm/ksm: fix exec/fork inheritance support for prctl
+To: stable@vger.kernel.org
+Cc: xu xin <xu.xin16@zte.com.cn>, Stefan Roesch <shr@devkernel.io>, David Hildenbrand <david@redhat.com>, Jinjiang Tu <tujinjiang@huawei.com>, Wang Yaxin <wang.yaxin@zte.com.cn>, Yang Yang <yang.yang29@zte.com.cn>, Andrew Morton <akpm@linux-foundation.org>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20251230025443.1980197-1-sashal@kernel.org>
+
+From: xu xin <xu.xin16@zte.com.cn>
+
+[ Upstream commit 590c03ca6a3fbb114396673314e2aa483839608b ]
+
+Patch series "ksm: fix exec/fork inheritance", v2.
+
+This series fixes exec/fork inheritance.  See the detailed description of
+the issue below.
+
+This patch (of 2):
+
+Background
+==========
+
+commit d7597f59d1d33 ("mm: add new api to enable ksm per process")
+introduced MMF_VM_MERGE_ANY for mm->flags, and allowed user to set it by
+prctl() so that the process's VMAs are forcibly scanned by ksmd.
+
+Subsequently, the 3c6f33b7273a ("mm/ksm: support fork/exec for prctl")
+supported inheriting the MMF_VM_MERGE_ANY flag when a task calls execve().
+
+Finally, commit 3a9e567ca45fb ("mm/ksm: fix ksm exec support for prctl")
+fixed the issue that ksmd doesn't scan the mm_struct with MMF_VM_MERGE_ANY
+by adding the mm_slot to ksm_mm_head in __bprm_mm_init().
+
+Problem
+=======
+
+In some extreme scenarios, however, this inheritance of MMF_VM_MERGE_ANY
+during exec/fork can fail.  For example, when the scanning frequency of
+ksmd is tuned extremely high, a process carrying MMF_VM_MERGE_ANY may
+still fail to pass it to the newly exec'd process.  This happens because
+ksm_execve() is executed too early in the do_execve flow (prematurely
+adding the new mm_struct to the ksm_mm_slot list).
+
+As a result, before do_execve completes, ksmd may have already performed a
+scan and found that this new mm_struct has no VM_MERGEABLE VMAs, thus
+clearing its MMF_VM_MERGE_ANY flag.  Consequently, when the new program
+executes, the flag MMF_VM_MERGE_ANY inheritance missed.
+
+Root reason
+===========
+
+commit d7597f59d1d33 ("mm: add new api to enable ksm per process") clear
+the flag MMF_VM_MERGE_ANY when ksmd found no VM_MERGEABLE VMAs.
+
+Solution
+========
+
+Firstly, Don't clear MMF_VM_MERGE_ANY when ksmd found no VM_MERGEABLE
+VMAs, because perhaps their mm_struct has just been added to ksm_mm_slot
+list, and its process has not yet officially started running or has not
+yet performed mmap/brk to allocate anonymous VMAS.
+
+Secondly, recheck MMF_VM_MERGEABLE again if a process takes
+MMF_VM_MERGE_ANY, and create a mm_slot and join it into ksm_scan_list
+again.
+
+Link: https://lkml.kernel.org/r/20251007182504440BJgK8VXRHh8TD7IGSUIY4@zte.com.cn
+Link: https://lkml.kernel.org/r/20251007182821572h_SoFqYZXEP1mvWI4n9VL@zte.com.cn
+Fixes: 3c6f33b7273a ("mm/ksm: support fork/exec for prctl")
+Fixes: d7597f59d1d3 ("mm: add new api to enable ksm per process")
+Signed-off-by: xu xin <xu.xin16@zte.com.cn>
+Cc: Stefan Roesch <shr@devkernel.io>
+Cc: David Hildenbrand <david@redhat.com>
+Cc: Jinjiang Tu <tujinjiang@huawei.com>
+Cc: Wang Yaxin <wang.yaxin@zte.com.cn>
+Cc: Yang Yang <yang.yang29@zte.com.cn>
+Cc: <stable@vger.kernel.org>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+[ changed mm_flags_test() and mm_flags_clear() calls to test_bit() and clear_bit() ]
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ mm/ksm.c |   18 ++++++++++++++++--
+ 1 file changed, 16 insertions(+), 2 deletions(-)
+
+--- a/mm/ksm.c
++++ b/mm/ksm.c
+@@ -2451,8 +2451,14 @@ no_vmas:
+               spin_unlock(&ksm_mmlist_lock);
+               mm_slot_free(mm_slot_cache, mm_slot);
++              /*
++               * Only clear MMF_VM_MERGEABLE. We must not clear
++               * MMF_VM_MERGE_ANY, because for those MMF_VM_MERGE_ANY process,
++               * perhaps their mm_struct has just been added to ksm_mm_slot
++               * list, and its process has not yet officially started running
++               * or has not yet performed mmap/brk to allocate anonymous VMAS.
++               */
+               clear_bit(MMF_VM_MERGEABLE, &mm->flags);
+-              clear_bit(MMF_VM_MERGE_ANY, &mm->flags);
+               mmap_read_unlock(mm);
+               mmdrop(mm);
+       } else {
+@@ -2567,8 +2573,16 @@ void ksm_add_vma(struct vm_area_struct *
+ {
+       struct mm_struct *mm = vma->vm_mm;
+-      if (test_bit(MMF_VM_MERGE_ANY, &mm->flags))
++      if (test_bit(MMF_VM_MERGE_ANY, &mm->flags)) {
+               __ksm_add_vma(vma);
++              /*
++               * Generally, the flags here always include MMF_VM_MERGEABLE.
++               * However, in rare cases, this flag may be cleared by ksmd who
++               * scans a cycle without finding any mergeable vma.
++               */
++              if (unlikely(!test_bit(MMF_VM_MERGEABLE, &mm->flags)))
++                      __ksm_enter(mm);
++      }
+ }
+ static void ksm_add_vmas(struct mm_struct *mm)
diff --git a/queue-6.6/mm-simplify-folio_expected_ref_count.patch b/queue-6.6/mm-simplify-folio_expected_ref_count.patch
new file mode 100644 (file)
index 0000000..4184c56
--- /dev/null
@@ -0,0 +1,100 @@
+From stable+bounces-206059-greg=kroah.com@vger.kernel.org Wed Jan  7 00:58:30 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue,  6 Jan 2026 18:58:13 -0500
+Subject: mm: simplify folio_expected_ref_count()
+To: stable@vger.kernel.org
+Cc: "David Hildenbrand" <david@redhat.com>, "Zi Yan" <ziy@nvidia.com>, "Lorenzo Stoakes" <lorenzo.stoakes@oracle.com>, "Harry Yoo" <harry.yoo@oracle.com>, "Alistair Popple" <apopple@nvidia.com>, "Al Viro" <viro@zeniv.linux.org.uk>, "Arnd Bergmann" <arnd@arndb.de>, "Brendan Jackman" <jackmanb@google.com>, "Byungchul Park" <byungchul@sk.com>, "Chengming Zhou" <chengming.zhou@linux.dev>, "Christian Brauner" <brauner@kernel.org>, "Christophe Leroy" <christophe.leroy@csgroup.eu>, "Eugenio Pé rez" <eperezma@redhat.com>, "Greg Kroah-Hartman" <gregkh@linuxfoundation.org>, "Gregory Price" <gourry@gourry.net>, "Huang, Ying" <ying.huang@linux.alibaba.com>, "Jan Kara" <jack@suse.cz>, "Jason Gunthorpe" <jgg@ziepe.ca>, "Jason Wang" <jasowang@redhat.com>, "Jerrin Shaji George" <jerrin.shaji-george@broadcom.com>, "Johannes Weiner" <hannes@cmpxchg.org>, "John Hubbard" <jhubbard@nvidia.com>, "Jonathan Corbet" <corbet@lwn.net>, "Joshua Hahn" <joshua.hahnjy@gmail.com>, "Liam Howlett" <liam.howlett@oracle.com>, "Madhavan Srinivasan" <maddy@linux.ibm.com>, "Mathew Brost" <matthew.brost@intel.com>, "Matthew Wilcox (Oracle)" <willy@infradead.org>, "Miaohe Lin" <linmiaohe@huawei.com>, "Michael Ellerman" <mpe@ellerman.id.au>, "Michael S. Tsirkin" <mst@redhat.com>, "Michal Hocko" <mhocko@suse.com>, "Mike Rapoport" <rppt@kernel.org>, "Minchan Kim" <minchan@kernel.org>, "Naoya Horiguchi" <nao.horiguchi@gmail.com>, "Nicholas Piggin" <npiggin@gmail.com>, "Oscar Salvador" <osalvador@suse.de>, "Peter Xu" <peterx@redhat.com>, "Qi Zheng" <zhengqi.arch@bytedance.com>, "Rakie Kim" <rakie.kim@sk.com>, "Rik van Riel" <riel@surriel.com>, "Sergey Senozhatsky" <senozhatsky@chromium.org>, "Shakeel Butt" <shakeel.butt@linux.dev>, "Suren Baghdasaryan" <surenb@google.com>, "Vlastimil Babka" <vbabka@suse.cz>, "Xuan Zhuo" <xuanzhuo@linux.alibaba.com>, "xu xin" <xu.xin16@zte.com.cn>, "Andrew Morton" <akpm@linux-foundation.org>, "Sasha Levin" <sashal@kernel.org>
+Message-ID: <20260106235814.3462036-1-sashal@kernel.org>
+
+From: David Hildenbrand <david@redhat.com>
+
+[ Upstream commit 78cb1a13c42a6d843e21389f74d1edb90ed07288 ]
+
+Now that PAGE_MAPPING_MOVABLE is gone, we can simplify and rely on the
+folio_test_anon() test only.
+
+... but staring at the users, this function should never even have been
+called on movable_ops pages. E.g.,
+* __buffer_migrate_folio() does not make sense for them
+* folio_migrate_mapping() does not make sense for them
+* migrate_huge_page_move_mapping() does not make sense for them
+* __migrate_folio() does not make sense for them
+* ... and khugepaged should never stumble over them
+
+Let's simply refuse typed pages (which includes slab) except hugetlb, and
+WARN.
+
+Link: https://lkml.kernel.org/r/20250704102524.326966-26-david@redhat.com
+Signed-off-by: David Hildenbrand <david@redhat.com>
+Reviewed-by: Zi Yan <ziy@nvidia.com>
+Reviewed-by: Lorenzo Stoakes <lorenzo.stoakes@oracle.com>
+Reviewed-by: Harry Yoo <harry.yoo@oracle.com>
+Cc: Alistair Popple <apopple@nvidia.com>
+Cc: Al Viro <viro@zeniv.linux.org.uk>
+Cc: Arnd Bergmann <arnd@arndb.de>
+Cc: Brendan Jackman <jackmanb@google.com>
+Cc: Byungchul Park <byungchul@sk.com>
+Cc: Chengming Zhou <chengming.zhou@linux.dev>
+Cc: Christian Brauner <brauner@kernel.org>
+Cc: Christophe Leroy <christophe.leroy@csgroup.eu>
+Cc: Eugenio Pé rez <eperezma@redhat.com>
+Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Cc: Gregory Price <gourry@gourry.net>
+Cc: "Huang, Ying" <ying.huang@linux.alibaba.com>
+Cc: Jan Kara <jack@suse.cz>
+Cc: Jason Gunthorpe <jgg@ziepe.ca>
+Cc: Jason Wang <jasowang@redhat.com>
+Cc: Jerrin Shaji George <jerrin.shaji-george@broadcom.com>
+Cc: Johannes Weiner <hannes@cmpxchg.org>
+Cc: John Hubbard <jhubbard@nvidia.com>
+Cc: Jonathan Corbet <corbet@lwn.net>
+Cc: Joshua Hahn <joshua.hahnjy@gmail.com>
+Cc: Liam Howlett <liam.howlett@oracle.com>
+Cc: Madhavan Srinivasan <maddy@linux.ibm.com>
+Cc: Mathew Brost <matthew.brost@intel.com>
+Cc: Matthew Wilcox (Oracle) <willy@infradead.org>
+Cc: Miaohe Lin <linmiaohe@huawei.com>
+Cc: Michael Ellerman <mpe@ellerman.id.au>
+Cc: "Michael S. Tsirkin" <mst@redhat.com>
+Cc: Michal Hocko <mhocko@suse.com>
+Cc: Mike Rapoport <rppt@kernel.org>
+Cc: Minchan Kim <minchan@kernel.org>
+Cc: Naoya Horiguchi <nao.horiguchi@gmail.com>
+Cc: Nicholas Piggin <npiggin@gmail.com>
+Cc: Oscar Salvador <osalvador@suse.de>
+Cc: Peter Xu <peterx@redhat.com>
+Cc: Qi Zheng <zhengqi.arch@bytedance.com>
+Cc: Rakie Kim <rakie.kim@sk.com>
+Cc: Rik van Riel <riel@surriel.com>
+Cc: Sergey Senozhatsky <senozhatsky@chromium.org>
+Cc: Shakeel Butt <shakeel.butt@linux.dev>
+Cc: Suren Baghdasaryan <surenb@google.com>
+Cc: Vlastimil Babka <vbabka@suse.cz>
+Cc: Xuan Zhuo <xuanzhuo@linux.alibaba.com>
+Cc: xu xin <xu.xin16@zte.com.cn>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Stable-dep-of: f183663901f2 ("mm: consider non-anon swap cache folios in folio_expected_ref_count()")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ include/linux/mm.h |    4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+--- a/include/linux/mm.h
++++ b/include/linux/mm.h
+@@ -2194,13 +2194,13 @@ static inline int folio_expected_ref_cou
+       const int order = folio_order(folio);
+       int ref_count = 0;
+-      if (WARN_ON_ONCE(folio_test_slab(folio)))
++      if (WARN_ON_ONCE(page_has_type(&folio->page) && !folio_test_hugetlb(folio)))
+               return 0;
+       if (folio_test_anon(folio)) {
+               /* One reference per page from the swapcache. */
+               ref_count += folio_test_swapcache(folio) << order;
+-      } else if (!((unsigned long)folio->mapping & PAGE_MAPPING_FLAGS)) {
++      } else {
+               /* One reference per page from the pagecache. */
+               ref_count += !!folio->mapping << order;
+               /* One reference from PG_private. */
diff --git a/queue-6.6/mptcp-ensure-context-reset-on-disconnect.patch b/queue-6.6/mptcp-ensure-context-reset-on-disconnect.patch
new file mode 100644 (file)
index 0000000..9c62a5a
--- /dev/null
@@ -0,0 +1,122 @@
+From stable+bounces-206079-greg=kroah.com@vger.kernel.org Wed Jan  7 03:37:40 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue,  6 Jan 2026 21:34:03 -0500
+Subject: mptcp: ensure context reset on disconnect()
+To: stable@vger.kernel.org
+Cc: Paolo Abeni <pabeni@redhat.com>, "Matthieu Baerts (NGI0)" <matttbe@kernel.org>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260107023403.3509706-1-sashal@kernel.org>
+
+From: Paolo Abeni <pabeni@redhat.com>
+
+[ Upstream commit 86730ac255b0497a272704de9a1df559f5d6602e ]
+
+After the blamed commit below, if the MPC subflow is already in TCP_CLOSE
+status or has fallback to TCP at mptcp_disconnect() time,
+mptcp_do_fastclose() skips setting the `send_fastclose flag` and the later
+__mptcp_close_ssk() does not reset anymore the related subflow context.
+
+Any later connection will be created with both the `request_mptcp` flag
+and the msk-level fallback status off (it is unconditionally cleared at
+MPTCP disconnect time), leading to a warning in subflow_data_ready():
+
+  WARNING: CPU: 26 PID: 8996 at net/mptcp/subflow.c:1519 subflow_data_ready (net/mptcp/subflow.c:1519 (discriminator 13))
+  Modules linked in:
+  CPU: 26 UID: 0 PID: 8996 Comm: syz.22.39 Not tainted 6.18.0-rc7-05427-g11fc074f6c36 #1 PREEMPT(voluntary)
+  Hardware name: Bochs Bochs, BIOS Bochs 01/01/2011
+  RIP: 0010:subflow_data_ready (net/mptcp/subflow.c:1519 (discriminator 13))
+  Code: 90 0f 0b 90 90 e9 04 fe ff ff e8 b7 1e f5 fe 89 ee bf 07 00 00 00 e8 db 19 f5 fe 83 fd 07 0f 84 35 ff ff ff e8 9d 1e f5 fe 90 <0f> 0b 90 e9 27 ff ff ff e8 8f 1e f5 fe 4c 89 e7 48 89 de e8 14 09
+  RSP: 0018:ffffc9002646fb30 EFLAGS: 00010293
+  RAX: 0000000000000000 RBX: ffff88813b218000 RCX: ffffffff825c8435
+  RDX: ffff8881300b3580 RSI: ffffffff825c8443 RDI: 0000000000000005
+  RBP: 000000000000000b R08: ffffffff825c8435 R09: 000000000000000b
+  R10: 0000000000000005 R11: 0000000000000007 R12: ffff888131ac0000
+  R13: 0000000000000000 R14: 0000000000000000 R15: 0000000000000000
+  FS:  00007f88330af6c0(0000) GS:ffff888a93dd2000(0000) knlGS:0000000000000000
+  CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
+  CR2: 00007f88330aefe8 CR3: 000000010ff59000 CR4: 0000000000350ef0
+  Call Trace:
+   <TASK>
+   tcp_data_ready (net/ipv4/tcp_input.c:5356)
+   tcp_data_queue (net/ipv4/tcp_input.c:5445)
+   tcp_rcv_state_process (net/ipv4/tcp_input.c:7165)
+   tcp_v4_do_rcv (net/ipv4/tcp_ipv4.c:1955)
+   __release_sock (include/net/sock.h:1158 (discriminator 6) net/core/sock.c:3180 (discriminator 6))
+   release_sock (net/core/sock.c:3737)
+   mptcp_sendmsg (net/mptcp/protocol.c:1763 net/mptcp/protocol.c:1857)
+   inet_sendmsg (net/ipv4/af_inet.c:853 (discriminator 7))
+   __sys_sendto (net/socket.c:727 (discriminator 15) net/socket.c:742 (discriminator 15) net/socket.c:2244 (discriminator 15))
+   __x64_sys_sendto (net/socket.c:2247)
+   do_syscall_64 (arch/x86/entry/syscall_64.c:63 (discriminator 1) arch/x86/entry/syscall_64.c:94 (discriminator 1))
+   entry_SYSCALL_64_after_hwframe (arch/x86/entry/entry_64.S:130)
+  RIP: 0033:0x7f883326702d
+
+Address the issue setting an explicit `fastclosing` flag at fastclose
+time, and checking such flag after mptcp_do_fastclose().
+
+Fixes: ae155060247b ("mptcp: fix duplicate reset on fastclose")
+Cc: stable@vger.kernel.org
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+Reviewed-by: Matthieu Baerts (NGI0) <matttbe@kernel.org>
+Signed-off-by: Matthieu Baerts (NGI0) <matttbe@kernel.org>
+Link: https://patch.msgid.link/20251212-net-mptcp-subflow_data_ready-warn-v1-2-d1f9fd1c36c8@kernel.org
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+[ adapted context in mptcp_do_fastclose() to exclude missing mptcp_backlog_purge() call ]
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/mptcp/protocol.c |    8 +++++---
+ net/mptcp/protocol.h |    3 ++-
+ 2 files changed, 7 insertions(+), 4 deletions(-)
+
+--- a/net/mptcp/protocol.c
++++ b/net/mptcp/protocol.c
+@@ -2441,10 +2441,10 @@ bool __mptcp_retransmit_pending_data(str
+  */
+ static void __mptcp_subflow_disconnect(struct sock *ssk,
+                                      struct mptcp_subflow_context *subflow,
+-                                     unsigned int flags)
++                                     bool fastclosing)
+ {
+       if (((1 << ssk->sk_state) & (TCPF_CLOSE | TCPF_LISTEN)) ||
+-          subflow->send_fastclose) {
++          fastclosing) {
+               /* The MPTCP code never wait on the subflow sockets, TCP-level
+                * disconnect should never fail
+                */
+@@ -2496,7 +2496,7 @@ static void __mptcp_close_ssk(struct soc
+       need_push = (flags & MPTCP_CF_PUSH) && __mptcp_retransmit_pending_data(sk);
+       if (!dispose_it) {
+-              __mptcp_subflow_disconnect(ssk, subflow, flags);
++              __mptcp_subflow_disconnect(ssk, subflow, msk->fastclosing);
+               release_sock(ssk);
+               goto out;
+@@ -2808,6 +2808,7 @@ static void mptcp_do_fastclose(struct so
+       struct mptcp_sock *msk = mptcp_sk(sk);
+       mptcp_set_state(sk, TCP_CLOSE);
++      msk->fastclosing = 1;
+       /* Explicitly send the fastclose reset as need */
+       if (__mptcp_check_fallback(msk))
+@@ -3320,6 +3321,7 @@ static int mptcp_disconnect(struct sock
+       msk->bytes_sent = 0;
+       msk->bytes_retrans = 0;
+       msk->rcvspace_init = 0;
++      msk->fastclosing = 0;
+       WRITE_ONCE(sk->sk_shutdown, 0);
+       sk_error_report(sk);
+--- a/net/mptcp/protocol.h
++++ b/net/mptcp/protocol.h
+@@ -305,7 +305,8 @@ struct mptcp_sock {
+                       fastopening:1,
+                       in_accept_queue:1,
+                       free_first:1,
+-                      rcvspace_init:1;
++                      rcvspace_init:1,
++                      fastclosing:1;
+       int             keepalive_cnt;
+       int             keepalive_idle;
+       int             keepalive_intvl;
diff --git a/queue-6.6/mptcp-fallback-earlier-on-simult-connection.patch b/queue-6.6/mptcp-fallback-earlier-on-simult-connection.patch
new file mode 100644 (file)
index 0000000..1024711
--- /dev/null
@@ -0,0 +1,154 @@
+From stable+bounces-205177-greg=kroah.com@vger.kernel.org Tue Jan  6 18:25:31 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue,  6 Jan 2026 12:17:09 -0500
+Subject: mptcp: fallback earlier on simult connection
+To: stable@vger.kernel.org
+Cc: Paolo Abeni <pabeni@redhat.com>, syzbot+0ff6b771b4f7a5bce83b@syzkaller.appspotmail.com, "Matthieu Baerts (NGI0)" <matttbe@kernel.org>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260106171709.3088177-1-sashal@kernel.org>
+
+From: Paolo Abeni <pabeni@redhat.com>
+
+[ Upstream commit 71154bbe49423128c1c8577b6576de1ed6836830 ]
+
+Syzkaller reports a simult-connect race leading to inconsistent fallback
+status:
+
+  WARNING: CPU: 3 PID: 33 at net/mptcp/subflow.c:1515 subflow_data_ready+0x40b/0x7c0 net/mptcp/subflow.c:1515
+  Modules linked in:
+  CPU: 3 UID: 0 PID: 33 Comm: ksoftirqd/3 Not tainted syzkaller #0 PREEMPT(full)
+  Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 1.16.3-debian-1.16.3-2~bpo12+1 04/01/2014
+  RIP: 0010:subflow_data_ready+0x40b/0x7c0 net/mptcp/subflow.c:1515
+  Code: 89 ee e8 78 61 3c f6 40 84 ed 75 21 e8 8e 66 3c f6 44 89 fe bf 07 00 00 00 e8 c1 61 3c f6 41 83 ff 07 74 09 e8 76 66 3c f6 90 <0f> 0b 90 e8 6d 66 3c f6 48 89 df e8 e5 ad ff ff 31 ff 89 c5 89 c6
+  RSP: 0018:ffffc900006cf338 EFLAGS: 00010246
+  RAX: 0000000000000000 RBX: ffff888031acd100 RCX: ffffffff8b7f2abf
+  RDX: ffff88801e6ea440 RSI: ffffffff8b7f2aca RDI: 0000000000000005
+  RBP: 0000000000000000 R08: 0000000000000005 R09: 0000000000000007
+  R10: 0000000000000004 R11: 0000000000002c10 R12: ffff88802ba69900
+  R13: 1ffff920000d9e67 R14: ffff888046f81800 R15: 0000000000000004
+  FS:  0000000000000000(0000) GS:ffff8880d69bc000(0000) knlGS:0000000000000000
+  CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
+  CR2: 0000560fc0ca1670 CR3: 0000000032c3a000 CR4: 0000000000352ef0
+  Call Trace:
+   <TASK>
+   tcp_data_queue+0x13b0/0x4f90 net/ipv4/tcp_input.c:5197
+   tcp_rcv_state_process+0xfdf/0x4ec0 net/ipv4/tcp_input.c:6922
+   tcp_v6_do_rcv+0x492/0x1740 net/ipv6/tcp_ipv6.c:1672
+   tcp_v6_rcv+0x2976/0x41e0 net/ipv6/tcp_ipv6.c:1918
+   ip6_protocol_deliver_rcu+0x188/0x1520 net/ipv6/ip6_input.c:438
+   ip6_input_finish+0x1e4/0x4b0 net/ipv6/ip6_input.c:489
+   NF_HOOK include/linux/netfilter.h:318 [inline]
+   NF_HOOK include/linux/netfilter.h:312 [inline]
+   ip6_input+0x105/0x2f0 net/ipv6/ip6_input.c:500
+   dst_input include/net/dst.h:471 [inline]
+   ip6_rcv_finish net/ipv6/ip6_input.c:79 [inline]
+   NF_HOOK include/linux/netfilter.h:318 [inline]
+   NF_HOOK include/linux/netfilter.h:312 [inline]
+   ipv6_rcv+0x264/0x650 net/ipv6/ip6_input.c:311
+   __netif_receive_skb_one_core+0x12d/0x1e0 net/core/dev.c:5979
+   __netif_receive_skb+0x1d/0x160 net/core/dev.c:6092
+   process_backlog+0x442/0x15e0 net/core/dev.c:6444
+   __napi_poll.constprop.0+0xba/0x550 net/core/dev.c:7494
+   napi_poll net/core/dev.c:7557 [inline]
+   net_rx_action+0xa9f/0xfe0 net/core/dev.c:7684
+   handle_softirqs+0x216/0x8e0 kernel/softirq.c:579
+   run_ksoftirqd kernel/softirq.c:968 [inline]
+   run_ksoftirqd+0x3a/0x60 kernel/softirq.c:960
+   smpboot_thread_fn+0x3f7/0xae0 kernel/smpboot.c:160
+   kthread+0x3c2/0x780 kernel/kthread.c:463
+   ret_from_fork+0x5d7/0x6f0 arch/x86/kernel/process.c:148
+   ret_from_fork_asm+0x1a/0x30 arch/x86/entry/entry_64.S:245
+   </TASK>
+
+The TCP subflow can process the simult-connect syn-ack packet after
+transitioning to TCP_FIN1 state, bypassing the MPTCP fallback check,
+as the sk_state_change() callback is not invoked for * -> FIN_WAIT1
+transitions.
+
+That will move the msk socket to an inconsistent status and the next
+incoming data will hit the reported splat.
+
+Close the race moving the simult-fallback check at the earliest possible
+stage - that is at syn-ack generation time.
+
+About the fixes tags: [2] was supposed to also fix this issue introduced
+by [3]. [1] is required as a dependence: it was not explicitly marked as
+a fix, but it is one and it has already been backported before [3]. In
+other words, this commit should be backported up to [3], including [2]
+and [1] if that's not already there.
+
+Fixes: 23e89e8ee7be ("tcp: Don't drop SYN+ACK for simultaneous connect().") [1]
+Fixes: 4fd19a307016 ("mptcp: fix inconsistent state on fastopen race") [2]
+Fixes: 1e777f39b4d7 ("mptcp: add MSG_FASTOPEN sendmsg flag support") [3]
+Cc: stable@vger.kernel.org
+Reported-by: syzbot+0ff6b771b4f7a5bce83b@syzkaller.appspotmail.com
+Closes: https://github.com/multipath-tcp/mptcp_net-next/issues/586
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+Reviewed-by: Matthieu Baerts (NGI0) <matttbe@kernel.org>
+Signed-off-by: Matthieu Baerts (NGI0) <matttbe@kernel.org>
+Link: https://patch.msgid.link/20251212-net-mptcp-subflow_data_ready-warn-v1-1-d1f9fd1c36c8@kernel.org
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+[ adapted mptcp_try_fallback() call ]
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/mptcp/options.c  |   10 ++++++++++
+ net/mptcp/protocol.h |    6 ++----
+ net/mptcp/subflow.c  |   10 +---------
+ 3 files changed, 13 insertions(+), 13 deletions(-)
+
+--- a/net/mptcp/options.c
++++ b/net/mptcp/options.c
+@@ -408,6 +408,16 @@ bool mptcp_syn_options(struct sock *sk,
+        */
+       subflow->snd_isn = TCP_SKB_CB(skb)->end_seq;
+       if (subflow->request_mptcp) {
++              if (unlikely(subflow_simultaneous_connect(sk))) {
++                      WARN_ON_ONCE(!mptcp_try_fallback(sk));
++
++                      /* Ensure mptcp_finish_connect() will not process the
++                       * MPC handshake.
++                       */
++                      subflow->request_mptcp = 0;
++                      return false;
++              }
++
+               opts->suboptions = OPTION_MPTCP_MPC_SYN;
+               opts->csum_reqd = mptcp_is_checksum_enabled(sock_net(sk));
+               opts->allow_join_id0 = mptcp_allow_join_id0(sock_net(sk));
+--- a/net/mptcp/protocol.h
++++ b/net/mptcp/protocol.h
+@@ -1175,10 +1175,8 @@ static inline bool subflow_simultaneous_
+ {
+       struct mptcp_subflow_context *subflow = mptcp_subflow_ctx(sk);
+-      return (1 << sk->sk_state) &
+-             (TCPF_ESTABLISHED | TCPF_FIN_WAIT1 | TCPF_FIN_WAIT2 | TCPF_CLOSING) &&
+-             is_active_ssk(subflow) &&
+-             !subflow->conn_finished;
++      /* Note that the sk state implies !subflow->conn_finished. */
++      return sk->sk_state == TCP_SYN_RECV && is_active_ssk(subflow);
+ }
+ #ifdef CONFIG_SYN_COOKIES
+--- a/net/mptcp/subflow.c
++++ b/net/mptcp/subflow.c
+@@ -1793,18 +1793,10 @@ static void subflow_state_change(struct
+ {
+       struct mptcp_subflow_context *subflow = mptcp_subflow_ctx(sk);
+       struct sock *parent = subflow->conn;
+-      struct mptcp_sock *msk;
++      struct mptcp_sock *msk = mptcp_sk(parent);
+       __subflow_state_change(sk);
+-      msk = mptcp_sk(parent);
+-      if (subflow_simultaneous_connect(sk)) {
+-              WARN_ON_ONCE(!mptcp_try_fallback(sk));
+-              pr_fallback(msk);
+-              subflow->conn_finished = 1;
+-              mptcp_propagate_state(parent, sk, subflow, NULL);
+-      }
+-
+       /* as recvmsg() does not acquire the subflow socket for ssk selection
+        * a fin packet carrying a DSS can be unnoticed if we don't trigger
+        * the data available machinery here.
diff --git a/queue-6.6/mptcp-initialise-rcv_mss-before-calling-tcp_send_active_reset-in-mptcp_do_fastclose.patch b/queue-6.6/mptcp-initialise-rcv_mss-before-calling-tcp_send_active_reset-in-mptcp_do_fastclose.patch
new file mode 100644 (file)
index 0000000..4407bec
--- /dev/null
@@ -0,0 +1,95 @@
+From stable+bounces-200345-greg=kroah.com@vger.kernel.org Mon Dec  8 12:36:09 2025
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon,  8 Dec 2025 06:36:00 -0500
+Subject: mptcp: Initialise rcv_mss before calling tcp_send_active_reset() in mptcp_do_fastclose().
+To: stable@vger.kernel.org
+Cc: Kuniyuki Iwashima <kuniyu@google.com>, syzbot+3a92d359bc2ec6255a33@syzkaller.appspotmail.com, "Matthieu Baerts (NGI0)" <matttbe@kernel.org>, Paolo Abeni <pabeni@redhat.com>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20251208113600.277918-1-sashal@kernel.org>
+
+From: Kuniyuki Iwashima <kuniyu@google.com>
+
+[ Upstream commit f07f4ea53e22429c84b20832fa098b5ecc0d4e35 ]
+
+syzbot reported divide-by-zero in __tcp_select_window() by
+MPTCP socket. [0]
+
+We had a similar issue for the bare TCP and fixed in commit
+499350a5a6e7 ("tcp: initialize rcv_mss to TCP_MIN_MSS instead
+of 0").
+
+Let's apply the same fix to mptcp_do_fastclose().
+
+[0]:
+Oops: divide error: 0000 [#1] SMP KASAN PTI
+CPU: 0 UID: 0 PID: 6068 Comm: syz.0.17 Not tainted syzkaller #0 PREEMPT(full)
+Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 10/25/2025
+RIP: 0010:__tcp_select_window+0x824/0x1320 net/ipv4/tcp_output.c:3336
+Code: ff ff ff 44 89 f1 d3 e0 89 c1 f7 d1 41 01 cc 41 21 c4 e9 a9 00 00 00 e8 ca 49 01 f8 e9 9c 00 00 00 e8 c0 49 01 f8 44 89 e0 99 <f7> 7c 24 1c 41 29 d4 48 bb 00 00 00 00 00 fc ff df e9 80 00 00 00
+RSP: 0018:ffffc90003017640 EFLAGS: 00010293
+RAX: 0000000000000000 RBX: 0000000000000000 RCX: ffff88807b469e40
+RDX: 0000000000000000 RSI: 0000000000000000 RDI: 0000000000000000
+RBP: ffffc90003017730 R08: ffff888033268143 R09: 1ffff1100664d028
+R10: dffffc0000000000 R11: ffffed100664d029 R12: 0000000000000000
+R13: 0000000000000000 R14: 0000000000000000 R15: 0000000000000000
+FS:  000055557faa0500(0000) GS:ffff888126135000(0000) knlGS:0000000000000000
+CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
+CR2: 00007f64a1912ff8 CR3: 0000000072122000 CR4: 00000000003526f0
+Call Trace:
+ <TASK>
+ tcp_select_window net/ipv4/tcp_output.c:281 [inline]
+ __tcp_transmit_skb+0xbc7/0x3aa0 net/ipv4/tcp_output.c:1568
+ tcp_transmit_skb net/ipv4/tcp_output.c:1649 [inline]
+ tcp_send_active_reset+0x2d1/0x5b0 net/ipv4/tcp_output.c:3836
+ mptcp_do_fastclose+0x27e/0x380 net/mptcp/protocol.c:2793
+ mptcp_disconnect+0x238/0x710 net/mptcp/protocol.c:3253
+ mptcp_sendmsg_fastopen+0x2f8/0x580 net/mptcp/protocol.c:1776
+ mptcp_sendmsg+0x1774/0x1980 net/mptcp/protocol.c:1855
+ sock_sendmsg_nosec net/socket.c:727 [inline]
+ __sock_sendmsg+0xe5/0x270 net/socket.c:742
+ __sys_sendto+0x3bd/0x520 net/socket.c:2244
+ __do_sys_sendto net/socket.c:2251 [inline]
+ __se_sys_sendto net/socket.c:2247 [inline]
+ __x64_sys_sendto+0xde/0x100 net/socket.c:2247
+ do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline]
+ do_syscall_64+0xfa/0xfa0 arch/x86/entry/syscall_64.c:94
+ entry_SYSCALL_64_after_hwframe+0x77/0x7f
+RIP: 0033:0x7f66e998f749
+Code: ff ff c3 66 2e 0f 1f 84 00 00 00 00 00 0f 1f 40 00 48 89 f8 48 89 f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 c7 c1 a8 ff ff ff f7 d8 64 89 01 48
+RSP: 002b:00007ffff9acedb8 EFLAGS: 00000246 ORIG_RAX: 000000000000002c
+RAX: ffffffffffffffda RBX: 00007f66e9be5fa0 RCX: 00007f66e998f749
+RDX: 0000000000000000 RSI: 0000000000000000 RDI: 0000000000000003
+RBP: 00007ffff9acee10 R08: 0000000000000000 R09: 0000000000000000
+R10: 0000000000000000 R11: 0000000000000246 R12: 0000000000000001
+R13: 00007f66e9be5fa0 R14: 00007f66e9be5fa0 R15: 0000000000000006
+ </TASK>
+
+Fixes: ae155060247b ("mptcp: fix duplicate reset on fastclose")
+Reported-by: syzbot+3a92d359bc2ec6255a33@syzkaller.appspotmail.com
+Closes: https://lore.kernel.org/netdev/69260882.a70a0220.d98e3.00b4.GAE@google.com/
+Signed-off-by: Kuniyuki Iwashima <kuniyu@google.com>
+Reviewed-by: Matthieu Baerts (NGI0) <matttbe@kernel.org>
+Cc: stable@vger.kernel.org
+Link: https://patch.msgid.link/20251125195331.309558-1-kuniyu@google.com
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+[ Adjust context ]
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/mptcp/protocol.c |    6 ++++++
+ 1 file changed, 6 insertions(+)
+
+--- a/net/mptcp/protocol.c
++++ b/net/mptcp/protocol.c
+@@ -2823,6 +2823,12 @@ static void mptcp_do_fastclose(struct so
+                       goto unlock;
+               subflow->send_fastclose = 1;
++
++              /* Initialize rcv_mss to TCP_MIN_MSS to avoid division by 0
++               * issue in __tcp_select_window(), see tcp_disconnect().
++               */
++              inet_csk(ssk)->icsk_ack.rcv_mss = TCP_MIN_MSS;
++
+               tcp_send_active_reset(ssk, ssk->sk_allocation);
+ unlock:
+               release_sock(ssk);
diff --git a/queue-6.6/mptcp-pm-ignore-unknown-endpoint-flags.patch b/queue-6.6/mptcp-pm-ignore-unknown-endpoint-flags.patch
new file mode 100644 (file)
index 0000000..46f2531
--- /dev/null
@@ -0,0 +1,68 @@
+From stable+bounces-204219-greg=kroah.com@vger.kernel.org Tue Dec 30 14:42:15 2025
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 30 Dec 2025 08:42:06 -0500
+Subject: mptcp: pm: ignore unknown endpoint flags
+To: stable@vger.kernel.org
+Cc: "Matthieu Baerts (NGI0)" <matttbe@kernel.org>, Mat Martineau <martineau@kernel.org>, Jakub Kicinski <kuba@kernel.org>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20251230134206.2207988-1-sashal@kernel.org>
+
+From: "Matthieu Baerts (NGI0)" <matttbe@kernel.org>
+
+[ Upstream commit 0ace3297a7301911e52d8195cb1006414897c859 ]
+
+Before this patch, the kernel was saving any flags set by the userspace,
+even unknown ones. This doesn't cause critical issues because the kernel
+is only looking at specific ones. But on the other hand, endpoints dumps
+could tell the userspace some recent flags seem to be supported on older
+kernel versions.
+
+Instead, ignore all unknown flags when parsing them. By doing that, the
+userspace can continue to set unsupported flags, but it has a way to
+verify what is supported by the kernel.
+
+Note that it sounds better to continue accepting unsupported flags not
+to change the behaviour, but also that eases things on the userspace
+side by adding "optional" endpoint types only supported by newer kernel
+versions without having to deal with the different kernel versions.
+
+A note for the backports: there will be conflicts in mptcp.h on older
+versions not having the mentioned flags, the new line should still be
+added last, and the '5' needs to be adapted to have the same value as
+the last entry.
+
+Fixes: 01cacb00b35c ("mptcp: add netlink-based PM")
+Cc: stable@vger.kernel.org
+Reviewed-by: Mat Martineau <martineau@kernel.org>
+Signed-off-by: Matthieu Baerts (NGI0) <matttbe@kernel.org>
+Link: https://patch.msgid.link/20251205-net-mptcp-misc-fixes-6-19-rc1-v1-1-9e4781a6c1b8@kernel.org
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+[ GENMASK(5, 0) => GENMASK(4, 0) + context ]
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ include/uapi/linux/mptcp.h |    1 +
+ net/mptcp/pm_netlink.c     |    3 ++-
+ 2 files changed, 3 insertions(+), 1 deletion(-)
+
+--- a/include/uapi/linux/mptcp.h
++++ b/include/uapi/linux/mptcp.h
+@@ -88,6 +88,7 @@ enum {
+ #define MPTCP_PM_ADDR_FLAG_BACKUP                     (1 << 2)
+ #define MPTCP_PM_ADDR_FLAG_FULLMESH                   (1 << 3)
+ #define MPTCP_PM_ADDR_FLAG_IMPLICIT                   (1 << 4)
++#define MPTCP_PM_ADDR_FLAGS_MASK                      GENMASK(4, 0)
+ enum {
+       MPTCP_PM_CMD_UNSPEC,
+--- a/net/mptcp/pm_netlink.c
++++ b/net/mptcp/pm_netlink.c
+@@ -1435,7 +1435,8 @@ int mptcp_pm_parse_entry(struct nlattr *
+       }
+       if (tb[MPTCP_PM_ADDR_ATTR_FLAGS])
+-              entry->flags = nla_get_u32(tb[MPTCP_PM_ADDR_ATTR_FLAGS]);
++              entry->flags = nla_get_u32(tb[MPTCP_PM_ADDR_ATTR_FLAGS]) &
++                             MPTCP_PM_ADDR_FLAGS_MASK;
+       if (tb[MPTCP_PM_ADDR_ATTR_PORT])
+               entry->addr.port = htons(nla_get_u16(tb[MPTCP_PM_ADDR_ATTR_PORT]));
diff --git a/queue-6.6/net-phy-mediatek-fix-nvmem-cell-reference-leak-in-mt798x_phy_calibration.patch b/queue-6.6/net-phy-mediatek-fix-nvmem-cell-reference-leak-in-mt798x_phy_calibration.patch
new file mode 100644 (file)
index 0000000..0af15e1
--- /dev/null
@@ -0,0 +1,46 @@
+From stable+bounces-206078-greg=kroah.com@vger.kernel.org Wed Jan  7 03:37:34 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue,  6 Jan 2026 21:33:35 -0500
+Subject: net: phy: mediatek: fix nvmem cell reference leak in mt798x_phy_calibration
+To: stable@vger.kernel.org
+Cc: Miaoqian Lin <linmq006@gmail.com>, Daniel Golle <daniel@makrotopia.org>, Andrew Lunn <andrew@lunn.ch>, Paolo Abeni <pabeni@redhat.com>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260107023335.3509482-1-sashal@kernel.org>
+
+From: Miaoqian Lin <linmq006@gmail.com>
+
+[ Upstream commit 1e5a541420b8c6d87d88eb50b6b978cdeafee1c9 ]
+
+When nvmem_cell_read() fails in mt798x_phy_calibration(), the function
+returns without calling nvmem_cell_put(), leaking the cell reference.
+
+Move nvmem_cell_put() right after nvmem_cell_read() to ensure the cell
+reference is always released regardless of the read result.
+
+Found via static analysis and code review.
+
+Fixes: 98c485eaf509 ("net: phy: add driver for MediaTek SoC built-in GE PHYs")
+Cc: stable@vger.kernel.org
+Signed-off-by: Miaoqian Lin <linmq006@gmail.com>
+Reviewed-by: Daniel Golle <daniel@makrotopia.org>
+Reviewed-by: Andrew Lunn <andrew@lunn.ch>
+Link: https://patch.msgid.link/20251211081313.2368460-1-linmq006@gmail.com
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/net/phy/mediatek-ge-soc.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/net/phy/mediatek-ge-soc.c
++++ b/drivers/net/phy/mediatek-ge-soc.c
+@@ -1082,9 +1082,9 @@ static int mt798x_phy_calibration(struct
+       }
+       buf = (u32 *)nvmem_cell_read(cell, &len);
++      nvmem_cell_put(cell);
+       if (IS_ERR(buf))
+               return PTR_ERR(buf);
+-      nvmem_cell_put(cell);
+       if (!buf[0] || !buf[1] || !buf[2] || !buf[3] || len < 4 * sizeof(u32)) {
+               phydev_err(phydev, "invalid efuse data\n");
diff --git a/queue-6.6/net-remove-rtnl-dance-for-siocbraddif-and-siocbrdelif.patch b/queue-6.6/net-remove-rtnl-dance-for-siocbraddif-and-siocbrdelif.patch
new file mode 100644 (file)
index 0000000..36d5229
--- /dev/null
@@ -0,0 +1,300 @@
+From stable+bounces-206189-greg=kroah.com@vger.kernel.org Wed Jan  7 19:17:16 2026
+From: Thadeu Lima de Souza Cascardo <cascardo@igalia.com>
+Date: Wed,  7 Jan 2026 14:21:02 -0300
+Subject: net: Remove RTNL dance for SIOCBRADDIF and SIOCBRDELIF.
+To: stable@vger.kernel.org
+Cc: Thadeu Lima de Souza Cascardo <cascardo@igalia.com>, syzkaller <syzkaller@googlegroups.com>, yan kang <kangyan91@outlook.com>, yue sun <samsun1006219@gmail.com>, Kuniyuki Iwashima <kuniyu@amazon.com>, Stanislav Fomichev <sdf@fomichev.me>, Ido Schimmel <idosch@nvidia.com>, Nikolay Aleksandrov <razor@blackwall.org>, Paolo Abeni <pabeni@redhat.com>
+Message-ID: <20260107172102.2488465-1-cascardo@igalia.com>
+
+From: Thadeu Lima de Souza Cascardo <cascardo@igalia.com>
+
+commit ed3ba9b6e280e14cc3148c1b226ba453f02fa76c upstream.
+
+SIOCBRDELIF is passed to dev_ioctl() first and later forwarded to
+br_ioctl_call(), which causes unnecessary RTNL dance and the splat
+below [0] under RTNL pressure.
+
+Let's say Thread A is trying to detach a device from a bridge and
+Thread B is trying to remove the bridge.
+
+In dev_ioctl(), Thread A bumps the bridge device's refcnt by
+netdev_hold() and releases RTNL because the following br_ioctl_call()
+also re-acquires RTNL.
+
+In the race window, Thread B could acquire RTNL and try to remove
+the bridge device.  Then, rtnl_unlock() by Thread B will release RTNL
+and wait for netdev_put() by Thread A.
+
+Thread A, however, must hold RTNL after the unlock in dev_ifsioc(),
+which may take long under RTNL pressure, resulting in the splat by
+Thread B.
+
+  Thread A (SIOCBRDELIF)           Thread B (SIOCBRDELBR)
+  ----------------------           ----------------------
+  sock_ioctl                       sock_ioctl
+  `- sock_do_ioctl                 `- br_ioctl_call
+     `- dev_ioctl                     `- br_ioctl_stub
+        |- rtnl_lock                     |
+        |- dev_ifsioc                    '
+        '  |- dev = __dev_get_by_name(...)
+           |- netdev_hold(dev, ...)      .
+       /   |- rtnl_unlock  ------.       |
+       |   |- br_ioctl_call       `--->  |- rtnl_lock
+  Race |   |  `- br_ioctl_stub           |- br_del_bridge
+  Window   |     |                       |  |- dev = __dev_get_by_name(...)
+       |   |     |  May take long        |  `- br_dev_delete(dev, ...)
+       |   |     |  under RTNL pressure  |     `- unregister_netdevice_queue(dev, ...)
+       |   |     |               |       `- rtnl_unlock
+       \   |     |- rtnl_lock  <-'          `- netdev_run_todo
+           |     |- ...                        `- netdev_run_todo
+           |     `- rtnl_unlock                   |- __rtnl_unlock
+           |                                      |- netdev_wait_allrefs_any
+           |- netdev_put(dev, ...)  <----------------'
+                                                Wait refcnt decrement
+                                                and log splat below
+
+To avoid blocking SIOCBRDELBR unnecessarily, let's not call
+dev_ioctl() for SIOCBRADDIF and SIOCBRDELIF.
+
+In the dev_ioctl() path, we do the following:
+
+  1. Copy struct ifreq by get_user_ifreq in sock_do_ioctl()
+  2. Check CAP_NET_ADMIN in dev_ioctl()
+  3. Call dev_load() in dev_ioctl()
+  4. Fetch the master dev from ifr.ifr_name in dev_ifsioc()
+
+3. can be done by request_module() in br_ioctl_call(), so we move
+1., 2., and 4. to br_ioctl_stub().
+
+Note that 2. is also checked later in add_del_if(), but it's better
+performed before RTNL.
+
+SIOCBRADDIF and SIOCBRDELIF have been processed in dev_ioctl() since
+the pre-git era, and there seems to be no specific reason to process
+them there.
+
+[0]:
+unregister_netdevice: waiting for wpan3 to become free. Usage count = 2
+ref_tracker: wpan3@ffff8880662d8608 has 1/1 users at
+     __netdev_tracker_alloc include/linux/netdevice.h:4282 [inline]
+     netdev_hold include/linux/netdevice.h:4311 [inline]
+     dev_ifsioc+0xc6a/0x1160 net/core/dev_ioctl.c:624
+     dev_ioctl+0x255/0x10c0 net/core/dev_ioctl.c:826
+     sock_do_ioctl+0x1ca/0x260 net/socket.c:1213
+     sock_ioctl+0x23a/0x6c0 net/socket.c:1318
+     vfs_ioctl fs/ioctl.c:51 [inline]
+     __do_sys_ioctl fs/ioctl.c:906 [inline]
+     __se_sys_ioctl fs/ioctl.c:892 [inline]
+     __x64_sys_ioctl+0x1a4/0x210 fs/ioctl.c:892
+     do_syscall_x64 arch/x86/entry/common.c:52 [inline]
+     do_syscall_64+0xcb/0x250 arch/x86/entry/common.c:83
+     entry_SYSCALL_64_after_hwframe+0x77/0x7f
+
+Fixes: 893b19587534 ("net: bridge: fix ioctl locking")
+Reported-by: syzkaller <syzkaller@googlegroups.com>
+Reported-by: yan kang <kangyan91@outlook.com>
+Reported-by: yue sun <samsun1006219@gmail.com>
+Closes: https://lore.kernel.org/netdev/SY8P300MB0421225D54EB92762AE8F0F2A1D32@SY8P300MB0421.AUSP300.PROD.OUTLOOK.COM/
+Signed-off-by: Kuniyuki Iwashima <kuniyu@amazon.com>
+Acked-by: Stanislav Fomichev <sdf@fomichev.me>
+Reviewed-by: Ido Schimmel <idosch@nvidia.com>
+Acked-by: Nikolay Aleksandrov <razor@blackwall.org>
+Link: https://patch.msgid.link/20250316192851.19781-1-kuniyu@amazon.com
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+[cascardo: fixed conflict at dev_ifsioc]
+Signed-off-by: Thadeu Lima de Souza Cascardo <cascardo@igalia.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ include/linux/if_bridge.h |    6 ++----
+ net/bridge/br_ioctl.c     |   36 +++++++++++++++++++++++++++++++++---
+ net/bridge/br_private.h   |    3 +--
+ net/core/dev_ioctl.c      |   16 ----------------
+ net/socket.c              |   19 +++++++++----------
+ 5 files changed, 45 insertions(+), 35 deletions(-)
+
+--- a/include/linux/if_bridge.h
++++ b/include/linux/if_bridge.h
+@@ -65,11 +65,9 @@ struct br_ip_list {
+ #define BR_DEFAULT_AGEING_TIME        (300 * HZ)
+ struct net_bridge;
+-void brioctl_set(int (*hook)(struct net *net, struct net_bridge *br,
+-                           unsigned int cmd, struct ifreq *ifr,
++void brioctl_set(int (*hook)(struct net *net, unsigned int cmd,
+                            void __user *uarg));
+-int br_ioctl_call(struct net *net, struct net_bridge *br, unsigned int cmd,
+-                struct ifreq *ifr, void __user *uarg);
++int br_ioctl_call(struct net *net, unsigned int cmd, void __user *uarg);
+ #if IS_ENABLED(CONFIG_BRIDGE) && IS_ENABLED(CONFIG_BRIDGE_IGMP_SNOOPING)
+ int br_multicast_list_adjacent(struct net_device *dev,
+--- a/net/bridge/br_ioctl.c
++++ b/net/bridge/br_ioctl.c
+@@ -394,10 +394,26 @@ static int old_deviceless(struct net *ne
+       return -EOPNOTSUPP;
+ }
+-int br_ioctl_stub(struct net *net, struct net_bridge *br, unsigned int cmd,
+-                struct ifreq *ifr, void __user *uarg)
++int br_ioctl_stub(struct net *net, unsigned int cmd, void __user *uarg)
+ {
+       int ret = -EOPNOTSUPP;
++      struct ifreq ifr;
++
++      if (cmd == SIOCBRADDIF || cmd == SIOCBRDELIF) {
++              void __user *data;
++              char *colon;
++
++              if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
++                      return -EPERM;
++
++              if (get_user_ifreq(&ifr, &data, uarg))
++                      return -EFAULT;
++
++              ifr.ifr_name[IFNAMSIZ - 1] = 0;
++              colon = strchr(ifr.ifr_name, ':');
++              if (colon)
++                      *colon = 0;
++      }
+       rtnl_lock();
+@@ -430,7 +446,21 @@ int br_ioctl_stub(struct net *net, struc
+               break;
+       case SIOCBRADDIF:
+       case SIOCBRDELIF:
+-              ret = add_del_if(br, ifr->ifr_ifindex, cmd == SIOCBRADDIF);
++      {
++              struct net_device *dev;
++
++              dev = __dev_get_by_name(net, ifr.ifr_name);
++              if (!dev || !netif_device_present(dev)) {
++                      ret = -ENODEV;
++                      break;
++              }
++              if (!netif_is_bridge_master(dev)) {
++                      ret = -EOPNOTSUPP;
++                      break;
++              }
++
++              ret = add_del_if(netdev_priv(dev), ifr.ifr_ifindex, cmd == SIOCBRADDIF);
++      }
+               break;
+       }
+--- a/net/bridge/br_private.h
++++ b/net/bridge/br_private.h
+@@ -948,8 +948,7 @@ br_port_get_check_rtnl(const struct net_
+ /* br_ioctl.c */
+ int br_dev_siocdevprivate(struct net_device *dev, struct ifreq *rq,
+                         void __user *data, int cmd);
+-int br_ioctl_stub(struct net *net, struct net_bridge *br, unsigned int cmd,
+-                struct ifreq *ifr, void __user *uarg);
++int br_ioctl_stub(struct net *net, unsigned int cmd, void __user *uarg);
+ /* br_multicast.c */
+ #ifdef CONFIG_BRIDGE_IGMP_SNOOPING
+--- a/net/core/dev_ioctl.c
++++ b/net/core/dev_ioctl.c
+@@ -517,7 +517,6 @@ static int dev_ifsioc(struct net *net, s
+       int err;
+       struct net_device *dev = __dev_get_by_name(net, ifr->ifr_name);
+       const struct net_device_ops *ops;
+-      netdevice_tracker dev_tracker;
+       if (!dev)
+               return -ENODEV;
+@@ -580,19 +579,6 @@ static int dev_ifsioc(struct net *net, s
+       case SIOCWANDEV:
+               return dev_siocwandev(dev, &ifr->ifr_settings);
+-      case SIOCBRADDIF:
+-      case SIOCBRDELIF:
+-              if (!netif_device_present(dev))
+-                      return -ENODEV;
+-              if (!netif_is_bridge_master(dev))
+-                      return -EOPNOTSUPP;
+-              netdev_hold(dev, &dev_tracker, GFP_KERNEL);
+-              rtnl_unlock();
+-              err = br_ioctl_call(net, netdev_priv(dev), cmd, ifr, NULL);
+-              netdev_put(dev, &dev_tracker);
+-              rtnl_lock();
+-              return err;
+-
+       case SIOCDEVPRIVATE ... SIOCDEVPRIVATE + 15:
+               return dev_siocdevprivate(dev, ifr, data, cmd);
+@@ -773,8 +759,6 @@ int dev_ioctl(struct net *net, unsigned
+       case SIOCBONDRELEASE:
+       case SIOCBONDSETHWADDR:
+       case SIOCBONDCHANGEACTIVE:
+-      case SIOCBRADDIF:
+-      case SIOCBRDELIF:
+       case SIOCSHWTSTAMP:
+               if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
+                       return -EPERM;
+--- a/net/socket.c
++++ b/net/socket.c
+@@ -1168,12 +1168,10 @@ static ssize_t sock_write_iter(struct ki
+  */
+ static DEFINE_MUTEX(br_ioctl_mutex);
+-static int (*br_ioctl_hook)(struct net *net, struct net_bridge *br,
+-                          unsigned int cmd, struct ifreq *ifr,
++static int (*br_ioctl_hook)(struct net *net, unsigned int cmd,
+                           void __user *uarg);
+-void brioctl_set(int (*hook)(struct net *net, struct net_bridge *br,
+-                           unsigned int cmd, struct ifreq *ifr,
++void brioctl_set(int (*hook)(struct net *net, unsigned int cmd,
+                            void __user *uarg))
+ {
+       mutex_lock(&br_ioctl_mutex);
+@@ -1182,8 +1180,7 @@ void brioctl_set(int (*hook)(struct net
+ }
+ EXPORT_SYMBOL(brioctl_set);
+-int br_ioctl_call(struct net *net, struct net_bridge *br, unsigned int cmd,
+-                struct ifreq *ifr, void __user *uarg)
++int br_ioctl_call(struct net *net, unsigned int cmd, void __user *uarg)
+ {
+       int err = -ENOPKG;
+@@ -1192,7 +1189,7 @@ int br_ioctl_call(struct net *net, struc
+       mutex_lock(&br_ioctl_mutex);
+       if (br_ioctl_hook)
+-              err = br_ioctl_hook(net, br, cmd, ifr, uarg);
++              err = br_ioctl_hook(net, cmd, uarg);
+       mutex_unlock(&br_ioctl_mutex);
+       return err;
+@@ -1292,7 +1289,9 @@ static long sock_ioctl(struct file *file
+               case SIOCSIFBR:
+               case SIOCBRADDBR:
+               case SIOCBRDELBR:
+-                      err = br_ioctl_call(net, NULL, cmd, NULL, argp);
++              case SIOCBRADDIF:
++              case SIOCBRDELIF:
++                      err = br_ioctl_call(net, cmd, argp);
+                       break;
+               case SIOCGIFVLAN:
+               case SIOCSIFVLAN:
+@@ -3454,6 +3453,8 @@ static int compat_sock_ioctl_trans(struc
+       case SIOCGPGRP:
+       case SIOCBRADDBR:
+       case SIOCBRDELBR:
++      case SIOCBRADDIF:
++      case SIOCBRDELIF:
+       case SIOCGIFVLAN:
+       case SIOCSIFVLAN:
+       case SIOCGSKNS:
+@@ -3493,8 +3494,6 @@ static int compat_sock_ioctl_trans(struc
+       case SIOCGIFPFLAGS:
+       case SIOCGIFTXQLEN:
+       case SIOCSIFTXQLEN:
+-      case SIOCBRADDIF:
+-      case SIOCBRDELIF:
+       case SIOCGIFNAME:
+       case SIOCSIFNAME:
+       case SIOCGMIIPHY:
diff --git a/queue-6.6/nfsd-clear-seclabel-in-the-suppattr_exclcreat-bitmap.patch b/queue-6.6/nfsd-clear-seclabel-in-the-suppattr_exclcreat-bitmap.patch
new file mode 100644 (file)
index 0000000..77d0923
--- /dev/null
@@ -0,0 +1,57 @@
+From stable+bounces-204317-greg=kroah.com@vger.kernel.org Wed Dec 31 04:46:56 2025
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 30 Dec 2025 22:46:07 -0500
+Subject: NFSD: Clear SECLABEL in the suppattr_exclcreat bitmap
+To: stable@vger.kernel.org
+Cc: Chuck Lever <chuck.lever@oracle.com>, Jeff Layton <jlayton@kernel.org>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20251231034607.2717171-1-sashal@kernel.org>
+
+From: Chuck Lever <chuck.lever@oracle.com>
+
+[ Upstream commit 27d17641cacfedd816789b75d342430f6b912bd2 ]
+
+>>From RFC 8881:
+
+5.8.1.14. Attribute 75: suppattr_exclcreat
+
+> The bit vector that would set all REQUIRED and RECOMMENDED
+> attributes that are supported by the EXCLUSIVE4_1 method of file
+> creation via the OPEN operation. The scope of this attribute
+> applies to all objects with a matching fsid.
+
+There's nothing in RFC 8881 that states that suppattr_exclcreat is
+or is not allowed to contain bits for attributes that are clear in
+the reported supported_attrs bitmask. But it doesn't make sense for
+an NFS server to indicate that it /doesn't/ implement an attribute,
+but then also indicate that clients /are/ allowed to set that
+attribute using OPEN(create) with EXCLUSIVE4_1.
+
+Ensure that the SECURITY_LABEL and ACL bits are not set in the
+suppattr_exclcreat bitmask when they are also not set in the
+supported_attrs bitmask.
+
+Fixes: 8c18f2052e75 ("nfsd41: SUPPATTR_EXCLCREAT attribute")
+Cc: stable@vger.kernel.org
+Reviewed-by: Jeff Layton <jlayton@kernel.org>
+Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
+[ Adjust context ]
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/nfsd/nfs4xdr.c |    5 +++++
+ 1 file changed, 5 insertions(+)
+
+--- a/fs/nfsd/nfs4xdr.c
++++ b/fs/nfsd/nfs4xdr.c
+@@ -3419,6 +3419,11 @@ out_acl:
+               u32 supp[3];
+               memcpy(supp, nfsd_suppattrs[minorversion], sizeof(supp));
++              if (!IS_POSIXACL(d_inode(dentry)))
++                      supp[0] &= ~FATTR4_WORD0_ACL;
++              if (!contextsupport)
++                      supp[2] &= ~FATTR4_WORD2_SECURITY_LABEL;
++
+               supp[0] &= NFSD_SUPPATTR_EXCLCREAT_WORD0;
+               supp[1] &= NFSD_SUPPATTR_EXCLCREAT_WORD1;
+               supp[2] &= NFSD_SUPPATTR_EXCLCREAT_WORD2;
diff --git a/queue-6.6/pci-brcmstb-fix-disabling-l0s-capability.patch b/queue-6.6/pci-brcmstb-fix-disabling-l0s-capability.patch
new file mode 100644 (file)
index 0000000..173c6eb
--- /dev/null
@@ -0,0 +1,79 @@
+From stable+bounces-204891-greg=kroah.com@vger.kernel.org Mon Jan  5 19:56:05 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon,  5 Jan 2026 13:55:56 -0500
+Subject: PCI: brcmstb: Fix disabling L0s capability
+To: stable@vger.kernel.org
+Cc: Jim Quinlan <james.quinlan@broadcom.com>, Bjorn Helgaas <bhelgaas@google.com>, Manivannan Sadhasivam <mani@kernel.org>, Florian Fainelli <florian.fainelli@broadcom.com>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260105185556.2726479-1-sashal@kernel.org>
+
+From: Jim Quinlan <james.quinlan@broadcom.com>
+
+[ Upstream commit 9583f9d22991d2cfb5cc59a2552040c4ae98d998 ]
+
+caab002d5069 ("PCI: brcmstb: Disable L0s component of ASPM if requested")
+set PCI_EXP_LNKCAP_ASPM_L1 and (optionally) PCI_EXP_LNKCAP_ASPM_L0S in
+PCI_EXP_LNKCAP (aka PCIE_RC_CFG_PRIV1_LINK_CAPABILITY in brcmstb).
+
+But instead of using PCI_EXP_LNKCAP_ASPM_L1 and PCI_EXP_LNKCAP_ASPM_L0S
+directly, it used PCIE_LINK_STATE_L1 and PCIE_LINK_STATE_L0S, which are
+Linux-created values that only coincidentally matched the PCIe spec.
+b478e162f227 ("PCI/ASPM: Consolidate link state defines") later changed
+them so they no longer matched the PCIe spec, so the bits ended up in the
+wrong place in PCI_EXP_LNKCAP.
+
+Use PCI_EXP_LNKCAP_ASPM_L0S to clear L0s support when there's an
+'aspm-no-l0s' property.  Rely on brcmstb hardware to advertise L0s and/or
+L1 support otherwise.
+
+Fixes: caab002d5069 ("PCI: brcmstb: Disable L0s component of ASPM if requested")
+Reported-by: Bjorn Helgaas <bhelgaas@google.com>
+Closes: https://lore.kernel.org/linux-pci/20250925194424.GA2197200@bhelgaas
+Signed-off-by: Jim Quinlan <james.quinlan@broadcom.com>
+[mani: reworded subject and description, added closes tag and CCed stable]
+Signed-off-by: Manivannan Sadhasivam <mani@kernel.org>
+[bhelgaas: commit log]
+Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
+Reviewed-by: Florian Fainelli <florian.fainelli@broadcom.com>
+Cc: stable@vger.kernel.org
+Link: https://patch.msgid.link/20251003170436.1446030-1-james.quinlan@broadcom.com
+[ adapted context due to missing link width negotiation defines and variables ]
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/pci/controller/pcie-brcmstb.c |   10 +++-------
+ 1 file changed, 3 insertions(+), 7 deletions(-)
+
+--- a/drivers/pci/controller/pcie-brcmstb.c
++++ b/drivers/pci/controller/pcie-brcmstb.c
+@@ -46,7 +46,6 @@
+ #define  PCIE_RC_CFG_PRIV1_ID_VAL3_CLASS_CODE_MASK    0xffffff
+ #define PCIE_RC_CFG_PRIV1_LINK_CAPABILITY                     0x04dc
+-#define  PCIE_RC_CFG_PRIV1_LINK_CAPABILITY_ASPM_SUPPORT_MASK  0xc00
+ #define PCIE_RC_DL_MDIO_ADDR                          0x1100
+ #define PCIE_RC_DL_MDIO_WR_DATA                               0x1104
+@@ -867,7 +866,7 @@ static int brcm_pcie_setup(struct brcm_p
+       void __iomem *base = pcie->base;
+       struct pci_host_bridge *bridge;
+       struct resource_entry *entry;
+-      u32 tmp, burst, aspm_support;
++      u32 tmp, burst;
+       int num_out_wins = 0;
+       int ret, memc;
+@@ -971,12 +970,9 @@ static int brcm_pcie_setup(struct brcm_p
+       writel(tmp, base + PCIE_MISC_RC_BAR3_CONFIG_LO);
+       /* Don't advertise L0s capability if 'aspm-no-l0s' */
+-      aspm_support = PCIE_LINK_STATE_L1;
+-      if (!of_property_read_bool(pcie->np, "aspm-no-l0s"))
+-              aspm_support |= PCIE_LINK_STATE_L0S;
+       tmp = readl(base + PCIE_RC_CFG_PRIV1_LINK_CAPABILITY);
+-      u32p_replace_bits(&tmp, aspm_support,
+-              PCIE_RC_CFG_PRIV1_LINK_CAPABILITY_ASPM_SUPPORT_MASK);
++      if (of_property_read_bool(pcie->np, "aspm-no-l0s"))
++              tmp &= ~PCI_EXP_LNKCAP_ASPM_L0S;
+       writel(tmp, base + PCIE_RC_CFG_PRIV1_LINK_CAPABILITY);
+       /*
diff --git a/queue-6.6/pmdomain-imx-fix-reference-count-leak-in-imx_gpc_probe.patch b/queue-6.6/pmdomain-imx-fix-reference-count-leak-in-imx_gpc_probe.patch
new file mode 100644 (file)
index 0000000..4dd47b8
--- /dev/null
@@ -0,0 +1,48 @@
+From stable+bounces-205121-greg=kroah.com@vger.kernel.org Tue Jan  6 16:56:53 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue,  6 Jan 2026 10:56:03 -0500
+Subject: pmdomain: imx: Fix reference count leak in imx_gpc_probe()
+To: stable@vger.kernel.org
+Cc: Wentao Liang <vulab@iscas.ac.cn>, Frank Li <Frank.Li@nxp.com>, Ulf Hansson <ulf.hansson@linaro.org>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260106155609.3056915-2-sashal@kernel.org>
+
+From: Wentao Liang <vulab@iscas.ac.cn>
+
+[ Upstream commit 73cb5f6eafb0ac7aea8cdeb8ff12981aa741d8fb ]
+
+of_get_child_by_name() returns a node pointer with refcount incremented.
+Use the __free() attribute to manage the pgc_node reference, ensuring
+automatic of_node_put() cleanup when pgc_node goes out of scope.
+
+This eliminates the need for explicit error handling paths and avoids
+reference count leaks.
+
+Fixes: 721cabf6c660 ("soc: imx: move PGC handling to a new GPC driver")
+Cc: stable@vger.kernel.org
+Signed-off-by: Wentao Liang <vulab@iscas.ac.cn>
+Reviewed-by: Frank Li <Frank.Li@nxp.com>
+Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/pmdomain/imx/gpc.c |    5 ++---
+ 1 file changed, 2 insertions(+), 3 deletions(-)
+
+--- a/drivers/pmdomain/imx/gpc.c
++++ b/drivers/pmdomain/imx/gpc.c
+@@ -405,13 +405,12 @@ clk_err:
+ static int imx_gpc_probe(struct platform_device *pdev)
+ {
+       const struct imx_gpc_dt_data *of_id_data = device_get_match_data(&pdev->dev);
+-      struct device_node *pgc_node;
++      struct device_node *pgc_node __free(device_node)
++              = of_get_child_by_name(pdev->dev.of_node, "pgc");
+       struct regmap *regmap;
+       void __iomem *base;
+       int ret;
+-      pgc_node = of_get_child_by_name(pdev->dev.of_node, "pgc");
+-
+       /* bail out if DT too old and doesn't provide the necessary info */
+       if (!of_property_read_bool(pdev->dev.of_node, "#power-domain-cells") &&
+           !pgc_node)
diff --git a/queue-6.6/pmdomain-use-device_get_match_data.patch b/queue-6.6/pmdomain-use-device_get_match_data.patch
new file mode 100644 (file)
index 0000000..be902fb
--- /dev/null
@@ -0,0 +1,134 @@
+From stable+bounces-205120-greg=kroah.com@vger.kernel.org Tue Jan  6 16:56:45 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue,  6 Jan 2026 10:56:02 -0500
+Subject: pmdomain: Use device_get_match_data()
+To: stable@vger.kernel.org
+Cc: Rob Herring <robh@kernel.org>, Ulf Hansson <ulf.hansson@linaro.org>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260106155609.3056915-1-sashal@kernel.org>
+
+From: Rob Herring <robh@kernel.org>
+
+[ Upstream commit 3ba9fdfaa550936837b50b73d6c27ac401fde875 ]
+
+Use preferred device_get_match_data() instead of of_match_device() to
+get the driver match data. With this, adjust the includes to explicitly
+include the correct headers.
+
+Signed-off-by: Rob Herring <robh@kernel.org>
+Link: https://lore.kernel.org/r/20231006224614.444488-1-robh@kernel.org
+Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
+Stable-dep-of: 73cb5f6eafb0 ("pmdomain: imx: Fix reference count leak in imx_gpc_probe()")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/pmdomain/actions/owl-sps.c     |   16 +++++-----------
+ drivers/pmdomain/imx/gpc.c             |    7 +++----
+ drivers/pmdomain/rockchip/pm-domains.c |   13 ++++---------
+ 3 files changed, 12 insertions(+), 24 deletions(-)
+
+--- a/drivers/pmdomain/actions/owl-sps.c
++++ b/drivers/pmdomain/actions/owl-sps.c
+@@ -8,8 +8,10 @@
+  * Copyright (c) 2017 Andreas Färber
+  */
++#include <linux/mod_devicetable.h>
+ #include <linux/of_address.h>
+-#include <linux/of_platform.h>
++#include <linux/platform_device.h>
++#include <linux/property.h>
+ #include <linux/pm_domain.h>
+ #include <linux/soc/actions/owl-sps.h>
+ #include <dt-bindings/power/owl-s500-powergate.h>
+@@ -96,24 +98,16 @@ static int owl_sps_init_domain(struct ow
+ static int owl_sps_probe(struct platform_device *pdev)
+ {
+-      const struct of_device_id *match;
+       const struct owl_sps_info *sps_info;
+       struct owl_sps *sps;
+       int i, ret;
+-      if (!pdev->dev.of_node) {
+-              dev_err(&pdev->dev, "no device node\n");
+-              return -ENODEV;
+-      }
+-
+-      match = of_match_device(pdev->dev.driver->of_match_table, &pdev->dev);
+-      if (!match || !match->data) {
++      sps_info = device_get_match_data(&pdev->dev);
++      if (!sps_info) {
+               dev_err(&pdev->dev, "unknown compatible or missing data\n");
+               return -EINVAL;
+       }
+-      sps_info = match->data;
+-
+       sps = devm_kzalloc(&pdev->dev,
+                          struct_size(sps, domains, sps_info->num_domains),
+                          GFP_KERNEL);
+--- a/drivers/pmdomain/imx/gpc.c
++++ b/drivers/pmdomain/imx/gpc.c
+@@ -7,9 +7,10 @@
+ #include <linux/clk.h>
+ #include <linux/delay.h>
+ #include <linux/io.h>
+-#include <linux/of_device.h>
++#include <linux/of.h>
+ #include <linux/platform_device.h>
+ #include <linux/pm_domain.h>
++#include <linux/property.h>
+ #include <linux/regmap.h>
+ #include <linux/regulator/consumer.h>
+@@ -403,9 +404,7 @@ clk_err:
+ static int imx_gpc_probe(struct platform_device *pdev)
+ {
+-      const struct of_device_id *of_id =
+-                      of_match_device(imx_gpc_dt_ids, &pdev->dev);
+-      const struct imx_gpc_dt_data *of_id_data = of_id->data;
++      const struct imx_gpc_dt_data *of_id_data = device_get_match_data(&pdev->dev);
+       struct device_node *pgc_node;
+       struct regmap *regmap;
+       void __iomem *base;
+--- a/drivers/pmdomain/rockchip/pm-domains.c
++++ b/drivers/pmdomain/rockchip/pm-domains.c
+@@ -9,11 +9,13 @@
+ #include <linux/iopoll.h>
+ #include <linux/err.h>
+ #include <linux/mutex.h>
++#include <linux/platform_device.h>
+ #include <linux/pm_clock.h>
+ #include <linux/pm_domain.h>
++#include <linux/property.h>
++#include <linux/of.h>
+ #include <linux/of_address.h>
+ #include <linux/of_clk.h>
+-#include <linux/of_platform.h>
+ #include <linux/clk.h>
+ #include <linux/regmap.h>
+ #include <linux/mfd/syscon.h>
+@@ -857,7 +859,6 @@ static int rockchip_pm_domain_probe(stru
+       struct device_node *node;
+       struct device *parent;
+       struct rockchip_pmu *pmu;
+-      const struct of_device_id *match;
+       const struct rockchip_pmu_info *pmu_info;
+       int error;
+@@ -866,13 +867,7 @@ static int rockchip_pm_domain_probe(stru
+               return -ENODEV;
+       }
+-      match = of_match_device(dev->driver->of_match_table, dev);
+-      if (!match || !match->data) {
+-              dev_err(dev, "missing pmu data\n");
+-              return -EINVAL;
+-      }
+-
+-      pmu_info = match->data;
++      pmu_info = device_get_match_data(dev);
+       pmu = devm_kzalloc(dev,
+                          struct_size(pmu, domains, pmu_info->num_domains),
diff --git a/queue-6.6/scsi-ufs-core-add-ufshcd_update_evt_hist-for-ufs-suspend-error.patch b/queue-6.6/scsi-ufs-core-add-ufshcd_update_evt_hist-for-ufs-suspend-error.patch
new file mode 100644 (file)
index 0000000..9778e9d
--- /dev/null
@@ -0,0 +1,50 @@
+From stable+bounces-204238-greg=kroah.com@vger.kernel.org Tue Dec 30 16:58:07 2025
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 30 Dec 2025 10:58:01 -0500
+Subject: scsi: ufs: core: Add ufshcd_update_evt_hist() for UFS suspend error
+To: stable@vger.kernel.org
+Cc: Seunghwan Baek <sh8267.baek@samsung.com>, Peter Wang <peter.wang@mediatek.com>, "Martin K. Petersen" <martin.petersen@oracle.com>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20251230155801.2291044-1-sashal@kernel.org>
+
+From: Seunghwan Baek <sh8267.baek@samsung.com>
+
+[ Upstream commit c9f36f04a8a2725172cdf2b5e32363e4addcb14c ]
+
+If UFS resume fails, the event history is updated in ufshcd_resume(), but
+there is no code anywhere to record UFS suspend. Therefore, add code to
+record UFS suspend error event history.
+
+Fixes: dd11376b9f1b ("scsi: ufs: Split the drivers/scsi/ufs directory")
+Cc: stable@vger.kernel.org
+Signed-off-by: Seunghwan Baek <sh8267.baek@samsung.com>
+Reviewed-by: Peter Wang <peter.wang@mediatek.com>
+Link: https://patch.msgid.link/20251210063854.1483899-2-sh8267.baek@samsung.com
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+[ Adjust context ]
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/ufs/core/ufshcd.c |    5 ++++-
+ 1 file changed, 4 insertions(+), 1 deletion(-)
+
+--- a/drivers/ufs/core/ufshcd.c
++++ b/drivers/ufs/core/ufshcd.c
+@@ -10182,7 +10182,7 @@ static int ufshcd_suspend(struct ufs_hba
+       ret = ufshcd_setup_clocks(hba, false);
+       if (ret) {
+               ufshcd_enable_irq(hba);
+-              return ret;
++              goto out;
+       }
+       if (ufshcd_is_clkgating_allowed(hba)) {
+               hba->clk_gating.state = CLKS_OFF;
+@@ -10193,6 +10193,9 @@ static int ufshcd_suspend(struct ufs_hba
+       ufshcd_vreg_set_lpm(hba);
+       /* Put the host controller in low power mode if possible */
+       ufshcd_hba_vreg_set_lpm(hba);
++out:
++      if (ret)
++              ufshcd_update_evt_hist(hba, UFS_EVT_SUSPEND_ERR, (u32)ret);
+       return ret;
+ }
index f5a3a6091219a0fd0a1aee093ec9a29069fc286e..156a673c6415da4f66bd1d7f5003e5c55bcda443 100644 (file)
@@ -626,3 +626,48 @@ drm-nouveau-dispnv50-don-t-call-drm_atomic_get_crtc_state-in-prepare_fb.patch
 usb-gadget-lpc32xx_udc-fix-clock-imbalance-in-error-path.patch
 blk-mq-add-helper-for-checking-if-one-cpu-is-mapped-to-specified-hctx.patch
 tpm-cap-the-number-of-pcr-banks.patch
+mptcp-initialise-rcv_mss-before-calling-tcp_send_active_reset-in-mptcp_do_fastclose.patch
+alsa-wavefront-use-standard-print-api.patch
+alsa-wavefront-fix-integer-overflow-in-sample-size-validation.patch
+alsa-wavefront-use-guard-for-spin-locks.patch
+alsa-wavefront-clear-substream-pointers-on-close.patch
+alsa-hda-cs35l41-fix-null-pointer-dereference-in-cs35l41_hda_read_acpi.patch
+ext4-fix-string-copying-in-parse_apply_sb_mount_options.patch
+jbd2-fix-the-inconsistency-between-checksum-and-data-in-memory-for-journal-sb.patch
+gfs2-fix-freeze-error-handling.patch
+btrfs-don-t-rewrite-ret-from-inode_permission.patch
+wifi-mt76-fix-dts-power-limits-on-little-endian-systems.patch
+mm-ksm-fix-exec-fork-inheritance-support-for-prctl.patch
+usb-ohci-nxp-use-helper-function-devm_clk_get_enabled.patch
+usb-ohci-nxp-fix-device-leak-on-probe-failure.patch
+scsi-ufs-core-add-ufshcd_update_evt_hist-for-ufs-suspend-error.patch
+mptcp-pm-ignore-unknown-endpoint-flags.patch
+f2fs-use-f2fs_err_ratelimited-to-avoid-redundant-logs.patch
+f2fs-fix-to-avoid-potential-deadlock.patch
+nfsd-clear-seclabel-in-the-suppattr_exclcreat-bitmap.patch
+gpiolib-acpi-add-quirk-for-dell-precision-7780.patch
+arm-dts-microchip-sama7g5-fix-uart-fifo-size-to-32.patch
+svcrdma-bound-check-rq_pages-index-in-inline-path.patch
+fuse-fix-readahead-reclaim-deadlock.patch
+pci-brcmstb-fix-disabling-l0s-capability.patch
+mptcp-fallback-earlier-on-simult-connection.patch
+lockd-fix-vfs_test_lock-calls.patch
+wifi-mac80211-discard-beacon-frames-to-non-broadcast-address.patch
+mm-simplify-folio_expected_ref_count.patch
+mm-consider-non-anon-swap-cache-folios-in-folio_expected_ref_count.patch
+pmdomain-use-device_get_match_data.patch
+pmdomain-imx-fix-reference-count-leak-in-imx_gpc_probe.patch
+net-phy-mediatek-fix-nvmem-cell-reference-leak-in-mt798x_phy_calibration.patch
+mptcp-ensure-context-reset-on-disconnect.patch
+drm-amdgpu-forward-vmid-reservation-errors.patch
+drm-mediatek-fix-probe-memory-leak.patch
+drm-mediatek-fix-probe-resource-leaks.patch
+drm-tilcdc-request-and-mapp-iomem-with-devres.patch
+drm-tilcdc-fix-removal-actions-in-case-of-failed-probe.patch
+tty-introduce-and-use-tty_port_tty_vhangup-helper.patch
+xhci-dbgtty-fix-device-unregister-fixup.patch
+usb-xhci-move-link-chain-bit-quirk-checks-into-one-helper-function.patch
+usb-xhci-apply-the-link-chain-quirk-on-nec-isoc-endpoints.patch
+net-remove-rtnl-dance-for-siocbraddif-and-siocbrdelif.patch
+drm-amd-display-fix-null-pointer-deref-in-dcn20_resource.c.patch
+loongarch-refactor-register-restoration-in-ftrace_common_return.patch
diff --git a/queue-6.6/svcrdma-bound-check-rq_pages-index-in-inline-path.patch b/queue-6.6/svcrdma-bound-check-rq_pages-index-in-inline-path.patch
new file mode 100644 (file)
index 0000000..824d8fa
--- /dev/null
@@ -0,0 +1,39 @@
+From stable+bounces-204396-greg=kroah.com@vger.kernel.org Wed Dec 31 23:32:25 2025
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 31 Dec 2025 17:32:17 -0500
+Subject: svcrdma: bound check rq_pages index in inline path
+To: stable@vger.kernel.org
+Cc: Joshua Rogers <linux@joshua.hu>, Chuck Lever <chuck.lever@oracle.com>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20251231223217.3548253-1-sashal@kernel.org>
+
+From: Joshua Rogers <linux@joshua.hu>
+
+[ Upstream commit d1bea0ce35b6095544ee82bb54156fc62c067e58 ]
+
+svc_rdma_copy_inline_range indexed rqstp->rq_pages[rc_curpage] without
+verifying rc_curpage stays within the allocated page array. Add guards
+before the first use and after advancing to a new page.
+
+Fixes: d7cc73972661 ("svcrdma: support multiple Read chunks per RPC")
+Cc: stable@vger.kernel.org
+Signed-off-by: Joshua Rogers <linux@joshua.hu>
+Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
+[ adapted rc_curpage and rq_maxpages fields to ri_pageno and RPCSVC_MAXPAGES constant ]
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/sunrpc/xprtrdma/svc_rdma_rw.c |    3 +++
+ 1 file changed, 3 insertions(+)
+
+--- a/net/sunrpc/xprtrdma/svc_rdma_rw.c
++++ b/net/sunrpc/xprtrdma/svc_rdma_rw.c
+@@ -815,6 +815,9 @@ static int svc_rdma_copy_inline_range(st
+       for (page_no = 0; page_no < numpages; page_no++) {
+               unsigned int page_len;
++              if (info->ri_pageno >= RPCSVC_MAXPAGES)
++                      return -EINVAL;
++
+               page_len = min_t(unsigned int, remaining,
+                                PAGE_SIZE - info->ri_pageoff);
diff --git a/queue-6.6/tty-introduce-and-use-tty_port_tty_vhangup-helper.patch b/queue-6.6/tty-introduce-and-use-tty_port_tty_vhangup-helper.patch
new file mode 100644 (file)
index 0000000..a48d403
--- /dev/null
@@ -0,0 +1,233 @@
+From stable+bounces-204275-greg=kroah.com@vger.kernel.org Tue Dec 30 19:44:23 2025
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 30 Dec 2025 13:43:20 -0500
+Subject: tty: introduce and use tty_port_tty_vhangup() helper
+To: stable@vger.kernel.org
+Cc: "Jiri Slaby (SUSE)" <jirislaby@kernel.org>, "Karsten Keil" <isdn@linux-pingi.de>, "David Lin" <dtwlin@gmail.com>, "Johan Hovold" <johan@kernel.org>, "Alex Elder" <elder@kernel.org>, "Oliver Neukum" <oneukum@suse.com>, "Marcel Holtmann" <marcel@holtmann.org>, "Johan Hedberg" <johan.hedberg@gmail.com>, "Luiz Augusto von Dentz" <luiz.dentz@gmail.com>, "Ilpo Järvinen" <ilpo.jarvinen@linux.intel.com>, "Greg Kroah-Hartman" <gregkh@linuxfoundation.org>, "Sasha Levin" <sashal@kernel.org>
+Message-ID: <20251230184321.2402789-1-sashal@kernel.org>
+
+From: "Jiri Slaby (SUSE)" <jirislaby@kernel.org>
+
+[ Upstream commit 2b5eac0f8c6e79bc152c8804f9f88d16717013ab ]
+
+This code (tty_get -> vhangup -> tty_put) is repeated on few places.
+Introduce a helper similar to tty_port_tty_hangup() (asynchronous) to
+handle even vhangup (synchronous).
+
+And use it on those places.
+
+In fact, reuse the tty_port_tty_hangup()'s code and call tty_vhangup()
+depending on a new bool parameter.
+
+Signed-off-by: "Jiri Slaby (SUSE)" <jirislaby@kernel.org>
+Cc: Karsten Keil <isdn@linux-pingi.de>
+Cc: David Lin <dtwlin@gmail.com>
+Cc: Johan Hovold <johan@kernel.org>
+Cc: Alex Elder <elder@kernel.org>
+Cc: Oliver Neukum <oneukum@suse.com>
+Cc: Marcel Holtmann <marcel@holtmann.org>
+Cc: Johan Hedberg <johan.hedberg@gmail.com>
+Cc: Luiz Augusto von Dentz <luiz.dentz@gmail.com>
+Reviewed-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
+Link: https://lore.kernel.org/r/20250611100319.186924-2-jirislaby@kernel.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Stable-dep-of: 74098cc06e75 ("xhci: dbgtty: fix device unregister: fixup")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/isdn/capi/capi.c         |    8 +-------
+ drivers/staging/greybus/uart.c   |    7 +------
+ drivers/tty/serial/serial_core.c |    7 +------
+ drivers/tty/tty_port.c           |   12 ++++++++----
+ drivers/usb/class/cdc-acm.c      |    7 +------
+ drivers/usb/serial/usb-serial.c  |    7 +------
+ include/linux/tty_port.h         |   12 +++++++++++-
+ net/bluetooth/rfcomm/tty.c       |    7 +------
+ 8 files changed, 25 insertions(+), 42 deletions(-)
+
+--- a/drivers/isdn/capi/capi.c
++++ b/drivers/isdn/capi/capi.c
+@@ -304,15 +304,9 @@ static void capincci_alloc_minor(struct
+ static void capincci_free_minor(struct capincci *np)
+ {
+       struct capiminor *mp = np->minorp;
+-      struct tty_struct *tty;
+       if (mp) {
+-              tty = tty_port_tty_get(&mp->port);
+-              if (tty) {
+-                      tty_vhangup(tty);
+-                      tty_kref_put(tty);
+-              }
+-
++              tty_port_tty_vhangup(&mp->port);
+               capiminor_free(mp);
+       }
+ }
+--- a/drivers/staging/greybus/uart.c
++++ b/drivers/staging/greybus/uart.c
+@@ -914,7 +914,6 @@ static void gb_uart_remove(struct gbphy_
+ {
+       struct gb_tty *gb_tty = gb_gbphy_get_data(gbphy_dev);
+       struct gb_connection *connection = gb_tty->connection;
+-      struct tty_struct *tty;
+       int ret;
+       ret = gbphy_runtime_get_sync(gbphy_dev);
+@@ -927,11 +926,7 @@ static void gb_uart_remove(struct gbphy_
+       wake_up_all(&gb_tty->wioctl);
+       mutex_unlock(&gb_tty->mutex);
+-      tty = tty_port_tty_get(&gb_tty->port);
+-      if (tty) {
+-              tty_vhangup(tty);
+-              tty_kref_put(tty);
+-      }
++      tty_port_tty_vhangup(&gb_tty->port);
+       gb_connection_disable_rx(connection);
+       tty_unregister_device(gb_tty_driver, gb_tty->minor);
+--- a/drivers/tty/serial/serial_core.c
++++ b/drivers/tty/serial/serial_core.c
+@@ -3250,7 +3250,6 @@ static void serial_core_remove_one_port(
+       struct uart_state *state = drv->state + uport->line;
+       struct tty_port *port = &state->port;
+       struct uart_port *uart_port;
+-      struct tty_struct *tty;
+       mutex_lock(&port->mutex);
+       uart_port = uart_port_check(state);
+@@ -3269,11 +3268,7 @@ static void serial_core_remove_one_port(
+        */
+       tty_port_unregister_device(port, drv->tty_driver, uport->line);
+-      tty = tty_port_tty_get(port);
+-      if (tty) {
+-              tty_vhangup(port->tty);
+-              tty_kref_put(tty);
+-      }
++      tty_port_tty_vhangup(port);
+       /*
+        * If the port is used as a console, unregister it
+--- a/drivers/tty/tty_port.c
++++ b/drivers/tty/tty_port.c
+@@ -414,15 +414,19 @@ EXPORT_SYMBOL(tty_port_hangup);
+  * @port: tty port
+  * @check_clocal: hang only ttys with %CLOCAL unset?
+  */
+-void tty_port_tty_hangup(struct tty_port *port, bool check_clocal)
++void __tty_port_tty_hangup(struct tty_port *port, bool check_clocal, bool async)
+ {
+       struct tty_struct *tty = tty_port_tty_get(port);
+-      if (tty && (!check_clocal || !C_CLOCAL(tty)))
+-              tty_hangup(tty);
++      if (tty && (!check_clocal || !C_CLOCAL(tty))) {
++              if (async)
++                      tty_hangup(tty);
++              else
++                      tty_vhangup(tty);
++      }
+       tty_kref_put(tty);
+ }
+-EXPORT_SYMBOL_GPL(tty_port_tty_hangup);
++EXPORT_SYMBOL_GPL(__tty_port_tty_hangup);
+ /**
+  * tty_port_tty_wakeup - helper to wake up a tty
+--- a/drivers/usb/class/cdc-acm.c
++++ b/drivers/usb/class/cdc-acm.c
+@@ -1572,7 +1572,6 @@ err_put_port:
+ static void acm_disconnect(struct usb_interface *intf)
+ {
+       struct acm *acm = usb_get_intfdata(intf);
+-      struct tty_struct *tty;
+       int i;
+       /* sibling interface is already cleaning up */
+@@ -1599,11 +1598,7 @@ static void acm_disconnect(struct usb_in
+       usb_set_intfdata(acm->data, NULL);
+       mutex_unlock(&acm->mutex);
+-      tty = tty_port_tty_get(&acm->port);
+-      if (tty) {
+-              tty_vhangup(tty);
+-              tty_kref_put(tty);
+-      }
++      tty_port_tty_vhangup(&acm->port);
+       cancel_delayed_work_sync(&acm->dwork);
+--- a/drivers/usb/serial/usb-serial.c
++++ b/drivers/usb/serial/usb-serial.c
+@@ -1178,7 +1178,6 @@ static void usb_serial_disconnect(struct
+       struct usb_serial *serial = usb_get_intfdata(interface);
+       struct device *dev = &interface->dev;
+       struct usb_serial_port *port;
+-      struct tty_struct *tty;
+       /* sibling interface is cleaning up */
+       if (!serial)
+@@ -1193,11 +1192,7 @@ static void usb_serial_disconnect(struct
+       for (i = 0; i < serial->num_ports; ++i) {
+               port = serial->port[i];
+-              tty = tty_port_tty_get(&port->port);
+-              if (tty) {
+-                      tty_vhangup(tty);
+-                      tty_kref_put(tty);
+-              }
++              tty_port_tty_vhangup(&port->port);
+               usb_serial_port_poison_urbs(port);
+               wake_up_interruptible(&port->port.delta_msr_wait);
+               cancel_work_sync(&port->work);
+--- a/include/linux/tty_port.h
++++ b/include/linux/tty_port.h
+@@ -235,7 +235,7 @@ bool tty_port_carrier_raised(struct tty_
+ void tty_port_raise_dtr_rts(struct tty_port *port);
+ void tty_port_lower_dtr_rts(struct tty_port *port);
+ void tty_port_hangup(struct tty_port *port);
+-void tty_port_tty_hangup(struct tty_port *port, bool check_clocal);
++void __tty_port_tty_hangup(struct tty_port *port, bool check_clocal, bool async);
+ void tty_port_tty_wakeup(struct tty_port *port);
+ int tty_port_block_til_ready(struct tty_port *port, struct tty_struct *tty,
+               struct file *filp);
+@@ -254,4 +254,14 @@ static inline int tty_port_users(struct
+       return port->count + port->blocked_open;
+ }
++static inline void tty_port_tty_hangup(struct tty_port *port, bool check_clocal)
++{
++      __tty_port_tty_hangup(port, check_clocal, true);
++}
++
++static inline void tty_port_tty_vhangup(struct tty_port *port)
++{
++      __tty_port_tty_hangup(port, false, false);
++}
++
+ #endif
+--- a/net/bluetooth/rfcomm/tty.c
++++ b/net/bluetooth/rfcomm/tty.c
+@@ -438,7 +438,6 @@ static int __rfcomm_release_dev(void __u
+ {
+       struct rfcomm_dev_req req;
+       struct rfcomm_dev *dev;
+-      struct tty_struct *tty;
+       if (copy_from_user(&req, arg, sizeof(req)))
+               return -EFAULT;
+@@ -464,11 +463,7 @@ static int __rfcomm_release_dev(void __u
+               rfcomm_dlc_close(dev->dlc, 0);
+       /* Shut down TTY synchronously before freeing rfcomm_dev */
+-      tty = tty_port_tty_get(&dev->port);
+-      if (tty) {
+-              tty_vhangup(tty);
+-              tty_kref_put(tty);
+-      }
++      tty_port_tty_vhangup(&dev->port);
+       if (!test_bit(RFCOMM_TTY_OWNED, &dev->status))
+               tty_port_put(&dev->port);
diff --git a/queue-6.6/usb-ohci-nxp-fix-device-leak-on-probe-failure.patch b/queue-6.6/usb-ohci-nxp-fix-device-leak-on-probe-failure.patch
new file mode 100644 (file)
index 0000000..ec0f747
--- /dev/null
@@ -0,0 +1,49 @@
+From stable+bounces-204203-greg=kroah.com@vger.kernel.org Tue Dec 30 14:19:29 2025
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 30 Dec 2025 08:19:21 -0500
+Subject: usb: ohci-nxp: fix device leak on probe failure
+To: stable@vger.kernel.org
+Cc: Johan Hovold <johan@kernel.org>, Ma Ke <make24@iscas.ac.cn>, Alan Stern <stern@rowland.harvard.edu>, Vladimir Zapolskiy <vz@mleia.com>, Greg Kroah-Hartman <gregkh@linuxfoundation.org>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20251230131921.2177523-2-sashal@kernel.org>
+
+From: Johan Hovold <johan@kernel.org>
+
+[ Upstream commit b4c61e542faf8c9131d69ecfc3ad6de96d1b2ab8 ]
+
+Make sure to drop the reference taken when looking up the PHY I2C device
+during probe on probe failure (e.g. probe deferral) and on driver
+unbind.
+
+Fixes: 73108aa90cbf ("USB: ohci-nxp: Use isp1301 driver")
+Cc: stable@vger.kernel.org     # 3.5
+Reported-by: Ma Ke <make24@iscas.ac.cn>
+Link: https://lore.kernel.org/lkml/20251117013428.21840-1-make24@iscas.ac.cn/
+Signed-off-by: Johan Hovold <johan@kernel.org>
+Acked-by: Alan Stern <stern@rowland.harvard.edu>
+Reviewed-by: Vladimir Zapolskiy <vz@mleia.com>
+Link: https://patch.msgid.link/20251218153519.19453-4-johan@kernel.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/usb/host/ohci-nxp.c |    2 ++
+ 1 file changed, 2 insertions(+)
+
+--- a/drivers/usb/host/ohci-nxp.c
++++ b/drivers/usb/host/ohci-nxp.c
+@@ -223,6 +223,7 @@ static int ohci_hcd_nxp_probe(struct pla
+ fail_resource:
+       usb_put_hcd(hcd);
+ fail_disable:
++      put_device(&isp1301_i2c_client->dev);
+       isp1301_i2c_client = NULL;
+       return ret;
+ }
+@@ -234,6 +235,7 @@ static void ohci_hcd_nxp_remove(struct p
+       usb_remove_hcd(hcd);
+       ohci_nxp_stop_hc();
+       usb_put_hcd(hcd);
++      put_device(&isp1301_i2c_client->dev);
+       isp1301_i2c_client = NULL;
+ }
diff --git a/queue-6.6/usb-ohci-nxp-use-helper-function-devm_clk_get_enabled.patch b/queue-6.6/usb-ohci-nxp-use-helper-function-devm_clk_get_enabled.patch
new file mode 100644 (file)
index 0000000..71fa5b0
--- /dev/null
@@ -0,0 +1,93 @@
+From stable+bounces-204202-greg=kroah.com@vger.kernel.org Tue Dec 30 14:19:44 2025
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 30 Dec 2025 08:19:20 -0500
+Subject: usb: ohci-nxp: Use helper function devm_clk_get_enabled()
+To: stable@vger.kernel.org
+Cc: Zhang Zekun <zhangzekun11@huawei.com>, Alan Stern <stern@rowland.harvard.edu>, Greg Kroah-Hartman <gregkh@linuxfoundation.org>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20251230131921.2177523-1-sashal@kernel.org>
+
+From: Zhang Zekun <zhangzekun11@huawei.com>
+
+[ Upstream commit c146ede472717f352b7283a525bd9a1a2b15e2cf ]
+
+devm_clk_get() and clk_prepare_enable() can be replaced by helper
+function devm_clk_get_enabled(). Let's use devm_clk_get_enabled() to
+simplify code and avoid calling clk_disable_unprepare().
+
+Signed-off-by: Zhang Zekun <zhangzekun11@huawei.com>
+Acked-by: Alan Stern <stern@rowland.harvard.edu>
+Link: https://lore.kernel.org/r/20240902123020.29267-3-zhangzekun11@huawei.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Stable-dep-of: b4c61e542faf ("usb: ohci-nxp: fix device leak on probe failure")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/usb/host/ohci-nxp.c |   18 ++++--------------
+ 1 file changed, 4 insertions(+), 14 deletions(-)
+
+--- a/drivers/usb/host/ohci-nxp.c
++++ b/drivers/usb/host/ohci-nxp.c
+@@ -51,8 +51,6 @@ static struct hc_driver __read_mostly oh
+ static struct i2c_client *isp1301_i2c_client;
+-static struct clk *usb_host_clk;
+-
+ static void isp1301_configure_lpc32xx(void)
+ {
+       /* LPC32XX only supports DAT_SE0 USB mode */
+@@ -155,6 +153,7 @@ static int ohci_hcd_nxp_probe(struct pla
+       struct resource *res;
+       int ret = 0, irq;
+       struct device_node *isp1301_node;
++      struct clk *usb_host_clk;
+       if (pdev->dev.of_node) {
+               isp1301_node = of_parse_phandle(pdev->dev.of_node,
+@@ -180,26 +179,20 @@ static int ohci_hcd_nxp_probe(struct pla
+       }
+       /* Enable USB host clock */
+-      usb_host_clk = devm_clk_get(&pdev->dev, NULL);
++      usb_host_clk = devm_clk_get_enabled(&pdev->dev, NULL);
+       if (IS_ERR(usb_host_clk)) {
+-              dev_err(&pdev->dev, "failed to acquire USB OHCI clock\n");
++              dev_err(&pdev->dev, "failed to acquire and start USB OHCI clock\n");
+               ret = PTR_ERR(usb_host_clk);
+               goto fail_disable;
+       }
+-      ret = clk_prepare_enable(usb_host_clk);
+-      if (ret < 0) {
+-              dev_err(&pdev->dev, "failed to start USB OHCI clock\n");
+-              goto fail_disable;
+-      }
+-
+       isp1301_configure();
+       hcd = usb_create_hcd(driver, &pdev->dev, dev_name(&pdev->dev));
+       if (!hcd) {
+               dev_err(&pdev->dev, "Failed to allocate HC buffer\n");
+               ret = -ENOMEM;
+-              goto fail_hcd;
++              goto fail_disable;
+       }
+       hcd->regs = devm_platform_get_and_ioremap_resource(pdev, 0, &res);
+@@ -229,8 +222,6 @@ static int ohci_hcd_nxp_probe(struct pla
+       ohci_nxp_stop_hc();
+ fail_resource:
+       usb_put_hcd(hcd);
+-fail_hcd:
+-      clk_disable_unprepare(usb_host_clk);
+ fail_disable:
+       isp1301_i2c_client = NULL;
+       return ret;
+@@ -243,7 +234,6 @@ static void ohci_hcd_nxp_remove(struct p
+       usb_remove_hcd(hcd);
+       ohci_nxp_stop_hc();
+       usb_put_hcd(hcd);
+-      clk_disable_unprepare(usb_host_clk);
+       isp1301_i2c_client = NULL;
+ }
diff --git a/queue-6.6/usb-xhci-apply-the-link-chain-quirk-on-nec-isoc-endpoints.patch b/queue-6.6/usb-xhci-apply-the-link-chain-quirk-on-nec-isoc-endpoints.patch
new file mode 100644 (file)
index 0000000..0cff289
--- /dev/null
@@ -0,0 +1,116 @@
+From shivani.agarwal@broadcom.com Thu Jan  8 10:11:27 2026
+From: Shivani Agarwal <shivani.agarwal@broadcom.com>
+Date: Thu,  8 Jan 2026 00:50:21 -0800
+Subject: usb: xhci: Apply the link chain quirk on NEC isoc endpoints
+To: stable@vger.kernel.org, gregkh@linuxfoundation.org
+Cc: mathias.nyman@intel.com, linux-usb@vger.kernel.org, linux-kernel@vger.kernel.org, ajay.kaher@broadcom.com, alexey.makhalov@broadcom.com, vamsi-krishna.brahmajosyula@broadcom.com, yin.ding@broadcom.com, tapas.kundu@broadcom.com, Michal Pecio <michal.pecio@gmail.com>, Mathias Nyman <mathias.nyman@linux.intel.com>, Shivani Agarwal <shivani.agarwal@broadcom.com>
+Message-ID: <20260108085021.671854-3-shivani.agarwal@broadcom.com>
+
+From: Michal Pecio <michal.pecio@gmail.com>
+
+commit bb0ba4cb1065e87f9cc75db1fa454e56d0894d01 upstream.
+
+Two clearly different specimens of NEC uPD720200 (one with start/stop
+bug, one without) were seen to cause IOMMU faults after some Missed
+Service Errors. Faulting address is immediately after a transfer ring
+segment and patched dynamic debug messages revealed that the MSE was
+received when waiting for a TD near the end of that segment:
+
+[ 1.041954] xhci_hcd: Miss service interval error for slot 1 ep 2 expected TD DMA ffa08fe0
+[ 1.042120] xhci_hcd: AMD-Vi: Event logged [IO_PAGE_FAULT domain=0x0005 address=0xffa09000 flags=0x0000]
+[ 1.042146] xhci_hcd: AMD-Vi: Event logged [IO_PAGE_FAULT domain=0x0005 address=0xffa09040 flags=0x0000]
+
+It gets even funnier if the next page is a ring segment accessible to
+the HC. Below, it reports MSE in segment at ff1e8000, plows through a
+zero-filled page at ff1e9000 and starts reporting events for TRBs in
+page at ff1ea000 every microframe, instead of jumping to seg ff1e6000.
+
+[ 7.041671] xhci_hcd: Miss service interval error for slot 1 ep 2 expected TD DMA ff1e8fe0
+[ 7.041999] xhci_hcd: Miss service interval error for slot 1 ep 2 expected TD DMA ff1e8fe0
+[ 7.042011] xhci_hcd: WARN: buffer overrun event for slot 1 ep 2 on endpoint
+[ 7.042028] xhci_hcd: All TDs skipped for slot 1 ep 2. Clear skip flag.
+[ 7.042134] xhci_hcd: WARN: buffer overrun event for slot 1 ep 2 on endpoint
+[ 7.042138] xhci_hcd: ERROR Transfer event TRB DMA ptr not part of current TD ep_index 2 comp_code 31
+[ 7.042144] xhci_hcd: Looking for event-dma 00000000ff1ea040 trb-start 00000000ff1e6820 trb-end 00000000ff1e6820
+[ 7.042259] xhci_hcd: WARN: buffer overrun event for slot 1 ep 2 on endpoint
+[ 7.042262] xhci_hcd: ERROR Transfer event TRB DMA ptr not part of current TD ep_index 2 comp_code 31
+[ 7.042266] xhci_hcd: Looking for event-dma 00000000ff1ea050 trb-start 00000000ff1e6820 trb-end 00000000ff1e6820
+
+At some point completion events change from Isoch Buffer Overrun to
+Short Packet and the HC finally finds cycle bit mismatch in ff1ec000.
+
+[ 7.098130] xhci_hcd: ERROR Transfer event TRB DMA ptr not part of current TD ep_index 2 comp_code 13
+[ 7.098132] xhci_hcd: Looking for event-dma 00000000ff1ecc50 trb-start 00000000ff1e6820 trb-end 00000000ff1e6820
+[ 7.098254] xhci_hcd: ERROR Transfer event TRB DMA ptr not part of current TD ep_index 2 comp_code 13
+[ 7.098256] xhci_hcd: Looking for event-dma 00000000ff1ecc60 trb-start 00000000ff1e6820 trb-end 00000000ff1e6820
+[ 7.098379] xhci_hcd: Overrun event on slot 1 ep 2
+
+It's possible that data from the isochronous device were written to
+random buffers of pending TDs on other endpoints (either IN or OUT),
+other devices or even other HCs in the same IOMMU domain.
+
+Lastly, an error from a different USB device on another HC. Was it
+caused by the above? I don't know, but it may have been. The disk
+was working without any other issues and generated PCIe traffic to
+starve the NEC of upstream BW and trigger those MSEs. The two HCs
+shared one x1 slot by means of a commercial "PCIe splitter" board.
+
+[ 7.162604] usb 10-2: reset SuperSpeed USB device number 3 using xhci_hcd
+[ 7.178990] sd 9:0:0:0: [sdb] tag#0 UNKNOWN(0x2003) Result: hostbyte=0x07 driverbyte=DRIVER_OK cmd_age=0s
+[ 7.179001] sd 9:0:0:0: [sdb] tag#0 CDB: opcode=0x28 28 00 04 02 ae 00 00 02 00 00
+[ 7.179004] I/O error, dev sdb, sector 67284480 op 0x0:(READ) flags 0x80700 phys_seg 5 prio class 0
+
+Fortunately, it appears that this ridiculous bug is avoided by setting
+the chain bit of Link TRBs on isochronous rings. Other ancient HCs are
+known which also expect the bit to be set and they ignore Link TRBs if
+it's not. Reportedly, 0.95 spec guaranteed that the bit is set.
+
+The bandwidth-starved NEC HC running a 32KB/uframe UVC endpoint reports
+tens of MSEs per second and runs into the bug within seconds. Chaining
+Link TRBs allows the same workload to run for many minutes, many times.
+
+No negative side effects seen in UVC recording and UAC playback with a
+few devices at full speed, high speed and SuperSpeed.
+
+The problem doesn't reproduce on the newer Renesas uPD720201/uPD720202
+and on old Etron EJ168 and VIA VL805 (but the VL805 has other bug).
+
+[shorten line length of log snippets in commit messge -Mathias]
+
+Signed-off-by: Michal Pecio <michal.pecio@gmail.com>
+Cc: stable@vger.kernel.org
+Signed-off-by: Mathias Nyman <mathias.nyman@linux.intel.com>
+Link: https://lore.kernel.org/r/20250306144954.3507700-14-mathias.nyman@linux.intel.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+[Shivani: Modified to apply on 6.6.y]
+Signed-off-by: Shivani Agarwal <shivani.agarwal@broadcom.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/usb/host/xhci.h |   13 +++++++++++--
+ 1 file changed, 11 insertions(+), 2 deletions(-)
+
+--- a/drivers/usb/host/xhci.h
++++ b/drivers/usb/host/xhci.h
+@@ -1785,11 +1785,20 @@ static inline void xhci_write_64(struct
+ }
+-/* Link TRB chain should always be set on 0.95 hosts, and AMD 0.96 ISOC rings */
++/*
++ * Reportedly, some chapters of v0.95 spec said that Link TRB always has its chain bit set.
++ * Other chapters and later specs say that it should only be set if the link is inside a TD
++ * which continues from the end of one segment to the next segment.
++ *
++ * Some 0.95 hardware was found to misbehave if any link TRB doesn't have the chain bit set.
++ *
++ * 0.96 hardware from AMD and NEC was found to ignore unchained isochronous link TRBs when
++ * "resynchronizing the pipe" after a Missed Service Error.
++ */
+ static inline bool xhci_link_chain_quirk(struct xhci_hcd *xhci, enum xhci_ring_type type)
+ {
+       return (xhci->quirks & XHCI_LINK_TRB_QUIRK) ||
+-             (type == TYPE_ISOC && (xhci->quirks & XHCI_AMD_0x96_HOST));
++             (type == TYPE_ISOC && (xhci->quirks & (XHCI_AMD_0x96_HOST | XHCI_NEC_HOST)));
+ }
+ /* xHCI debugging */
diff --git a/queue-6.6/usb-xhci-move-link-chain-bit-quirk-checks-into-one-helper-function.patch b/queue-6.6/usb-xhci-move-link-chain-bit-quirk-checks-into-one-helper-function.patch
new file mode 100644 (file)
index 0000000..0f8db10
--- /dev/null
@@ -0,0 +1,103 @@
+From shivani.agarwal@broadcom.com Thu Jan  8 10:11:25 2026
+From: Shivani Agarwal <shivani.agarwal@broadcom.com>
+Date: Thu,  8 Jan 2026 00:50:20 -0800
+Subject: usb: xhci: move link chain bit quirk checks into one helper function.
+To: stable@vger.kernel.org, gregkh@linuxfoundation.org
+Cc: mathias.nyman@intel.com, linux-usb@vger.kernel.org, linux-kernel@vger.kernel.org, ajay.kaher@broadcom.com, alexey.makhalov@broadcom.com, vamsi-krishna.brahmajosyula@broadcom.com, yin.ding@broadcom.com, tapas.kundu@broadcom.com, Niklas Neronin <niklas.neronin@linux.intel.com>, Mathias Nyman <mathias.nyman@linux.intel.com>, Shivani Agarwal <shivani.agarwal@broadcom.com>
+Message-ID: <20260108085021.671854-2-shivani.agarwal@broadcom.com>
+
+From: Niklas Neronin <niklas.neronin@linux.intel.com>
+
+commit 7476a2215c07703db5e95efaa3fc5b9f957b9417 upstream.
+
+Older 0.95 xHCI hosts and some other specific newer hosts require the
+chain bit to be set for Link TRBs even if the link TRB is not in the
+middle of a transfer descriptor (TD).
+
+move the checks for all those cases  into one xhci_link_chain_quirk()
+function to clean up and avoid code duplication.
+
+No functional changes.
+
+[skip renaming chain_links flag, reword commit message -Mathias]
+
+Signed-off-by: Niklas Neronin <niklas.neronin@linux.intel.com>
+Signed-off-by: Mathias Nyman <mathias.nyman@linux.intel.com>
+Link: https://lore.kernel.org/r/20240626124835.1023046-10-mathias.nyman@linux.intel.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+[Shivani: Modified to apply on 6.6.y]
+Signed-off-by: Shivani Agarwal <shivani.agarwal@broadcom.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/usb/host/xhci-mem.c  |   10 ++--------
+ drivers/usb/host/xhci-ring.c |    8 ++------
+ drivers/usb/host/xhci.h      |    7 +++++--
+ 3 files changed, 9 insertions(+), 16 deletions(-)
+
+--- a/drivers/usb/host/xhci-mem.c
++++ b/drivers/usb/host/xhci-mem.c
+@@ -136,10 +136,7 @@ static void xhci_link_rings(struct xhci_
+       if (!ring || !first || !last)
+               return;
+-      /* Set chain bit for 0.95 hosts, and for isoc rings on AMD 0.96 host */
+-      chain_links = !!(xhci_link_trb_quirk(xhci) ||
+-                       (ring->type == TYPE_ISOC &&
+-                        (xhci->quirks & XHCI_AMD_0x96_HOST)));
++      chain_links = xhci_link_chain_quirk(xhci, ring->type);
+       next = ring->enq_seg->next;
+       xhci_link_segments(ring->enq_seg, first, ring->type, chain_links);
+@@ -330,10 +327,7 @@ static int xhci_alloc_segments_for_ring(
+       unsigned int num = 0;
+       bool chain_links;
+-      /* Set chain bit for 0.95 hosts, and for isoc rings on AMD 0.96 host */
+-      chain_links = !!(xhci_link_trb_quirk(xhci) ||
+-                       (type == TYPE_ISOC &&
+-                        (xhci->quirks & XHCI_AMD_0x96_HOST)));
++      chain_links = xhci_link_chain_quirk(xhci, type);
+       prev = xhci_segment_alloc(xhci, cycle_state, max_packet, num, flags);
+       if (!prev)
+--- a/drivers/usb/host/xhci-ring.c
++++ b/drivers/usb/host/xhci-ring.c
+@@ -245,9 +245,7 @@ static void inc_enq(struct xhci_hcd *xhc
+                * AMD 0.96 host, carry over the chain bit of the previous TRB
+                * (which may mean the chain bit is cleared).
+                */
+-              if (!(ring->type == TYPE_ISOC &&
+-                    (xhci->quirks & XHCI_AMD_0x96_HOST)) &&
+-                  !xhci_link_trb_quirk(xhci)) {
++              if (!xhci_link_chain_quirk(xhci, ring->type)) {
+                       next->link.control &= cpu_to_le32(~TRB_CHAIN);
+                       next->link.control |= cpu_to_le32(chain);
+               }
+@@ -3381,9 +3379,7 @@ static int prepare_ring(struct xhci_hcd
+               /* If we're not dealing with 0.95 hardware or isoc rings
+                * on AMD 0.96 host, clear the chain bit.
+                */
+-              if (!xhci_link_trb_quirk(xhci) &&
+-                  !(ep_ring->type == TYPE_ISOC &&
+-                    (xhci->quirks & XHCI_AMD_0x96_HOST)))
++              if (!xhci_link_chain_quirk(xhci, ep_ring->type))
+                       ep_ring->enqueue->link.control &=
+                               cpu_to_le32(~TRB_CHAIN);
+               else
+--- a/drivers/usb/host/xhci.h
++++ b/drivers/usb/host/xhci.h
+@@ -1784,9 +1784,12 @@ static inline void xhci_write_64(struct
+       lo_hi_writeq(val, regs);
+ }
+-static inline int xhci_link_trb_quirk(struct xhci_hcd *xhci)
++
++/* Link TRB chain should always be set on 0.95 hosts, and AMD 0.96 ISOC rings */
++static inline bool xhci_link_chain_quirk(struct xhci_hcd *xhci, enum xhci_ring_type type)
+ {
+-      return xhci->quirks & XHCI_LINK_TRB_QUIRK;
++      return (xhci->quirks & XHCI_LINK_TRB_QUIRK) ||
++             (type == TYPE_ISOC && (xhci->quirks & XHCI_AMD_0x96_HOST));
+ }
+ /* xHCI debugging */
diff --git a/queue-6.6/wifi-mac80211-discard-beacon-frames-to-non-broadcast-address.patch b/queue-6.6/wifi-mac80211-discard-beacon-frames-to-non-broadcast-address.patch
new file mode 100644 (file)
index 0000000..daa8729
--- /dev/null
@@ -0,0 +1,62 @@
+From stable+bounces-206054-greg=kroah.com@vger.kernel.org Wed Jan  7 00:28:45 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue,  6 Jan 2026 18:28:39 -0500
+Subject: wifi: mac80211: Discard Beacon frames to non-broadcast address
+To: stable@vger.kernel.org
+Cc: Jouni Malinen <jouni.malinen@oss.qualcomm.com>, Johannes Berg <johannes.berg@intel.com>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260106232839.3452928-1-sashal@kernel.org>
+
+From: Jouni Malinen <jouni.malinen@oss.qualcomm.com>
+
+[ Upstream commit 193d18f60588e95d62e0f82b6a53893e5f2f19f8 ]
+
+Beacon frames are required to be sent to the broadcast address, see IEEE
+Std 802.11-2020, 11.1.3.1 ("The Address 1 field of the Beacon .. frame
+shall be set to the broadcast address"). A unicast Beacon frame might be
+used as a targeted attack to get one of the associated STAs to do
+something (e.g., using CSA to move it to another channel). As such, it
+is better have strict filtering for this on the received side and
+discard all Beacon frames that are sent to an unexpected address.
+
+This is even more important for cases where beacon protection is used.
+The current implementation in mac80211 is correctly discarding unicast
+Beacon frames if the Protected Frame bit in the Frame Control field is
+set to 0. However, if that bit is set to 1, the logic used for checking
+for configured BIGTK(s) does not actually work. If the driver does not
+have logic for dropping unicast Beacon frames with Protected Frame bit
+1, these frames would be accepted in mac80211 processing as valid Beacon
+frames even though they are not protected. This would allow beacon
+protection to be bypassed. While the logic for checking beacon
+protection could be extended to cover this corner case, a more generic
+check for discard all Beacon frames based on A1=unicast address covers
+this without needing additional changes.
+
+Address all these issues by dropping received Beacon frames if they are
+sent to a non-broadcast address.
+
+Cc: stable@vger.kernel.org
+Fixes: af2d14b01c32 ("mac80211: Beacon protection using the new BIGTK (STA)")
+Signed-off-by: Jouni Malinen <jouni.malinen@oss.qualcomm.com>
+Link: https://patch.msgid.link/20251215151134.104501-1-jouni.malinen@oss.qualcomm.com
+Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+[ changed RX_DROP to RX_DROP_MONITOR ]
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/mac80211/rx.c |    5 +++++
+ 1 file changed, 5 insertions(+)
+
+--- a/net/mac80211/rx.c
++++ b/net/mac80211/rx.c
+@@ -3388,6 +3388,11 @@ ieee80211_rx_h_mgmt_check(struct ieee802
+           rx->skb->len < IEEE80211_MIN_ACTION_SIZE)
+               return RX_DROP_U_RUNT_ACTION;
++      /* Drop non-broadcast Beacon frames */
++      if (ieee80211_is_beacon(mgmt->frame_control) &&
++          !is_broadcast_ether_addr(mgmt->da))
++              return RX_DROP_MONITOR;
++
+       if (rx->sdata->vif.type == NL80211_IFTYPE_AP &&
+           ieee80211_is_beacon(mgmt->frame_control) &&
+           !(rx->flags & IEEE80211_RX_BEACON_REPORTED)) {
diff --git a/queue-6.6/wifi-mt76-fix-dts-power-limits-on-little-endian-systems.patch b/queue-6.6/wifi-mt76-fix-dts-power-limits-on-little-endian-systems.patch
new file mode 100644 (file)
index 0000000..8b75467
--- /dev/null
@@ -0,0 +1,139 @@
+From stable+bounces-204133-greg=kroah.com@vger.kernel.org Mon Dec 29 21:36:43 2025
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 29 Dec 2025 15:36:31 -0500
+Subject: wifi: mt76: Fix DTS power-limits on little endian systems
+To: stable@vger.kernel.org
+Cc: "Sven Eckelmann (Plasma Cloud)" <se@simonwunderlich.de>, Felix Fietkau <nbd@nbd.name>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20251229203631.1694637-1-sashal@kernel.org>
+
+From: "Sven Eckelmann (Plasma Cloud)" <se@simonwunderlich.de>
+
+[ Upstream commit 38b845e1f9e810869b0a0b69f202b877b7b7fb12 ]
+
+The power-limits for ru and mcs and stored in the devicetree as bytewise
+array (often with sizes which are not a multiple of 4). These arrays have a
+prefix which defines for how many modes a line is applied. This prefix is
+also only a byte - but the code still tried to fix the endianness of this
+byte with a be32 operation. As result, loading was mostly failing or was
+sending completely unexpected values to the firmware.
+
+Since the other rates are also stored in the devicetree as bytewise arrays,
+just drop the u32 access + be32_to_cpu conversion and directly access them
+as bytes arrays.
+
+Cc: stable@vger.kernel.org
+Fixes: 22b980badc0f ("mt76: add functions for parsing rate power limits from DT")
+Fixes: a9627d992b5e ("mt76: extend DT rate power limits to support 11ax devices")
+Signed-off-by: Sven Eckelmann (Plasma Cloud) <se@simonwunderlich.de>
+Signed-off-by: Felix Fietkau <nbd@nbd.name>
+[ Adjust context ]
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/net/wireless/mediatek/mt76/eeprom.c |   37 ++++++++++++++++++----------
+ 1 file changed, 24 insertions(+), 13 deletions(-)
+
+--- a/drivers/net/wireless/mediatek/mt76/eeprom.c
++++ b/drivers/net/wireless/mediatek/mt76/eeprom.c
+@@ -245,6 +245,19 @@ mt76_get_of_array(struct device_node *np
+       return prop->value;
+ }
++static const s8 *
++mt76_get_of_array_s8(struct device_node *np, char *name, size_t *len, int min)
++{
++      struct property *prop = of_find_property(np, name, NULL);
++
++      if (!prop || !prop->value || prop->length < min)
++              return NULL;
++
++      *len = prop->length;
++
++      return prop->value;
++}
++
+ static struct device_node *
+ mt76_find_channel_node(struct device_node *np, struct ieee80211_channel *chan)
+ {
+@@ -284,7 +297,7 @@ mt76_get_txs_delta(struct device_node *n
+ }
+ static void
+-mt76_apply_array_limit(s8 *pwr, size_t pwr_len, const __be32 *data,
++mt76_apply_array_limit(s8 *pwr, size_t pwr_len, const s8 *data,
+                      s8 target_power, s8 nss_delta, s8 *max_power)
+ {
+       int i;
+@@ -293,15 +306,14 @@ mt76_apply_array_limit(s8 *pwr, size_t p
+               return;
+       for (i = 0; i < pwr_len; i++) {
+-              pwr[i] = min_t(s8, target_power,
+-                             be32_to_cpu(data[i]) + nss_delta);
++              pwr[i] = min_t(s8, target_power, data[i] + nss_delta);
+               *max_power = max(*max_power, pwr[i]);
+       }
+ }
+ static void
+ mt76_apply_multi_array_limit(s8 *pwr, size_t pwr_len, s8 pwr_num,
+-                           const __be32 *data, size_t len, s8 target_power,
++                           const s8 *data, size_t len, s8 target_power,
+                            s8 nss_delta, s8 *max_power)
+ {
+       int i, cur;
+@@ -309,8 +321,7 @@ mt76_apply_multi_array_limit(s8 *pwr, si
+       if (!data)
+               return;
+-      len /= 4;
+-      cur = be32_to_cpu(data[0]);
++      cur = data[0];
+       for (i = 0; i < pwr_num; i++) {
+               if (len < pwr_len + 1)
+                       break;
+@@ -325,7 +336,7 @@ mt76_apply_multi_array_limit(s8 *pwr, si
+               if (!len)
+                       break;
+-              cur = be32_to_cpu(data[0]);
++              cur = data[0];
+       }
+ }
+@@ -336,7 +347,7 @@ s8 mt76_get_rate_power_limits(struct mt7
+ {
+       struct mt76_dev *dev = phy->dev;
+       struct device_node *np;
+-      const __be32 *val;
++      const s8 *val;
+       char name[16];
+       u32 mcs_rates = dev->drv->mcs_rates;
+       u32 ru_rates = ARRAY_SIZE(dest->ru[0]);
+@@ -382,21 +393,21 @@ s8 mt76_get_rate_power_limits(struct mt7
+       txs_delta = mt76_get_txs_delta(np, hweight8(phy->antenna_mask));
+-      val = mt76_get_of_array(np, "rates-cck", &len, ARRAY_SIZE(dest->cck));
++      val = mt76_get_of_array_s8(np, "rates-cck", &len, ARRAY_SIZE(dest->cck));
+       mt76_apply_array_limit(dest->cck, ARRAY_SIZE(dest->cck), val,
+                              target_power, txs_delta, &max_power);
+-      val = mt76_get_of_array(np, "rates-ofdm",
+-                              &len, ARRAY_SIZE(dest->ofdm));
++      val = mt76_get_of_array_s8(np, "rates-ofdm",
++                                 &len, ARRAY_SIZE(dest->ofdm));
+       mt76_apply_array_limit(dest->ofdm, ARRAY_SIZE(dest->ofdm), val,
+                              target_power, txs_delta, &max_power);
+-      val = mt76_get_of_array(np, "rates-mcs", &len, mcs_rates + 1);
++      val = mt76_get_of_array_s8(np, "rates-mcs", &len, mcs_rates + 1);
+       mt76_apply_multi_array_limit(dest->mcs[0], ARRAY_SIZE(dest->mcs[0]),
+                                    ARRAY_SIZE(dest->mcs), val, len,
+                                    target_power, txs_delta, &max_power);
+-      val = mt76_get_of_array(np, "rates-ru", &len, ru_rates + 1);
++      val = mt76_get_of_array_s8(np, "rates-ru", &len, ru_rates + 1);
+       mt76_apply_multi_array_limit(dest->ru[0], ARRAY_SIZE(dest->ru[0]),
+                                    ARRAY_SIZE(dest->ru), val, len,
+                                    target_power, txs_delta, &max_power);
diff --git a/queue-6.6/xhci-dbgtty-fix-device-unregister-fixup.patch b/queue-6.6/xhci-dbgtty-fix-device-unregister-fixup.patch
new file mode 100644 (file)
index 0000000..12e41ea
--- /dev/null
@@ -0,0 +1,40 @@
+From stable+bounces-204276-greg=kroah.com@vger.kernel.org Tue Dec 30 19:44:39 2025
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 30 Dec 2025 13:43:21 -0500
+Subject: xhci: dbgtty: fix device unregister: fixup
+To: stable@vger.kernel.org
+Cc: "Łukasz Bartosik" <ukaszb@chromium.org>, stable <stable@kernel.org>, "Greg Kroah-Hartman" <gregkh@linuxfoundation.org>, "Sasha Levin" <sashal@kernel.org>
+Message-ID: <20251230184321.2402789-2-sashal@kernel.org>
+
+From: Łukasz Bartosik <ukaszb@chromium.org>
+
+[ Upstream commit 74098cc06e753d3ffd8398b040a3a1dfb65260c0 ]
+
+This fixup replaces tty_vhangup() call with call to
+tty_port_tty_vhangup(). Both calls hangup tty device
+synchronously however tty_port_tty_vhangup() increases
+reference count during the hangup operation using
+scoped_guard(tty_port_tty).
+
+Cc: stable <stable@kernel.org>
+Fixes: 1f73b8b56cf3 ("xhci: dbgtty: fix device unregister")
+Signed-off-by: Łukasz Bartosik <ukaszb@chromium.org>
+Link: https://patch.msgid.link/20251127111644.3161386-1-ukaszb@google.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/usb/host/xhci-dbgtty.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/usb/host/xhci-dbgtty.c
++++ b/drivers/usb/host/xhci-dbgtty.c
+@@ -522,7 +522,7 @@ static void xhci_dbc_tty_unregister_devi
+        * Hang up the TTY. This wakes up any blocked
+        * writers and causes subsequent writes to fail.
+        */
+-      tty_vhangup(port->port.tty);
++      tty_port_tty_vhangup(&port->port);
+       tty_unregister_device(dbc_tty_driver, port->minor);
+       xhci_dbc_tty_exit_port(port);