]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
6.1-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 8 Jan 2026 13:24:49 +0000 (14:24 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 8 Jan 2026 13:24:49 +0000 (14:24 +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-sama5d2-fix-spi-flexcom-fifo-size-to-32.patch
arm-dts-microchip-sama7g5-fix-uart-fifo-size-to-32.patch
arm64-dts-ti-k3-j721e-sk-fix-pinmux-for-pin-y1-used-by-power-regulator.patch
asoc-stm-stm32_sai_sub-convert-to-platform-remove-callback-returning-void.patch
asoc-stm32-sai-fix-clk-prepare-imbalance-on-probe-failure.patch
asoc-stm32-sai-fix-of-node-leak-on-probe.patch
asoc-stm32-sai-use-the-devm_clk_get_optional-helper.patch
btrfs-don-t-log-conflicting-inode-if-it-s-a-dir-moved-in-the-current-transaction.patch
btrfs-don-t-rewrite-ret-from-inode_permission.patch
can-gs_usb-gs_can_open-fix-error-handling.patch
crypto-af_alg-zero-initialize-memory-allocated-via-sock_kmalloc.patch
drm-amdgpu-add-missing-lock-to-amdgpu_ttm_access_memory_sdma.patch
drm-amdgpu-cleanup-scheduler-job-initialization-v2.patch
drm-gma500-remove-unused-helper-psb_fbdev_fb_setcolreg.patch
drm-mediatek-fix-probe-memory-leak.patch
ext4-fix-string-copying-in-parse_apply_sb_mount_options.patch
f2fs-drop-inode-from-the-donation-list-when-the-last-file-is-closed.patch
f2fs-fix-to-avoid-updating-compression-context-during-writeback.patch
f2fs-fix-to-avoid-updating-zero-sized-extent-in-extent-cache.patch
f2fs-fix-to-detect-recoverable-inode-during-dryrun-of-find_fsync_dnodes.patch
f2fs-fix-to-propagate-error-from-f2fs_enable_checkpoint.patch
f2fs-keep-posix_fadv_noreuse-ranges.patch
f2fs-remove-unused-gc_failure_pin.patch
f2fs-use-global-inline_xattr_slab-instead-of-per-sb-slab-cache.patch
fscache-delete-fscache_cookie_lru_timer-when-fscache-exits-to-avoid-uaf.patch
fuse-fix-readahead-reclaim-deadlock.patch
gfs2-fix-freeze-error-handling.patch
iommu-arm-smmu-convert-to-platform-remove-callback-returning-void.patch
iommu-arm-smmu-drop-if-with-an-always-false-condition.patch
iommu-mediatek-fix-use-after-free-on-probe-deferral.patch
iommu-mediatek-improve-safety-for-mediatek-smi-property-in-larb-nodes.patch
iommu-mediatek-v1-fix-device-leaks-on-probe.patch
iommu-mtk_iommu_v1-convert-to-platform-remove-callback-returning-void.patch
iommu-qcom-fix-device-leak-on-of_xlate.patch
iommu-qcom-index-contexts-by-asid-number-to-allow-asid-0.patch
iommu-qcom-use-the-asid-read-from-device-tree-if-specified.patch
jbd2-fix-the-inconsistency-between-checksum-and-data-in-memory-for-journal-sb.patch
kbuild-use-crc32-and-a-1mib-dictionary-for-xz-compressed-modules.patch
ksmbd-fix-out-of-bounds-in-parse_sec_desc.patch
kvm-nvmx-immediately-refresh-apicv-controls-as-needed-on-nested-vm-exit.patch
kvm-svm-don-t-skip-unrelated-instruction-if-int3-into-is-replaced.patch
kvm-x86-mmu-use-emultype-flag-to-track-write-pfs-to-shadow-pages.patch
lockd-fix-vfs_test_lock-calls.patch
media-amphion-add-a-frame-flush-mode-for-decoder.patch
media-amphion-make-some-vpu_v4l2-functions-static.patch
media-amphion-remove-vpu_vb_is_codecconfig.patch
media-mediatek-vcodec-fix-a-reference-leak-in-mtk_vcodec_fw_vpu_init.patch
media-verisilicon-fix-cpu-stalls-on-g2-bus-error.patch
mm-balloon_compaction-convert-balloon_page_delete-to-balloon_page_finalize.patch
mm-balloon_compaction-we-cannot-have-isolated-pages-in-the-balloon-list.patch
mm-consider-non-anon-swap-cache-folios-in-folio_expected_ref_count.patch
mm-simplify-folio_expected_ref_count.patch
mptcp-avoid-deadlock-on-fallback-while-reinjecting.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-dsa-sja1105-fix-kasan-out-of-bounds-warning-in-sja1105_table_delete_entry.patch
net-remove-rtnl-dance-for-siocbraddif-and-siocbrdelif.patch
nfsd-clear-seclabel-in-the-suppattr_exclcreat-bitmap.patch
nfsd-nfsv4-file-creation-neglects-setting-acl.patch
page_pool-fix-use-after-free-in-page_pool_recycle_in_ring.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
powerpc-pseries-cmm-adjust-balloon_migrate-when-migrating-pages.patch
scsi-ufs-core-add-ufshcd_update_evt_hist-for-ufs-suspend-error.patch
serial-make-uart_remove_one_port-return-void.patch
sunrpc-svcauth_gss-avoid-null-deref-on-zero-length-gss_token-in-gss_read_proxy_verf.patch
tty-introduce-and-use-tty_port_tty_vhangup-helper.patch
usb-dwc3-keep-susphy-enabled-during-exit-to-avoid-controller-faults.patch
usb-ohci-nxp-fix-device-leak-on-probe-failure.patch
usb-ohci-nxp-use-helper-function-devm_clk_get_enabled.patch
virtio_console-fix-order-of-fields-cols-and-rows.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

82 files changed:
queue-6.1/alsa-hda-cs35l41-fix-null-pointer-dereference-in-cs35l41_hda_read_acpi.patch [new file with mode: 0644]
queue-6.1/alsa-wavefront-clear-substream-pointers-on-close.patch [new file with mode: 0644]
queue-6.1/alsa-wavefront-fix-integer-overflow-in-sample-size-validation.patch [new file with mode: 0644]
queue-6.1/alsa-wavefront-use-guard-for-spin-locks.patch [new file with mode: 0644]
queue-6.1/alsa-wavefront-use-standard-print-api.patch [new file with mode: 0644]
queue-6.1/arm-dts-microchip-sama5d2-fix-spi-flexcom-fifo-size-to-32.patch [new file with mode: 0644]
queue-6.1/arm-dts-microchip-sama7g5-fix-uart-fifo-size-to-32.patch [new file with mode: 0644]
queue-6.1/arm64-dts-ti-k3-j721e-sk-fix-pinmux-for-pin-y1-used-by-power-regulator.patch [new file with mode: 0644]
queue-6.1/asoc-stm-stm32_sai_sub-convert-to-platform-remove-callback-returning-void.patch [new file with mode: 0644]
queue-6.1/asoc-stm32-sai-fix-clk-prepare-imbalance-on-probe-failure.patch [new file with mode: 0644]
queue-6.1/asoc-stm32-sai-fix-of-node-leak-on-probe.patch [new file with mode: 0644]
queue-6.1/asoc-stm32-sai-use-the-devm_clk_get_optional-helper.patch [new file with mode: 0644]
queue-6.1/btrfs-don-t-log-conflicting-inode-if-it-s-a-dir-moved-in-the-current-transaction.patch [new file with mode: 0644]
queue-6.1/btrfs-don-t-rewrite-ret-from-inode_permission.patch [new file with mode: 0644]
queue-6.1/can-gs_usb-gs_can_open-fix-error-handling.patch [new file with mode: 0644]
queue-6.1/crypto-af_alg-zero-initialize-memory-allocated-via-sock_kmalloc.patch [new file with mode: 0644]
queue-6.1/drm-amdgpu-add-missing-lock-to-amdgpu_ttm_access_memory_sdma.patch [new file with mode: 0644]
queue-6.1/drm-amdgpu-cleanup-scheduler-job-initialization-v2.patch [new file with mode: 0644]
queue-6.1/drm-gma500-remove-unused-helper-psb_fbdev_fb_setcolreg.patch [new file with mode: 0644]
queue-6.1/drm-mediatek-fix-probe-memory-leak.patch [new file with mode: 0644]
queue-6.1/ext4-fix-string-copying-in-parse_apply_sb_mount_options.patch [new file with mode: 0644]
queue-6.1/f2fs-drop-inode-from-the-donation-list-when-the-last-file-is-closed.patch [new file with mode: 0644]
queue-6.1/f2fs-fix-to-avoid-updating-compression-context-during-writeback.patch [new file with mode: 0644]
queue-6.1/f2fs-fix-to-avoid-updating-zero-sized-extent-in-extent-cache.patch [new file with mode: 0644]
queue-6.1/f2fs-fix-to-detect-recoverable-inode-during-dryrun-of-find_fsync_dnodes.patch [new file with mode: 0644]
queue-6.1/f2fs-fix-to-propagate-error-from-f2fs_enable_checkpoint.patch [new file with mode: 0644]
queue-6.1/f2fs-keep-posix_fadv_noreuse-ranges.patch [new file with mode: 0644]
queue-6.1/f2fs-remove-unused-gc_failure_pin.patch [new file with mode: 0644]
queue-6.1/f2fs-use-global-inline_xattr_slab-instead-of-per-sb-slab-cache.patch [new file with mode: 0644]
queue-6.1/fscache-delete-fscache_cookie_lru_timer-when-fscache-exits-to-avoid-uaf.patch [new file with mode: 0644]
queue-6.1/fuse-fix-readahead-reclaim-deadlock.patch [new file with mode: 0644]
queue-6.1/gfs2-fix-freeze-error-handling.patch [new file with mode: 0644]
queue-6.1/iommu-arm-smmu-convert-to-platform-remove-callback-returning-void.patch [new file with mode: 0644]
queue-6.1/iommu-arm-smmu-drop-if-with-an-always-false-condition.patch [new file with mode: 0644]
queue-6.1/iommu-mediatek-fix-use-after-free-on-probe-deferral.patch [new file with mode: 0644]
queue-6.1/iommu-mediatek-improve-safety-for-mediatek-smi-property-in-larb-nodes.patch [new file with mode: 0644]
queue-6.1/iommu-mediatek-v1-fix-device-leaks-on-probe.patch [new file with mode: 0644]
queue-6.1/iommu-mtk_iommu_v1-convert-to-platform-remove-callback-returning-void.patch [new file with mode: 0644]
queue-6.1/iommu-qcom-fix-device-leak-on-of_xlate.patch [new file with mode: 0644]
queue-6.1/iommu-qcom-index-contexts-by-asid-number-to-allow-asid-0.patch [new file with mode: 0644]
queue-6.1/iommu-qcom-use-the-asid-read-from-device-tree-if-specified.patch [new file with mode: 0644]
queue-6.1/jbd2-fix-the-inconsistency-between-checksum-and-data-in-memory-for-journal-sb.patch [new file with mode: 0644]
queue-6.1/kbuild-use-crc32-and-a-1mib-dictionary-for-xz-compressed-modules.patch [new file with mode: 0644]
queue-6.1/ksmbd-fix-out-of-bounds-in-parse_sec_desc.patch [new file with mode: 0644]
queue-6.1/kvm-nvmx-immediately-refresh-apicv-controls-as-needed-on-nested-vm-exit.patch [new file with mode: 0644]
queue-6.1/kvm-svm-don-t-skip-unrelated-instruction-if-int3-into-is-replaced.patch [new file with mode: 0644]
queue-6.1/kvm-x86-mmu-use-emultype-flag-to-track-write-pfs-to-shadow-pages.patch [new file with mode: 0644]
queue-6.1/lockd-fix-vfs_test_lock-calls.patch [new file with mode: 0644]
queue-6.1/media-amphion-add-a-frame-flush-mode-for-decoder.patch [new file with mode: 0644]
queue-6.1/media-amphion-make-some-vpu_v4l2-functions-static.patch [new file with mode: 0644]
queue-6.1/media-amphion-remove-vpu_vb_is_codecconfig.patch [new file with mode: 0644]
queue-6.1/media-mediatek-vcodec-fix-a-reference-leak-in-mtk_vcodec_fw_vpu_init.patch [new file with mode: 0644]
queue-6.1/media-verisilicon-fix-cpu-stalls-on-g2-bus-error.patch [new file with mode: 0644]
queue-6.1/mm-balloon_compaction-convert-balloon_page_delete-to-balloon_page_finalize.patch [new file with mode: 0644]
queue-6.1/mm-balloon_compaction-we-cannot-have-isolated-pages-in-the-balloon-list.patch [new file with mode: 0644]
queue-6.1/mm-consider-non-anon-swap-cache-folios-in-folio_expected_ref_count.patch [new file with mode: 0644]
queue-6.1/mm-simplify-folio_expected_ref_count.patch [new file with mode: 0644]
queue-6.1/mptcp-avoid-deadlock-on-fallback-while-reinjecting.patch [new file with mode: 0644]
queue-6.1/mptcp-fallback-earlier-on-simult-connection.patch [new file with mode: 0644]
queue-6.1/mptcp-initialise-rcv_mss-before-calling-tcp_send_active_reset-in-mptcp_do_fastclose.patch [new file with mode: 0644]
queue-6.1/mptcp-pm-ignore-unknown-endpoint-flags.patch [new file with mode: 0644]
queue-6.1/net-dsa-sja1105-fix-kasan-out-of-bounds-warning-in-sja1105_table_delete_entry.patch [new file with mode: 0644]
queue-6.1/net-remove-rtnl-dance-for-siocbraddif-and-siocbrdelif.patch [new file with mode: 0644]
queue-6.1/nfsd-clear-seclabel-in-the-suppattr_exclcreat-bitmap.patch [new file with mode: 0644]
queue-6.1/nfsd-nfsv4-file-creation-neglects-setting-acl.patch [new file with mode: 0644]
queue-6.1/page_pool-fix-use-after-free-in-page_pool_recycle_in_ring.patch [new file with mode: 0644]
queue-6.1/pci-brcmstb-fix-disabling-l0s-capability.patch [new file with mode: 0644]
queue-6.1/pmdomain-imx-fix-reference-count-leak-in-imx_gpc_probe.patch [new file with mode: 0644]
queue-6.1/pmdomain-use-device_get_match_data.patch [new file with mode: 0644]
queue-6.1/powerpc-pseries-cmm-adjust-balloon_migrate-when-migrating-pages.patch [new file with mode: 0644]
queue-6.1/scsi-ufs-core-add-ufshcd_update_evt_hist-for-ufs-suspend-error.patch [new file with mode: 0644]
queue-6.1/serial-make-uart_remove_one_port-return-void.patch [new file with mode: 0644]
queue-6.1/series
queue-6.1/sunrpc-svcauth_gss-avoid-null-deref-on-zero-length-gss_token-in-gss_read_proxy_verf.patch [new file with mode: 0644]
queue-6.1/tty-introduce-and-use-tty_port_tty_vhangup-helper.patch [new file with mode: 0644]
queue-6.1/usb-dwc3-keep-susphy-enabled-during-exit-to-avoid-controller-faults.patch [new file with mode: 0644]
queue-6.1/usb-ohci-nxp-fix-device-leak-on-probe-failure.patch [new file with mode: 0644]
queue-6.1/usb-ohci-nxp-use-helper-function-devm_clk_get_enabled.patch [new file with mode: 0644]
queue-6.1/virtio_console-fix-order-of-fields-cols-and-rows.patch [new file with mode: 0644]
queue-6.1/wifi-mac80211-discard-beacon-frames-to-non-broadcast-address.patch [new file with mode: 0644]
queue-6.1/wifi-mt76-fix-dts-power-limits-on-little-endian-systems.patch [new file with mode: 0644]
queue-6.1/xhci-dbgtty-fix-device-unregister-fixup.patch [new file with mode: 0644]

diff --git a/queue-6.1/alsa-hda-cs35l41-fix-null-pointer-dereference-in-cs35l41_hda_read_acpi.patch b/queue-6.1/alsa-hda-cs35l41-fix-null-pointer-dereference-in-cs35l41_hda_read_acpi.patch
new file mode 100644 (file)
index 0000000..7e58397
--- /dev/null
@@ -0,0 +1,42 @@
+From stable+bounces-201733-greg=kroah.com@vger.kernel.org Tue Dec 16 13:05:52 2025
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 16 Dec 2025 06:46:35 -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: <20251216114635.2768427-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
+@@ -1278,6 +1278,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.1/alsa-wavefront-clear-substream-pointers-on-close.patch b/queue-6.1/alsa-wavefront-clear-substream-pointers-on-close.patch
new file mode 100644 (file)
index 0000000..9bce1cd
--- /dev/null
@@ -0,0 +1,47 @@
+From stable+bounces-201341-greg=kroah.com@vger.kernel.org Tue Dec 16 12:29:40 2025
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 16 Dec 2025 06:24:47 -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: <20251216112447.2760018-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.1/alsa-wavefront-fix-integer-overflow-in-sample-size-validation.patch b/queue-6.1/alsa-wavefront-fix-integer-overflow-in-sample-size-validation.patch
new file mode 100644 (file)
index 0000000..6e21b52
--- /dev/null
@@ -0,0 +1,43 @@
+From stable+bounces-201180-greg=kroah.com@vger.kernel.org Tue Dec 16 12:01:28 2025
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 16 Dec 2025 05:59:24 -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: <20251216105924.2751369-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.1/alsa-wavefront-use-guard-for-spin-locks.patch b/queue-6.1/alsa-wavefront-use-guard-for-spin-locks.patch
new file mode 100644 (file)
index 0000000..585f2b7
--- /dev/null
@@ -0,0 +1,367 @@
+From stable+bounces-201337-greg=kroah.com@vger.kernel.org Tue Dec 16 12:29:29 2025
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 16 Dec 2025 06:24:46 -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: <20251216112447.2760018-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
+@@ -1740,10 +1740,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);
+ }
+@@ -1795,11 +1795,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.1/alsa-wavefront-use-standard-print-api.patch b/queue-6.1/alsa-wavefront-use-standard-print-api.patch
new file mode 100644 (file)
index 0000000..b394c69
--- /dev/null
@@ -0,0 +1,1000 @@
+From stable+bounces-201178-greg=kroah.com@vger.kernel.org Tue Dec 16 12:01:19 2025
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 16 Dec 2025 05:59:23 -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: <20251216105924.2751369-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
+@@ -476,7 +476,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;
+       }
+@@ -498,7 +499,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;
+       }
+@@ -506,7 +508,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 ? */
+       }
+@@ -522,14 +525,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.1/arm-dts-microchip-sama5d2-fix-spi-flexcom-fifo-size-to-32.patch b/queue-6.1/arm-dts-microchip-sama5d2-fix-spi-flexcom-fifo-size-to-32.patch
new file mode 100644 (file)
index 0000000..33d3058
--- /dev/null
@@ -0,0 +1,73 @@
+From stable+bounces-204389-greg=kroah.com@vger.kernel.org Wed Dec 31 22:07:42 2025
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 31 Dec 2025 16:07:37 -0500
+Subject: ARM: dts: microchip: sama5d2: fix spi flexcom 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: <20251231210737.3501550-1-sashal@kernel.org>
+
+From: Nicolas Ferre <nicolas.ferre@microchip.com>
+
+[ Upstream commit 7d5864dc5d5ea6a35983dd05295fb17f2f2f44ce ]
+
+Unlike standalone spi peripherals, on sama5d2, the flexcom spi have fifo
+size of 32 data. Fix flexcom/spi nodes where this property is wrong.
+
+Fixes: 6b9a3584c7ed ("ARM: dts: at91: sama5d2: Add missing flexcom definitions")
+Cc: stable@vger.kernel.org # 5.8+
+Signed-off-by: Nicolas Ferre <nicolas.ferre@microchip.com>
+Link: https://lore.kernel.org/r/20251114140225.30372-1-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/sama5d2.dtsi |   10 +++++-----
+ 1 file changed, 5 insertions(+), 5 deletions(-)
+
+--- a/arch/arm/boot/dts/sama5d2.dtsi
++++ b/arch/arm/boot/dts/sama5d2.dtsi
+@@ -568,7 +568,7 @@
+                                                AT91_XDMAC_DT_PER_IF(1) |
+                                                AT91_XDMAC_DT_PERID(12))>;
+                                       dma-names = "tx", "rx";
+-                                      atmel,fifo-size = <16>;
++                                      atmel,fifo-size = <32>;
+                                       status = "disabled";
+                               };
+@@ -639,7 +639,7 @@
+                                                AT91_XDMAC_DT_PER_IF(1) |
+                                                AT91_XDMAC_DT_PERID(14))>;
+                                       dma-names = "tx", "rx";
+-                                      atmel,fifo-size = <16>;
++                                      atmel,fifo-size = <32>;
+                                       status = "disabled";
+                               };
+@@ -852,7 +852,7 @@
+                                                AT91_XDMAC_DT_PER_IF(1) |
+                                                AT91_XDMAC_DT_PERID(16))>;
+                                       dma-names = "tx", "rx";
+-                                      atmel,fifo-size = <16>;
++                                      atmel,fifo-size = <32>;
+                                       status = "disabled";
+                               };
+@@ -923,7 +923,7 @@
+                                                AT91_XDMAC_DT_PER_IF(1) |
+                                                AT91_XDMAC_DT_PERID(18))>;
+                                       dma-names = "tx", "rx";
+-                                      atmel,fifo-size = <16>;
++                                      atmel,fifo-size = <32>;
+                                       status = "disabled";
+                               };
+@@ -995,7 +995,7 @@
+                                                AT91_XDMAC_DT_PER_IF(1) |
+                                                AT91_XDMAC_DT_PERID(20))>;
+                                       dma-names = "tx", "rx";
+-                                      atmel,fifo-size = <16>;
++                                      atmel,fifo-size = <32>;
+                                       status = "disabled";
+                               };
diff --git a/queue-6.1/arm-dts-microchip-sama7g5-fix-uart-fifo-size-to-32.patch b/queue-6.1/arm-dts-microchip-sama7g5-fix-uart-fifo-size-to-32.patch
new file mode 100644 (file)
index 0000000..fa985f3
--- /dev/null
@@ -0,0 +1,46 @@
+From stable+bounces-204394-greg=kroah.com@vger.kernel.org Wed Dec 31 23:31:52 2025
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 31 Dec 2025 17:31:46 -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: <20251231223146.3547624-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/sama7g5.dtsi |    4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+--- a/arch/arm/boot/dts/sama7g5.dtsi
++++ b/arch/arm/boot/dts/sama7g5.dtsi
+@@ -706,7 +706,7 @@
+                               dma-names = "tx", "rx";
+                               atmel,use-dma-rx;
+                               atmel,use-dma-tx;
+-                              atmel,fifo-size = <16>;
++                              atmel,fifo-size = <32>;
+                               status = "disabled";
+                       };
+               };
+@@ -732,7 +732,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.1/arm64-dts-ti-k3-j721e-sk-fix-pinmux-for-pin-y1-used-by-power-regulator.patch b/queue-6.1/arm64-dts-ti-k3-j721e-sk-fix-pinmux-for-pin-y1-used-by-power-regulator.patch
new file mode 100644 (file)
index 0000000..3d5f9eb
--- /dev/null
@@ -0,0 +1,67 @@
+From stable+bounces-204856-greg=kroah.com@vger.kernel.org Mon Jan  5 17:53:57 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon,  5 Jan 2026 11:48:43 -0500
+Subject: arm64: dts: ti: k3-j721e-sk: Fix pinmux for pin Y1 used by power regulator
+To: stable@vger.kernel.org
+Cc: Siddharth Vadapalli <s-vadapalli@ti.com>, Yemike Abhilash Chandra <y-abhilashchandra@ti.com>, Vignesh Raghavendra <vigneshr@ti.com>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260105164843.2676258-1-sashal@kernel.org>
+
+From: Siddharth Vadapalli <s-vadapalli@ti.com>
+
+[ Upstream commit 51f89c488f2ecc020f82bfedd77482584ce8027a ]
+
+The SoC pin Y1 is incorrectly defined in the WKUP Pinmux device-tree node
+(pinctrl@4301c000) leading to the following silent failure:
+
+    pinctrl-single 4301c000.pinctrl: mux offset out of range: 0x1dc (0x178)
+
+According to the datasheet for the J721E SoC [0], the pin Y1 belongs to the
+MAIN Pinmux device-tree node (pinctrl@11c000). This is confirmed by the
+address of the pinmux register for it on page 142 of the datasheet which is
+0x00011C1DC.
+
+Hence fix it.
+
+[0]: https://www.ti.com/lit/ds/symlink/tda4vm.pdf
+
+Fixes: 97b67cc102dc ("arm64: dts: ti: k3-j721e-sk: Add DT nodes for power regulators")
+Cc: stable@vger.kernel.org
+Signed-off-by: Siddharth Vadapalli <s-vadapalli@ti.com>
+Reviewed-by: Yemike Abhilash Chandra <y-abhilashchandra@ti.com>
+Link: https://patch.msgid.link/20251119160148.2752616-1-s-vadapalli@ti.com
+Signed-off-by: Vignesh Raghavendra <vigneshr@ti.com>
+[ Adjust context ]
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/arm64/boot/dts/ti/k3-j721e-sk.dts |   12 ++++++------
+ 1 file changed, 6 insertions(+), 6 deletions(-)
+
+--- a/arch/arm64/boot/dts/ti/k3-j721e-sk.dts
++++ b/arch/arm64/boot/dts/ti/k3-j721e-sk.dts
+@@ -425,6 +425,12 @@
+                       J721E_IOPAD(0x124, PIN_INPUT, 7) /* (Y24) PRG0_PRU1_GPO9.GPIO0_72 */
+               >;
+       };
++
++      vdd_sd_dv_pins_default: vdd-sd-dv-default-pins {
++              pinctrl-single,pins = <
++                      J721E_IOPAD(0x1dc, PIN_OUTPUT, 7) /* (Y1) SPI1_CLK.GPIO0_118 */
++              >;
++      };
+ };
+ &wkup_pmx0 {
+@@ -480,12 +486,6 @@
+               >;
+       };
+-      vdd_sd_dv_pins_default: vdd-sd-dv-default-pins {
+-              pinctrl-single,pins = <
+-                      J721E_IOPAD(0x1dc, PIN_OUTPUT, 7) /* (Y1) SPI1_CLK.GPIO0_118 */
+-              >;
+-      };
+-
+       wkup_i2c0_pins_default: wkup-i2c0-pins-default {
+               pinctrl-single,pins = <
+                       J721E_WKUP_IOPAD(0xf8, PIN_INPUT_PULLUP, 0) /* (J25) WKUP_I2C0_SCL */
diff --git a/queue-6.1/asoc-stm-stm32_sai_sub-convert-to-platform-remove-callback-returning-void.patch b/queue-6.1/asoc-stm-stm32_sai_sub-convert-to-platform-remove-callback-returning-void.patch
new file mode 100644 (file)
index 0000000..24bc090
--- /dev/null
@@ -0,0 +1,64 @@
+From stable+bounces-204817-greg=kroah.com@vger.kernel.org Mon Jan  5 16:04:04 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon,  5 Jan 2026 09:51:31 -0500
+Subject: ASoC: stm: stm32_sai_sub: Convert to platform remove callback returning void
+To: stable@vger.kernel.org
+Cc: "Uwe Kleine-König" <u.kleine-koenig@pengutronix.de>, "Takashi Iwai" <tiwai@suse.de>, "Nicolas Ferre" <nicolas.ferre@microchip.com>, "Mark Brown" <broonie@kernel.org>, "Sasha Levin" <sashal@kernel.org>
+Message-ID: <20260105145135.2613585-1-sashal@kernel.org>
+
+From: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
+
+[ Upstream commit a3bd37e2e2bce4fb1757a940fa985d556662ba80 ]
+
+The .remove() callback for a platform driver returns an int which makes
+many driver authors wrongly assume it's possible to do error handling by
+returning an error code. However the value returned is (mostly) ignored
+and this typically results in resource leaks. To improve here there is a
+quest to make the remove callback return void. In the first step of this
+quest all drivers are converted to .remove_new() which already returns
+void.
+
+Trivially convert this driver from always returning zero in the remove
+callback to the void returning variant.
+
+Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
+Acked-by: Takashi Iwai <tiwai@suse.de>
+Acked-by: Nicolas Ferre <nicolas.ferre@microchip.com>
+Link: https://lore.kernel.org/r/20230315150745.67084-139-u.kleine-koenig@pengutronix.de
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Stable-dep-of: 23261f0de094 ("ASoC: stm32: sai: fix OF node leak on probe")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ sound/soc/stm/stm32_sai_sub.c |    6 ++----
+ 1 file changed, 2 insertions(+), 4 deletions(-)
+
+--- a/sound/soc/stm/stm32_sai_sub.c
++++ b/sound/soc/stm/stm32_sai_sub.c
+@@ -1570,7 +1570,7 @@ err_unprepare_pclk:
+       return ret;
+ }
+-static int stm32_sai_sub_remove(struct platform_device *pdev)
++static void stm32_sai_sub_remove(struct platform_device *pdev)
+ {
+       struct stm32_sai_sub_data *sai = dev_get_drvdata(&pdev->dev);
+@@ -1578,8 +1578,6 @@ static int stm32_sai_sub_remove(struct p
+       snd_dmaengine_pcm_unregister(&pdev->dev);
+       snd_soc_unregister_component(&pdev->dev);
+       pm_runtime_disable(&pdev->dev);
+-
+-      return 0;
+ }
+ #ifdef CONFIG_PM_SLEEP
+@@ -1629,7 +1627,7 @@ static struct platform_driver stm32_sai_
+               .pm = &stm32_sai_sub_pm_ops,
+       },
+       .probe = stm32_sai_sub_probe,
+-      .remove = stm32_sai_sub_remove,
++      .remove_new = stm32_sai_sub_remove,
+ };
+ module_platform_driver(stm32_sai_sub_driver);
diff --git a/queue-6.1/asoc-stm32-sai-fix-clk-prepare-imbalance-on-probe-failure.patch b/queue-6.1/asoc-stm32-sai-fix-clk-prepare-imbalance-on-probe-failure.patch
new file mode 100644 (file)
index 0000000..47287d1
--- /dev/null
@@ -0,0 +1,93 @@
+From stable+bounces-204804-greg=kroah.com@vger.kernel.org Mon Jan  5 15:10:30 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon,  5 Jan 2026 09:06:13 -0500
+Subject: ASoC: stm32: sai: fix clk prepare imbalance on probe failure
+To: stable@vger.kernel.org
+Cc: Johan Hovold <johan@kernel.org>, Olivier Moysan <olivier.moysan@st.com>, olivier moysan <olivier.moysan@foss.st.com>, Mark Brown <broonie@kernel.org>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260105140613.2598547-2-sashal@kernel.org>
+
+From: Johan Hovold <johan@kernel.org>
+
+[ Upstream commit 312ec2f0d9d1a5656f76d770bbf1d967e9289aa7 ]
+
+Make sure to unprepare the parent clock also on probe failures (e.g.
+probe deferral).
+
+Fixes: a14bf98c045b ("ASoC: stm32: sai: fix possible circular locking")
+Cc: stable@vger.kernel.org     # 5.5
+Cc: Olivier Moysan <olivier.moysan@st.com>
+Signed-off-by: Johan Hovold <johan@kernel.org>
+Reviewed-by: olivier moysan <olivier.moysan@foss.st.com>
+Link: https://patch.msgid.link/20251124104908.15754-3-johan@kernel.org
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ sound/soc/stm/stm32_sai_sub.c |   28 +++++++++++++++++++++-------
+ 1 file changed, 21 insertions(+), 7 deletions(-)
+
+--- a/sound/soc/stm/stm32_sai_sub.c
++++ b/sound/soc/stm/stm32_sai_sub.c
+@@ -1483,14 +1483,21 @@ static int stm32_sai_sub_parse_of(struct
+       if (of_find_property(np, "#clock-cells", NULL)) {
+               ret = stm32_sai_add_mclk_provider(sai);
+               if (ret < 0)
+-                      return ret;
++                      goto err_unprepare_pclk;
+       } else {
+               sai->sai_mclk = devm_clk_get_optional(&pdev->dev, "MCLK");
+-              if (IS_ERR(sai->sai_mclk))
+-                      return PTR_ERR(sai->sai_mclk);
++              if (IS_ERR(sai->sai_mclk)) {
++                      ret = PTR_ERR(sai->sai_mclk);
++                      goto err_unprepare_pclk;
++              }
+       }
+       return 0;
++
++err_unprepare_pclk:
++      clk_unprepare(sai->pdata->pclk);
++
++      return ret;
+ }
+ static int stm32_sai_sub_probe(struct platform_device *pdev)
+@@ -1534,26 +1541,33 @@ static int stm32_sai_sub_probe(struct pl
+                              IRQF_SHARED, dev_name(&pdev->dev), sai);
+       if (ret) {
+               dev_err(&pdev->dev, "IRQ request returned %d\n", ret);
+-              return ret;
++              goto err_unprepare_pclk;
+       }
+       if (STM_SAI_PROTOCOL_IS_SPDIF(sai))
+               conf = &stm32_sai_pcm_config_spdif;
+       ret = snd_dmaengine_pcm_register(&pdev->dev, conf, 0);
+-      if (ret)
+-              return dev_err_probe(&pdev->dev, ret, "Could not register pcm dma\n");
++      if (ret) {
++              ret = dev_err_probe(&pdev->dev, ret, "Could not register pcm dma\n");
++              goto err_unprepare_pclk;
++      }
+       ret = snd_soc_register_component(&pdev->dev, &stm32_component,
+                                        &sai->cpu_dai_drv, 1);
+       if (ret) {
+               snd_dmaengine_pcm_unregister(&pdev->dev);
+-              return ret;
++              goto err_unprepare_pclk;
+       }
+       pm_runtime_enable(&pdev->dev);
+       return 0;
++
++err_unprepare_pclk:
++      clk_unprepare(sai->pdata->pclk);
++
++      return ret;
+ }
+ static int stm32_sai_sub_remove(struct platform_device *pdev)
diff --git a/queue-6.1/asoc-stm32-sai-fix-of-node-leak-on-probe.patch b/queue-6.1/asoc-stm32-sai-fix-of-node-leak-on-probe.patch
new file mode 100644 (file)
index 0000000..263f0e0
--- /dev/null
@@ -0,0 +1,149 @@
+From stable+bounces-204821-greg=kroah.com@vger.kernel.org Mon Jan  5 15:55:49 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon,  5 Jan 2026 09:51:35 -0500
+Subject: ASoC: stm32: sai: fix OF node leak on probe
+To: stable@vger.kernel.org
+Cc: Johan Hovold <johan@kernel.org>, Olivier Moysan <olivier.moysan@st.com>, olivier moysan <olivier.moysan@foss.st.com>, Mark Brown <broonie@kernel.org>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260105145135.2613585-5-sashal@kernel.org>
+
+From: Johan Hovold <johan@kernel.org>
+
+[ Upstream commit 23261f0de09427367e99f39f588e31e2856a690e ]
+
+The reference taken to the sync provider OF node when probing the
+platform device is currently only dropped if the set_sync() callback
+fails during DAI probe.
+
+Make sure to drop the reference on platform probe failures (e.g. probe
+deferral) and on driver unbind.
+
+This also avoids a potential use-after-free in case the DAI is ever
+reprobed without first rebinding the platform driver.
+
+Fixes: 5914d285f6b7 ("ASoC: stm32: sai: Add synchronization support")
+Fixes: d4180b4c02e7 ("ASoC: stm32: sai: fix set_sync service")
+Cc: Olivier Moysan <olivier.moysan@st.com>
+Cc: stable@vger.kernel.org      # 4.16: d4180b4c02e7
+Signed-off-by: Johan Hovold <johan@kernel.org>
+Reviewed-by: olivier moysan <olivier.moysan@foss.st.com>
+Link: https://patch.msgid.link/20251124104908.15754-4-johan@kernel.org
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ sound/soc/stm/stm32_sai.c     |   12 +++---------
+ sound/soc/stm/stm32_sai_sub.c |   23 ++++++++++++++++-------
+ 2 files changed, 19 insertions(+), 16 deletions(-)
+
+--- a/sound/soc/stm/stm32_sai.c
++++ b/sound/soc/stm/stm32_sai.c
+@@ -122,7 +122,6 @@ static int stm32_sai_set_sync(struct stm
+       if (!pdev) {
+               dev_err(&sai_client->pdev->dev,
+                       "Device not found for node %pOFn\n", np_provider);
+-              of_node_put(np_provider);
+               return -ENODEV;
+       }
+@@ -131,21 +130,16 @@ static int stm32_sai_set_sync(struct stm
+       if (!sai_provider) {
+               dev_err(&sai_client->pdev->dev,
+                       "SAI sync provider data not found\n");
+-              ret = -EINVAL;
+-              goto error;
++              return -EINVAL;
+       }
+       /* Configure sync client */
+       ret = stm32_sai_sync_conf_client(sai_client, synci);
+       if (ret < 0)
+-              goto error;
++              return ret;
+       /* Configure sync provider */
+-      ret = stm32_sai_sync_conf_provider(sai_provider, synco);
+-
+-error:
+-      of_node_put(np_provider);
+-      return ret;
++      return stm32_sai_sync_conf_provider(sai_provider, synco);
+ }
+ static int stm32_sai_probe(struct platform_device *pdev)
+--- a/sound/soc/stm/stm32_sai_sub.c
++++ b/sound/soc/stm/stm32_sai_sub.c
+@@ -1435,7 +1435,8 @@ static int stm32_sai_sub_parse_of(struct
+                               dev_err(&pdev->dev,
+                                       "External synchro not supported\n");
+                               of_node_put(args.np);
+-                              return -EINVAL;
++                              ret = -EINVAL;
++                              goto err_put_sync_provider;
+                       }
+                       sai->sync = SAI_SYNC_EXTERNAL;
+@@ -1444,7 +1445,8 @@ static int stm32_sai_sub_parse_of(struct
+                           (sai->synci > (SAI_GCR_SYNCIN_MAX + 1))) {
+                               dev_err(&pdev->dev, "Wrong SAI index\n");
+                               of_node_put(args.np);
+-                              return -EINVAL;
++                              ret = -EINVAL;
++                              goto err_put_sync_provider;
+                       }
+                       if (of_property_match_string(args.np, "compatible",
+@@ -1458,7 +1460,8 @@ static int stm32_sai_sub_parse_of(struct
+                       if (!sai->synco) {
+                               dev_err(&pdev->dev, "Unknown SAI sub-block\n");
+                               of_node_put(args.np);
+-                              return -EINVAL;
++                              ret = -EINVAL;
++                              goto err_put_sync_provider;
+                       }
+               }
+@@ -1468,13 +1471,15 @@ static int stm32_sai_sub_parse_of(struct
+       of_node_put(args.np);
+       sai->sai_ck = devm_clk_get(&pdev->dev, "sai_ck");
+-      if (IS_ERR(sai->sai_ck))
+-              return dev_err_probe(&pdev->dev, PTR_ERR(sai->sai_ck),
+-                                   "Missing kernel clock sai_ck\n");
++      if (IS_ERR(sai->sai_ck)) {
++              ret = dev_err_probe(&pdev->dev, PTR_ERR(sai->sai_ck),
++                                  "Missing kernel clock sai_ck\n");
++              goto err_put_sync_provider;
++      }
+       ret = clk_prepare(sai->pdata->pclk);
+       if (ret < 0)
+-              return ret;
++              goto err_put_sync_provider;
+       if (STM_SAI_IS_F4(sai->pdata))
+               return 0;
+@@ -1496,6 +1501,8 @@ static int stm32_sai_sub_parse_of(struct
+ err_unprepare_pclk:
+       clk_unprepare(sai->pdata->pclk);
++err_put_sync_provider:
++      of_node_put(sai->np_sync_provider);
+       return ret;
+ }
+@@ -1566,6 +1573,7 @@ static int stm32_sai_sub_probe(struct pl
+ err_unprepare_pclk:
+       clk_unprepare(sai->pdata->pclk);
++      of_node_put(sai->np_sync_provider);
+       return ret;
+ }
+@@ -1578,6 +1586,7 @@ static void stm32_sai_sub_remove(struct
+       snd_dmaengine_pcm_unregister(&pdev->dev);
+       snd_soc_unregister_component(&pdev->dev);
+       pm_runtime_disable(&pdev->dev);
++      of_node_put(sai->np_sync_provider);
+ }
+ #ifdef CONFIG_PM_SLEEP
diff --git a/queue-6.1/asoc-stm32-sai-use-the-devm_clk_get_optional-helper.patch b/queue-6.1/asoc-stm32-sai-use-the-devm_clk_get_optional-helper.patch
new file mode 100644 (file)
index 0000000..4e770fe
--- /dev/null
@@ -0,0 +1,43 @@
+From stable+bounces-204803-greg=kroah.com@vger.kernel.org Mon Jan  5 15:06:20 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon,  5 Jan 2026 09:06:12 -0500
+Subject: ASoC: stm32: sai: Use the devm_clk_get_optional() helper
+To: stable@vger.kernel.org
+Cc: Christophe JAILLET <christophe.jaillet@wanadoo.fr>, Mark Brown <broonie@kernel.org>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260105140613.2598547-1-sashal@kernel.org>
+
+From: Christophe JAILLET <christophe.jaillet@wanadoo.fr>
+
+[ Upstream commit 374628fb668e50b42fe81f2a63af616182415bcd ]
+
+Use devm_clk_get_optional() instead of hand writing it.
+This saves some LoC and improves the semantic.
+
+Signed-off-by: Christophe JAILLET <christophe.jaillet@wanadoo.fr>
+Link: https://lore.kernel.org/r/f7987f18dadf77bfa09969fd4c82d5a0f4e4e3b7.1684594838.git.christophe.jaillet@wanadoo.fr
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Stable-dep-of: 312ec2f0d9d1 ("ASoC: stm32: sai: fix clk prepare imbalance on probe failure")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ sound/soc/stm/stm32_sai_sub.c |    9 +++------
+ 1 file changed, 3 insertions(+), 6 deletions(-)
+
+--- a/sound/soc/stm/stm32_sai_sub.c
++++ b/sound/soc/stm/stm32_sai_sub.c
+@@ -1485,12 +1485,9 @@ static int stm32_sai_sub_parse_of(struct
+               if (ret < 0)
+                       return ret;
+       } else {
+-              sai->sai_mclk = devm_clk_get(&pdev->dev, "MCLK");
+-              if (IS_ERR(sai->sai_mclk)) {
+-                      if (PTR_ERR(sai->sai_mclk) != -ENOENT)
+-                              return PTR_ERR(sai->sai_mclk);
+-                      sai->sai_mclk = NULL;
+-              }
++              sai->sai_mclk = devm_clk_get_optional(&pdev->dev, "MCLK");
++              if (IS_ERR(sai->sai_mclk))
++                      return PTR_ERR(sai->sai_mclk);
+       }
+       return 0;
diff --git a/queue-6.1/btrfs-don-t-log-conflicting-inode-if-it-s-a-dir-moved-in-the-current-transaction.patch b/queue-6.1/btrfs-don-t-log-conflicting-inode-if-it-s-a-dir-moved-in-the-current-transaction.patch
new file mode 100644 (file)
index 0000000..edfb0c6
--- /dev/null
@@ -0,0 +1,274 @@
+From stable+bounces-204368-greg=kroah.com@vger.kernel.org Wed Dec 31 17:12:11 2025
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 31 Dec 2025 11:11:55 -0500
+Subject: btrfs: don't log conflicting inode if it's a dir moved in the current transaction
+To: stable@vger.kernel.org
+Cc: Filipe Manana <fdmanana@suse.com>, Vyacheslav Kovalevsky <slva.kovalevskiy.2014@gmail.com>, David Sterba <dsterba@suse.com>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20251231161155.3221875-1-sashal@kernel.org>
+
+From: Filipe Manana <fdmanana@suse.com>
+
+[ Upstream commit 266273eaf4d99475f1ae57f687b3e42bc71ec6f0 ]
+
+We can't log a conflicting inode if it's a directory and it was moved
+from one parent directory to another parent directory in the current
+transaction, as this can result an attempt to have a directory with
+two hard links during log replay, one for the old parent directory and
+another for the new parent directory.
+
+The following scenario triggers that issue:
+
+1) We have directories "dir1" and "dir2" created in a past transaction.
+   Directory "dir1" has inode A as its parent directory;
+
+2) We move "dir1" to some other directory;
+
+3) We create a file with the name "dir1" in directory inode A;
+
+4) We fsync the new file. This results in logging the inode of the new file
+   and the inode for the directory "dir1" that was previously moved in the
+   current transaction. So the log tree has the INODE_REF item for the
+   new location of "dir1";
+
+5) We move the new file to some other directory. This results in updating
+   the log tree to included the new INODE_REF for the new location of the
+   file and removes the INODE_REF for the old location. This happens
+   during the rename when we call btrfs_log_new_name();
+
+6) We fsync the file, and that persists the log tree changes done in the
+   previous step (btrfs_log_new_name() only updates the log tree in
+   memory);
+
+7) We have a power failure;
+
+8) Next time the fs is mounted, log replay happens and when processing
+   the inode for directory "dir1" we find a new INODE_REF and add that
+   link, but we don't remove the old link of the inode since we have
+   not logged the old parent directory of the directory inode "dir1".
+
+As a result after log replay finishes when we trigger writeback of the
+subvolume tree's extent buffers, the tree check will detect that we have
+a directory a hard link count of 2 and we get a mount failure.
+The errors and stack traces reported in dmesg/syslog are like this:
+
+   [ 3845.729764] BTRFS info (device dm-0): start tree-log replay
+   [ 3845.730304] page: refcount:3 mapcount:0 mapping:000000005c8a3027 index:0x1d00 pfn:0x11510c
+   [ 3845.731236] memcg:ffff9264c02f4e00
+   [ 3845.731751] aops:btree_aops [btrfs] ino:1
+   [ 3845.732300] flags: 0x17fffc00000400a(uptodate|private|writeback|node=0|zone=2|lastcpupid=0x1ffff)
+   [ 3845.733346] raw: 017fffc00000400a 0000000000000000 dead000000000122 ffff9264d978aea8
+   [ 3845.734265] raw: 0000000000001d00 ffff92650e6d4738 00000003ffffffff ffff9264c02f4e00
+   [ 3845.735305] page dumped because: eb page dump
+   [ 3845.735981] BTRFS critical (device dm-0): corrupt leaf: root=5 block=30408704 slot=6 ino=257, invalid nlink: has 2 expect no more than 1 for dir
+   [ 3845.737786] BTRFS info (device dm-0): leaf 30408704 gen 10 total ptrs 17 free space 14881 owner 5
+   [ 3845.737789] BTRFS info (device dm-0): refs 4 lock_owner 0 current 30701
+   [ 3845.737792]      item 0 key (256 INODE_ITEM 0) itemoff 16123 itemsize 160
+   [ 3845.737794]              inode generation 3 transid 9 size 16 nbytes 16384
+   [ 3845.737795]              block group 0 mode 40755 links 1 uid 0 gid 0
+   [ 3845.737797]              rdev 0 sequence 2 flags 0x0
+   [ 3845.737798]              atime 1764259517.0
+   [ 3845.737800]              ctime 1764259517.572889464
+   [ 3845.737801]              mtime 1764259517.572889464
+   [ 3845.737802]              otime 1764259517.0
+   [ 3845.737803]      item 1 key (256 INODE_REF 256) itemoff 16111 itemsize 12
+   [ 3845.737805]              index 0 name_len 2
+   [ 3845.737807]      item 2 key (256 DIR_ITEM 2363071922) itemoff 16077 itemsize 34
+   [ 3845.737808]              location key (257 1 0) type 2
+   [ 3845.737810]              transid 9 data_len 0 name_len 4
+   [ 3845.737811]      item 3 key (256 DIR_ITEM 2676584006) itemoff 16043 itemsize 34
+   [ 3845.737813]              location key (258 1 0) type 2
+   [ 3845.737814]              transid 9 data_len 0 name_len 4
+   [ 3845.737815]      item 4 key (256 DIR_INDEX 2) itemoff 16009 itemsize 34
+   [ 3845.737816]              location key (257 1 0) type 2
+   [ 3845.737818]              transid 9 data_len 0 name_len 4
+   [ 3845.737819]      item 5 key (256 DIR_INDEX 3) itemoff 15975 itemsize 34
+   [ 3845.737820]              location key (258 1 0) type 2
+   [ 3845.737821]              transid 9 data_len 0 name_len 4
+   [ 3845.737822]      item 6 key (257 INODE_ITEM 0) itemoff 15815 itemsize 160
+   [ 3845.737824]              inode generation 9 transid 10 size 6 nbytes 0
+   [ 3845.737825]              block group 0 mode 40755 links 2 uid 0 gid 0
+   [ 3845.737826]              rdev 0 sequence 1 flags 0x0
+   [ 3845.737827]              atime 1764259517.572889464
+   [ 3845.737828]              ctime 1764259517.572889464
+   [ 3845.737830]              mtime 1764259517.572889464
+   [ 3845.737831]              otime 1764259517.572889464
+   [ 3845.737832]      item 7 key (257 INODE_REF 256) itemoff 15801 itemsize 14
+   [ 3845.737833]              index 2 name_len 4
+   [ 3845.737834]      item 8 key (257 INODE_REF 258) itemoff 15787 itemsize 14
+   [ 3845.737836]              index 2 name_len 4
+   [ 3845.737837]      item 9 key (257 DIR_ITEM 2507850652) itemoff 15754 itemsize 33
+   [ 3845.737838]              location key (259 1 0) type 1
+   [ 3845.737839]              transid 10 data_len 0 name_len 3
+   [ 3845.737840]      item 10 key (257 DIR_INDEX 2) itemoff 15721 itemsize 33
+   [ 3845.737842]              location key (259 1 0) type 1
+   [ 3845.737843]              transid 10 data_len 0 name_len 3
+   [ 3845.737844]      item 11 key (258 INODE_ITEM 0) itemoff 15561 itemsize 160
+   [ 3845.737846]              inode generation 9 transid 10 size 8 nbytes 0
+   [ 3845.737847]              block group 0 mode 40755 links 1 uid 0 gid 0
+   [ 3845.737848]              rdev 0 sequence 1 flags 0x0
+   [ 3845.737849]              atime 1764259517.572889464
+   [ 3845.737850]              ctime 1764259517.572889464
+   [ 3845.737851]              mtime 1764259517.572889464
+   [ 3845.737852]              otime 1764259517.572889464
+   [ 3845.737853]      item 12 key (258 INODE_REF 256) itemoff 15547 itemsize 14
+   [ 3845.737855]              index 3 name_len 4
+   [ 3845.737856]      item 13 key (258 DIR_ITEM 1843588421) itemoff 15513 itemsize 34
+   [ 3845.737857]              location key (257 1 0) type 2
+   [ 3845.737858]              transid 10 data_len 0 name_len 4
+   [ 3845.737860]      item 14 key (258 DIR_INDEX 2) itemoff 15479 itemsize 34
+   [ 3845.737861]              location key (257 1 0) type 2
+   [ 3845.737862]              transid 10 data_len 0 name_len 4
+   [ 3845.737863]      item 15 key (259 INODE_ITEM 0) itemoff 15319 itemsize 160
+   [ 3845.737865]              inode generation 10 transid 10 size 0 nbytes 0
+   [ 3845.737866]              block group 0 mode 100600 links 1 uid 0 gid 0
+   [ 3845.737867]              rdev 0 sequence 2 flags 0x0
+   [ 3845.737868]              atime 1764259517.580874966
+   [ 3845.737869]              ctime 1764259517.586121869
+   [ 3845.737870]              mtime 1764259517.580874966
+   [ 3845.737872]              otime 1764259517.580874966
+   [ 3845.737873]      item 16 key (259 INODE_REF 257) itemoff 15306 itemsize 13
+   [ 3845.737874]              index 2 name_len 3
+   [ 3845.737875] BTRFS error (device dm-0): block=30408704 write time tree block corruption detected
+   [ 3845.739448] ------------[ cut here ]------------
+   [ 3845.740092] WARNING: CPU: 5 PID: 30701 at fs/btrfs/disk-io.c:335 btree_csum_one_bio+0x25a/0x270 [btrfs]
+   [ 3845.741439] Modules linked in: btrfs dm_flakey crc32c_cryptoapi (...)
+   [ 3845.750626] CPU: 5 UID: 0 PID: 30701 Comm: mount Tainted: G        W           6.18.0-rc6-btrfs-next-218+ #1 PREEMPT(full)
+   [ 3845.752414] Tainted: [W]=WARN
+   [ 3845.752828] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS rel-1.16.2-0-gea1b7a073390-prebuilt.qemu.org 04/01/2014
+   [ 3845.754499] RIP: 0010:btree_csum_one_bio+0x25a/0x270 [btrfs]
+   [ 3845.755460] Code: 31 f6 48 89 (...)
+   [ 3845.758685] RSP: 0018:ffffa8d9c5677678 EFLAGS: 00010246
+   [ 3845.759450] RAX: 0000000000000000 RBX: ffff92650e6d4738 RCX: 0000000000000000
+   [ 3845.760309] RDX: 0000000000000000 RSI: ffffffff9aab45b9 RDI: ffff9264c4748000
+   [ 3845.761239] RBP: ffff9264d4324000 R08: 0000000000000000 R09: ffffa8d9c5677468
+   [ 3845.762607] R10: ffff926bdc1fffa8 R11: 0000000000000003 R12: ffffa8d9c5677680
+   [ 3845.764099] R13: 0000000000004000 R14: ffff9264dd624000 R15: ffff9264d978aba8
+   [ 3845.765094] FS:  00007f751fa5a840(0000) GS:ffff926c42a82000(0000) knlGS:0000000000000000
+   [ 3845.766226] CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
+   [ 3845.766970] CR2: 0000558df1815380 CR3: 000000010ed88003 CR4: 0000000000370ef0
+   [ 3845.768009] Call Trace:
+   [ 3845.768392]  <TASK>
+   [ 3845.768714]  btrfs_submit_bbio+0x6ee/0x7f0 [btrfs]
+   [ 3845.769640]  ? write_one_eb+0x28e/0x340 [btrfs]
+   [ 3845.770588]  btree_write_cache_pages+0x2f0/0x550 [btrfs]
+   [ 3845.771286]  ? alloc_extent_state+0x19/0x100 [btrfs]
+   [ 3845.771967]  ? merge_next_state+0x1a/0x90 [btrfs]
+   [ 3845.772586]  ? set_extent_bit+0x233/0x8b0 [btrfs]
+   [ 3845.773198]  ? xas_load+0x9/0xc0
+   [ 3845.773589]  ? xas_find+0x14d/0x1a0
+   [ 3845.773969]  do_writepages+0xc6/0x160
+   [ 3845.774367]  filemap_fdatawrite_wbc+0x48/0x60
+   [ 3845.775003]  __filemap_fdatawrite_range+0x5b/0x80
+   [ 3845.775902]  btrfs_write_marked_extents+0x61/0x170 [btrfs]
+   [ 3845.776707]  btrfs_write_and_wait_transaction+0x4e/0xc0 [btrfs]
+   [ 3845.777379]  ? _raw_spin_unlock_irqrestore+0x23/0x40
+   [ 3845.777923]  btrfs_commit_transaction+0x5ea/0xd20 [btrfs]
+   [ 3845.778551]  ? _raw_spin_unlock+0x15/0x30
+   [ 3845.778986]  ? release_extent_buffer+0x34/0x160 [btrfs]
+   [ 3845.779659]  btrfs_recover_log_trees+0x7a3/0x7c0 [btrfs]
+   [ 3845.780416]  ? __pfx_replay_one_buffer+0x10/0x10 [btrfs]
+   [ 3845.781499]  open_ctree+0x10bb/0x15f0 [btrfs]
+   [ 3845.782194]  btrfs_get_tree.cold+0xb/0x16c [btrfs]
+   [ 3845.782764]  ? fscontext_read+0x15c/0x180
+   [ 3845.783202]  ? rw_verify_area+0x50/0x180
+   [ 3845.783667]  vfs_get_tree+0x25/0xd0
+   [ 3845.784047]  vfs_cmd_create+0x59/0xe0
+   [ 3845.784458]  __do_sys_fsconfig+0x4f6/0x6b0
+   [ 3845.784914]  do_syscall_64+0x50/0x1220
+   [ 3845.785340]  entry_SYSCALL_64_after_hwframe+0x76/0x7e
+   [ 3845.785980] RIP: 0033:0x7f751fc7f4aa
+   [ 3845.786759] Code: 73 01 c3 48 (...)
+   [ 3845.789951] RSP: 002b:00007ffcdba45dc8 EFLAGS: 00000246 ORIG_RAX: 00000000000001af
+   [ 3845.791402] RAX: ffffffffffffffda RBX: 000055ccc8291c20 RCX: 00007f751fc7f4aa
+   [ 3845.792688] RDX: 0000000000000000 RSI: 0000000000000006 RDI: 0000000000000003
+   [ 3845.794308] RBP: 000055ccc8292120 R08: 0000000000000000 R09: 0000000000000000
+   [ 3845.795829] R10: 0000000000000000 R11: 0000000000000246 R12: 0000000000000000
+   [ 3845.797183] R13: 00007f751fe11580 R14: 00007f751fe1326c R15: 00007f751fdf8a23
+   [ 3845.798633]  </TASK>
+   [ 3845.799067] ---[ end trace 0000000000000000 ]---
+   [ 3845.800215] BTRFS: error (device dm-0) in btrfs_commit_transaction:2553: errno=-5 IO failure (Error while writing out transaction)
+   [ 3845.801860] BTRFS warning (device dm-0 state E): Skipping commit of aborted transaction.
+   [ 3845.802815] BTRFS error (device dm-0 state EA): Transaction aborted (error -5)
+   [ 3845.803728] BTRFS: error (device dm-0 state EA) in cleanup_transaction:2036: errno=-5 IO failure
+   [ 3845.805374] BTRFS: error (device dm-0 state EA) in btrfs_replay_log:2083: errno=-5 IO failure (Failed to recover log tree)
+   [ 3845.807919] BTRFS error (device dm-0 state EA): open_ctree failed: -5
+
+Fix this by never logging a conflicting inode that is a directory and was
+moved in the current transaction (its last_unlink_trans equals the current
+transaction) and instead fallback to a transaction commit.
+
+A test case for fstests will follow soon.
+
+Reported-by: Vyacheslav Kovalevsky <slva.kovalevskiy.2014@gmail.com>
+Link: https://lore.kernel.org/linux-btrfs/7bbc9419-5c56-450a-b5a0-efeae7457113@gmail.com/
+CC: stable@vger.kernel.org # 6.1+
+Signed-off-by: Filipe Manana <fdmanana@suse.com>
+Signed-off-by: David Sterba <dsterba@suse.com>
+[ wrapped inode parameter with BTRFS_I() ]
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/btrfs/tree-log.c |   38 ++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 38 insertions(+)
+
+--- a/fs/btrfs/tree-log.c
++++ b/fs/btrfs/tree-log.c
+@@ -5638,6 +5638,33 @@ static int conflicting_inode_is_dir(stru
+       return ret;
+ }
++static bool can_log_conflicting_inode(const struct btrfs_trans_handle *trans,
++                                    const struct btrfs_inode *inode)
++{
++      if (!S_ISDIR(inode->vfs_inode.i_mode))
++              return true;
++
++      if (inode->last_unlink_trans < trans->transid)
++              return true;
++
++      /*
++       * If this is a directory and its unlink_trans is not from a past
++       * transaction then we must fallback to a transaction commit in order
++       * to avoid getting a directory with 2 hard links after log replay.
++       *
++       * This happens if a directory A is renamed, moved from one parent
++       * directory to another one, a new file is created in the old parent
++       * directory with the old name of our directory A, the new file is
++       * fsynced, then we moved the new file to some other parent directory
++       * and fsync again the new file. This results in a log tree where we
++       * logged that directory A existed, with the INODE_REF item for the
++       * new location but without having logged its old parent inode, so
++       * that on log replay we add a new link for the new location but the
++       * old link remains, resulting in a link count of 2.
++       */
++      return false;
++}
++
+ static int add_conflicting_inode(struct btrfs_trans_handle *trans,
+                                struct btrfs_root *root,
+                                struct btrfs_path *path,
+@@ -5743,6 +5770,11 @@ static int add_conflicting_inode(struct
+               return 0;
+       }
++      if (!can_log_conflicting_inode(trans, BTRFS_I(inode))) {
++              btrfs_add_delayed_iput(inode);
++              return BTRFS_LOG_FORCE_COMMIT;
++      }
++
+       btrfs_add_delayed_iput(inode);
+       ino_elem = kmalloc(sizeof(*ino_elem), GFP_NOFS);
+@@ -5808,6 +5840,12 @@ static int log_conflicting_inodes(struct
+                               break;
+                       }
++                      if (!can_log_conflicting_inode(trans, BTRFS_I(inode))) {
++                              btrfs_add_delayed_iput(inode);
++                              ret = BTRFS_LOG_FORCE_COMMIT;
++                              break;
++                      }
++
+                       /*
+                        * Always log the directory, we cannot make this
+                        * conditional on need_log_inode() because the directory
diff --git a/queue-6.1/btrfs-don-t-rewrite-ret-from-inode_permission.patch b/queue-6.1/btrfs-don-t-rewrite-ret-from-inode_permission.patch
new file mode 100644 (file)
index 0000000..e34632d
--- /dev/null
@@ -0,0 +1,51 @@
+From stable+bounces-204141-greg=kroah.com@vger.kernel.org Mon Dec 29 23:04:20 2025
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 29 Dec 2025 17:03:37 -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: <20251229220337.1736680-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
+@@ -2897,10 +2897,8 @@ static int btrfs_search_path_in_tree_use
+                       ret = inode_permission(mnt_userns, 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.1/can-gs_usb-gs_can_open-fix-error-handling.patch b/queue-6.1/can-gs_usb-gs_can_open-fix-error-handling.patch
new file mode 100644 (file)
index 0000000..02d54df
--- /dev/null
@@ -0,0 +1,48 @@
+From stable+bounces-203322-greg=kroah.com@vger.kernel.org Tue Dec 23 18:36:21 2025
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 23 Dec 2025 12:33:44 -0500
+Subject: can: gs_usb: gs_can_open(): fix error handling
+To: stable@vger.kernel.org
+Cc: Marc Kleine-Budde <mkl@pengutronix.de>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20251223173344.2929930-1-sashal@kernel.org>
+
+From: Marc Kleine-Budde <mkl@pengutronix.de>
+
+[ Upstream commit 3e54d3b4a8437b6783d4145c86962a2aa51022f3 ]
+
+Commit 2603be9e8167 ("can: gs_usb: gs_can_open(): improve error handling")
+added missing error handling to the gs_can_open() function.
+
+The driver uses 2 USB anchors to track the allocated URBs: the TX URBs in
+struct gs_can::tx_submitted for each netdev and the RX URBs in struct
+gs_usb::rx_submitted for the USB device. gs_can_open() allocates the RX
+URBs, while TX URBs are allocated during gs_can_start_xmit().
+
+The cleanup in gs_can_open() kills all anchored dev->tx_submitted
+URBs (which is not necessary since the netdev is not yet registered), but
+misses the parent->rx_submitted URBs.
+
+Fix the problem by killing the rx_submitted instead of the tx_submitted.
+
+Fixes: 2603be9e8167 ("can: gs_usb: gs_can_open(): improve error handling")
+Cc: stable@vger.kernel.org
+Link: https://patch.msgid.link/20251210-gs_usb-fix-error-handling-v1-1-d6a5a03f10bb@pengutronix.de
+Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
+[ adapted error handling for simpler code structure without timestamp stop functionality ]
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/net/can/usb/gs_usb.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/net/can/usb/gs_usb.c
++++ b/drivers/net/can/usb/gs_usb.c
+@@ -985,7 +985,7 @@ out_usb_free_urb:
+       usb_free_urb(urb);
+ out_usb_kill_anchored_urbs:
+       if (!parent->active_channels)
+-              usb_kill_anchored_urbs(&dev->tx_submitted);
++              usb_kill_anchored_urbs(&parent->rx_submitted);
+       close_candev(netdev);
diff --git a/queue-6.1/crypto-af_alg-zero-initialize-memory-allocated-via-sock_kmalloc.patch b/queue-6.1/crypto-af_alg-zero-initialize-memory-allocated-via-sock_kmalloc.patch
new file mode 100644 (file)
index 0000000..61eb344
--- /dev/null
@@ -0,0 +1,102 @@
+From stable+bounces-204380-greg=kroah.com@vger.kernel.org Wed Dec 31 19:35:35 2025
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 31 Dec 2025 13:35:24 -0500
+Subject: crypto: af_alg - zero initialize memory allocated via sock_kmalloc
+To: stable@vger.kernel.org
+Cc: Shivani Agarwal <shivani.agarwal@broadcom.com>, Herbert Xu <herbert@gondor.apana.org.au>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20251231183524.3368512-1-sashal@kernel.org>
+
+From: Shivani Agarwal <shivani.agarwal@broadcom.com>
+
+[ Upstream commit 6f6e309328d53a10c0fe1f77dec2db73373179b6 ]
+
+Several crypto user API contexts and requests allocated with
+sock_kmalloc() were left uninitialized, relying on callers to
+set fields explicitly. This resulted in the use of uninitialized
+data in certain error paths or when new fields are added in the
+future.
+
+The ACVP patches also contain two user-space interface files:
+algif_kpp.c and algif_akcipher.c. These too rely on proper
+initialization of their context structures.
+
+A particular issue has been observed with the newly added
+'inflight' variable introduced in af_alg_ctx by commit:
+
+  67b164a871af ("crypto: af_alg - Disallow multiple in-flight AIO requests")
+
+Because the context is not memset to zero after allocation,
+the inflight variable has contained garbage values. As a result,
+af_alg_alloc_areq() has incorrectly returned -EBUSY randomly when
+the garbage value was interpreted as true:
+
+  https://github.com/gregkh/linux/blame/master/crypto/af_alg.c#L1209
+
+The check directly tests ctx->inflight without explicitly
+comparing against true/false. Since inflight is only ever set to
+true or false later, an uninitialized value has triggered
+-EBUSY failures. Zero-initializing memory allocated with
+sock_kmalloc() ensures inflight and other fields start in a known
+state, removing random issues caused by uninitialized data.
+
+Fixes: fe869cdb89c9 ("crypto: algif_hash - User-space interface for hash operations")
+Fixes: 5afdfd22e6ba ("crypto: algif_rng - add random number generator support")
+Fixes: 2d97591ef43d ("crypto: af_alg - consolidation of duplicate code")
+Fixes: 67b164a871af ("crypto: af_alg - Disallow multiple in-flight AIO requests")
+Cc: stable@vger.kernel.org
+Signed-off-by: Shivani Agarwal <shivani.agarwal@broadcom.com>
+Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
+[ Adjust context ]
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ crypto/af_alg.c     |    5 ++---
+ crypto/algif_hash.c |    3 +--
+ crypto/algif_rng.c  |    3 +--
+ 3 files changed, 4 insertions(+), 7 deletions(-)
+
+--- a/crypto/af_alg.c
++++ b/crypto/af_alg.c
+@@ -1108,14 +1108,13 @@ struct af_alg_async_req *af_alg_alloc_ar
+       if (unlikely(!areq))
+               return ERR_PTR(-ENOMEM);
++      memset(areq, 0, areqlen);
++
+       ctx->inflight = true;
+       areq->areqlen = areqlen;
+       areq->sk = sk;
+-      areq->last_rsgl = NULL;
+       INIT_LIST_HEAD(&areq->rsgl_list);
+-      areq->tsgl = NULL;
+-      areq->tsgl_entries = 0;
+       return areq;
+ }
+--- a/crypto/algif_hash.c
++++ b/crypto/algif_hash.c
+@@ -424,9 +424,8 @@ static int hash_accept_parent_nokey(void
+       if (!ctx)
+               return -ENOMEM;
+-      ctx->result = NULL;
++      memset(ctx, 0, len);
+       ctx->len = len;
+-      ctx->more = false;
+       crypto_init_wait(&ctx->wait);
+       ask->private = ctx;
+--- a/crypto/algif_rng.c
++++ b/crypto/algif_rng.c
+@@ -250,9 +250,8 @@ static int rng_accept_parent(void *priva
+       if (!ctx)
+               return -ENOMEM;
++      memset(ctx, 0, len);
+       ctx->len = len;
+-      ctx->addtl = NULL;
+-      ctx->addtl_len = 0;
+       /*
+        * No seeding done at that point -- if multiple accepts are
diff --git a/queue-6.1/drm-amdgpu-add-missing-lock-to-amdgpu_ttm_access_memory_sdma.patch b/queue-6.1/drm-amdgpu-add-missing-lock-to-amdgpu_ttm_access_memory_sdma.patch
new file mode 100644 (file)
index 0000000..35cd14e
--- /dev/null
@@ -0,0 +1,44 @@
+From stable+bounces-206134-greg=kroah.com@vger.kernel.org Wed Jan  7 13:00:17 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed,  7 Jan 2026 06:54:26 -0500
+Subject: drm/amdgpu: add missing lock to amdgpu_ttm_access_memory_sdma
+To: stable@vger.kernel.org
+Cc: "Pierre-Eric Pelloux-Prayer" <pierre-eric.pelloux-prayer@amd.com>, "Christian König" <christian.koenig@amd.com>, "Alex Deucher" <alexander.deucher@amd.com>, "Sasha Levin" <sashal@kernel.org>
+Message-ID: <20260107115426.3985494-2-sashal@kernel.org>
+
+From: Pierre-Eric Pelloux-Prayer <pierre-eric.pelloux-prayer@amd.com>
+
+[ Upstream commit 4fa944255be521b1bbd9780383f77206303a3a5c ]
+
+Users of ttm entities need to hold the gtt_window_lock before using them
+to guarantee proper ordering of jobs.
+
+Cc: stable@vger.kernel.org
+Fixes: cb5cc4f573e1 ("drm/amdgpu: improve debug VRAM access performance using sdma")
+Signed-off-by: Pierre-Eric Pelloux-Prayer <pierre-eric.pelloux-prayer@amd.com>
+Reviewed-by: Christian König <christian.koenig@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c |    2 ++
+ 1 file changed, 2 insertions(+)
+
+--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c
++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c
+@@ -1425,6 +1425,7 @@ static int amdgpu_ttm_access_memory_sdma
+       if (r)
+               goto out;
++      mutex_lock(&adev->mman.gtt_window_lock);
+       amdgpu_res_first(abo->tbo.resource, offset, len, &src_mm);
+       src_addr = amdgpu_ttm_domain_start(adev, bo->resource->mem_type) +
+               src_mm.start;
+@@ -1439,6 +1440,7 @@ static int amdgpu_ttm_access_memory_sdma
+       WARN_ON(job->ibs[0].length_dw > num_dw);
+       fence = amdgpu_job_submit(job);
++      mutex_unlock(&adev->mman.gtt_window_lock);
+       if (!dma_fence_wait_timeout(fence, false, adev->sdma_timeout))
+               r = -ETIMEDOUT;
diff --git a/queue-6.1/drm-amdgpu-cleanup-scheduler-job-initialization-v2.patch b/queue-6.1/drm-amdgpu-cleanup-scheduler-job-initialization-v2.patch
new file mode 100644 (file)
index 0000000..55d2e09
--- /dev/null
@@ -0,0 +1,712 @@
+From stable+bounces-206133-greg=kroah.com@vger.kernel.org Wed Jan  7 12:54:40 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed,  7 Jan 2026 06:54:25 -0500
+Subject: drm/amdgpu: cleanup scheduler job initialization v2
+To: stable@vger.kernel.org
+Cc: "Christian König" <christian.koenig@amd.com>, "Luben Tuikov" <luben.tuikov@amd.com>, "Sasha Levin" <sashal@kernel.org>
+Message-ID: <20260107115426.3985494-1-sashal@kernel.org>
+
+From: Christian König <christian.koenig@amd.com>
+
+[ Upstream commit f7d66fb2ea43a3016e78a700a2ca6c77a74579f9 ]
+
+Init the DRM scheduler base class while allocating the job.
+
+This makes the whole handling much more cleaner.
+
+v2: fix coding style
+
+Signed-off-by: Christian König <christian.koenig@amd.com>
+Reviewed-by: Luben Tuikov <luben.tuikov@amd.com>
+Link: https://patchwork.freedesktop.org/patch/msgid/20221014084641.128280-7-christian.koenig@amd.com
+Stable-dep-of: 4fa944255be5 ("drm/amdgpu: add missing lock to amdgpu_ttm_access_memory_sdma")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c  |    2 
+ drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c      |    8 ---
+ drivers/gpu/drm/amd/amdgpu/amdgpu_job.c     |   44 ++++++++++----------
+ drivers/gpu/drm/amd/amdgpu/amdgpu_job.h     |   14 +++---
+ drivers/gpu/drm/amd/amdgpu/amdgpu_jpeg.c    |    7 +--
+ drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c     |   56 +++++++++----------------
+ drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c     |    9 +---
+ drivers/gpu/drm/amd/amdgpu/amdgpu_vce.c     |   13 +++--
+ drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c     |   22 +++++-----
+ drivers/gpu/drm/amd/amdgpu/amdgpu_vm_sdma.c |   61 ++++++++++++++--------------
+ drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c      |   12 +----
+ drivers/gpu/drm/amd/amdgpu/uvd_v6_0.c       |    8 +--
+ drivers/gpu/drm/amd/amdgpu/uvd_v7_0.c       |   12 ++---
+ drivers/gpu/drm/amd/amdkfd/kfd_migrate.c    |   17 ++-----
+ 14 files changed, 135 insertions(+), 150 deletions(-)
+
+--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c
++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c
+@@ -673,7 +673,7 @@ int amdgpu_amdkfd_submit_ib(struct amdgp
+               goto err;
+       }
+-      ret = amdgpu_job_alloc(adev, 1, &job, NULL);
++      ret = amdgpu_job_alloc(adev, NULL, NULL, NULL, 1, &job);
+       if (ret)
+               goto err;
+--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c
++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c
+@@ -285,12 +285,8 @@ static int amdgpu_cs_pass1(struct amdgpu
+       }
+       for (i = 0; i < p->gang_size; ++i) {
+-              ret = amdgpu_job_alloc(p->adev, num_ibs[i], &p->jobs[i], vm);
+-              if (ret)
+-                      goto free_all_kdata;
+-
+-              ret = drm_sched_job_init(&p->jobs[i]->base, p->entities[i],
+-                                       &fpriv->vm);
++              ret = amdgpu_job_alloc(p->adev, vm, p->entities[i], vm,
++                                     num_ibs[i], &p->jobs[i]);
+               if (ret)
+                       goto free_all_kdata;
+       }
+--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c
++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c
+@@ -88,8 +88,9 @@ exit:
+       return DRM_GPU_SCHED_STAT_NOMINAL;
+ }
+-int amdgpu_job_alloc(struct amdgpu_device *adev, unsigned num_ibs,
+-                   struct amdgpu_job **job, struct amdgpu_vm *vm)
++int amdgpu_job_alloc(struct amdgpu_device *adev, struct amdgpu_vm *vm,
++                   struct drm_sched_entity *entity, void *owner,
++                   unsigned int num_ibs, struct amdgpu_job **job)
+ {
+       if (num_ibs == 0)
+               return -EINVAL;
+@@ -110,23 +111,30 @@ int amdgpu_job_alloc(struct amdgpu_devic
+       (*job)->vram_lost_counter = atomic_read(&adev->vram_lost_counter);
+       (*job)->vm_pd_addr = AMDGPU_BO_INVALID_OFFSET;
+-      return 0;
++      if (!entity)
++              return 0;
++
++      return drm_sched_job_init(&(*job)->base, entity, owner);
+ }
+-int amdgpu_job_alloc_with_ib(struct amdgpu_device *adev, unsigned size,
+-              enum amdgpu_ib_pool_type pool_type,
+-              struct amdgpu_job **job)
++int amdgpu_job_alloc_with_ib(struct amdgpu_device *adev,
++                           struct drm_sched_entity *entity, void *owner,
++                           size_t size, enum amdgpu_ib_pool_type pool_type,
++                           struct amdgpu_job **job)
+ {
+       int r;
+-      r = amdgpu_job_alloc(adev, 1, job, NULL);
++      r = amdgpu_job_alloc(adev, NULL, entity, owner, 1, job);
+       if (r)
+               return r;
+       (*job)->num_ibs = 1;
+       r = amdgpu_ib_get(adev, NULL, size, pool_type, &(*job)->ibs[0]);
+-      if (r)
++      if (r) {
++              if (entity)
++                      drm_sched_job_cleanup(&(*job)->base);
+               kfree(*job);
++      }
+       return r;
+ }
+@@ -199,6 +207,9 @@ void amdgpu_job_set_gang_leader(struct a
+ void amdgpu_job_free(struct amdgpu_job *job)
+ {
++      if (job->base.entity)
++              drm_sched_job_cleanup(&job->base);
++
+       amdgpu_job_free_resources(job);
+       amdgpu_sync_free(&job->sync);
+       amdgpu_sync_free(&job->sched_sync);
+@@ -211,25 +222,16 @@ void amdgpu_job_free(struct amdgpu_job *
+               dma_fence_put(&job->hw_fence);
+ }
+-int amdgpu_job_submit(struct amdgpu_job *job, struct drm_sched_entity *entity,
+-                    void *owner, struct dma_fence **f)
++struct dma_fence *amdgpu_job_submit(struct amdgpu_job *job)
+ {
+-      int r;
+-
+-      if (!f)
+-              return -EINVAL;
+-
+-      r = drm_sched_job_init(&job->base, entity, owner);
+-      if (r)
+-              return r;
++      struct dma_fence *f;
+       drm_sched_job_arm(&job->base);
+-
+-      *f = dma_fence_get(&job->base.s_fence->finished);
++      f = dma_fence_get(&job->base.s_fence->finished);
+       amdgpu_job_free_resources(job);
+       drm_sched_entity_push_job(&job->base);
+-      return 0;
++      return f;
+ }
+ int amdgpu_job_submit_direct(struct amdgpu_job *job, struct amdgpu_ring *ring,
+--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_job.h
++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_job.h
+@@ -78,18 +78,20 @@ static inline struct amdgpu_ring *amdgpu
+       return to_amdgpu_ring(job->base.entity->rq->sched);
+ }
+-int amdgpu_job_alloc(struct amdgpu_device *adev, unsigned num_ibs,
+-                   struct amdgpu_job **job, struct amdgpu_vm *vm);
+-int amdgpu_job_alloc_with_ib(struct amdgpu_device *adev, unsigned size,
+-              enum amdgpu_ib_pool_type pool, struct amdgpu_job **job);
++int amdgpu_job_alloc(struct amdgpu_device *adev, struct amdgpu_vm *vm,
++                   struct drm_sched_entity *entity, void *owner,
++                   unsigned int num_ibs, struct amdgpu_job **job);
++int amdgpu_job_alloc_with_ib(struct amdgpu_device *adev,
++                           struct drm_sched_entity *entity, void *owner,
++                           size_t size, enum amdgpu_ib_pool_type pool_type,
++                           struct amdgpu_job **job);
+ void amdgpu_job_set_resources(struct amdgpu_job *job, struct amdgpu_bo *gds,
+                             struct amdgpu_bo *gws, struct amdgpu_bo *oa);
+ void amdgpu_job_free_resources(struct amdgpu_job *job);
+ void amdgpu_job_set_gang_leader(struct amdgpu_job *job,
+                               struct amdgpu_job *leader);
+ void amdgpu_job_free(struct amdgpu_job *job);
+-int amdgpu_job_submit(struct amdgpu_job *job, struct drm_sched_entity *entity,
+-                    void *owner, struct dma_fence **f);
++struct dma_fence *amdgpu_job_submit(struct amdgpu_job *job);
+ int amdgpu_job_submit_direct(struct amdgpu_job *job, struct amdgpu_ring *ring,
+                            struct dma_fence **fence);
+--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_jpeg.c
++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_jpeg.c
+@@ -152,14 +152,15 @@ static int amdgpu_jpeg_dec_set_reg(struc
+       const unsigned ib_size_dw = 16;
+       int i, r;
+-      r = amdgpu_job_alloc_with_ib(ring->adev, ib_size_dw * 4,
+-                                      AMDGPU_IB_POOL_DIRECT, &job);
++      r = amdgpu_job_alloc_with_ib(ring->adev, NULL, NULL, ib_size_dw * 4,
++                                   AMDGPU_IB_POOL_DIRECT, &job);
+       if (r)
+               return r;
+       ib = &job->ibs[0];
+-      ib->ptr[0] = PACKETJ(adev->jpeg.internal.jpeg_pitch, 0, 0, PACKETJ_TYPE0);
++      ib->ptr[0] = PACKETJ(adev->jpeg.internal.jpeg_pitch, 0, 0,
++                           PACKETJ_TYPE0);
+       ib->ptr[1] = 0xDEADBEEF;
+       for (i = 2; i < 16; i += 2) {
+               ib->ptr[i] = PACKETJ(0, 0, 0, PACKETJ_TYPE6);
+--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c
++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c
+@@ -189,7 +189,6 @@ static int amdgpu_ttm_map_buffer(struct
+       struct amdgpu_device *adev = ring->adev;
+       unsigned offset, num_pages, num_dw, num_bytes;
+       uint64_t src_addr, dst_addr;
+-      struct dma_fence *fence;
+       struct amdgpu_job *job;
+       void *cpu_addr;
+       uint64_t flags;
+@@ -229,7 +228,9 @@ static int amdgpu_ttm_map_buffer(struct
+       num_dw = ALIGN(adev->mman.buffer_funcs->copy_num_dw, 8);
+       num_bytes = num_pages * 8 * AMDGPU_GPU_PAGES_IN_CPU_PAGE;
+-      r = amdgpu_job_alloc_with_ib(adev, num_dw * 4 + num_bytes,
++      r = amdgpu_job_alloc_with_ib(adev, &adev->mman.entity,
++                                   AMDGPU_FENCE_OWNER_UNDEFINED,
++                                   num_dw * 4 + num_bytes,
+                                    AMDGPU_IB_POOL_DELAYED, &job);
+       if (r)
+               return r;
+@@ -269,18 +270,8 @@ static int amdgpu_ttm_map_buffer(struct
+               }
+       }
+-      r = amdgpu_job_submit(job, &adev->mman.entity,
+-                            AMDGPU_FENCE_OWNER_UNDEFINED, &fence);
+-      if (r)
+-              goto error_free;
+-
+-      dma_fence_put(fence);
+-
+-      return r;
+-
+-error_free:
+-      amdgpu_job_free(job);
+-      return r;
++      dma_fence_put(amdgpu_job_submit(job));
++      return 0;
+ }
+ /**
+@@ -1402,7 +1393,8 @@ static void amdgpu_ttm_vram_mm_access(st
+ }
+ static int amdgpu_ttm_access_memory_sdma(struct ttm_buffer_object *bo,
+-                                      unsigned long offset, void *buf, int len, int write)
++                                      unsigned long offset, void *buf,
++                                      int len, int write)
+ {
+       struct amdgpu_bo *abo = ttm_to_amdgpu_bo(bo);
+       struct amdgpu_device *adev = amdgpu_ttm_adev(abo->tbo.bdev);
+@@ -1426,26 +1418,27 @@ static int amdgpu_ttm_access_memory_sdma
+               memcpy(adev->mman.sdma_access_ptr, buf, len);
+       num_dw = ALIGN(adev->mman.buffer_funcs->copy_num_dw, 8);
+-      r = amdgpu_job_alloc_with_ib(adev, num_dw * 4, AMDGPU_IB_POOL_DELAYED, &job);
++      r = amdgpu_job_alloc_with_ib(adev, &adev->mman.entity,
++                                   AMDGPU_FENCE_OWNER_UNDEFINED,
++                                   num_dw * 4, AMDGPU_IB_POOL_DELAYED,
++                                   &job);
+       if (r)
+               goto out;
+       amdgpu_res_first(abo->tbo.resource, offset, len, &src_mm);
+-      src_addr = amdgpu_ttm_domain_start(adev, bo->resource->mem_type) + src_mm.start;
++      src_addr = amdgpu_ttm_domain_start(adev, bo->resource->mem_type) +
++              src_mm.start;
+       dst_addr = amdgpu_bo_gpu_offset(adev->mman.sdma_access_bo);
+       if (write)
+               swap(src_addr, dst_addr);
+-      amdgpu_emit_copy_buffer(adev, &job->ibs[0], src_addr, dst_addr, PAGE_SIZE, false);
++      amdgpu_emit_copy_buffer(adev, &job->ibs[0], src_addr, dst_addr,
++                              PAGE_SIZE, false);
+       amdgpu_ring_pad_ib(adev->mman.buffer_funcs_ring, &job->ibs[0]);
+       WARN_ON(job->ibs[0].length_dw > num_dw);
+-      r = amdgpu_job_submit(job, &adev->mman.entity, AMDGPU_FENCE_OWNER_UNDEFINED, &fence);
+-      if (r) {
+-              amdgpu_job_free(job);
+-              goto out;
+-      }
++      fence = amdgpu_job_submit(job);
+       if (!dma_fence_wait_timeout(fence, false, adev->sdma_timeout))
+               r = -ETIMEDOUT;
+@@ -1994,7 +1987,9 @@ static int amdgpu_ttm_prepare_job(struct
+               AMDGPU_IB_POOL_DELAYED;
+       int r;
+-      r = amdgpu_job_alloc_with_ib(adev, num_dw * 4, pool, job);
++      r = amdgpu_job_alloc_with_ib(adev, &adev->mman.entity,
++                                   AMDGPU_FENCE_OWNER_UNDEFINED,
++                                   num_dw * 4, pool, job);
+       if (r)
+               return r;
+@@ -2059,8 +2054,7 @@ int amdgpu_copy_buffer(struct amdgpu_rin
+       if (direct_submit)
+               r = amdgpu_job_submit_direct(job, ring, fence);
+       else
+-              r = amdgpu_job_submit(job, &adev->mman.entity,
+-                                    AMDGPU_FENCE_OWNER_UNDEFINED, fence);
++              *fence = amdgpu_job_submit(job);
+       if (r)
+               goto error_free;
+@@ -2105,16 +2099,8 @@ static int amdgpu_ttm_fill_mem(struct am
+       amdgpu_ring_pad_ib(ring, &job->ibs[0]);
+       WARN_ON(job->ibs[0].length_dw > num_dw);
+-      r = amdgpu_job_submit(job, &adev->mman.entity,
+-                            AMDGPU_FENCE_OWNER_UNDEFINED, fence);
+-      if (r)
+-              goto error_free;
+-
++      *fence = amdgpu_job_submit(job);
+       return 0;
+-
+-error_free:
+-      amdgpu_job_free(job);
+-      return r;
+ }
+ int amdgpu_fill_buffer(struct amdgpu_bo *bo,
+--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c
++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c
+@@ -1132,7 +1132,9 @@ static int amdgpu_uvd_send_msg(struct am
+       unsigned offset_idx = 0;
+       unsigned offset[3] = { UVD_BASE_SI, 0, 0 };
+-      r = amdgpu_job_alloc_with_ib(adev, 64, direct ? AMDGPU_IB_POOL_DIRECT :
++      r = amdgpu_job_alloc_with_ib(ring->adev, &adev->uvd.entity,
++                                   AMDGPU_FENCE_OWNER_UNDEFINED,
++                                   64, direct ? AMDGPU_IB_POOL_DIRECT :
+                                    AMDGPU_IB_POOL_DELAYED, &job);
+       if (r)
+               return r;
+@@ -1181,10 +1183,7 @@ static int amdgpu_uvd_send_msg(struct am
+               if (r)
+                       goto err_free;
+-              r = amdgpu_job_submit(job, &adev->uvd.entity,
+-                                    AMDGPU_FENCE_OWNER_UNDEFINED, &f);
+-              if (r)
+-                      goto err_free;
++              f = amdgpu_job_submit(job);
+       }
+       amdgpu_bo_reserve(bo, true);
+--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vce.c
++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vce.c
+@@ -450,8 +450,10 @@ static int amdgpu_vce_get_create_msg(str
+       uint64_t addr;
+       int i, r;
+-      r = amdgpu_job_alloc_with_ib(ring->adev, ib_size_dw * 4,
+-                                   AMDGPU_IB_POOL_DIRECT, &job);
++      r = amdgpu_job_alloc_with_ib(ring->adev, &ring->adev->vce.entity,
++                                   AMDGPU_FENCE_OWNER_UNDEFINED,
++                                   ib_size_dw * 4, AMDGPU_IB_POOL_DIRECT,
++                                   &job);
+       if (r)
+               return r;
+@@ -538,7 +540,9 @@ static int amdgpu_vce_get_destroy_msg(st
+       struct dma_fence *f = NULL;
+       int i, r;
+-      r = amdgpu_job_alloc_with_ib(ring->adev, ib_size_dw * 4,
++      r = amdgpu_job_alloc_with_ib(ring->adev, &ring->adev->vce.entity,
++                                   AMDGPU_FENCE_OWNER_UNDEFINED,
++                                   ib_size_dw * 4,
+                                    direct ? AMDGPU_IB_POOL_DIRECT :
+                                    AMDGPU_IB_POOL_DELAYED, &job);
+       if (r)
+@@ -570,8 +574,7 @@ static int amdgpu_vce_get_destroy_msg(st
+       if (direct)
+               r = amdgpu_job_submit_direct(job, ring, &f);
+       else
+-              r = amdgpu_job_submit(job, &ring->adev->vce.entity,
+-                                    AMDGPU_FENCE_OWNER_UNDEFINED, &f);
++              f = amdgpu_job_submit(job);
+       if (r)
+               goto err;
+--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c
++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c
+@@ -627,15 +627,16 @@ static int amdgpu_vcn_dec_send_msg(struc
+                                  struct amdgpu_ib *ib_msg,
+                                  struct dma_fence **fence)
+ {
++      u64 addr = AMDGPU_GPU_PAGE_ALIGN(ib_msg->gpu_addr);
+       struct amdgpu_device *adev = ring->adev;
+       struct dma_fence *f = NULL;
+       struct amdgpu_job *job;
+       struct amdgpu_ib *ib;
+-      uint64_t addr = AMDGPU_GPU_PAGE_ALIGN(ib_msg->gpu_addr);
+       int i, r;
+-      r = amdgpu_job_alloc_with_ib(adev, 64,
+-                                      AMDGPU_IB_POOL_DIRECT, &job);
++      r = amdgpu_job_alloc_with_ib(ring->adev, NULL, NULL,
++                                   64, AMDGPU_IB_POOL_DIRECT,
++                                   &job);
+       if (r)
+               goto err;
+@@ -813,8 +814,9 @@ static int amdgpu_vcn_dec_sw_send_msg(st
+       if (adev->vcn.using_unified_queue)
+               ib_size_dw += 8;
+-      r = amdgpu_job_alloc_with_ib(adev, ib_size_dw * 4,
+-                              AMDGPU_IB_POOL_DIRECT, &job);
++      r = amdgpu_job_alloc_with_ib(ring->adev, NULL, NULL,
++                                   ib_size_dw * 4, AMDGPU_IB_POOL_DIRECT,
++                                   &job);
+       if (r)
+               goto err;
+@@ -942,8 +944,9 @@ static int amdgpu_vcn_enc_get_create_msg
+       if (adev->vcn.using_unified_queue)
+               ib_size_dw += 8;
+-      r = amdgpu_job_alloc_with_ib(ring->adev, ib_size_dw * 4,
+-                                      AMDGPU_IB_POOL_DIRECT, &job);
++      r = amdgpu_job_alloc_with_ib(ring->adev, NULL, NULL,
++                                   ib_size_dw * 4, AMDGPU_IB_POOL_DIRECT,
++                                   &job);
+       if (r)
+               return r;
+@@ -1008,8 +1011,9 @@ static int amdgpu_vcn_enc_get_destroy_ms
+       if (adev->vcn.using_unified_queue)
+               ib_size_dw += 8;
+-      r = amdgpu_job_alloc_with_ib(ring->adev, ib_size_dw * 4,
+-                                      AMDGPU_IB_POOL_DIRECT, &job);
++      r = amdgpu_job_alloc_with_ib(ring->adev, NULL, NULL,
++                                   ib_size_dw * 4, AMDGPU_IB_POOL_DIRECT,
++                                   &job);
+       if (r)
+               return r;
+--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm_sdma.c
++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm_sdma.c
+@@ -47,6 +47,32 @@ static int amdgpu_vm_sdma_map_table(stru
+       return r;
+ }
++/* Allocate a new job for @count PTE updates */
++static int amdgpu_vm_sdma_alloc_job(struct amdgpu_vm_update_params *p,
++                                  unsigned int count)
++{
++      enum amdgpu_ib_pool_type pool = p->immediate ? AMDGPU_IB_POOL_IMMEDIATE
++              : AMDGPU_IB_POOL_DELAYED;
++      struct drm_sched_entity *entity = p->immediate ? &p->vm->immediate
++              : &p->vm->delayed;
++      unsigned int ndw;
++      int r;
++
++      /* estimate how many dw we need */
++      ndw = AMDGPU_VM_SDMA_MIN_NUM_DW;
++      if (p->pages_addr)
++              ndw += count * 2;
++      ndw = min(ndw, AMDGPU_VM_SDMA_MAX_NUM_DW);
++
++      r = amdgpu_job_alloc_with_ib(p->adev, entity, AMDGPU_FENCE_OWNER_VM,
++                                   ndw * 4, pool, &p->job);
++      if (r)
++              return r;
++
++      p->num_dw_left = ndw;
++      return 0;
++}
++
+ /**
+  * amdgpu_vm_sdma_prepare - prepare SDMA command submission
+  *
+@@ -61,17 +87,12 @@ static int amdgpu_vm_sdma_prepare(struct
+                                 struct dma_resv *resv,
+                                 enum amdgpu_sync_mode sync_mode)
+ {
+-      enum amdgpu_ib_pool_type pool = p->immediate ? AMDGPU_IB_POOL_IMMEDIATE
+-              : AMDGPU_IB_POOL_DELAYED;
+-      unsigned int ndw = AMDGPU_VM_SDMA_MIN_NUM_DW;
+       int r;
+-      r = amdgpu_job_alloc_with_ib(p->adev, ndw * 4, pool, &p->job);
++      r = amdgpu_vm_sdma_alloc_job(p, 0);
+       if (r)
+               return r;
+-      p->num_dw_left = ndw;
+-
+       if (!resv)
+               return 0;
+@@ -91,20 +112,16 @@ static int amdgpu_vm_sdma_commit(struct
+                                struct dma_fence **fence)
+ {
+       struct amdgpu_ib *ib = p->job->ibs;
+-      struct drm_sched_entity *entity;
+       struct amdgpu_ring *ring;
+       struct dma_fence *f;
+-      int r;
+-      entity = p->immediate ? &p->vm->immediate : &p->vm->delayed;
+-      ring = container_of(entity->rq->sched, struct amdgpu_ring, sched);
++      ring = container_of(p->vm->delayed.rq->sched, struct amdgpu_ring,
++                          sched);
+       WARN_ON(ib->length_dw == 0);
+       amdgpu_ring_pad_ib(ring, ib);
+       WARN_ON(ib->length_dw > p->num_dw_left);
+-      r = amdgpu_job_submit(p->job, entity, AMDGPU_FENCE_OWNER_VM, &f);
+-      if (r)
+-              goto error;
++      f = amdgpu_job_submit(p->job);
+       if (p->unlocked) {
+               struct dma_fence *tmp = dma_fence_get(f);
+@@ -127,10 +144,6 @@ static int amdgpu_vm_sdma_commit(struct
+       }
+       dma_fence_put(f);
+       return 0;
+-
+-error:
+-      amdgpu_job_free(p->job);
+-      return r;
+ }
+ /**
+@@ -210,8 +223,6 @@ static int amdgpu_vm_sdma_update(struct
+                                uint64_t flags)
+ {
+       struct amdgpu_bo *bo = &vmbo->bo;
+-      enum amdgpu_ib_pool_type pool = p->immediate ? AMDGPU_IB_POOL_IMMEDIATE
+-              : AMDGPU_IB_POOL_DELAYED;
+       struct dma_resv_iter cursor;
+       unsigned int i, ndw, nptes;
+       struct dma_fence *fence;
+@@ -238,19 +249,9 @@ static int amdgpu_vm_sdma_update(struct
+                       if (r)
+                               return r;
+-                      /* estimate how many dw we need */
+-                      ndw = 32;
+-                      if (p->pages_addr)
+-                              ndw += count * 2;
+-                      ndw = max(ndw, AMDGPU_VM_SDMA_MIN_NUM_DW);
+-                      ndw = min(ndw, AMDGPU_VM_SDMA_MAX_NUM_DW);
+-
+-                      r = amdgpu_job_alloc_with_ib(p->adev, ndw * 4, pool,
+-                                                   &p->job);
++                      r = amdgpu_vm_sdma_alloc_job(p, count);
+                       if (r)
+                               return r;
+-
+-                      p->num_dw_left = ndw;
+               }
+               if (!p->pages_addr) {
+--- a/drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c
++++ b/drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c
+@@ -371,7 +371,9 @@ static void gmc_v10_0_flush_gpu_tlb(stru
+        * translation. Avoid this by doing the invalidation from the SDMA
+        * itself.
+        */
+-      r = amdgpu_job_alloc_with_ib(adev, 16 * 4, AMDGPU_IB_POOL_IMMEDIATE,
++      r = amdgpu_job_alloc_with_ib(ring->adev, &adev->mman.entity,
++                                   AMDGPU_FENCE_OWNER_UNDEFINED,
++                                   16 * 4, AMDGPU_IB_POOL_IMMEDIATE,
+                                    &job);
+       if (r)
+               goto error_alloc;
+@@ -380,10 +382,7 @@ static void gmc_v10_0_flush_gpu_tlb(stru
+       job->vm_needs_flush = true;
+       job->ibs->ptr[job->ibs->length_dw++] = ring->funcs->nop;
+       amdgpu_ring_pad_ib(ring, &job->ibs[0]);
+-      r = amdgpu_job_submit(job, &adev->mman.entity,
+-                            AMDGPU_FENCE_OWNER_UNDEFINED, &fence);
+-      if (r)
+-              goto error_submit;
++      fence = amdgpu_job_submit(job);
+       mutex_unlock(&adev->mman.gtt_window_lock);
+@@ -392,9 +391,6 @@ static void gmc_v10_0_flush_gpu_tlb(stru
+       return;
+-error_submit:
+-      amdgpu_job_free(job);
+-
+ error_alloc:
+       mutex_unlock(&adev->mman.gtt_window_lock);
+       DRM_ERROR("Error flushing GPU TLB using the SDMA (%d)!\n", r);
+--- a/drivers/gpu/drm/amd/amdgpu/uvd_v6_0.c
++++ b/drivers/gpu/drm/amd/amdgpu/uvd_v6_0.c
+@@ -216,8 +216,8 @@ static int uvd_v6_0_enc_get_create_msg(s
+       uint64_t addr;
+       int i, r;
+-      r = amdgpu_job_alloc_with_ib(ring->adev, ib_size_dw * 4,
+-                                      AMDGPU_IB_POOL_DIRECT, &job);
++      r = amdgpu_job_alloc_with_ib(ring->adev, NULL, NULL, ib_size_dw * 4,
++                                   AMDGPU_IB_POOL_DIRECT, &job);
+       if (r)
+               return r;
+@@ -280,8 +280,8 @@ static int uvd_v6_0_enc_get_destroy_msg(
+       uint64_t addr;
+       int i, r;
+-      r = amdgpu_job_alloc_with_ib(ring->adev, ib_size_dw * 4,
+-                                      AMDGPU_IB_POOL_DIRECT, &job);
++      r = amdgpu_job_alloc_with_ib(ring->adev, NULL, NULL, ib_size_dw * 4,
++                                   AMDGPU_IB_POOL_DIRECT, &job);
+       if (r)
+               return r;
+--- a/drivers/gpu/drm/amd/amdgpu/uvd_v7_0.c
++++ b/drivers/gpu/drm/amd/amdgpu/uvd_v7_0.c
+@@ -213,7 +213,7 @@ static int uvd_v7_0_enc_ring_test_ring(s
+  *
+  * Open up a stream for HW test
+  */
+-static int uvd_v7_0_enc_get_create_msg(struct amdgpu_ring *ring, uint32_t handle,
++static int uvd_v7_0_enc_get_create_msg(struct amdgpu_ring *ring, u32 handle,
+                                      struct amdgpu_bo *bo,
+                                      struct dma_fence **fence)
+ {
+@@ -224,8 +224,8 @@ static int uvd_v7_0_enc_get_create_msg(s
+       uint64_t addr;
+       int i, r;
+-      r = amdgpu_job_alloc_with_ib(ring->adev, ib_size_dw * 4,
+-                                      AMDGPU_IB_POOL_DIRECT, &job);
++      r = amdgpu_job_alloc_with_ib(ring->adev, NULL, NULL, ib_size_dw * 4,
++                                   AMDGPU_IB_POOL_DIRECT, &job);
+       if (r)
+               return r;
+@@ -276,7 +276,7 @@ err:
+  *
+  * Close up a stream for HW test or if userspace failed to do so
+  */
+-static int uvd_v7_0_enc_get_destroy_msg(struct amdgpu_ring *ring, uint32_t handle,
++static int uvd_v7_0_enc_get_destroy_msg(struct amdgpu_ring *ring, u32 handle,
+                                       struct amdgpu_bo *bo,
+                                       struct dma_fence **fence)
+ {
+@@ -287,8 +287,8 @@ static int uvd_v7_0_enc_get_destroy_msg(
+       uint64_t addr;
+       int i, r;
+-      r = amdgpu_job_alloc_with_ib(ring->adev, ib_size_dw * 4,
+-                                      AMDGPU_IB_POOL_DIRECT, &job);
++      r = amdgpu_job_alloc_with_ib(ring->adev, NULL, NULL, ib_size_dw * 4,
++                                   AMDGPU_IB_POOL_DIRECT, &job);
+       if (r)
+               return r;
+--- a/drivers/gpu/drm/amd/amdkfd/kfd_migrate.c
++++ b/drivers/gpu/drm/amd/amdkfd/kfd_migrate.c
+@@ -65,8 +65,11 @@ svm_migrate_gart_map(struct amdgpu_ring
+       num_dw = ALIGN(adev->mman.buffer_funcs->copy_num_dw, 8);
+       num_bytes = npages * 8;
+-      r = amdgpu_job_alloc_with_ib(adev, num_dw * 4 + num_bytes,
+-                                   AMDGPU_IB_POOL_DELAYED, &job);
++      r = amdgpu_job_alloc_with_ib(adev, &adev->mman.entity,
++                                   AMDGPU_FENCE_OWNER_UNDEFINED,
++                                   num_dw * 4 + num_bytes,
++                                   AMDGPU_IB_POOL_DELAYED,
++                                   &job);
+       if (r)
+               return r;
+@@ -89,18 +92,10 @@ svm_migrate_gart_map(struct amdgpu_ring
+       cpu_addr = &job->ibs[0].ptr[num_dw];
+       amdgpu_gart_map(adev, 0, npages, addr, pte_flags, cpu_addr);
+-      r = amdgpu_job_submit(job, &adev->mman.entity,
+-                            AMDGPU_FENCE_OWNER_UNDEFINED, &fence);
+-      if (r)
+-              goto error_free;
+-
++      fence = amdgpu_job_submit(job);
+       dma_fence_put(fence);
+       return r;
+-
+-error_free:
+-      amdgpu_job_free(job);
+-      return r;
+ }
+ /**
diff --git a/queue-6.1/drm-gma500-remove-unused-helper-psb_fbdev_fb_setcolreg.patch b/queue-6.1/drm-gma500-remove-unused-helper-psb_fbdev_fb_setcolreg.patch
new file mode 100644 (file)
index 0000000..436a3ba
--- /dev/null
@@ -0,0 +1,101 @@
+From stable+bounces-206160-greg=kroah.com@vger.kernel.org Wed Jan  7 17:10:53 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed,  7 Jan 2026 10:48:24 -0500
+Subject: drm/gma500: Remove unused helper psb_fbdev_fb_setcolreg()
+To: stable@vger.kernel.org
+Cc: Thomas Zimmermann <tzimmermann@suse.de>, Patrik Jakobsson <patrik.r.jakobsson@gmail.com>, Stefan Christ <contact@stefanchrist.eu>, Daniel Vetter <daniel.vetter@ffwll.ch>, dri-devel@lists.freedesktop.org, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260107154824.4057632-1-sashal@kernel.org>
+
+From: Thomas Zimmermann <tzimmermann@suse.de>
+
+[ Upstream commit be729f9de6c64240645dc80a24162ac4d3fe00a8 ]
+
+Remove psb_fbdev_fb_setcolreg(), which hasn't been called in almost
+a decade.
+
+Gma500 commit 4d8d096e9ae8 ("gma500: introduce the framebuffer support
+code") added the helper psb_fbdev_fb_setcolreg() for setting the fbdev
+palette via fbdev's fb_setcolreg callback. Later
+commit 3da6c2f3b730 ("drm/gma500: use DRM_FB_HELPER_DEFAULT_OPS for
+fb_ops") set several default helpers for fbdev emulation, including
+fb_setcmap.
+
+The fbdev subsystem always prefers fb_setcmap over fb_setcolreg. [1]
+Hence, the gma500 code is no longer in use and gma500 has been using
+drm_fb_helper_setcmap() for several years without issues.
+
+Fixes: 3da6c2f3b730 ("drm/gma500: use DRM_FB_HELPER_DEFAULT_OPS for fb_ops")
+Cc: Patrik Jakobsson <patrik.r.jakobsson@gmail.com>
+Cc: Stefan Christ <contact@stefanchrist.eu>
+Cc: Daniel Vetter <daniel.vetter@ffwll.ch>
+Cc: dri-devel@lists.freedesktop.org
+Cc: <stable@vger.kernel.org> # v4.10+
+Link: https://elixir.bootlin.com/linux/v6.16.9/source/drivers/video/fbdev/core/fbcmap.c#L246 # [1]
+Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
+Acked-by: Patrik Jakobsson <patrik.r.jakobsson@gmail.com>
+Link: https://lore.kernel.org/r/20250929082338.18845-1-tzimmermann@suse.de
+[ adapted patch from fbdev.c to framebuffer.c where the function was named psbfb_setcolreg() instead of psb_fbdev_fb_setcolreg() ]
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/gpu/drm/gma500/framebuffer.c |   42 -----------------------------------
+ 1 file changed, 42 deletions(-)
+
+--- a/drivers/gpu/drm/gma500/framebuffer.c
++++ b/drivers/gpu/drm/gma500/framebuffer.c
+@@ -35,47 +35,6 @@ static const struct drm_framebuffer_func
+       .create_handle = drm_gem_fb_create_handle,
+ };
+-#define CMAP_TOHW(_val, _width) ((((_val) << (_width)) + 0x7FFF - (_val)) >> 16)
+-
+-static int psbfb_setcolreg(unsigned regno, unsigned red, unsigned green,
+-                         unsigned blue, unsigned transp,
+-                         struct fb_info *info)
+-{
+-      struct drm_fb_helper *fb_helper = info->par;
+-      struct drm_framebuffer *fb = fb_helper->fb;
+-      uint32_t v;
+-
+-      if (!fb)
+-              return -ENOMEM;
+-
+-      if (regno > 255)
+-              return 1;
+-
+-      red = CMAP_TOHW(red, info->var.red.length);
+-      blue = CMAP_TOHW(blue, info->var.blue.length);
+-      green = CMAP_TOHW(green, info->var.green.length);
+-      transp = CMAP_TOHW(transp, info->var.transp.length);
+-
+-      v = (red << info->var.red.offset) |
+-          (green << info->var.green.offset) |
+-          (blue << info->var.blue.offset) |
+-          (transp << info->var.transp.offset);
+-
+-      if (regno < 16) {
+-              switch (fb->format->cpp[0] * 8) {
+-              case 16:
+-                      ((uint32_t *) info->pseudo_palette)[regno] = v;
+-                      break;
+-              case 24:
+-              case 32:
+-                      ((uint32_t *) info->pseudo_palette)[regno] = v;
+-                      break;
+-              }
+-      }
+-
+-      return 0;
+-}
+-
+ static vm_fault_t psbfb_vm_fault(struct vm_fault *vmf)
+ {
+       struct vm_area_struct *vma = vmf->vma;
+@@ -146,7 +105,6 @@ static int psbfb_mmap(struct fb_info *in
+ static const struct fb_ops psbfb_unaccel_ops = {
+       .owner = THIS_MODULE,
+       DRM_FB_HELPER_DEFAULT_OPS,
+-      .fb_setcolreg = psbfb_setcolreg,
+       .fb_fillrect = drm_fb_helper_cfb_fillrect,
+       .fb_copyarea = drm_fb_helper_cfb_copyarea,
+       .fb_imageblit = drm_fb_helper_cfb_imageblit,
diff --git a/queue-6.1/drm-mediatek-fix-probe-memory-leak.patch b/queue-6.1/drm-mediatek-fix-probe-memory-leak.patch
new file mode 100644 (file)
index 0000000..90ad7bc
--- /dev/null
@@ -0,0 +1,44 @@
+From stable+bounces-206139-greg=kroah.com@vger.kernel.org Wed Jan  7 13:19:11 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed,  7 Jan 2026 07:17:00 -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: <20260107121700.3993037-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
+@@ -555,7 +555,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.1/ext4-fix-string-copying-in-parse_apply_sb_mount_options.patch b/queue-6.1/ext4-fix-string-copying-in-parse_apply_sb_mount_options.patch
new file mode 100644 (file)
index 0000000..439aaf5
--- /dev/null
@@ -0,0 +1,86 @@
+From stable+bounces-204161-greg=kroah.com@vger.kernel.org Tue Dec 30 02:01:05 2025
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 29 Dec 2025 20:00:59 -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: <20251230010059.1899363-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
+@@ -2416,7 +2416,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;
+@@ -2424,7 +2424,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.1/f2fs-drop-inode-from-the-donation-list-when-the-last-file-is-closed.patch b/queue-6.1/f2fs-drop-inode-from-the-donation-list-when-the-last-file-is-closed.patch
new file mode 100644 (file)
index 0000000..0e0bf69
--- /dev/null
@@ -0,0 +1,90 @@
+From stable+bounces-204259-greg=kroah.com@vger.kernel.org Tue Dec 30 18:20:05 2025
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 30 Dec 2025 12:19:57 -0500
+Subject: f2fs: drop inode from the donation list when the last file is closed
+To: stable@vger.kernel.org
+Cc: Jaegeuk Kim <jaegeuk@kernel.org>, Chao Yu <chao@kernel.org>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20251230171958.2344337-3-sashal@kernel.org>
+
+From: Jaegeuk Kim <jaegeuk@kernel.org>
+
+[ Upstream commit 078cad8212ce4f4ebbafcc0936475b8215e1ca2a ]
+
+Let's drop the inode from the donation list when there is no other
+open file.
+
+Reviewed-by: Chao Yu <chao@kernel.org>
+Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
+Stable-dep-of: 10b591e7fb7c ("f2fs: fix to avoid updating compression context during writeback")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/f2fs/f2fs.h  |    2 ++
+ fs/f2fs/file.c  |    8 +++++++-
+ fs/f2fs/inode.c |    2 +-
+ fs/f2fs/super.c |    1 +
+ 4 files changed, 11 insertions(+), 2 deletions(-)
+
+--- a/fs/f2fs/f2fs.h
++++ b/fs/f2fs/f2fs.h
+@@ -824,6 +824,7 @@ struct f2fs_inode_info {
+       /* linked in global inode list for cache donation */
+       struct list_head gdonate_list;
+       pgoff_t donate_start, donate_end; /* inclusive */
++      atomic_t open_count;            /* # of open files */
+       struct task_struct *atomic_write_task;  /* store atomic write task */
+       struct extent_tree *extent_tree[NR_EXTENT_CACHES];
+@@ -3473,6 +3474,7 @@ int f2fs_try_to_free_nats(struct f2fs_sb
+ void f2fs_update_inode(struct inode *inode, struct page *node_page);
+ void f2fs_update_inode_page(struct inode *inode);
+ int f2fs_write_inode(struct inode *inode, struct writeback_control *wbc);
++void f2fs_remove_donate_inode(struct inode *inode);
+ void f2fs_evict_inode(struct inode *inode);
+ void f2fs_handle_failed_inode(struct inode *inode);
+--- a/fs/f2fs/file.c
++++ b/fs/f2fs/file.c
+@@ -595,7 +595,10 @@ static int f2fs_file_open(struct inode *
+       if (err)
+               return err;
+-      return finish_preallocate_blocks(inode);
++      err = finish_preallocate_blocks(inode);
++      if (!err)
++              atomic_inc(&F2FS_I(inode)->open_count);
++      return err;
+ }
+ void f2fs_truncate_data_blocks_range(struct dnode_of_data *dn, int count)
+@@ -1923,6 +1926,9 @@ out:
+ static int f2fs_release_file(struct inode *inode, struct file *filp)
+ {
++      if (atomic_dec_and_test(&F2FS_I(inode)->open_count))
++              f2fs_remove_donate_inode(inode);
++
+       /*
+        * f2fs_release_file is called at every close calls. So we should
+        * not drop any inmemory pages by close called by other process.
+--- a/fs/f2fs/inode.c
++++ b/fs/f2fs/inode.c
+@@ -743,7 +743,7 @@ int f2fs_write_inode(struct inode *inode
+       return 0;
+ }
+-static void f2fs_remove_donate_inode(struct inode *inode)
++void f2fs_remove_donate_inode(struct inode *inode)
+ {
+       struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
+--- a/fs/f2fs/super.c
++++ b/fs/f2fs/super.c
+@@ -1425,6 +1425,7 @@ static struct inode *f2fs_alloc_inode(st
+       /* Initialize f2fs-specific inode info */
+       atomic_set(&fi->dirty_pages, 0);
+       atomic_set(&fi->i_compr_blocks, 0);
++      atomic_set(&fi->open_count, 0);
+       init_f2fs_rwsem(&fi->i_sem);
+       spin_lock_init(&fi->i_size_lock);
+       INIT_LIST_HEAD(&fi->dirty_list);
diff --git a/queue-6.1/f2fs-fix-to-avoid-updating-compression-context-during-writeback.patch b/queue-6.1/f2fs-fix-to-avoid-updating-compression-context-during-writeback.patch
new file mode 100644 (file)
index 0000000..31e8088
--- /dev/null
@@ -0,0 +1,164 @@
+From stable+bounces-204260-greg=kroah.com@vger.kernel.org Tue Dec 30 18:20:06 2025
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 30 Dec 2025 12:19:58 -0500
+Subject: f2fs: fix to avoid updating compression context during writeback
+To: stable@vger.kernel.org
+Cc: Chao Yu <chao@kernel.org>, stable@kernel.org, "Bai, Shuangpeng" <sjb7183@psu.edu>, Jaegeuk Kim <jaegeuk@kernel.org>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20251230171958.2344337-4-sashal@kernel.org>
+
+From: Chao Yu <chao@kernel.org>
+
+[ Upstream commit 10b591e7fb7cdc8c1e53e9c000dc0ef7069aaa76 ]
+
+Bai, Shuangpeng <sjb7183@psu.edu> reported a bug as below:
+
+Oops: divide error: 0000 [#1] SMP KASAN PTI
+CPU: 0 UID: 0 PID: 11441 Comm: syz.0.46 Not tainted 6.17.0 #1 PREEMPT(full)
+Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.15.0-1 04/01/2014
+RIP: 0010:f2fs_all_cluster_page_ready+0x106/0x550 fs/f2fs/compress.c:857
+Call Trace:
+ <TASK>
+ f2fs_write_cache_pages fs/f2fs/data.c:3078 [inline]
+ __f2fs_write_data_pages fs/f2fs/data.c:3290 [inline]
+ f2fs_write_data_pages+0x1c19/0x3600 fs/f2fs/data.c:3317
+ do_writepages+0x38e/0x640 mm/page-writeback.c:2634
+ filemap_fdatawrite_wbc mm/filemap.c:386 [inline]
+ __filemap_fdatawrite_range mm/filemap.c:419 [inline]
+ file_write_and_wait_range+0x2ba/0x3e0 mm/filemap.c:794
+ f2fs_do_sync_file+0x6e6/0x1b00 fs/f2fs/file.c:294
+ generic_write_sync include/linux/fs.h:3043 [inline]
+ f2fs_file_write_iter+0x76e/0x2700 fs/f2fs/file.c:5259
+ new_sync_write fs/read_write.c:593 [inline]
+ vfs_write+0x7e9/0xe00 fs/read_write.c:686
+ ksys_write+0x19d/0x2d0 fs/read_write.c:738
+ do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline]
+ do_syscall_64+0xf7/0x470 arch/x86/entry/syscall_64.c:94
+ entry_SYSCALL_64_after_hwframe+0x77/0x7f
+
+The bug was triggered w/ below race condition:
+
+fsync                          setattr                 ioctl
+- f2fs_do_sync_file
+ - file_write_and_wait_range
+  - f2fs_write_cache_pages
+  : inode is non-compressed
+  : cc.cluster_size =
+    F2FS_I(inode)->i_cluster_size = 0
+   - tag_pages_for_writeback
+                               - f2fs_setattr
+                                - truncate_setsize
+                                - f2fs_truncate
+                                                       - f2fs_fileattr_set
+                                                        - f2fs_setflags_common
+                                                         - set_compress_context
+                                                         : F2FS_I(inode)->i_cluster_size = 4
+                                                         : set_inode_flag(inode, FI_COMPRESSED_FILE)
+   - f2fs_compressed_file
+   : return true
+   - f2fs_all_cluster_page_ready
+   : "pgidx % cc->cluster_size" trigger dividing 0 issue
+
+Let's change as below to fix this issue:
+- introduce a new atomic type variable .writeback in structure f2fs_inode_info
+to track the number of threads which calling f2fs_write_cache_pages().
+- use .i_sem lock to protect .writeback update.
+- check .writeback before update compression context in f2fs_setflags_common()
+to avoid race w/ ->writepages.
+
+Fixes: 4c8ff7095bef ("f2fs: support data compression")
+Cc: stable@kernel.org
+Reported-by: Bai, Shuangpeng <sjb7183@psu.edu>
+Tested-by: Bai, Shuangpeng <sjb7183@psu.edu>
+Closes: https://lore.kernel.org/lkml/44D8F7B3-68AD-425F-9915-65D27591F93F@psu.edu
+Signed-off-by: Chao Yu <chao@kernel.org>
+Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
+[ Adjust context ]
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/f2fs/data.c  |   17 +++++++++++++++++
+ fs/f2fs/f2fs.h  |    3 ++-
+ fs/f2fs/file.c  |    5 +++--
+ fs/f2fs/super.c |    1 +
+ 4 files changed, 23 insertions(+), 3 deletions(-)
+
+--- a/fs/f2fs/data.c
++++ b/fs/f2fs/data.c
+@@ -3262,6 +3262,19 @@ static inline bool __should_serialize_io
+       return false;
+ }
++static inline void account_writeback(struct inode *inode, bool inc)
++{
++      if (!f2fs_sb_has_compression(F2FS_I_SB(inode)))
++              return;
++
++      f2fs_down_read(&F2FS_I(inode)->i_sem);
++      if (inc)
++              atomic_inc(&F2FS_I(inode)->writeback);
++      else
++              atomic_dec(&F2FS_I(inode)->writeback);
++      f2fs_up_read(&F2FS_I(inode)->i_sem);
++}
++
+ static int __f2fs_write_data_pages(struct address_space *mapping,
+                                               struct writeback_control *wbc,
+                                               enum iostat_type io_type)
+@@ -3311,10 +3324,14 @@ static int __f2fs_write_data_pages(struc
+               locked = true;
+       }
++      account_writeback(inode, true);
++
+       blk_start_plug(&plug);
+       ret = f2fs_write_cache_pages(mapping, wbc, io_type);
+       blk_finish_plug(&plug);
++      account_writeback(inode, false);
++
+       if (locked)
+               mutex_unlock(&sbi->writepages);
+--- a/fs/f2fs/f2fs.h
++++ b/fs/f2fs/f2fs.h
+@@ -848,6 +848,7 @@ struct f2fs_inode_info {
+       unsigned char i_compress_level;         /* compress level (lz4hc,zstd) */
+       unsigned char i_compress_flag;          /* compress flag */
+       unsigned int i_cluster_size;            /* cluster size */
++      atomic_t writeback;                     /* count # of writeback thread */
+       unsigned int atomic_write_cnt;
+       loff_t original_i_size;         /* original i_size before atomic write */
+@@ -4375,7 +4376,7 @@ static inline bool f2fs_disable_compress
+               f2fs_up_write(&F2FS_I(inode)->i_sem);
+               return true;
+       }
+-      if (f2fs_is_mmap_file(inode) ||
++      if (f2fs_is_mmap_file(inode) || atomic_read(&fi->writeback) ||
+               (S_ISREG(inode->i_mode) && F2FS_HAS_BLOCKS(inode))) {
+               f2fs_up_write(&F2FS_I(inode)->i_sem);
+               return false;
+--- a/fs/f2fs/file.c
++++ b/fs/f2fs/file.c
+@@ -2002,8 +2002,9 @@ static int f2fs_setflags_common(struct i
+                       f2fs_down_write(&F2FS_I(inode)->i_sem);
+                       if (!f2fs_may_compress(inode) ||
+-                                      (S_ISREG(inode->i_mode) &&
+-                                      F2FS_HAS_BLOCKS(inode))) {
++                              atomic_read(&fi->writeback) ||
++                              (S_ISREG(inode->i_mode) &&
++                              F2FS_HAS_BLOCKS(inode))) {
+                               f2fs_up_write(&F2FS_I(inode)->i_sem);
+                               return -EINVAL;
+                       }
+--- a/fs/f2fs/super.c
++++ b/fs/f2fs/super.c
+@@ -1426,6 +1426,7 @@ static struct inode *f2fs_alloc_inode(st
+       atomic_set(&fi->dirty_pages, 0);
+       atomic_set(&fi->i_compr_blocks, 0);
+       atomic_set(&fi->open_count, 0);
++      atomic_set(&fi->writeback, 0);
+       init_f2fs_rwsem(&fi->i_sem);
+       spin_lock_init(&fi->i_size_lock);
+       INIT_LIST_HEAD(&fi->dirty_list);
diff --git a/queue-6.1/f2fs-fix-to-avoid-updating-zero-sized-extent-in-extent-cache.patch b/queue-6.1/f2fs-fix-to-avoid-updating-zero-sized-extent-in-extent-cache.patch
new file mode 100644 (file)
index 0000000..a6aef5f
--- /dev/null
@@ -0,0 +1,67 @@
+From stable+bounces-204255-greg=kroah.com@vger.kernel.org Tue Dec 30 18:13:14 2025
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 30 Dec 2025 12:06:23 -0500
+Subject: f2fs: fix to avoid updating zero-sized extent in extent cache
+To: stable@vger.kernel.org
+Cc: Chao Yu <chao@kernel.org>, stable@kernel.org, syzbot+24124df3170c3638b35f@syzkaller.appspotmail.com, Jaegeuk Kim <jaegeuk@kernel.org>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20251230170624.2337217-1-sashal@kernel.org>
+
+From: Chao Yu <chao@kernel.org>
+
+[ Upstream commit 7c37c79510329cd951a4dedf3f7bf7e2b18dccec ]
+
+As syzbot reported:
+
+F2FS-fs (loop0): __update_extent_tree_range: extent len is zero, type: 0, extent [0, 0, 0], age [0, 0]
+------------[ cut here ]------------
+kernel BUG at fs/f2fs/extent_cache.c:678!
+Oops: invalid opcode: 0000 [#1] SMP KASAN NOPTI
+CPU: 0 UID: 0 PID: 5336 Comm: syz.0.0 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:__update_extent_tree_range+0x13bc/0x1500 fs/f2fs/extent_cache.c:678
+Call Trace:
+ <TASK>
+ f2fs_update_read_extent_cache_range+0x192/0x3e0 fs/f2fs/extent_cache.c:1085
+ f2fs_do_zero_range fs/f2fs/file.c:1657 [inline]
+ f2fs_zero_range+0x10c1/0x1580 fs/f2fs/file.c:1737
+ f2fs_fallocate+0x583/0x990 fs/f2fs/file.c:2030
+ vfs_fallocate+0x669/0x7e0 fs/open.c:342
+ ioctl_preallocate fs/ioctl.c:289 [inline]
+ file_ioctl+0x611/0x780 fs/ioctl.c:-1
+ do_vfs_ioctl+0xb33/0x1430 fs/ioctl.c:576
+ __do_sys_ioctl fs/ioctl.c:595 [inline]
+ __se_sys_ioctl+0x82/0x170 fs/ioctl.c:583
+ do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline]
+ do_syscall_64+0xfa/0x3b0 arch/x86/entry/syscall_64.c:94
+ entry_SYSCALL_64_after_hwframe+0x77/0x7f
+RIP: 0033:0x7f07bc58eec9
+
+In error path of f2fs_zero_range(), it may add a zero-sized extent
+into extent cache, it should be avoided.
+
+Fixes: 6e9619499f53 ("f2fs: support in batch fzero in dnode page")
+Cc: stable@kernel.org
+Reported-by: syzbot+24124df3170c3638b35f@syzkaller.appspotmail.com
+Closes: https://lore.kernel.org/linux-f2fs-devel/68e5d698.050a0220.256323.0032.GAE@google.com
+Signed-off-by: Chao Yu <chao@kernel.org>
+Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
+[ adapted patch to only guard f2fs_update_read_extent_cache_range() ]
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/f2fs/file.c |    4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+--- a/fs/f2fs/file.c
++++ b/fs/f2fs/file.c
+@@ -1552,7 +1552,9 @@ static int f2fs_do_zero_range(struct dno
+               f2fs_set_data_blkaddr(dn, NEW_ADDR);
+       }
+-      f2fs_update_read_extent_cache_range(dn, start, 0, index - start);
++      if (index > start)
++              f2fs_update_read_extent_cache_range(dn, start, 0,
++                                                      index - start);
+       return ret;
+ }
diff --git a/queue-6.1/f2fs-fix-to-detect-recoverable-inode-during-dryrun-of-find_fsync_dnodes.patch b/queue-6.1/f2fs-fix-to-detect-recoverable-inode-during-dryrun-of-find_fsync_dnodes.patch
new file mode 100644 (file)
index 0000000..efbbaac
--- /dev/null
@@ -0,0 +1,93 @@
+From stable+bounces-204284-greg=kroah.com@vger.kernel.org Tue Dec 30 20:54:36 2025
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 30 Dec 2025 14:54:31 -0500
+Subject: f2fs: fix to detect recoverable inode during dryrun of find_fsync_dnodes()
+To: stable@vger.kernel.org
+Cc: Chao Yu <chao@kernel.org>, stable@kernel.org, Jaegeuk Kim <jaegeuk@kernel.org>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20251230195431.2446807-1-sashal@kernel.org>
+
+From: Chao Yu <chao@kernel.org>
+
+[ Upstream commit 68d05693f8c031257a0822464366e1c2a239a512 ]
+
+mkfs.f2fs -f /dev/vdd
+mount /dev/vdd /mnt/f2fs
+touch /mnt/f2fs/foo
+sync           # avoid CP_UMOUNT_FLAG in last f2fs_checkpoint.ckpt_flags
+touch /mnt/f2fs/bar
+f2fs_io fsync /mnt/f2fs/bar
+f2fs_io shutdown 2 /mnt/f2fs
+umount /mnt/f2fs
+blockdev --setro /dev/vdd
+mount /dev/vdd /mnt/f2fs
+mount: /mnt/f2fs: WARNING: source write-protected, mounted read-only.
+
+For the case if we create and fsync a new inode before sudden power-cut,
+without norecovery or disable_roll_forward mount option, the following
+mount will succeed w/o recovering last fsynced inode.
+
+The problem here is that we only check inode_list list after
+find_fsync_dnodes() in f2fs_recover_fsync_data() to find out whether
+there is recoverable data in the iamge, but there is a missed case, if
+last fsynced inode is not existing in last checkpoint, then, we will
+fail to get its inode due to nat of inode node is not existing in last
+checkpoint, so the inode won't be linked in inode_list.
+
+Let's detect such case in dyrun mode to fix this issue.
+
+After this change, mount will fail as expected below:
+mount: /mnt/f2fs: cannot mount /dev/vdd read-only.
+       dmesg(1) may have more information after failed mount system call.
+demsg:
+F2FS-fs (vdd): Need to recover fsync data, but write access unavailable, please try mount w/ disable_roll_forward or norecovery
+
+Cc: stable@kernel.org
+Fixes: 6781eabba1bd ("f2fs: give -EINVAL for norecovery and rw mount")
+Signed-off-by: Chao Yu <chao@kernel.org>
+Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
+[ folio => page ]
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/f2fs/recovery.c |    9 ++++++---
+ 1 file changed, 6 insertions(+), 3 deletions(-)
+
+--- a/fs/f2fs/recovery.c
++++ b/fs/f2fs/recovery.c
+@@ -360,7 +360,7 @@ static unsigned int adjust_por_ra_blocks
+ }
+ static int find_fsync_dnodes(struct f2fs_sb_info *sbi, struct list_head *head,
+-                              bool check_only)
++                              bool check_only, bool *new_inode)
+ {
+       struct curseg_info *curseg;
+       struct page *page = NULL;
+@@ -418,6 +418,8 @@ static int find_fsync_dnodes(struct f2fs
+                       if (IS_ERR(entry)) {
+                               err = PTR_ERR(entry);
+                               if (err == -ENOENT) {
++                                      if (check_only)
++                                              *new_inode = true;
+                                       err = 0;
+                                       goto next;
+                               }
+@@ -834,6 +836,7 @@ int f2fs_recover_fsync_data(struct f2fs_
+       unsigned long s_flags = sbi->sb->s_flags;
+       bool need_writecp = false;
+       bool fix_curseg_write_pointer = false;
++      bool new_inode = false;
+ #ifdef CONFIG_QUOTA
+       int quota_enabled;
+ #endif
+@@ -856,8 +859,8 @@ int f2fs_recover_fsync_data(struct f2fs_
+       f2fs_down_write(&sbi->cp_global_sem);
+       /* step #1: find fsynced inode numbers */
+-      err = find_fsync_dnodes(sbi, &inode_list, check_only);
+-      if (err || list_empty(&inode_list))
++      err = find_fsync_dnodes(sbi, &inode_list, check_only, &new_inode);
++      if (err < 0 || (list_empty(&inode_list) && (!check_only || !new_inode)))
+               goto skip;
+       if (check_only) {
diff --git a/queue-6.1/f2fs-fix-to-propagate-error-from-f2fs_enable_checkpoint.patch b/queue-6.1/f2fs-fix-to-propagate-error-from-f2fs_enable_checkpoint.patch
new file mode 100644 (file)
index 0000000..65e72e2
--- /dev/null
@@ -0,0 +1,86 @@
+From stable+bounces-204262-greg=kroah.com@vger.kernel.org Tue Dec 30 18:26:12 2025
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 30 Dec 2025 12:26:06 -0500
+Subject: f2fs: fix to propagate error from f2fs_enable_checkpoint()
+To: stable@vger.kernel.org
+Cc: Chao Yu <chao@kernel.org>, stable@kernel.org, Jaegeuk Kim <jaegeuk@kernel.org>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20251230172606.2349129-1-sashal@kernel.org>
+
+From: Chao Yu <chao@kernel.org>
+
+[ Upstream commit be112e7449a6e1b54aa9feac618825d154b3a5c7 ]
+
+In order to let userspace detect such error rather than suffering
+silent failure.
+
+Fixes: 4354994f097d ("f2fs: checkpoint disabling")
+Cc: stable@kernel.org
+Signed-off-by: Chao Yu <chao@kernel.org>
+Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
+[ Adjust context, no rollback ]
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/f2fs/super.c |   24 +++++++++++++++---------
+ 1 file changed, 15 insertions(+), 9 deletions(-)
+
+--- a/fs/f2fs/super.c
++++ b/fs/f2fs/super.c
+@@ -2222,9 +2222,10 @@ restore_flag:
+       return err;
+ }
+-static void f2fs_enable_checkpoint(struct f2fs_sb_info *sbi)
++static int f2fs_enable_checkpoint(struct f2fs_sb_info *sbi)
+ {
+       int retry = DEFAULT_RETRY_IO_COUNT;
++      int ret;
+       /* we should flush all the data to keep data consistency */
+       do {
+@@ -2242,10 +2243,14 @@ static void f2fs_enable_checkpoint(struc
+       set_sbi_flag(sbi, SBI_IS_DIRTY);
+       f2fs_up_write(&sbi->gc_lock);
+-      f2fs_sync_fs(sbi->sb, 1);
++      ret = f2fs_sync_fs(sbi->sb, 1);
++      if (ret)
++              f2fs_err(sbi, "%s sync_fs failed, ret: %d", __func__, ret);
+       /* Let's ensure there's no pending checkpoint anymore */
+       f2fs_flush_ckpt_thread(sbi);
++
++      return ret;
+ }
+ static int f2fs_remount(struct super_block *sb, int *flags, char *data)
+@@ -2460,7 +2465,9 @@ static int f2fs_remount(struct super_blo
+                       if (err)
+                               goto restore_discard;
+               } else {
+-                      f2fs_enable_checkpoint(sbi);
++                      err = f2fs_enable_checkpoint(sbi);
++                      if (err)
++                              goto restore_discard;
+               }
+       }
+@@ -4528,13 +4535,12 @@ reset_checkpoint:
+       /* f2fs_recover_fsync_data() cleared this already */
+       clear_sbi_flag(sbi, SBI_POR_DOING);
+-      if (test_opt(sbi, DISABLE_CHECKPOINT)) {
++      if (test_opt(sbi, DISABLE_CHECKPOINT))
+               err = f2fs_disable_checkpoint(sbi);
+-              if (err)
+-                      goto sync_free_meta;
+-      } else if (is_set_ckpt_flags(sbi, CP_DISABLED_FLAG)) {
+-              f2fs_enable_checkpoint(sbi);
+-      }
++      else if (is_set_ckpt_flags(sbi, CP_DISABLED_FLAG))
++              err = f2fs_enable_checkpoint(sbi);
++      if (err)
++              goto sync_free_meta;
+       /*
+        * If filesystem is not mounted as read-only then
diff --git a/queue-6.1/f2fs-keep-posix_fadv_noreuse-ranges.patch b/queue-6.1/f2fs-keep-posix_fadv_noreuse-ranges.patch
new file mode 100644 (file)
index 0000000..dfb64f6
--- /dev/null
@@ -0,0 +1,206 @@
+From stable+bounces-204258-greg=kroah.com@vger.kernel.org Tue Dec 30 18:20:07 2025
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 30 Dec 2025 12:19:56 -0500
+Subject: f2fs: keep POSIX_FADV_NOREUSE ranges
+To: stable@vger.kernel.org
+Cc: Jaegeuk Kim <jaegeuk@kernel.org>, Chao Yu <chao@kernel.org>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20251230171958.2344337-2-sashal@kernel.org>
+
+From: Jaegeuk Kim <jaegeuk@kernel.org>
+
+[ Upstream commit ef0c333cad8d1940f132a7ce15f15920216a3bd5 ]
+
+This patch records POSIX_FADV_NOREUSE ranges for users to reclaim the caches
+instantly off from LRU.
+
+Reviewed-by: Chao Yu <chao@kernel.org>
+Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
+Stable-dep-of: 10b591e7fb7c ("f2fs: fix to avoid updating compression context during writeback")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/f2fs/debug.c |    3 ++
+ fs/f2fs/f2fs.h  |   12 ++++++++++-
+ fs/f2fs/file.c  |   60 +++++++++++++++++++++++++++++++++++++++++++++++++++-----
+ fs/f2fs/inode.c |   14 +++++++++++++
+ fs/f2fs/super.c |    1 
+ 5 files changed, 84 insertions(+), 6 deletions(-)
+
+--- a/fs/f2fs/debug.c
++++ b/fs/f2fs/debug.c
+@@ -97,6 +97,7 @@ static void update_general_status(struct
+       si->ndirty_imeta = get_pages(sbi, F2FS_DIRTY_IMETA);
+       si->ndirty_dirs = sbi->ndirty_inode[DIR_INODE];
+       si->ndirty_files = sbi->ndirty_inode[FILE_INODE];
++      si->ndonate_files = sbi->donate_files;
+       si->nquota_files = sbi->nquota_files;
+       si->ndirty_all = sbi->ndirty_inode[DIRTY_META];
+       si->aw_cnt = atomic_read(&sbi->atomic_files);
+@@ -402,6 +403,8 @@ static int stat_show(struct seq_file *s,
+                          si->compr_inode, si->compr_blocks);
+               seq_printf(s, "  - Swapfile Inode: %u\n",
+                          si->swapfile_inode);
++              seq_printf(s, "  - Donate Inode: %u\n",
++                         si->ndonate_files);
+               seq_printf(s, "  - Orphan/Append/Update Inode: %u, %u, %u\n",
+                          si->orphans, si->append, si->update);
+               seq_printf(s, "\nMain area: %d segs, %d secs %d zones\n",
+--- a/fs/f2fs/f2fs.h
++++ b/fs/f2fs/f2fs.h
+@@ -820,6 +820,11 @@ struct f2fs_inode_info {
+ #endif
+       struct list_head dirty_list;    /* dirty list for dirs and files */
+       struct list_head gdirty_list;   /* linked in global dirty list */
++
++      /* linked in global inode list for cache donation */
++      struct list_head gdonate_list;
++      pgoff_t donate_start, donate_end; /* inclusive */
++
+       struct task_struct *atomic_write_task;  /* store atomic write task */
+       struct extent_tree *extent_tree[NR_EXTENT_CACHES];
+                                       /* cached extent_tree entry */
+@@ -1236,6 +1241,7 @@ enum inode_type {
+       DIR_INODE,                      /* for dirty dir inode */
+       FILE_INODE,                     /* for dirty regular/symlink inode */
+       DIRTY_META,                     /* for all dirtied inode metadata */
++      DONATE_INODE,                   /* for all inode to donate pages */
+       NR_INODE_TYPE,
+ };
+@@ -1650,6 +1656,9 @@ struct f2fs_sb_info {
+       /* for extent tree cache */
+       struct extent_tree_info extent_tree[NR_EXTENT_CACHES];
++      /* control donate caches */
++      unsigned int donate_files;
++
+       /* basic filesystem units */
+       unsigned int log_sectors_per_block;     /* log2 sectors per block */
+       unsigned int log_blocksize;             /* log2 block size */
+@@ -3854,7 +3863,8 @@ struct f2fs_stat_info {
+       unsigned long long hit_largest;
+       int ndirty_node, ndirty_dent, ndirty_meta, ndirty_imeta;
+       int ndirty_data, ndirty_qdata;
+-      unsigned int ndirty_dirs, ndirty_files, nquota_files, ndirty_all;
++      unsigned int ndirty_dirs, ndirty_files, ndirty_all;
++      unsigned int nquota_files, ndonate_files;
+       int nats, dirty_nats, sits, dirty_sits;
+       int free_nids, avail_nids, alloc_nids;
+       int total_count, utilization;
+--- a/fs/f2fs/file.c
++++ b/fs/f2fs/file.c
+@@ -2367,6 +2367,52 @@ out:
+       return ret;
+ }
++static void f2fs_keep_noreuse_range(struct inode *inode,
++                              loff_t offset, loff_t len)
++{
++      struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
++      u64 max_bytes = F2FS_BLK_TO_BYTES(max_file_blocks(inode));
++      u64 start, end;
++
++      if (!S_ISREG(inode->i_mode))
++              return;
++
++      if (offset >= max_bytes || len > max_bytes ||
++          (offset + len) > max_bytes)
++              return;
++
++      start = offset >> PAGE_SHIFT;
++      end = DIV_ROUND_UP(offset + len, PAGE_SIZE);
++
++      inode_lock(inode);
++      if (f2fs_is_atomic_file(inode)) {
++              inode_unlock(inode);
++              return;
++      }
++
++      spin_lock(&sbi->inode_lock[DONATE_INODE]);
++      /* let's remove the range, if len = 0 */
++      if (!len) {
++              if (!list_empty(&F2FS_I(inode)->gdonate_list)) {
++                      list_del_init(&F2FS_I(inode)->gdonate_list);
++                      sbi->donate_files--;
++              }
++      } else {
++              if (list_empty(&F2FS_I(inode)->gdonate_list)) {
++                      list_add_tail(&F2FS_I(inode)->gdonate_list,
++                                      &sbi->inode_list[DONATE_INODE]);
++                      sbi->donate_files++;
++              } else {
++                      list_move_tail(&F2FS_I(inode)->gdonate_list,
++                                      &sbi->inode_list[DONATE_INODE]);
++              }
++              F2FS_I(inode)->donate_start = start;
++              F2FS_I(inode)->donate_end = end - 1;
++      }
++      spin_unlock(&sbi->inode_lock[DONATE_INODE]);
++      inode_unlock(inode);
++}
++
+ static int f2fs_ioc_fitrim(struct file *filp, unsigned long arg)
+ {
+       struct inode *inode = file_inode(filp);
+@@ -4901,12 +4947,16 @@ static int f2fs_file_fadvise(struct file
+       }
+       err = generic_fadvise(filp, offset, len, advice);
+-      if (!err && advice == POSIX_FADV_DONTNEED &&
+-              test_opt(F2FS_I_SB(inode), COMPRESS_CACHE) &&
+-              f2fs_compressed_file(inode))
+-              f2fs_invalidate_compress_pages(F2FS_I_SB(inode), inode->i_ino);
++      if (err)
++              return err;
+-      return err;
++      if (advice == POSIX_FADV_DONTNEED &&
++          (test_opt(F2FS_I_SB(inode), COMPRESS_CACHE) &&
++           f2fs_compressed_file(inode)))
++              f2fs_invalidate_compress_pages(F2FS_I_SB(inode), inode->i_ino);
++      else if (advice == POSIX_FADV_NOREUSE)
++              f2fs_keep_noreuse_range(inode, offset, len);
++      return 0;
+ }
+ #ifdef CONFIG_COMPAT
+--- a/fs/f2fs/inode.c
++++ b/fs/f2fs/inode.c
+@@ -743,6 +743,19 @@ int f2fs_write_inode(struct inode *inode
+       return 0;
+ }
++static void f2fs_remove_donate_inode(struct inode *inode)
++{
++      struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
++
++      if (list_empty(&F2FS_I(inode)->gdonate_list))
++              return;
++
++      spin_lock(&sbi->inode_lock[DONATE_INODE]);
++      list_del_init(&F2FS_I(inode)->gdonate_list);
++      sbi->donate_files--;
++      spin_unlock(&sbi->inode_lock[DONATE_INODE]);
++}
++
+ /*
+  * Called at the last iput() if i_nlink is zero
+  */
+@@ -775,6 +788,7 @@ void f2fs_evict_inode(struct inode *inod
+       f2fs_bug_on(sbi, get_dirty_pages(inode));
+       f2fs_remove_dirty_inode(inode);
++      f2fs_remove_donate_inode(inode);
+       f2fs_destroy_extent_tree(inode);
+--- a/fs/f2fs/super.c
++++ b/fs/f2fs/super.c
+@@ -1429,6 +1429,7 @@ static struct inode *f2fs_alloc_inode(st
+       spin_lock_init(&fi->i_size_lock);
+       INIT_LIST_HEAD(&fi->dirty_list);
+       INIT_LIST_HEAD(&fi->gdirty_list);
++      INIT_LIST_HEAD(&fi->gdonate_list);
+       init_f2fs_rwsem(&fi->i_gc_rwsem[READ]);
+       init_f2fs_rwsem(&fi->i_gc_rwsem[WRITE]);
+       init_f2fs_rwsem(&fi->i_xattr_sem);
diff --git a/queue-6.1/f2fs-remove-unused-gc_failure_pin.patch b/queue-6.1/f2fs-remove-unused-gc_failure_pin.patch
new file mode 100644 (file)
index 0000000..8d5e6f0
--- /dev/null
@@ -0,0 +1,139 @@
+From stable+bounces-204257-greg=kroah.com@vger.kernel.org Tue Dec 30 18:20:05 2025
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 30 Dec 2025 12:19:55 -0500
+Subject: f2fs: remove unused GC_FAILURE_PIN
+To: stable@vger.kernel.org
+Cc: Chao Yu <chao@kernel.org>, Jaegeuk Kim <jaegeuk@kernel.org>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20251230171958.2344337-1-sashal@kernel.org>
+
+From: Chao Yu <chao@kernel.org>
+
+[ Upstream commit 968c4f72b23c0c8f1e94e942eab89b8c5a3022e7 ]
+
+After commit 3db1de0e582c ("f2fs: change the current atomic write way"),
+we removed all GC_FAILURE_ATOMIC usage, let's change i_gc_failures[]
+array to i_pin_failure for cleanup.
+
+Meanwhile, let's define i_current_depth and i_gc_failures as union
+variable due to they won't be valid at the same time.
+
+Signed-off-by: Chao Yu <chao@kernel.org>
+Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
+Stable-dep-of: 10b591e7fb7c ("f2fs: fix to avoid updating compression context during writeback")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/f2fs/f2fs.h     |   14 +++++---------
+ fs/f2fs/file.c     |   12 +++++-------
+ fs/f2fs/inode.c    |    6 ++----
+ fs/f2fs/recovery.c |    3 +--
+ 4 files changed, 13 insertions(+), 22 deletions(-)
+
+--- a/fs/f2fs/f2fs.h
++++ b/fs/f2fs/f2fs.h
+@@ -747,11 +747,6 @@ enum {
+ #define DEF_DIR_LEVEL         0
+-enum {
+-      GC_FAILURE_PIN,
+-      MAX_GC_FAILURE
+-};
+-
+ /* used for f2fs_inode_info->flags */
+ enum {
+       FI_NEW_INODE,           /* indicate newly allocated inode */
+@@ -797,9 +792,10 @@ struct f2fs_inode_info {
+       unsigned long i_flags;          /* keep an inode flags for ioctl */
+       unsigned char i_advise;         /* use to give file attribute hints */
+       unsigned char i_dir_level;      /* use for dentry level for large dir */
+-      unsigned int i_current_depth;   /* only for directory depth */
+-      /* for gc failure statistic */
+-      unsigned int i_gc_failures[MAX_GC_FAILURE];
++      union {
++              unsigned int i_current_depth;   /* only for directory depth */
++              unsigned int i_gc_failures;     /* for gc failure statistic */
++      };
+       unsigned int i_pino;            /* parent inode number */
+       umode_t i_acl_mode;             /* keep file acl mode temporarily */
+@@ -3100,7 +3096,7 @@ static inline void f2fs_i_depth_write(st
+ static inline void f2fs_i_gc_failures_write(struct inode *inode,
+                                       unsigned int count)
+ {
+-      F2FS_I(inode)->i_gc_failures[GC_FAILURE_PIN] = count;
++      F2FS_I(inode)->i_gc_failures = count;
+       f2fs_mark_inode_dirty_sync(inode, true);
+ }
+--- a/fs/f2fs/file.c
++++ b/fs/f2fs/file.c
+@@ -3247,13 +3247,11 @@ int f2fs_pin_file_control(struct inode *
+       /* Use i_gc_failures for normal file as a risk signal. */
+       if (inc)
+-              f2fs_i_gc_failures_write(inode,
+-                              fi->i_gc_failures[GC_FAILURE_PIN] + 1);
++              f2fs_i_gc_failures_write(inode, fi->i_gc_failures + 1);
+-      if (fi->i_gc_failures[GC_FAILURE_PIN] > sbi->gc_pin_file_threshold) {
++      if (fi->i_gc_failures > sbi->gc_pin_file_threshold) {
+               f2fs_warn(sbi, "%s: Enable GC = ino %lx after %x GC trials",
+-                        __func__, inode->i_ino,
+-                        fi->i_gc_failures[GC_FAILURE_PIN]);
++                        __func__, inode->i_ino, fi->i_gc_failures);
+               clear_inode_flag(inode, FI_PIN_FILE);
+               return -EAGAIN;
+       }
+@@ -3312,7 +3310,7 @@ static int f2fs_ioc_set_pin_file(struct
+       }
+       set_inode_flag(inode, FI_PIN_FILE);
+-      ret = F2FS_I(inode)->i_gc_failures[GC_FAILURE_PIN];
++      ret = F2FS_I(inode)->i_gc_failures;
+ done:
+       f2fs_update_time(F2FS_I_SB(inode), REQ_TIME);
+ out:
+@@ -3327,7 +3325,7 @@ static int f2fs_ioc_get_pin_file(struct
+       __u32 pin = 0;
+       if (is_inode_flag_set(inode, FI_PIN_FILE))
+-              pin = F2FS_I(inode)->i_gc_failures[GC_FAILURE_PIN];
++              pin = F2FS_I(inode)->i_gc_failures;
+       return put_user(pin, (u32 __user *)arg);
+ }
+--- a/fs/f2fs/inode.c
++++ b/fs/f2fs/inode.c
+@@ -362,8 +362,7 @@ static int do_read_inode(struct inode *i
+       if (S_ISDIR(inode->i_mode))
+               fi->i_current_depth = le32_to_cpu(ri->i_current_depth);
+       else if (S_ISREG(inode->i_mode))
+-              fi->i_gc_failures[GC_FAILURE_PIN] =
+-                                      le16_to_cpu(ri->i_gc_failures);
++              fi->i_gc_failures = le16_to_cpu(ri->i_gc_failures);
+       fi->i_xattr_nid = le32_to_cpu(ri->i_xattr_nid);
+       fi->i_flags = le32_to_cpu(ri->i_flags);
+       if (S_ISREG(inode->i_mode))
+@@ -623,8 +622,7 @@ void f2fs_update_inode(struct inode *ino
+               ri->i_current_depth =
+                       cpu_to_le32(F2FS_I(inode)->i_current_depth);
+       else if (S_ISREG(inode->i_mode))
+-              ri->i_gc_failures =
+-                      cpu_to_le16(F2FS_I(inode)->i_gc_failures[GC_FAILURE_PIN]);
++              ri->i_gc_failures = cpu_to_le16(F2FS_I(inode)->i_gc_failures);
+       ri->i_xattr_nid = cpu_to_le32(F2FS_I(inode)->i_xattr_nid);
+       ri->i_flags = cpu_to_le32(F2FS_I(inode)->i_flags);
+       ri->i_pino = cpu_to_le32(F2FS_I(inode)->i_pino);
+--- a/fs/f2fs/recovery.c
++++ b/fs/f2fs/recovery.c
+@@ -330,8 +330,7 @@ static int recover_inode(struct inode *i
+       F2FS_I(inode)->i_advise = raw->i_advise;
+       F2FS_I(inode)->i_flags = le32_to_cpu(raw->i_flags);
+       f2fs_set_inode_flags(inode);
+-      F2FS_I(inode)->i_gc_failures[GC_FAILURE_PIN] =
+-                              le16_to_cpu(raw->i_gc_failures);
++      F2FS_I(inode)->i_gc_failures = le16_to_cpu(raw->i_gc_failures);
+       recover_inline_flags(inode, raw);
diff --git a/queue-6.1/f2fs-use-global-inline_xattr_slab-instead-of-per-sb-slab-cache.patch b/queue-6.1/f2fs-use-global-inline_xattr_slab-instead-of-per-sb-slab-cache.patch
new file mode 100644 (file)
index 0000000..74ed723
--- /dev/null
@@ -0,0 +1,235 @@
+From stable+bounces-204278-greg=kroah.com@vger.kernel.org Tue Dec 30 19:54:18 2025
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 30 Dec 2025 13:54:13 -0500
+Subject: f2fs: use global inline_xattr_slab instead of per-sb slab cache
+To: stable@vger.kernel.org
+Cc: Chao Yu <chao@kernel.org>, stable@kernel.org, Hong Yun <yhong@link.cuhk.edu.hk>, Jaegeuk Kim <jaegeuk@kernel.org>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20251230185413.2413273-1-sashal@kernel.org>
+
+From: Chao Yu <chao@kernel.org>
+
+[ Upstream commit 1f27ef42bb0b7c0740c5616ec577ec188b8a1d05 ]
+
+As Hong Yun reported in mailing list:
+
+loop7: detected capacity change from 0 to 131072
+------------[ cut here ]------------
+kmem_cache of name 'f2fs_xattr_entry-7:7' already exists
+WARNING: CPU: 0 PID: 24426 at mm/slab_common.c:110 kmem_cache_sanity_check mm/slab_common.c:109 [inline]
+WARNING: CPU: 0 PID: 24426 at mm/slab_common.c:110 __kmem_cache_create_args+0xa6/0x320 mm/slab_common.c:307
+CPU: 0 UID: 0 PID: 24426 Comm: syz.7.1370 Not tainted 6.17.0-rc4 #1 PREEMPT(full)
+Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.13.0-1ubuntu1.1 04/01/2014
+RIP: 0010:kmem_cache_sanity_check mm/slab_common.c:109 [inline]
+RIP: 0010:__kmem_cache_create_args+0xa6/0x320 mm/slab_common.c:307
+Call Trace:
+ __kmem_cache_create include/linux/slab.h:353 [inline]
+ f2fs_kmem_cache_create fs/f2fs/f2fs.h:2943 [inline]
+ f2fs_init_xattr_caches+0xa5/0xe0 fs/f2fs/xattr.c:843
+ f2fs_fill_super+0x1645/0x2620 fs/f2fs/super.c:4918
+ get_tree_bdev_flags+0x1fb/0x260 fs/super.c:1692
+ vfs_get_tree+0x43/0x140 fs/super.c:1815
+ do_new_mount+0x201/0x550 fs/namespace.c:3808
+ do_mount fs/namespace.c:4136 [inline]
+ __do_sys_mount fs/namespace.c:4347 [inline]
+ __se_sys_mount+0x298/0x2f0 fs/namespace.c:4324
+ do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline]
+ do_syscall_64+0x8e/0x3a0 arch/x86/entry/syscall_64.c:94
+ entry_SYSCALL_64_after_hwframe+0x76/0x7e
+
+The bug can be reproduced w/ below scripts:
+- mount /dev/vdb /mnt1
+- mount /dev/vdc /mnt2
+- umount /mnt1
+- mounnt /dev/vdb /mnt1
+
+The reason is if we created two slab caches, named f2fs_xattr_entry-7:3
+and f2fs_xattr_entry-7:7, and they have the same slab size. Actually,
+slab system will only create one slab cache core structure which has
+slab name of "f2fs_xattr_entry-7:3", and two slab caches share the same
+structure and cache address.
+
+So, if we destroy f2fs_xattr_entry-7:3 cache w/ cache address, it will
+decrease reference count of slab cache, rather than release slab cache
+entirely, since there is one more user has referenced the cache.
+
+Then, if we try to create slab cache w/ name "f2fs_xattr_entry-7:3" again,
+slab system will find that there is existed cache which has the same name
+and trigger the warning.
+
+Let's changes to use global inline_xattr_slab instead of per-sb slab cache
+for fixing.
+
+Fixes: a999150f4fe3 ("f2fs: use kmem_cache pool during inline xattr lookups")
+Cc: stable@kernel.org
+Reported-by: Hong Yun <yhong@link.cuhk.edu.hk>
+Tested-by: Hong Yun <yhong@link.cuhk.edu.hk>
+Signed-off-by: Chao Yu <chao@kernel.org>
+Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
+[ folio => page , context ]
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/f2fs/f2fs.h  |    3 ---
+ fs/f2fs/super.c |   15 +++++++--------
+ fs/f2fs/xattr.c |   30 ++++++++++--------------------
+ fs/f2fs/xattr.h |   10 ++++++----
+ 4 files changed, 23 insertions(+), 35 deletions(-)
+
+--- a/fs/f2fs/f2fs.h
++++ b/fs/f2fs/f2fs.h
+@@ -1807,9 +1807,6 @@ struct f2fs_sb_info {
+       spinlock_t error_lock;                  /* protect errors array */
+       bool error_dirty;                       /* errors of sb is dirty */
+-      struct kmem_cache *inline_xattr_slab;   /* inline xattr entry */
+-      unsigned int inline_xattr_slab_size;    /* default inline xattr slab size */
+-
+       /* For reclaimed segs statistics per each GC mode */
+       unsigned int gc_segment_mode;           /* GC state for reclaimed segments */
+       unsigned int gc_reclaimed_segs[MAX_GC_MODE];    /* Reclaimed segs for each mode */
+--- a/fs/f2fs/super.c
++++ b/fs/f2fs/super.c
+@@ -1674,7 +1674,6 @@ static void f2fs_put_super(struct super_
+       destroy_device_list(sbi);
+       f2fs_destroy_page_array_cache(sbi);
+-      f2fs_destroy_xattr_caches(sbi);
+       mempool_destroy(sbi->write_io_dummy);
+ #ifdef CONFIG_QUOTA
+       for (i = 0; i < MAXQUOTAS; i++)
+@@ -4305,13 +4304,9 @@ try_onemore:
+               }
+       }
+-      /* init per sbi slab cache */
+-      err = f2fs_init_xattr_caches(sbi);
+-      if (err)
+-              goto free_io_dummy;
+       err = f2fs_init_page_array_cache(sbi);
+       if (err)
+-              goto free_xattr_cache;
++              goto free_io_dummy;
+       /* get an inode for meta space */
+       sbi->meta_inode = f2fs_iget(sb, F2FS_META_INO(sbi));
+@@ -4624,8 +4619,6 @@ free_meta_inode:
+       sbi->meta_inode = NULL;
+ free_page_array_cache:
+       f2fs_destroy_page_array_cache(sbi);
+-free_xattr_cache:
+-      f2fs_destroy_xattr_caches(sbi);
+ free_io_dummy:
+       mempool_destroy(sbi->write_io_dummy);
+ free_percpu:
+@@ -4792,7 +4785,12 @@ static int __init init_f2fs_fs(void)
+       err = f2fs_create_casefold_cache();
+       if (err)
+               goto free_compress_cache;
++      err = f2fs_init_xattr_cache();
++      if (err)
++              goto free_casefold_cache;
+       return 0;
++free_casefold_cache:
++      f2fs_destroy_casefold_cache();
+ free_compress_cache:
+       f2fs_destroy_compress_cache();
+ free_compress_mempool:
+@@ -4832,6 +4830,7 @@ fail:
+ static void __exit exit_f2fs_fs(void)
+ {
++      f2fs_destroy_xattr_cache();
+       f2fs_destroy_casefold_cache();
+       f2fs_destroy_compress_cache();
+       f2fs_destroy_compress_mempool();
+--- a/fs/f2fs/xattr.c
++++ b/fs/f2fs/xattr.c
+@@ -23,11 +23,12 @@
+ #include "xattr.h"
+ #include "segment.h"
++static struct kmem_cache *inline_xattr_slab;
+ static void *xattr_alloc(struct f2fs_sb_info *sbi, int size, bool *is_inline)
+ {
+-      if (likely(size == sbi->inline_xattr_slab_size)) {
++      if (likely(size == DEFAULT_XATTR_SLAB_SIZE)) {
+               *is_inline = true;
+-              return f2fs_kmem_cache_alloc(sbi->inline_xattr_slab,
++              return f2fs_kmem_cache_alloc(inline_xattr_slab,
+                                       GFP_F2FS_ZERO, false, sbi);
+       }
+       *is_inline = false;
+@@ -38,7 +39,7 @@ static void xattr_free(struct f2fs_sb_in
+                                                       bool is_inline)
+ {
+       if (is_inline)
+-              kmem_cache_free(sbi->inline_xattr_slab, xattr_addr);
++              kmem_cache_free(inline_xattr_slab, xattr_addr);
+       else
+               kfree(xattr_addr);
+ }
+@@ -830,25 +831,14 @@ int f2fs_setxattr(struct inode *inode, i
+       return err;
+ }
+-int f2fs_init_xattr_caches(struct f2fs_sb_info *sbi)
++int __init f2fs_init_xattr_cache(void)
+ {
+-      dev_t dev = sbi->sb->s_bdev->bd_dev;
+-      char slab_name[32];
+-
+-      sprintf(slab_name, "f2fs_xattr_entry-%u:%u", MAJOR(dev), MINOR(dev));
+-
+-      sbi->inline_xattr_slab_size = F2FS_OPTION(sbi).inline_xattr_size *
+-                                      sizeof(__le32) + XATTR_PADDING_SIZE;
+-
+-      sbi->inline_xattr_slab = f2fs_kmem_cache_create(slab_name,
+-                                      sbi->inline_xattr_slab_size);
+-      if (!sbi->inline_xattr_slab)
+-              return -ENOMEM;
+-
+-      return 0;
++      inline_xattr_slab = f2fs_kmem_cache_create("f2fs_xattr_entry",
++                                      DEFAULT_XATTR_SLAB_SIZE);
++      return inline_xattr_slab ? 0 : -ENOMEM;
+ }
+-void f2fs_destroy_xattr_caches(struct f2fs_sb_info *sbi)
++void f2fs_destroy_xattr_cache(void)
+ {
+-      kmem_cache_destroy(sbi->inline_xattr_slab);
++      kmem_cache_destroy(inline_xattr_slab);
+ }
+--- a/fs/f2fs/xattr.h
++++ b/fs/f2fs/xattr.h
+@@ -88,6 +88,8 @@ struct f2fs_xattr_entry {
+                       F2FS_TOTAL_EXTRA_ATTR_SIZE / sizeof(__le32) -   \
+                       DEF_INLINE_RESERVED_SIZE -                      \
+                       MIN_INLINE_DENTRY_SIZE / sizeof(__le32))
++#define DEFAULT_XATTR_SLAB_SIZE       (DEFAULT_INLINE_XATTR_ADDRS *           \
++                              sizeof(__le32) + XATTR_PADDING_SIZE)
+ /*
+  * On-disk structure of f2fs_xattr
+@@ -131,8 +133,8 @@ extern int f2fs_setxattr(struct inode *,
+ extern int f2fs_getxattr(struct inode *, int, const char *, void *,
+                                               size_t, struct page *);
+ extern ssize_t f2fs_listxattr(struct dentry *, char *, size_t);
+-extern int f2fs_init_xattr_caches(struct f2fs_sb_info *);
+-extern void f2fs_destroy_xattr_caches(struct f2fs_sb_info *);
++int __init f2fs_init_xattr_cache(void);
++void f2fs_destroy_xattr_cache(void);
+ #else
+ #define f2fs_xattr_handlers   NULL
+@@ -149,8 +151,8 @@ static inline int f2fs_getxattr(struct i
+ {
+       return -EOPNOTSUPP;
+ }
+-static inline int f2fs_init_xattr_caches(struct f2fs_sb_info *sbi) { return 0; }
+-static inline void f2fs_destroy_xattr_caches(struct f2fs_sb_info *sbi) { }
++static inline int __init f2fs_init_xattr_cache(void) { return 0; }
++static inline void f2fs_destroy_xattr_cache(void) { }
+ #endif
+ #ifdef CONFIG_F2FS_FS_SECURITY
diff --git a/queue-6.1/fscache-delete-fscache_cookie_lru_timer-when-fscache-exits-to-avoid-uaf.patch b/queue-6.1/fscache-delete-fscache_cookie_lru_timer-when-fscache-exits-to-avoid-uaf.patch
new file mode 100644 (file)
index 0000000..208a376
--- /dev/null
@@ -0,0 +1,74 @@
+From stable+bounces-199963-greg=kroah.com@vger.kernel.org Thu Dec  4 08:00:34 2025
+From: Chen Yu <xnguchen@sina.cn>
+Date: Thu,  4 Dec 2025 14:57:33 +0800
+Subject: fscache: delete fscache_cookie_lru_timer when fscache exits to avoid UAF
+To: libaokun1@huawei.com, dhowells@redhat.com, brauner@kernel.org, stable@vger.kernel.org
+Message-ID: <20251204065733.21270-1-xnguchen@sina.cn>
+
+From: Baokun Li <libaokun1@huawei.com>
+
+commit 72a6e22c604c95ddb3b10b5d3bb85b6ff4dbc34f upstream.
+
+The fscache_cookie_lru_timer is initialized when the fscache module
+is inserted, but is not deleted when the fscache module is removed.
+If timer_reduce() is called before removing the fscache module,
+the fscache_cookie_lru_timer will be added to the timer list of
+the current cpu. Afterwards, a use-after-free will be triggered
+in the softIRQ after removing the fscache module, as follows:
+
+==================================================================
+BUG: unable to handle page fault for address: fffffbfff803c9e9
+ PF: supervisor read access in kernel mode
+ PF: error_code(0x0000) - not-present page
+PGD 21ffea067 P4D 21ffea067 PUD 21ffe6067 PMD 110a7c067 PTE 0
+Oops: Oops: 0000 [#1] PREEMPT SMP KASAN PTI
+CPU: 1 UID: 0 PID: 0 Comm: swapper/1 Tainted: G W 6.11.0-rc3 #855
+Tainted: [W]=WARN
+RIP: 0010:__run_timer_base.part.0+0x254/0x8a0
+Call Trace:
+ <IRQ>
+ tmigr_handle_remote_up+0x627/0x810
+ __walk_groups.isra.0+0x47/0x140
+ tmigr_handle_remote+0x1fa/0x2f0
+ handle_softirqs+0x180/0x590
+ irq_exit_rcu+0x84/0xb0
+ sysvec_apic_timer_interrupt+0x6e/0x90
+ </IRQ>
+ <TASK>
+ asm_sysvec_apic_timer_interrupt+0x1a/0x20
+RIP: 0010:default_idle+0xf/0x20
+ default_idle_call+0x38/0x60
+ do_idle+0x2b5/0x300
+ cpu_startup_entry+0x54/0x60
+ start_secondary+0x20d/0x280
+ common_startup_64+0x13e/0x148
+ </TASK>
+Modules linked in: [last unloaded: netfs]
+==================================================================
+
+Therefore delete fscache_cookie_lru_timer when removing the fscahe module.
+
+Fixes: 12bb21a29c19 ("fscache: Implement cookie user counting and resource pinning")
+Cc: stable@kernel.org
+Signed-off-by: Baokun Li <libaokun1@huawei.com>
+Link: https://lore.kernel.org/r/20240826112056.2458299-1-libaokun@huaweicloud.com
+Acked-by: David Howells <dhowells@redhat.com>
+Signed-off-by: Christian Brauner <brauner@kernel.org>
+[ Changed the file path due to missing commit:47757ea83a54 ("netfs,
+fscache: Move fs/fscache/* into fs/netfs/") ]
+Signed-off-by: Chen Yu <xnguchen@sina.cn>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/fscache/main.c |    1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/fs/fscache/main.c
++++ b/fs/fscache/main.c
+@@ -114,6 +114,7 @@ static void __exit fscache_exit(void)
+       kmem_cache_destroy(fscache_cookie_jar);
+       fscache_proc_cleanup();
++      timer_shutdown_sync(&fscache_cookie_lru_timer);
+       destroy_workqueue(fscache_wq);
+       pr_notice("Unloaded\n");
+ }
diff --git a/queue-6.1/fuse-fix-readahead-reclaim-deadlock.patch b/queue-6.1/fuse-fix-readahead-reclaim-deadlock.patch
new file mode 100644 (file)
index 0000000..cf64158
--- /dev/null
@@ -0,0 +1,120 @@
+From stable+bounces-204417-greg=kroah.com@vger.kernel.org Thu Jan  1 16:20:17 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu,  1 Jan 2026 10:20:12 -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: <20260101152012.4110447-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
+@@ -112,7 +112,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);
+@@ -133,8 +135,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);
+@@ -153,13 +164,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.1/gfs2-fix-freeze-error-handling.patch b/queue-6.1/gfs2-fix-freeze-error-handling.patch
new file mode 100644 (file)
index 0000000..faee8ce
--- /dev/null
@@ -0,0 +1,47 @@
+From stable+bounces-204150-greg=kroah.com@vger.kernel.org Tue Dec 30 00:25:13 2025
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 29 Dec 2025 18:25:04 -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: <20251229232504.1818648-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
+@@ -771,9 +771,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.1/iommu-arm-smmu-convert-to-platform-remove-callback-returning-void.patch b/queue-6.1/iommu-arm-smmu-convert-to-platform-remove-callback-returning-void.patch
new file mode 100644 (file)
index 0000000..f7d20a3
--- /dev/null
@@ -0,0 +1,119 @@
+From stable+bounces-204841-greg=kroah.com@vger.kernel.org Mon Jan  5 16:54:54 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon,  5 Jan 2026 10:44:50 -0500
+Subject: iommu/arm-smmu: Convert to platform remove callback returning void
+To: stable@vger.kernel.org
+Cc: "Uwe Kleine-König" <u.kleine-koenig@pengutronix.de>, "Joerg Roedel" <jroedel@suse.de>, "Sasha Levin" <sashal@kernel.org>
+Message-ID: <20260105154453.2644685-2-sashal@kernel.org>
+
+From: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
+
+[ Upstream commit 62565a77c2323d32f2be737455729ac7d3efe6ad ]
+
+The .remove() callback for a platform driver returns an int which makes
+many driver authors wrongly assume it's possible to do error handling by
+returning an error code. However the value returned is (mostly) ignored
+and this typically results in resource leaks. To improve here there is a
+quest to make the remove callback return void. In the first step of this
+quest all drivers are converted to .remove_new() which already returns
+void.
+
+Trivially convert this driver from always returning zero in the remove
+callback to the void returning variant.
+
+Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
+Link: https://lore.kernel.org/r/20230321084125.337021-5-u.kleine-koenig@pengutronix.de
+Signed-off-by: Joerg Roedel <jroedel@suse.de>
+Stable-dep-of: 6a3908ce56e6 ("iommu/qcom: fix device leak on of_xlate()")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/iommu/arm/arm-smmu/arm-smmu.c   |    6 ++----
+ drivers/iommu/arm/arm-smmu/qcom_iommu.c |   12 ++++--------
+ 2 files changed, 6 insertions(+), 12 deletions(-)
+
+--- a/drivers/iommu/arm/arm-smmu/arm-smmu.c
++++ b/drivers/iommu/arm/arm-smmu/arm-smmu.c
+@@ -2225,7 +2225,7 @@ static void arm_smmu_device_shutdown(str
+       clk_bulk_unprepare(smmu->num_clks, smmu->clks);
+ }
+-static int arm_smmu_device_remove(struct platform_device *pdev)
++static void arm_smmu_device_remove(struct platform_device *pdev)
+ {
+       struct arm_smmu_device *smmu = platform_get_drvdata(pdev);
+@@ -2233,8 +2233,6 @@ static int arm_smmu_device_remove(struct
+       iommu_device_sysfs_remove(&smmu->iommu);
+       arm_smmu_device_shutdown(pdev);
+-
+-      return 0;
+ }
+ static int __maybe_unused arm_smmu_runtime_resume(struct device *dev)
+@@ -2310,7 +2308,7 @@ static struct platform_driver arm_smmu_d
+               .suppress_bind_attrs    = true,
+       },
+       .probe  = arm_smmu_device_probe,
+-      .remove = arm_smmu_device_remove,
++      .remove_new = arm_smmu_device_remove,
+       .shutdown = arm_smmu_device_shutdown,
+ };
+ module_platform_driver(arm_smmu_driver);
+--- a/drivers/iommu/arm/arm-smmu/qcom_iommu.c
++++ b/drivers/iommu/arm/arm-smmu/qcom_iommu.c
+@@ -715,7 +715,7 @@ static int qcom_iommu_ctx_probe(struct p
+       return 0;
+ }
+-static int qcom_iommu_ctx_remove(struct platform_device *pdev)
++static void qcom_iommu_ctx_remove(struct platform_device *pdev)
+ {
+       struct qcom_iommu_dev *qcom_iommu = dev_get_drvdata(pdev->dev.parent);
+       struct qcom_iommu_ctx *ctx = platform_get_drvdata(pdev);
+@@ -723,8 +723,6 @@ static int qcom_iommu_ctx_remove(struct
+       platform_set_drvdata(pdev, NULL);
+       qcom_iommu->ctxs[ctx->asid - 1] = NULL;
+-
+-      return 0;
+ }
+ static const struct of_device_id ctx_of_match[] = {
+@@ -739,7 +737,7 @@ static struct platform_driver qcom_iommu
+               .of_match_table = ctx_of_match,
+       },
+       .probe  = qcom_iommu_ctx_probe,
+-      .remove = qcom_iommu_ctx_remove,
++      .remove_new = qcom_iommu_ctx_remove,
+ };
+ static bool qcom_iommu_has_secure_context(struct qcom_iommu_dev *qcom_iommu)
+@@ -857,7 +855,7 @@ err_pm_disable:
+       return ret;
+ }
+-static int qcom_iommu_device_remove(struct platform_device *pdev)
++static void qcom_iommu_device_remove(struct platform_device *pdev)
+ {
+       struct qcom_iommu_dev *qcom_iommu = platform_get_drvdata(pdev);
+@@ -865,8 +863,6 @@ static int qcom_iommu_device_remove(stru
+       platform_set_drvdata(pdev, NULL);
+       iommu_device_sysfs_remove(&qcom_iommu->iommu);
+       iommu_device_unregister(&qcom_iommu->iommu);
+-
+-      return 0;
+ }
+ static int __maybe_unused qcom_iommu_resume(struct device *dev)
+@@ -903,7 +899,7 @@ static struct platform_driver qcom_iommu
+               .pm             = &qcom_iommu_pm_ops,
+       },
+       .probe  = qcom_iommu_device_probe,
+-      .remove = qcom_iommu_device_remove,
++      .remove_new = qcom_iommu_device_remove,
+ };
+ static int __init qcom_iommu_init(void)
diff --git a/queue-6.1/iommu-arm-smmu-drop-if-with-an-always-false-condition.patch b/queue-6.1/iommu-arm-smmu-drop-if-with-an-always-false-condition.patch
new file mode 100644 (file)
index 0000000..b8e262f
--- /dev/null
@@ -0,0 +1,56 @@
+From stable+bounces-204840-greg=kroah.com@vger.kernel.org Mon Jan  5 16:52:41 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon,  5 Jan 2026 10:44:49 -0500
+Subject: iommu/arm-smmu: Drop if with an always false condition
+To: stable@vger.kernel.org
+Cc: "Uwe Kleine-König" <u.kleine-koenig@pengutronix.de>, "Robin Murphy" <robin.murphy@arm.com>, "Joerg Roedel" <jroedel@suse.de>, "Sasha Levin" <sashal@kernel.org>
+Message-ID: <20260105154453.2644685-1-sashal@kernel.org>
+
+From: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
+
+[ Upstream commit a2972cb89935160bfe515b15d28a77694723ac06 ]
+
+The remove and shutdown callback are only called after probe completed
+successfully. In this case platform_set_drvdata() was called with a
+non-NULL argument and so smmu is never NULL. Other functions in this
+driver also don't check for smmu being non-NULL before using it.
+
+Also note that returning an error code from a remove callback doesn't
+result in the device staying bound. It's still removed and devm allocated
+resources are freed (among others *smmu and the register mapping). So
+after an early exit to iommu device stayed around and using it probably
+oopses.
+
+Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
+Reviewed-by: Robin Murphy <robin.murphy@arm.com>
+Link: https://lore.kernel.org/r/20230321084125.337021-2-u.kleine-koenig@pengutronix.de
+Signed-off-by: Joerg Roedel <jroedel@suse.de>
+Stable-dep-of: 6a3908ce56e6 ("iommu/qcom: fix device leak on of_xlate()")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/iommu/arm/arm-smmu/arm-smmu.c |    6 ------
+ 1 file changed, 6 deletions(-)
+
+--- a/drivers/iommu/arm/arm-smmu/arm-smmu.c
++++ b/drivers/iommu/arm/arm-smmu/arm-smmu.c
+@@ -2209,9 +2209,6 @@ static void arm_smmu_device_shutdown(str
+ {
+       struct arm_smmu_device *smmu = platform_get_drvdata(pdev);
+-      if (!smmu)
+-              return;
+-
+       if (!bitmap_empty(smmu->context_map, ARM_SMMU_MAX_CBS))
+               dev_notice(&pdev->dev, "disabling translation\n");
+@@ -2232,9 +2229,6 @@ static int arm_smmu_device_remove(struct
+ {
+       struct arm_smmu_device *smmu = platform_get_drvdata(pdev);
+-      if (!smmu)
+-              return -ENODEV;
+-
+       iommu_device_unregister(&smmu->iommu);
+       iommu_device_sysfs_remove(&smmu->iommu);
diff --git a/queue-6.1/iommu-mediatek-fix-use-after-free-on-probe-deferral.patch b/queue-6.1/iommu-mediatek-fix-use-after-free-on-probe-deferral.patch
new file mode 100644 (file)
index 0000000..e8dba5c
--- /dev/null
@@ -0,0 +1,95 @@
+From stable+bounces-204400-greg=kroah.com@vger.kernel.org Thu Jan  1 00:39:05 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 31 Dec 2025 18:38:58 -0500
+Subject: iommu/mediatek: fix use-after-free on probe deferral
+To: stable@vger.kernel.org
+Cc: Johan Hovold <johan@kernel.org>, Yong Wu <yong.wu@mediatek.com>, Robin Murphy <robin.murphy@arm.com>, AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>, Joerg Roedel <joerg.roedel@amd.com>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20251231233858.3696664-2-sashal@kernel.org>
+
+From: Johan Hovold <johan@kernel.org>
+
+[ Upstream commit de83d4617f9fe059623e97acf7e1e10d209625b5 ]
+
+The driver is dropping the references taken to the larb devices during
+probe after successful lookup as well as on errors. This can
+potentially lead to a use-after-free in case a larb device has not yet
+been bound to its driver so that the iommu driver probe defers.
+
+Fix this by keeping the references as expected while the iommu driver is
+bound.
+
+Fixes: 26593928564c ("iommu/mediatek: Add error path for loop of mm_dts_parse")
+Cc: stable@vger.kernel.org
+Cc: Yong Wu <yong.wu@mediatek.com>
+Acked-by: Robin Murphy <robin.murphy@arm.com>
+Signed-off-by: Johan Hovold <johan@kernel.org>
+Reviewed-by: Yong Wu <yong.wu@mediatek.com>
+Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
+Signed-off-by: Joerg Roedel <joerg.roedel@amd.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/iommu/mtk_iommu.c |   25 ++++++++++++++++++-------
+ 1 file changed, 18 insertions(+), 7 deletions(-)
+
+--- a/drivers/iommu/mtk_iommu.c
++++ b/drivers/iommu/mtk_iommu.c
+@@ -1134,16 +1134,19 @@ static int mtk_iommu_mm_dts_parse(struct
+               }
+               component_match_add(dev, match, component_compare_dev, &plarbdev->dev);
+-              platform_device_put(plarbdev);
+       }
+-      if (!frst_avail_smicomm_node)
+-              return -EINVAL;
++      if (!frst_avail_smicomm_node) {
++              ret = -EINVAL;
++              goto err_larbdev_put;
++      }
+       pcommdev = of_find_device_by_node(frst_avail_smicomm_node);
+       of_node_put(frst_avail_smicomm_node);
+-      if (!pcommdev)
+-              return -ENODEV;
++      if (!pcommdev) {
++              ret = -ENODEV;
++              goto err_larbdev_put;
++      }
+       data->smicomm_dev = &pcommdev->dev;
+       link = device_link_add(data->smicomm_dev, dev,
+@@ -1151,7 +1154,8 @@ static int mtk_iommu_mm_dts_parse(struct
+       platform_device_put(pcommdev);
+       if (!link) {
+               dev_err(dev, "Unable to link %s.\n", dev_name(data->smicomm_dev));
+-              return -EINVAL;
++              ret = -EINVAL;
++              goto err_larbdev_put;
+       }
+       return 0;
+@@ -1322,8 +1326,12 @@ out_sysfs_remove:
+       iommu_device_sysfs_remove(&data->iommu);
+ out_list_del:
+       list_del(&data->list);
+-      if (MTK_IOMMU_IS_TYPE(data->plat_data, MTK_IOMMU_TYPE_MM))
++      if (MTK_IOMMU_IS_TYPE(data->plat_data, MTK_IOMMU_TYPE_MM)) {
+               device_link_remove(data->smicomm_dev, dev);
++
++              for (i = 0; i < MTK_LARB_NR_MAX; i++)
++                      put_device(data->larb_imu[i].dev);
++      }
+ out_runtime_disable:
+       pm_runtime_disable(dev);
+       return ret;
+@@ -1343,6 +1351,9 @@ static int mtk_iommu_remove(struct platf
+       if (MTK_IOMMU_IS_TYPE(data->plat_data, MTK_IOMMU_TYPE_MM)) {
+               device_link_remove(data->smicomm_dev, &pdev->dev);
+               component_master_del(&pdev->dev, &mtk_iommu_com_ops);
++
++              for (i = 0; i < MTK_LARB_NR_MAX; i++)
++                      put_device(data->larb_imu[i].dev);
+       }
+       pm_runtime_disable(&pdev->dev);
+       for (i = 0; i < data->plat_data->banks_num; i++) {
diff --git a/queue-6.1/iommu-mediatek-improve-safety-for-mediatek-smi-property-in-larb-nodes.patch b/queue-6.1/iommu-mediatek-improve-safety-for-mediatek-smi-property-in-larb-nodes.patch
new file mode 100644 (file)
index 0000000..00ad8aa
--- /dev/null
@@ -0,0 +1,114 @@
+From stable+bounces-204399-greg=kroah.com@vger.kernel.org Thu Jan  1 00:39:05 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 31 Dec 2025 18:38:57 -0500
+Subject: iommu/mediatek: Improve safety for mediatek,smi property in larb nodes
+To: stable@vger.kernel.org
+Cc: Yong Wu <yong.wu@mediatek.com>, Guenter Roeck <groeck@chromium.org>, AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>, Matthias Brugger <matthias.bgg@gmail.com>, Joerg Roedel <jroedel@suse.de>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20251231233858.3696664-1-sashal@kernel.org>
+
+From: Yong Wu <yong.wu@mediatek.com>
+
+[ Upstream commit 6cde583d5352818a51985b32a960cdde85ab3821 ]
+
+No functional change. Just improve safety from dts.
+
+All the larbs that connect to one IOMMU must connect with the same
+smi-common. This patch checks all the mediatek,smi property for each
+larb, If their mediatek,smi are different, it will return fails.
+Also avoid there is no available smi-larb nodes.
+
+Suggested-by: Guenter Roeck <groeck@chromium.org>
+Signed-off-by: Yong Wu <yong.wu@mediatek.com>
+Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
+Reviewed-by: Matthias Brugger <matthias.bgg@gmail.com>
+Link: https://lore.kernel.org/r/20221018024258.19073-6-yong.wu@mediatek.com
+Signed-off-by: Joerg Roedel <jroedel@suse.de>
+Stable-dep-of: de83d4617f9f ("iommu/mediatek: fix use-after-free on probe deferral")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/iommu/mtk_iommu.c |   53 ++++++++++++++++++++++++++++++++--------------
+ 1 file changed, 37 insertions(+), 16 deletions(-)
+
+--- a/drivers/iommu/mtk_iommu.c
++++ b/drivers/iommu/mtk_iommu.c
+@@ -1048,7 +1048,7 @@ static const struct component_master_ops
+ static int mtk_iommu_mm_dts_parse(struct device *dev, struct component_match **match,
+                                 struct mtk_iommu_data *data)
+ {
+-      struct device_node *larbnode, *smicomm_node, *smi_subcomm_node;
++      struct device_node *larbnode, *frst_avail_smicomm_node = NULL;
+       struct platform_device *plarbdev, *pcommdev;
+       struct device_link *link;
+       int i, larb_nr, ret;
+@@ -1060,6 +1060,7 @@ static int mtk_iommu_mm_dts_parse(struct
+               return -EINVAL;
+       for (i = 0; i < larb_nr; i++) {
++              struct device_node *smicomm_node, *smi_subcomm_node;
+               u32 id;
+               larbnode = of_parse_phandle(dev->of_node, "mediatek,larbs", i);
+@@ -1100,27 +1101,47 @@ static int mtk_iommu_mm_dts_parse(struct
+                       goto err_larbdev_put;
+               }
++              /* Get smi-(sub)-common dev from the last larb. */
++              smi_subcomm_node = of_parse_phandle(larbnode, "mediatek,smi", 0);
++              if (!smi_subcomm_node) {
++                      ret = -EINVAL;
++                      goto err_larbdev_put;
++              }
++
++              /*
++               * It may have two level smi-common. the node is smi-sub-common if it
++               * has a new mediatek,smi property. otherwise it is smi-commmon.
++               */
++              smicomm_node = of_parse_phandle(smi_subcomm_node, "mediatek,smi", 0);
++              if (smicomm_node)
++                      of_node_put(smi_subcomm_node);
++              else
++                      smicomm_node = smi_subcomm_node;
++
++              /*
++               * All the larbs that connect to one IOMMU must connect with the same
++               * smi-common.
++               */
++              if (!frst_avail_smicomm_node) {
++                      frst_avail_smicomm_node = smicomm_node;
++              } else if (frst_avail_smicomm_node != smicomm_node) {
++                      dev_err(dev, "mediatek,smi property is not right @larb%d.", id);
++                      of_node_put(smicomm_node);
++                      ret = -EINVAL;
++                      goto err_larbdev_put;
++              } else {
++                      of_node_put(smicomm_node);
++              }
++
+               component_match_add(dev, match, component_compare_dev, &plarbdev->dev);
+               platform_device_put(plarbdev);
+       }
+-      /* Get smi-(sub)-common dev from the last larb. */
+-      smi_subcomm_node = of_parse_phandle(larbnode, "mediatek,smi", 0);
+-      if (!smi_subcomm_node)
++      if (!frst_avail_smicomm_node)
+               return -EINVAL;
+-      /*
+-       * It may have two level smi-common. the node is smi-sub-common if it
+-       * has a new mediatek,smi property. otherwise it is smi-commmon.
+-       */
+-      smicomm_node = of_parse_phandle(smi_subcomm_node, "mediatek,smi", 0);
+-      if (smicomm_node)
+-              of_node_put(smi_subcomm_node);
+-      else
+-              smicomm_node = smi_subcomm_node;
+-
+-      pcommdev = of_find_device_by_node(smicomm_node);
+-      of_node_put(smicomm_node);
++      pcommdev = of_find_device_by_node(frst_avail_smicomm_node);
++      of_node_put(frst_avail_smicomm_node);
+       if (!pcommdev)
+               return -ENODEV;
+       data->smicomm_dev = &pcommdev->dev;
diff --git a/queue-6.1/iommu-mediatek-v1-fix-device-leaks-on-probe.patch b/queue-6.1/iommu-mediatek-v1-fix-device-leaks-on-probe.patch
new file mode 100644 (file)
index 0000000..9f22caf
--- /dev/null
@@ -0,0 +1,97 @@
+From stable+bounces-204838-greg=kroah.com@vger.kernel.org Mon Jan  5 16:45:21 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon,  5 Jan 2026 10:32:20 -0500
+Subject: iommu/mediatek-v1: fix device leaks on probe()
+To: stable@vger.kernel.org
+Cc: Johan Hovold <johan@kernel.org>, Honghui Zhang <honghui.zhang@mediatek.com>, Robin Murphy <robin.murphy@arm.com>, AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>, Joerg Roedel <joerg.roedel@amd.com>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260105153220.2637603-2-sashal@kernel.org>
+
+From: Johan Hovold <johan@kernel.org>
+
+[ Upstream commit 46207625c9f33da0e43bb4ae1e91f0791b6ed633 ]
+
+Make sure to drop the references taken to the larb devices during
+probe on probe failure (e.g. probe deferral) and on driver unbind.
+
+Fixes: b17336c55d89 ("iommu/mediatek: add support for mtk iommu generation one HW")
+Cc: stable@vger.kernel.org     # 4.8
+Cc: Honghui Zhang <honghui.zhang@mediatek.com>
+Acked-by: Robin Murphy <robin.murphy@arm.com>
+Signed-off-by: Johan Hovold <johan@kernel.org>
+Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
+Signed-off-by: Joerg Roedel <joerg.roedel@amd.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/iommu/mtk_iommu_v1.c |   23 ++++++++++++++++++-----
+ 1 file changed, 18 insertions(+), 5 deletions(-)
+
+--- a/drivers/iommu/mtk_iommu_v1.c
++++ b/drivers/iommu/mtk_iommu_v1.c
+@@ -656,8 +656,10 @@ static int mtk_iommu_v1_probe(struct pla
+               struct platform_device *plarbdev;
+               larbnode = of_parse_phandle(dev->of_node, "mediatek,larbs", i);
+-              if (!larbnode)
+-                      return -EINVAL;
++              if (!larbnode) {
++                      ret = -EINVAL;
++                      goto out_put_larbs;
++              }
+               if (!of_device_is_available(larbnode)) {
+                       of_node_put(larbnode);
+@@ -667,11 +669,14 @@ static int mtk_iommu_v1_probe(struct pla
+               plarbdev = of_find_device_by_node(larbnode);
+               if (!plarbdev) {
+                       of_node_put(larbnode);
+-                      return -ENODEV;
++                      ret = -ENODEV;
++                      goto out_put_larbs;
+               }
+               if (!plarbdev->dev.driver) {
+                       of_node_put(larbnode);
+-                      return -EPROBE_DEFER;
++                      put_device(&plarbdev->dev);
++                      ret = -EPROBE_DEFER;
++                      goto out_put_larbs;
+               }
+               data->larb_imu[i].dev = &plarbdev->dev;
+@@ -683,7 +688,7 @@ static int mtk_iommu_v1_probe(struct pla
+       ret = mtk_iommu_v1_hw_init(data);
+       if (ret)
+-              return ret;
++              goto out_put_larbs;
+       ret = iommu_device_sysfs_add(&data->iommu, &pdev->dev, NULL,
+                                    dev_name(&pdev->dev));
+@@ -705,12 +710,17 @@ out_sysfs_remove:
+       iommu_device_sysfs_remove(&data->iommu);
+ out_clk_unprepare:
+       clk_disable_unprepare(data->bclk);
++out_put_larbs:
++      for (i = 0; i < MTK_LARB_NR_MAX; i++)
++              put_device(data->larb_imu[i].dev);
++
+       return ret;
+ }
+ static void mtk_iommu_v1_remove(struct platform_device *pdev)
+ {
+       struct mtk_iommu_v1_data *data = platform_get_drvdata(pdev);
++      int i;
+       iommu_device_sysfs_remove(&data->iommu);
+       iommu_device_unregister(&data->iommu);
+@@ -718,6 +728,9 @@ static void mtk_iommu_v1_remove(struct p
+       clk_disable_unprepare(data->bclk);
+       devm_free_irq(&pdev->dev, data->irq, data);
+       component_master_del(&pdev->dev, &mtk_iommu_v1_com_ops);
++
++      for (i = 0; i < MTK_LARB_NR_MAX; i++)
++              put_device(data->larb_imu[i].dev);
+ }
+ static int __maybe_unused mtk_iommu_v1_suspend(struct device *dev)
diff --git a/queue-6.1/iommu-mtk_iommu_v1-convert-to-platform-remove-callback-returning-void.patch b/queue-6.1/iommu-mtk_iommu_v1-convert-to-platform-remove-callback-returning-void.patch
new file mode 100644 (file)
index 0000000..7b03b5c
--- /dev/null
@@ -0,0 +1,62 @@
+From stable+bounces-204837-greg=kroah.com@vger.kernel.org Mon Jan  5 16:48:58 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon,  5 Jan 2026 10:32:19 -0500
+Subject: iommu/mtk_iommu_v1: Convert to platform remove callback returning void
+To: stable@vger.kernel.org
+Cc: "Uwe Kleine-König" <u.kleine-koenig@pengutronix.de>, "AngeloGioacchino Del Regno" <angelogioacchino.delregno@collabora.com>, "Joerg Roedel" <jroedel@suse.de>, "Sasha Levin" <sashal@kernel.org>
+Message-ID: <20260105153220.2637603-1-sashal@kernel.org>
+
+From: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
+
+[ Upstream commit 85e1049e50da9409678fc247ebad4c019d68041f ]
+
+The .remove() callback for a platform driver returns an int which makes
+many driver authors wrongly assume it's possible to do error handling by
+returning an error code. However the value returned is (mostly) ignored
+and this typically results in resource leaks. To improve here there is a
+quest to make the remove callback return void. In the first step of this
+quest all drivers are converted to .remove_new() which already returns
+void.
+
+Trivially convert this driver from always returning zero in the remove
+callback to the void returning variant.
+
+Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
+Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
+Link: https://lore.kernel.org/r/20230321084125.337021-9-u.kleine-koenig@pengutronix.de
+Signed-off-by: Joerg Roedel <jroedel@suse.de>
+Stable-dep-of: 46207625c9f3 ("iommu/mediatek-v1: fix device leaks on probe()")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/iommu/mtk_iommu_v1.c |    5 ++---
+ 1 file changed, 2 insertions(+), 3 deletions(-)
+
+--- a/drivers/iommu/mtk_iommu_v1.c
++++ b/drivers/iommu/mtk_iommu_v1.c
+@@ -708,7 +708,7 @@ out_clk_unprepare:
+       return ret;
+ }
+-static int mtk_iommu_v1_remove(struct platform_device *pdev)
++static void mtk_iommu_v1_remove(struct platform_device *pdev)
+ {
+       struct mtk_iommu_v1_data *data = platform_get_drvdata(pdev);
+@@ -718,7 +718,6 @@ static int mtk_iommu_v1_remove(struct pl
+       clk_disable_unprepare(data->bclk);
+       devm_free_irq(&pdev->dev, data->irq, data);
+       component_master_del(&pdev->dev, &mtk_iommu_v1_com_ops);
+-      return 0;
+ }
+ static int __maybe_unused mtk_iommu_v1_suspend(struct device *dev)
+@@ -757,7 +756,7 @@ static const struct dev_pm_ops mtk_iommu
+ static struct platform_driver mtk_iommu_v1_driver = {
+       .probe  = mtk_iommu_v1_probe,
+-      .remove = mtk_iommu_v1_remove,
++      .remove_new = mtk_iommu_v1_remove,
+       .driver = {
+               .name = "mtk-iommu-v1",
+               .of_match_table = mtk_iommu_v1_of_ids,
diff --git a/queue-6.1/iommu-qcom-fix-device-leak-on-of_xlate.patch b/queue-6.1/iommu-qcom-fix-device-leak-on-of_xlate.patch
new file mode 100644 (file)
index 0000000..f816463
--- /dev/null
@@ -0,0 +1,64 @@
+From stable+bounces-204844-greg=kroah.com@vger.kernel.org Mon Jan  5 16:46:59 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon,  5 Jan 2026 10:44:53 -0500
+Subject: iommu/qcom: fix device leak on of_xlate()
+To: stable@vger.kernel.org
+Cc: Johan Hovold <johan@kernel.org>, Rob Clark <robin.clark@oss.qualcomm.com>, Yu Kuai <yukuai3@huawei.com>, Robin Murphy <robin.murphy@arm.com>, Joerg Roedel <joerg.roedel@amd.com>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260105154453.2644685-5-sashal@kernel.org>
+
+From: Johan Hovold <johan@kernel.org>
+
+[ Upstream commit 6a3908ce56e6879920b44ef136252b2f0c954194 ]
+
+Make sure to drop the reference taken to the iommu platform device when
+looking up its driver data during of_xlate().
+
+Note that commit e2eae09939a8 ("iommu/qcom: add missing put_device()
+call in qcom_iommu_of_xlate()") fixed the leak in a couple of error
+paths, but the reference is still leaking on success and late failures.
+
+Fixes: 0ae349a0f33f ("iommu/qcom: Add qcom_iommu")
+Cc: stable@vger.kernel.org     # 4.14: e2eae09939a8
+Cc: Rob Clark <robin.clark@oss.qualcomm.com>
+Cc: Yu Kuai <yukuai3@huawei.com>
+Acked-by: Robin Murphy <robin.murphy@arm.com>
+Signed-off-by: Johan Hovold <johan@kernel.org>
+Signed-off-by: Joerg Roedel <joerg.roedel@amd.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/iommu/arm/arm-smmu/qcom_iommu.c |   10 ++++------
+ 1 file changed, 4 insertions(+), 6 deletions(-)
+
+--- a/drivers/iommu/arm/arm-smmu/qcom_iommu.c
++++ b/drivers/iommu/arm/arm-smmu/qcom_iommu.c
+@@ -558,14 +558,14 @@ static int qcom_iommu_of_xlate(struct de
+       qcom_iommu = platform_get_drvdata(iommu_pdev);
++      put_device(&iommu_pdev->dev);
++
+       /* make sure the asid specified in dt is valid, so we don't have
+        * to sanity check this elsewhere:
+        */
+       if (WARN_ON(asid > qcom_iommu->max_asid) ||
+-          WARN_ON(qcom_iommu->ctxs[asid] == NULL)) {
+-              put_device(&iommu_pdev->dev);
++          WARN_ON(qcom_iommu->ctxs[asid] == NULL))
+               return -EINVAL;
+-      }
+       if (!dev_iommu_priv_get(dev)) {
+               dev_iommu_priv_set(dev, qcom_iommu);
+@@ -574,10 +574,8 @@ static int qcom_iommu_of_xlate(struct de
+                * multiple different iommu devices.  Multiple context
+                * banks are ok, but multiple devices are not:
+                */
+-              if (WARN_ON(qcom_iommu != dev_iommu_priv_get(dev))) {
+-                      put_device(&iommu_pdev->dev);
++              if (WARN_ON(qcom_iommu != dev_iommu_priv_get(dev)))
+                       return -EINVAL;
+-              }
+       }
+       return iommu_fwspec_add_ids(dev, &asid, 1);
diff --git a/queue-6.1/iommu-qcom-index-contexts-by-asid-number-to-allow-asid-0.patch b/queue-6.1/iommu-qcom-index-contexts-by-asid-number-to-allow-asid-0.patch
new file mode 100644 (file)
index 0000000..d7f0510
--- /dev/null
@@ -0,0 +1,103 @@
+From stable+bounces-204843-greg=kroah.com@vger.kernel.org Mon Jan  5 16:47:00 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon,  5 Jan 2026 10:44:52 -0500
+Subject: iommu/qcom: Index contexts by asid number to allow asid 0
+To: stable@vger.kernel.org
+Cc: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>, Konrad Dybcio <konrad.dybcio@linaro.org>, Will Deacon <will@kernel.org>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260105154453.2644685-4-sashal@kernel.org>
+
+From: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
+
+[ Upstream commit ec5601661bfcdc206e6ceba1b97837e763dab1ba ]
+
+This driver was indexing the contexts by asid-1, which is probably
+done under the assumption that the first ASID is always 1.
+Unfortunately this is not always true: at least for MSM8956 and
+MSM8976's GPU IOMMU, the gpu_user context's ASID number is zero.
+To allow using a zero asid number, index the contexts by `asid`
+instead of by `asid - 1`.
+
+While at it, also enhance human readability by renaming the
+`num_ctxs` member of struct qcom_iommu_dev to `max_asid`.
+
+Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
+Reviewed-by: Konrad Dybcio <konrad.dybcio@linaro.org>
+Link: https://lore.kernel.org/r/20230622092742.74819-5-angelogioacchino.delregno@collabora.com
+Signed-off-by: Will Deacon <will@kernel.org>
+Stable-dep-of: 6a3908ce56e6 ("iommu/qcom: fix device leak on of_xlate()")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/iommu/arm/arm-smmu/qcom_iommu.c |   22 ++++++++++------------
+ 1 file changed, 10 insertions(+), 12 deletions(-)
+
+--- a/drivers/iommu/arm/arm-smmu/qcom_iommu.c
++++ b/drivers/iommu/arm/arm-smmu/qcom_iommu.c
+@@ -51,8 +51,8 @@ struct qcom_iommu_dev {
+       struct clk_bulk_data clks[CLK_NUM];
+       void __iomem            *local_base;
+       u32                      sec_id;
+-      u8                       num_ctxs;
+-      struct qcom_iommu_ctx   *ctxs[];   /* indexed by asid-1 */
++      u8                       max_asid;
++      struct qcom_iommu_ctx   *ctxs[];   /* indexed by asid */
+ };
+ struct qcom_iommu_ctx {
+@@ -94,7 +94,7 @@ static struct qcom_iommu_ctx * to_ctx(st
+       struct qcom_iommu_dev *qcom_iommu = d->iommu;
+       if (!qcom_iommu)
+               return NULL;
+-      return qcom_iommu->ctxs[asid - 1];
++      return qcom_iommu->ctxs[asid];
+ }
+ static inline void
+@@ -559,12 +559,10 @@ static int qcom_iommu_of_xlate(struct de
+       qcom_iommu = platform_get_drvdata(iommu_pdev);
+       /* make sure the asid specified in dt is valid, so we don't have
+-       * to sanity check this elsewhere, since 'asid - 1' is used to
+-       * index into qcom_iommu->ctxs:
++       * to sanity check this elsewhere:
+        */
+-      if (WARN_ON(asid < 1) ||
+-          WARN_ON(asid > qcom_iommu->num_ctxs) ||
+-          WARN_ON(qcom_iommu->ctxs[asid - 1] == NULL)) {
++      if (WARN_ON(asid > qcom_iommu->max_asid) ||
++          WARN_ON(qcom_iommu->ctxs[asid] == NULL)) {
+               put_device(&iommu_pdev->dev);
+               return -EINVAL;
+       }
+@@ -722,7 +720,7 @@ static int qcom_iommu_ctx_probe(struct p
+       dev_dbg(dev, "found asid %u\n", ctx->asid);
+-      qcom_iommu->ctxs[ctx->asid - 1] = ctx;
++      qcom_iommu->ctxs[ctx->asid] = ctx;
+       return 0;
+ }
+@@ -734,7 +732,7 @@ static void qcom_iommu_ctx_remove(struct
+       platform_set_drvdata(pdev, NULL);
+-      qcom_iommu->ctxs[ctx->asid - 1] = NULL;
++      qcom_iommu->ctxs[ctx->asid] = NULL;
+ }
+ static const struct of_device_id ctx_of_match[] = {
+@@ -781,11 +779,11 @@ static int qcom_iommu_device_probe(struc
+       for_each_child_of_node(dev->of_node, child)
+               max_asid = max(max_asid, get_asid(child));
+-      qcom_iommu = devm_kzalloc(dev, struct_size(qcom_iommu, ctxs, max_asid),
++      qcom_iommu = devm_kzalloc(dev, struct_size(qcom_iommu, ctxs, max_asid + 1),
+                                 GFP_KERNEL);
+       if (!qcom_iommu)
+               return -ENOMEM;
+-      qcom_iommu->num_ctxs = max_asid;
++      qcom_iommu->max_asid = max_asid;
+       qcom_iommu->dev = dev;
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
diff --git a/queue-6.1/iommu-qcom-use-the-asid-read-from-device-tree-if-specified.patch b/queue-6.1/iommu-qcom-use-the-asid-read-from-device-tree-if-specified.patch
new file mode 100644 (file)
index 0000000..b3f64b7
--- /dev/null
@@ -0,0 +1,82 @@
+From stable+bounces-204842-greg=kroah.com@vger.kernel.org Mon Jan  5 16:55:01 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon,  5 Jan 2026 10:44:51 -0500
+Subject: iommu/qcom: Use the asid read from device-tree if specified
+To: stable@vger.kernel.org
+Cc: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>, Marijn Suijten <marijn.suijten@somainline.org>, Konrad Dybcio <konrad.dybcio@linaro.org>, Will Deacon <will@kernel.org>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260105154453.2644685-3-sashal@kernel.org>
+
+From: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
+
+[ Upstream commit fcf226f1f7083cba76af47bf8dd764b68b149cd2 ]
+
+As specified in this driver, the context banks are 0x1000 apart but
+on some SoCs the context number does not necessarily match this
+logic, hence we end up using the wrong ASID: keeping in mind that
+this IOMMU implementation relies heavily on SCM (TZ) calls, it is
+mandatory that we communicate the right context number.
+
+Since this is all about how context banks are mapped in firmware,
+which may be board dependent (as a different firmware version may
+eventually change the expected context bank numbers), introduce a
+new property "qcom,ctx-asid": when found, the ASID will be forced
+as read from the devicetree.
+
+When "qcom,ctx-asid" is not found, this driver retains the previous
+behavior as to avoid breaking older devicetrees or systems that do
+not require forcing ASID numbers.
+
+Signed-off-by: Marijn Suijten <marijn.suijten@somainline.org>
+[Marijn: Rebased over next-20221111]
+Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
+Reviewed-by: Konrad Dybcio <konrad.dybcio@linaro.org>
+Link: https://lore.kernel.org/r/20230622092742.74819-3-angelogioacchino.delregno@collabora.com
+Signed-off-by: Will Deacon <will@kernel.org>
+Stable-dep-of: 6a3908ce56e6 ("iommu/qcom: fix device leak on of_xlate()")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/iommu/arm/arm-smmu/qcom_iommu.c |   18 +++++++++++++++---
+ 1 file changed, 15 insertions(+), 3 deletions(-)
+
+--- a/drivers/iommu/arm/arm-smmu/qcom_iommu.c
++++ b/drivers/iommu/arm/arm-smmu/qcom_iommu.c
+@@ -563,7 +563,8 @@ static int qcom_iommu_of_xlate(struct de
+        * index into qcom_iommu->ctxs:
+        */
+       if (WARN_ON(asid < 1) ||
+-          WARN_ON(asid > qcom_iommu->num_ctxs)) {
++          WARN_ON(asid > qcom_iommu->num_ctxs) ||
++          WARN_ON(qcom_iommu->ctxs[asid - 1] == NULL)) {
+               put_device(&iommu_pdev->dev);
+               return -EINVAL;
+       }
+@@ -650,7 +651,8 @@ free_mem:
+ static int get_asid(const struct device_node *np)
+ {
+-      u32 reg;
++      u32 reg, val;
++      int asid;
+       /* read the "reg" property directly to get the relative address
+        * of the context bank, and calculate the asid from that:
+@@ -658,7 +660,17 @@ static int get_asid(const struct device_
+       if (of_property_read_u32_index(np, "reg", 0, &reg))
+               return -ENODEV;
+-      return reg / 0x1000;      /* context banks are 0x1000 apart */
++      /*
++       * Context banks are 0x1000 apart but, in some cases, the ASID
++       * number doesn't match to this logic and needs to be passed
++       * from the DT configuration explicitly.
++       */
++      if (!of_property_read_u32(np, "qcom,ctx-asid", &val))
++              asid = val;
++      else
++              asid = reg / 0x1000;
++
++      return asid;
+ }
+ static int qcom_iommu_ctx_probe(struct platform_device *pdev)
diff --git a/queue-6.1/jbd2-fix-the-inconsistency-between-checksum-and-data-in-memory-for-journal-sb.patch b/queue-6.1/jbd2-fix-the-inconsistency-between-checksum-and-data-in-memory-for-journal-sb.patch
new file mode 100644 (file)
index 0000000..f75120d
--- /dev/null
@@ -0,0 +1,94 @@
+From stable+bounces-204159-greg=kroah.com@vger.kernel.org Tue Dec 30 01:47:21 2025
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 29 Dec 2025 19:46:45 -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: <20251230004645.1895239-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
+[ Changed jbd2_superblock_csum(sb) to jbd2_superblock_csum(journal, sb) ]
+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
+@@ -2393,6 +2393,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);
+       journal->j_revoke_records_per_block =
+                               journal_revoke_records_per_block(journal);
+@@ -2423,9 +2429,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);
+       journal->j_revoke_records_per_block =
+                               journal_revoke_records_per_block(journal);
+ }
diff --git a/queue-6.1/kbuild-use-crc32-and-a-1mib-dictionary-for-xz-compressed-modules.patch b/queue-6.1/kbuild-use-crc32-and-a-1mib-dictionary-for-xz-compressed-modules.patch
new file mode 100644 (file)
index 0000000..8dee1f6
--- /dev/null
@@ -0,0 +1,39 @@
+From fbf5892df21a8ccfcb2fda0fd65bc3169c89ed28 Mon Sep 17 00:00:00 2001
+From: Martin Nybo Andersen <tweek@tweek.dk>
+Date: Fri, 15 Sep 2023 12:15:39 +0200
+Subject: kbuild: Use CRC32 and a 1MiB dictionary for XZ compressed modules
+
+From: Martin Nybo Andersen <tweek@tweek.dk>
+
+commit fbf5892df21a8ccfcb2fda0fd65bc3169c89ed28 upstream.
+
+Kmod is now (since kmod commit 09c9f8c5df04 ("libkmod: Use kernel
+decompression when available")) using the kernel decompressor, when
+loading compressed modules.
+
+However, the kernel XZ decompressor is XZ Embedded, which doesn't
+handle CRC64 and dictionaries larger than 1MiB.
+
+Use CRC32 and 1MiB dictionary when XZ compressing and installing
+kernel modules.
+
+Link: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=1050582
+Signed-off-by: Martin Nybo Andersen <tweek@tweek.dk>
+Signed-off-by: Masahiro Yamada <masahiroy@kernel.org>
+Cc: Christoph Biedl <linux-kernel.bfrz@manchmal.in-ulm.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ scripts/Makefile.modinst |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/scripts/Makefile.modinst
++++ b/scripts/Makefile.modinst
+@@ -99,7 +99,7 @@ endif
+ quiet_cmd_gzip = GZIP    $@
+       cmd_gzip = $(KGZIP) -n -f $<
+ quiet_cmd_xz = XZ      $@
+-      cmd_xz = $(XZ) --lzma2=dict=2MiB -f $<
++      cmd_xz = $(XZ) --check=crc32 --lzma2=dict=1MiB -f $<
+ quiet_cmd_zstd = ZSTD    $@
+       cmd_zstd = $(ZSTD) -T0 --rm -f -q $<
diff --git a/queue-6.1/ksmbd-fix-out-of-bounds-in-parse_sec_desc.patch b/queue-6.1/ksmbd-fix-out-of-bounds-in-parse_sec_desc.patch
new file mode 100644 (file)
index 0000000..ac189fc
--- /dev/null
@@ -0,0 +1,73 @@
+From stable+bounces-200127-greg=kroah.com@vger.kernel.org Fri Dec  5 09:24:29 2025
+From: Rajani Kantha <681739313@139.com>
+Date: Fri,  5 Dec 2025 15:35:08 +0800
+Subject: ksmbd: fix out-of-bounds in parse_sec_desc()
+To: norbert@doyensec.com, linkinjeon@kernel.org, stfrench@microsoft.com
+Cc: stable@vger.kernel.org
+Message-ID: <20251205073508.4650-1-681739313@139.com>
+
+From: Namjae Jeon <linkinjeon@kernel.org>
+
+commit d6e13e19063db24f94b690159d0633aaf72a0f03 upstream.
+
+If osidoffset, gsidoffset and dacloffset could be greater than smb_ntsd
+struct size. If it is smaller, It could cause slab-out-of-bounds.
+And when validating sid, It need to check it included subauth array size.
+
+Cc: stable@vger.kernel.org
+Reported-by: Norbert Szetei <norbert@doyensec.com>
+Tested-by: Norbert Szetei <norbert@doyensec.com>
+Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
+Signed-off-by: Steve French <stfrench@microsoft.com>
+Signed-off-by: Rajani Kantha <681739313@139.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/smb/server/smbacl.c |   16 ++++++++++++++++
+ 1 file changed, 16 insertions(+)
+
+--- a/fs/smb/server/smbacl.c
++++ b/fs/smb/server/smbacl.c
+@@ -815,6 +815,13 @@ static int parse_sid(struct smb_sid *psi
+               return -EINVAL;
+       }
++      if (!psid->num_subauth)
++              return 0;
++
++      if (psid->num_subauth > SID_MAX_SUB_AUTHORITIES ||
++          end_of_acl < (char *)psid + 8 + sizeof(__le32) * psid->num_subauth)
++              return -EINVAL;
++
+       return 0;
+ }
+@@ -856,6 +863,9 @@ int parse_sec_desc(struct user_namespace
+       pntsd->type = cpu_to_le16(DACL_PRESENT);
+       if (pntsd->osidoffset) {
++              if (le32_to_cpu(pntsd->osidoffset) < sizeof(struct smb_ntsd))
++                      return -EINVAL;
++
+               rc = parse_sid(owner_sid_ptr, end_of_acl);
+               if (rc) {
+                       pr_err("%s: Error %d parsing Owner SID\n", __func__, rc);
+@@ -871,6 +881,9 @@ int parse_sec_desc(struct user_namespace
+       }
+       if (pntsd->gsidoffset) {
++              if (le32_to_cpu(pntsd->gsidoffset) < sizeof(struct smb_ntsd))
++                      return -EINVAL;
++
+               rc = parse_sid(group_sid_ptr, end_of_acl);
+               if (rc) {
+                       pr_err("%s: Error %d mapping Owner SID to gid\n",
+@@ -892,6 +905,9 @@ int parse_sec_desc(struct user_namespace
+               pntsd->type |= cpu_to_le16(DACL_PROTECTED);
+       if (dacloffset) {
++              if (dacloffset < sizeof(struct smb_ntsd))
++                      return -EINVAL;
++
+               parse_dacl(user_ns, dacl_ptr, end_of_acl,
+                          owner_sid_ptr, group_sid_ptr, fattr);
+       }
diff --git a/queue-6.1/kvm-nvmx-immediately-refresh-apicv-controls-as-needed-on-nested-vm-exit.patch b/queue-6.1/kvm-nvmx-immediately-refresh-apicv-controls-as-needed-on-nested-vm-exit.patch
new file mode 100644 (file)
index 0000000..a04ab05
--- /dev/null
@@ -0,0 +1,93 @@
+From stable+bounces-204363-greg=kroah.com@vger.kernel.org Wed Dec 31 16:12:00 2025
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 31 Dec 2025 10:11:53 -0500
+Subject: KVM: nVMX: Immediately refresh APICv controls as needed on nested VM-Exit
+To: stable@vger.kernel.org
+Cc: Dongli Zhang <dongli.zhang@oracle.com>, Chao Gao <chao.gao@intel.com>, Sean Christopherson <seanjc@google.com>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20251231151153.3146021-1-sashal@kernel.org>
+
+From: Dongli Zhang <dongli.zhang@oracle.com>
+
+[ Upstream commit 29763138830916f46daaa50e83e7f4f907a3236b ]
+
+If an APICv status updated was pended while L2 was active, immediately
+refresh vmcs01's controls instead of pending KVM_REQ_APICV_UPDATE as
+kvm_vcpu_update_apicv() only calls into vendor code if a change is
+necessary.
+
+E.g. if APICv is inhibited, and then activated while L2 is running:
+
+  kvm_vcpu_update_apicv()
+  |
+  -> __kvm_vcpu_update_apicv()
+     |
+     -> apic->apicv_active = true
+      |
+      -> vmx_refresh_apicv_exec_ctrl()
+         |
+         -> vmx->nested.update_vmcs01_apicv_status = true
+          |
+          -> return
+
+Then L2 exits to L1:
+
+  __nested_vmx_vmexit()
+  |
+  -> kvm_make_request(KVM_REQ_APICV_UPDATE)
+
+  vcpu_enter_guest(): KVM_REQ_APICV_UPDATE
+  -> kvm_vcpu_update_apicv()
+     |
+     -> __kvm_vcpu_update_apicv()
+        |
+        -> return // because if (apic->apicv_active == activate)
+
+Reported-by: Chao Gao <chao.gao@intel.com>
+Closes: https://lore.kernel.org/all/aQ2jmnN8wUYVEawF@intel.com
+Fixes: 7c69661e225c ("KVM: nVMX: Defer APICv updates while L2 is active until L1 is active")
+Cc: stable@vger.kernel.org
+Signed-off-by: Dongli Zhang <dongli.zhang@oracle.com>
+[sean: write changelog]
+Link: https://patch.msgid.link/20251205231913.441872-3-seanjc@google.com
+Signed-off-by: Sean Christopherson <seanjc@google.com>
+[ exported vmx_refresh_apicv_exec_ctrl() and added declaration in vmx.h ]
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/x86/kvm/vmx/nested.c |    2 +-
+ arch/x86/kvm/vmx/vmx.c    |    2 +-
+ arch/x86/kvm/vmx/vmx.h    |    1 +
+ 3 files changed, 3 insertions(+), 2 deletions(-)
+
+--- a/arch/x86/kvm/vmx/nested.c
++++ b/arch/x86/kvm/vmx/nested.c
+@@ -4847,7 +4847,7 @@ void nested_vmx_vmexit(struct kvm_vcpu *
+       if (vmx->nested.update_vmcs01_apicv_status) {
+               vmx->nested.update_vmcs01_apicv_status = false;
+-              kvm_make_request(KVM_REQ_APICV_UPDATE, vcpu);
++              vmx_refresh_apicv_exec_ctrl(vcpu);
+       }
+       if (vmx->nested.update_vmcs01_hwapic_isr) {
+--- a/arch/x86/kvm/vmx/vmx.c
++++ b/arch/x86/kvm/vmx/vmx.c
+@@ -4387,7 +4387,7 @@ static u32 vmx_vmexit_ctrl(void)
+               ~(VM_EXIT_LOAD_IA32_PERF_GLOBAL_CTRL | VM_EXIT_LOAD_IA32_EFER);
+ }
+-static void vmx_refresh_apicv_exec_ctrl(struct kvm_vcpu *vcpu)
++void vmx_refresh_apicv_exec_ctrl(struct kvm_vcpu *vcpu)
+ {
+       struct vcpu_vmx *vmx = to_vmx(vcpu);
+--- a/arch/x86/kvm/vmx/vmx.h
++++ b/arch/x86/kvm/vmx/vmx.h
+@@ -408,6 +408,7 @@ void __vmx_set_segment(struct kvm_vcpu *
+ u64 construct_eptp(struct kvm_vcpu *vcpu, hpa_t root_hpa, int root_level);
+ bool vmx_guest_inject_ac(struct kvm_vcpu *vcpu);
++void vmx_refresh_apicv_exec_ctrl(struct kvm_vcpu *vcpu);
+ void vmx_update_exception_bitmap(struct kvm_vcpu *vcpu);
+ bool vmx_nmi_blocked(struct kvm_vcpu *vcpu);
+ bool __vmx_interrupt_blocked(struct kvm_vcpu *vcpu);
diff --git a/queue-6.1/kvm-svm-don-t-skip-unrelated-instruction-if-int3-into-is-replaced.patch b/queue-6.1/kvm-svm-don-t-skip-unrelated-instruction-if-int3-into-is-replaced.patch
new file mode 100644 (file)
index 0000000..db3879c
--- /dev/null
@@ -0,0 +1,202 @@
+From stable+bounces-200323-greg=kroah.com@vger.kernel.org Mon Dec  8 07:17:34 2025
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon,  8 Dec 2025 01:17:27 -0500
+Subject: KVM: SVM: Don't skip unrelated instruction if INT3/INTO is replaced
+To: stable@vger.kernel.org
+Cc: Omar Sandoval <osandov@fb.com>, Sean Christopherson <seanjc@google.com>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20251208061727.249698-2-sashal@kernel.org>
+
+From: Omar Sandoval <osandov@fb.com>
+
+[ Upstream commit 4da3768e1820cf15cced390242d8789aed34f54d ]
+
+When re-injecting a soft interrupt from an INT3, INT0, or (select) INTn
+instruction, discard the exception and retry the instruction if the code
+stream is changed (e.g. by a different vCPU) between when the CPU
+executes the instruction and when KVM decodes the instruction to get the
+next RIP.
+
+As effectively predicted by commit 6ef88d6e36c2 ("KVM: SVM: Re-inject
+INT3/INTO instead of retrying the instruction"), failure to verify that
+the correct INTn instruction was decoded can effectively clobber guest
+state due to decoding the wrong instruction and thus specifying the
+wrong next RIP.
+
+The bug most often manifests as "Oops: int3" panics on static branch
+checks in Linux guests.  Enabling or disabling a static branch in Linux
+uses the kernel's "text poke" code patching mechanism.  To modify code
+while other CPUs may be executing that code, Linux (temporarily)
+replaces the first byte of the original instruction with an int3 (opcode
+0xcc), then patches in the new code stream except for the first byte,
+and finally replaces the int3 with the first byte of the new code
+stream.  If a CPU hits the int3, i.e. executes the code while it's being
+modified, then the guest kernel must look up the RIP to determine how to
+handle the #BP, e.g. by emulating the new instruction.  If the RIP is
+incorrect, then this lookup fails and the guest kernel panics.
+
+The bug reproduces almost instantly by hacking the guest kernel to
+repeatedly check a static branch[1] while running a drgn script[2] on
+the host to constantly swap out the memory containing the guest's TSS.
+
+[1]: https://gist.github.com/osandov/44d17c51c28c0ac998ea0334edf90b5a
+[2]: https://gist.github.com/osandov/10e45e45afa29b11e0c7209247afc00b
+
+Fixes: 6ef88d6e36c2 ("KVM: SVM: Re-inject INT3/INTO instead of retrying the instruction")
+Cc: stable@vger.kernel.org
+Co-developed-by: Sean Christopherson <seanjc@google.com>
+Signed-off-by: Omar Sandoval <osandov@fb.com>
+Link: https://patch.msgid.link/1cc6dcdf36e3add7ee7c8d90ad58414eeb6c3d34.1762278762.git.osandov@fb.com
+Signed-off-by: Sean Christopherson <seanjc@google.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/x86/include/asm/kvm_host.h |    9 +++++++++
+ arch/x86/kvm/svm/svm.c          |   24 +++++++++++++-----------
+ arch/x86/kvm/x86.c              |   21 +++++++++++++++++++++
+ 3 files changed, 43 insertions(+), 11 deletions(-)
+
+--- a/arch/x86/include/asm/kvm_host.h
++++ b/arch/x86/include/asm/kvm_host.h
+@@ -1827,6 +1827,11 @@ u64 vcpu_tsc_khz(struct kvm_vcpu *vcpu);
+  *                         the gfn, i.e. retrying the instruction will hit a
+  *                         !PRESENT fault, which results in a new shadow page
+  *                         and sends KVM back to square one.
++ *
++ * EMULTYPE_SKIP_SOFT_INT - Set in combination with EMULTYPE_SKIP to only skip
++ *                          an instruction if it could generate a given software
++ *                          interrupt, which must be encoded via
++ *                          EMULTYPE_SET_SOFT_INT_VECTOR().
+  */
+ #define EMULTYPE_NO_DECODE        (1 << 0)
+ #define EMULTYPE_TRAP_UD          (1 << 1)
+@@ -1837,6 +1842,10 @@ u64 vcpu_tsc_khz(struct kvm_vcpu *vcpu);
+ #define EMULTYPE_PF               (1 << 6)
+ #define EMULTYPE_COMPLETE_USER_EXIT (1 << 7)
+ #define EMULTYPE_WRITE_PF_TO_SP           (1 << 8)
++#define EMULTYPE_SKIP_SOFT_INT            (1 << 9)
++
++#define EMULTYPE_SET_SOFT_INT_VECTOR(v)       ((u32)((v) & 0xff) << 16)
++#define EMULTYPE_GET_SOFT_INT_VECTOR(e)       (((e) >> 16) & 0xff)
+ int kvm_emulate_instruction(struct kvm_vcpu *vcpu, int emulation_type);
+ int kvm_emulate_instruction_from_buffer(struct kvm_vcpu *vcpu,
+--- a/arch/x86/kvm/svm/svm.c
++++ b/arch/x86/kvm/svm/svm.c
+@@ -370,6 +370,7 @@ static bool svm_can_emulate_instruction(
+                                       void *insn, int insn_len);
+ static int __svm_skip_emulated_instruction(struct kvm_vcpu *vcpu,
++                                         int emul_type,
+                                          bool commit_side_effects)
+ {
+       struct vcpu_svm *svm = to_svm(vcpu);
+@@ -399,7 +400,7 @@ static int __svm_skip_emulated_instructi
+               if (unlikely(!commit_side_effects))
+                       old_rflags = svm->vmcb->save.rflags;
+-              if (!kvm_emulate_instruction(vcpu, EMULTYPE_SKIP))
++              if (!kvm_emulate_instruction(vcpu, emul_type))
+                       return 0;
+               if (unlikely(!commit_side_effects))
+@@ -417,11 +418,13 @@ done:
+ static int svm_skip_emulated_instruction(struct kvm_vcpu *vcpu)
+ {
+-      return __svm_skip_emulated_instruction(vcpu, true);
++      return __svm_skip_emulated_instruction(vcpu, EMULTYPE_SKIP, true);
+ }
+-static int svm_update_soft_interrupt_rip(struct kvm_vcpu *vcpu)
++static int svm_update_soft_interrupt_rip(struct kvm_vcpu *vcpu, u8 vector)
+ {
++      const int emul_type = EMULTYPE_SKIP | EMULTYPE_SKIP_SOFT_INT |
++                            EMULTYPE_SET_SOFT_INT_VECTOR(vector);
+       unsigned long rip, old_rip = kvm_rip_read(vcpu);
+       struct vcpu_svm *svm = to_svm(vcpu);
+@@ -437,7 +440,7 @@ static int svm_update_soft_interrupt_rip
+        * in use, the skip must not commit any side effects such as clearing
+        * the interrupt shadow or RFLAGS.RF.
+        */
+-      if (!__svm_skip_emulated_instruction(vcpu, !nrips))
++      if (!__svm_skip_emulated_instruction(vcpu, emul_type, !nrips))
+               return -EIO;
+       rip = kvm_rip_read(vcpu);
+@@ -473,7 +476,7 @@ static void svm_inject_exception(struct
+       kvm_deliver_exception_payload(vcpu, ex);
+       if (kvm_exception_is_soft(ex->vector) &&
+-          svm_update_soft_interrupt_rip(vcpu))
++          svm_update_soft_interrupt_rip(vcpu, ex->vector))
+               return;
+       svm->vmcb->control.event_inj = ex->vector
+@@ -3524,11 +3527,12 @@ static void svm_inject_nmi(struct kvm_vc
+ static void svm_inject_irq(struct kvm_vcpu *vcpu, bool reinjected)
+ {
++      struct kvm_queued_interrupt *intr = &vcpu->arch.interrupt;
+       struct vcpu_svm *svm = to_svm(vcpu);
+       u32 type;
+-      if (vcpu->arch.interrupt.soft) {
+-              if (svm_update_soft_interrupt_rip(vcpu))
++      if (intr->soft) {
++              if (svm_update_soft_interrupt_rip(vcpu, intr->nr))
+                       return;
+               type = SVM_EVTINJ_TYPE_SOFT;
+@@ -3536,12 +3540,10 @@ static void svm_inject_irq(struct kvm_vc
+               type = SVM_EVTINJ_TYPE_INTR;
+       }
+-      trace_kvm_inj_virq(vcpu->arch.interrupt.nr,
+-                         vcpu->arch.interrupt.soft, reinjected);
++      trace_kvm_inj_virq(intr->nr, intr->soft, reinjected);
+       ++vcpu->stat.irq_injections;
+-      svm->vmcb->control.event_inj = vcpu->arch.interrupt.nr |
+-                                     SVM_EVTINJ_VALID | type;
++      svm->vmcb->control.event_inj = intr->nr | SVM_EVTINJ_VALID | type;
+ }
+ void svm_complete_interrupt_delivery(struct kvm_vcpu *vcpu, int delivery_mode,
+--- a/arch/x86/kvm/x86.c
++++ b/arch/x86/kvm/x86.c
+@@ -8840,6 +8840,23 @@ static bool is_vmware_backdoor_opcode(st
+       return false;
+ }
++static bool is_soft_int_instruction(struct x86_emulate_ctxt *ctxt,
++                                  int emulation_type)
++{
++      u8 vector = EMULTYPE_GET_SOFT_INT_VECTOR(emulation_type);
++
++      switch (ctxt->b) {
++      case 0xcc:
++              return vector == BP_VECTOR;
++      case 0xcd:
++              return vector == ctxt->src.val;
++      case 0xce:
++              return vector == OF_VECTOR;
++      default:
++              return false;
++      }
++}
++
+ /*
+  * Decode an instruction for emulation.  The caller is responsible for handling
+  * code breakpoints.  Note, manually detecting code breakpoints is unnecessary
+@@ -8930,6 +8947,10 @@ int x86_emulate_instruction(struct kvm_v
+        * injecting single-step #DBs.
+        */
+       if (emulation_type & EMULTYPE_SKIP) {
++              if (emulation_type & EMULTYPE_SKIP_SOFT_INT &&
++                  !is_soft_int_instruction(ctxt, emulation_type))
++                      return 0;
++
+               if (ctxt->mode != X86EMUL_MODE_PROT64)
+                       ctxt->eip = (u32)ctxt->_eip;
+               else
diff --git a/queue-6.1/kvm-x86-mmu-use-emultype-flag-to-track-write-pfs-to-shadow-pages.patch b/queue-6.1/kvm-x86-mmu-use-emultype-flag-to-track-write-pfs-to-shadow-pages.patch
new file mode 100644 (file)
index 0000000..81e1352
--- /dev/null
@@ -0,0 +1,230 @@
+From stable+bounces-200322-greg=kroah.com@vger.kernel.org Mon Dec  8 07:17:38 2025
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon,  8 Dec 2025 01:17:26 -0500
+Subject: KVM: x86/mmu: Use EMULTYPE flag to track write #PFs to shadow pages
+To: stable@vger.kernel.org
+Cc: Sean Christopherson <seanjc@google.com>, Paolo Bonzini <pbonzini@redhat.com>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20251208061727.249698-1-sashal@kernel.org>
+
+From: Sean Christopherson <seanjc@google.com>
+
+[ Upstream commit 258d985f6eb360c9c7aacd025d0dbc080a59423f ]
+
+Use a new EMULTYPE flag, EMULTYPE_WRITE_PF_TO_SP, to track page faults
+on self-changing writes to shadowed page tables instead of propagating
+that information to the emulator via a semi-persistent vCPU flag.  Using
+a flag in "struct kvm_vcpu_arch" is confusing, especially as implemented,
+as it's not at all obvious that clearing the flag only when emulation
+actually occurs is correct.
+
+E.g. if KVM sets the flag and then retries the fault without ever getting
+to the emulator, the flag will be left set for future calls into the
+emulator.  But because the flag is consumed if and only if both
+EMULTYPE_PF and EMULTYPE_ALLOW_RETRY_PF are set, and because
+EMULTYPE_ALLOW_RETRY_PF is deliberately not set for direct MMUs, emulated
+MMIO, or while L2 is active, KVM avoids false positives on a stale flag
+since FNAME(page_fault) is guaranteed to be run and refresh the flag
+before it's ultimately consumed by the tail end of reexecute_instruction().
+
+Signed-off-by: Sean Christopherson <seanjc@google.com>
+Message-Id: <20230202182817.407394-2-seanjc@google.com>
+Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
+Stable-dep-of: 4da3768e1820 ("KVM: SVM: Don't skip unrelated instruction if INT3/INTO is replaced")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/x86/include/asm/kvm_host.h |   37 ++++++++++++++++++++-----------------
+ arch/x86/kvm/mmu/mmu.c          |    5 +++--
+ arch/x86/kvm/mmu/mmu_internal.h |   12 +++++++++++-
+ arch/x86/kvm/mmu/paging_tmpl.h  |    4 +---
+ arch/x86/kvm/x86.c              |   15 ++-------------
+ 5 files changed, 37 insertions(+), 36 deletions(-)
+
+--- a/arch/x86/include/asm/kvm_host.h
++++ b/arch/x86/include/asm/kvm_host.h
+@@ -890,23 +890,6 @@ struct kvm_vcpu_arch {
+       u64 msr_kvm_poll_control;
+-      /*
+-       * Indicates the guest is trying to write a gfn that contains one or
+-       * more of the PTEs used to translate the write itself, i.e. the access
+-       * is changing its own translation in the guest page tables.  KVM exits
+-       * to userspace if emulation of the faulting instruction fails and this
+-       * flag is set, as KVM cannot make forward progress.
+-       *
+-       * If emulation fails for a write to guest page tables, KVM unprotects
+-       * (zaps) the shadow page for the target gfn and resumes the guest to
+-       * retry the non-emulatable instruction (on hardware).  Unprotecting the
+-       * gfn doesn't allow forward progress for a self-changing access because
+-       * doing so also zaps the translation for the gfn, i.e. retrying the
+-       * instruction will hit a !PRESENT fault, which results in a new shadow
+-       * page and sends KVM back to square one.
+-       */
+-      bool write_fault_to_shadow_pgtable;
+-
+       /* set at EPT violation at this point */
+       unsigned long exit_qualification;
+@@ -1825,6 +1808,25 @@ u64 vcpu_tsc_khz(struct kvm_vcpu *vcpu);
+  * EMULTYPE_COMPLETE_USER_EXIT - Set when the emulator should update interruptibility
+  *                             state and inject single-step #DBs after skipping
+  *                             an instruction (after completing userspace I/O).
++ *
++ * EMULTYPE_WRITE_PF_TO_SP - Set when emulating an intercepted page fault that
++ *                         is attempting to write a gfn that contains one or
++ *                         more of the PTEs used to translate the write itself,
++ *                         and the owning page table is being shadowed by KVM.
++ *                         If emulation of the faulting instruction fails and
++ *                         this flag is set, KVM will exit to userspace instead
++ *                         of retrying emulation as KVM cannot make forward
++ *                         progress.
++ *
++ *                         If emulation fails for a write to guest page tables,
++ *                         KVM unprotects (zaps) the shadow page for the target
++ *                         gfn and resumes the guest to retry the non-emulatable
++ *                         instruction (on hardware).  Unprotecting the gfn
++ *                         doesn't allow forward progress for a self-changing
++ *                         access because doing so also zaps the translation for
++ *                         the gfn, i.e. retrying the instruction will hit a
++ *                         !PRESENT fault, which results in a new shadow page
++ *                         and sends KVM back to square one.
+  */
+ #define EMULTYPE_NO_DECODE        (1 << 0)
+ #define EMULTYPE_TRAP_UD          (1 << 1)
+@@ -1834,6 +1836,7 @@ u64 vcpu_tsc_khz(struct kvm_vcpu *vcpu);
+ #define EMULTYPE_VMWARE_GP        (1 << 5)
+ #define EMULTYPE_PF               (1 << 6)
+ #define EMULTYPE_COMPLETE_USER_EXIT (1 << 7)
++#define EMULTYPE_WRITE_PF_TO_SP           (1 << 8)
+ int kvm_emulate_instruction(struct kvm_vcpu *vcpu, int emulation_type);
+ int kvm_emulate_instruction_from_buffer(struct kvm_vcpu *vcpu,
+--- a/arch/x86/kvm/mmu/mmu.c
++++ b/arch/x86/kvm/mmu/mmu.c
+@@ -4152,7 +4152,7 @@ void kvm_arch_async_page_ready(struct kv
+             work->arch.cr3 != kvm_mmu_get_guest_pgd(vcpu, vcpu->arch.mmu))
+               return;
+-      kvm_mmu_do_page_fault(vcpu, work->cr2_or_gpa, 0, true);
++      kvm_mmu_do_page_fault(vcpu, work->cr2_or_gpa, 0, true, NULL);
+ }
+ static int kvm_faultin_pfn(struct kvm_vcpu *vcpu, struct kvm_page_fault *fault)
+@@ -5580,7 +5580,8 @@ int noinline kvm_mmu_page_fault(struct k
+       if (r == RET_PF_INVALID) {
+               r = kvm_mmu_do_page_fault(vcpu, cr2_or_gpa,
+-                                        lower_32_bits(error_code), false);
++                                        lower_32_bits(error_code), false,
++                                        &emulation_type);
+               if (KVM_BUG_ON(r == RET_PF_INVALID, vcpu->kvm))
+                       return -EIO;
+       }
+--- a/arch/x86/kvm/mmu/mmu_internal.h
++++ b/arch/x86/kvm/mmu/mmu_internal.h
+@@ -223,6 +223,13 @@ struct kvm_page_fault {
+       kvm_pfn_t pfn;
+       hva_t hva;
+       bool map_writable;
++
++      /*
++       * Indicates the guest is trying to write a gfn that contains one or
++       * more of the PTEs used to translate the write itself, i.e. the access
++       * is changing its own translation in the guest page tables.
++       */
++      bool write_fault_to_shadow_pgtable;
+ };
+ int kvm_tdp_page_fault(struct kvm_vcpu *vcpu, struct kvm_page_fault *fault);
+@@ -256,7 +263,7 @@ enum {
+ };
+ static inline int kvm_mmu_do_page_fault(struct kvm_vcpu *vcpu, gpa_t cr2_or_gpa,
+-                                      u32 err, bool prefetch)
++                                      u32 err, bool prefetch, int *emulation_type)
+ {
+       struct kvm_page_fault fault = {
+               .addr = cr2_or_gpa,
+@@ -290,6 +297,9 @@ static inline int kvm_mmu_do_page_fault(
+       else
+               r = vcpu->arch.mmu->page_fault(vcpu, &fault);
++      if (fault.write_fault_to_shadow_pgtable && emulation_type)
++              *emulation_type |= EMULTYPE_WRITE_PF_TO_SP;
++
+       /*
+        * Similar to above, prefetch faults aren't truly spurious, and the
+        * async #PF path doesn't do emulation.  Do count faults that are fixed
+--- a/arch/x86/kvm/mmu/paging_tmpl.h
++++ b/arch/x86/kvm/mmu/paging_tmpl.h
+@@ -829,10 +829,8 @@ static int FNAME(page_fault)(struct kvm_
+       if (r)
+               return r;
+-      vcpu->arch.write_fault_to_shadow_pgtable = false;
+-
+       is_self_change_mapping = FNAME(is_self_change_mapping)(vcpu,
+-            &walker, fault->user, &vcpu->arch.write_fault_to_shadow_pgtable);
++            &walker, fault->user, &fault->write_fault_to_shadow_pgtable);
+       if (is_self_change_mapping)
+               fault->max_level = PG_LEVEL_4K;
+--- a/arch/x86/kvm/x86.c
++++ b/arch/x86/kvm/x86.c
+@@ -8532,7 +8532,6 @@ static int handle_emulation_failure(stru
+ }
+ static bool reexecute_instruction(struct kvm_vcpu *vcpu, gpa_t cr2_or_gpa,
+-                                bool write_fault_to_shadow_pgtable,
+                                 int emulation_type)
+ {
+       gpa_t gpa = cr2_or_gpa;
+@@ -8603,7 +8602,7 @@ static bool reexecute_instruction(struct
+        * be fixed by unprotecting shadow page and it should
+        * be reported to userspace.
+        */
+-      return !write_fault_to_shadow_pgtable;
++      return !(emulation_type & EMULTYPE_WRITE_PF_TO_SP);
+ }
+ static bool retry_instruction(struct x86_emulate_ctxt *ctxt,
+@@ -8874,20 +8873,12 @@ int x86_emulate_instruction(struct kvm_v
+       int r;
+       struct x86_emulate_ctxt *ctxt = vcpu->arch.emulate_ctxt;
+       bool writeback = true;
+-      bool write_fault_to_spt;
+       if (unlikely(!kvm_can_emulate_insn(vcpu, emulation_type, insn, insn_len)))
+               return 1;
+       vcpu->arch.l1tf_flush_l1d = true;
+-      /*
+-       * Clear write_fault_to_shadow_pgtable here to ensure it is
+-       * never reused.
+-       */
+-      write_fault_to_spt = vcpu->arch.write_fault_to_shadow_pgtable;
+-      vcpu->arch.write_fault_to_shadow_pgtable = false;
+-
+       if (!(emulation_type & EMULTYPE_NO_DECODE)) {
+               kvm_clear_exception_queue(vcpu);
+@@ -8908,7 +8899,6 @@ int x86_emulate_instruction(struct kvm_v
+                               return 1;
+                       }
+                       if (reexecute_instruction(vcpu, cr2_or_gpa,
+-                                                write_fault_to_spt,
+                                                 emulation_type))
+                               return 1;
+@@ -8994,8 +8984,7 @@ restart:
+               return 1;
+       if (r == EMULATION_FAILED) {
+-              if (reexecute_instruction(vcpu, cr2_or_gpa, write_fault_to_spt,
+-                                      emulation_type))
++              if (reexecute_instruction(vcpu, cr2_or_gpa, emulation_type))
+                       return 1;
+               return handle_emulation_failure(vcpu, emulation_type);
diff --git a/queue-6.1/lockd-fix-vfs_test_lock-calls.patch b/queue-6.1/lockd-fix-vfs_test_lock-calls.patch
new file mode 100644 (file)
index 0000000..f8f3f67
--- /dev/null
@@ -0,0 +1,182 @@
+From stable+bounces-206049-greg=kroah.com@vger.kernel.org Wed Jan  7 00:08:23 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue,  6 Jan 2026 18:08:16 -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: <20260106230816.3448854-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 c.flc_* field accesses to direct fl_* fields ]
+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          |   13 +++++++++++--
+ 4 files changed, 25 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
+@@ -604,7 +604,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)
+@@ -614,22 +620,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
+@@ -2140,13 +2140,22 @@ 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);
+       posix_test_lock(filp, fl);
diff --git a/queue-6.1/media-amphion-add-a-frame-flush-mode-for-decoder.patch b/queue-6.1/media-amphion-add-a-frame-flush-mode-for-decoder.patch
new file mode 100644 (file)
index 0000000..6511338
--- /dev/null
@@ -0,0 +1,64 @@
+From stable+bounces-204943-greg=kroah.com@vger.kernel.org Mon Jan  5 22:33:57 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon,  5 Jan 2026 16:32:22 -0500
+Subject: media: amphion: Add a frame flush mode for decoder
+To: stable@vger.kernel.org
+Cc: Ming Qian <ming.qian@oss.nxp.com>, Nicolas Dufresne <nicolas.dufresne@collabora.com>, Sebastian Fricke <sebastian.fricke@collabora.com>, Hans Verkuil <hverkuil@xs4all.nl>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260105213224.2805653-1-sashal@kernel.org>
+
+From: Ming Qian <ming.qian@oss.nxp.com>
+
+[ Upstream commit 9ea16ba6eaf93f25f61855751f71e2e701709ddf ]
+
+By default the amphion decoder will pre-parse 3 frames before starting
+to decode the first frame. Alternatively, a block of flush padding data
+can be appended to the frame, which will ensure that the decoder can
+start decoding immediately after parsing the flush padding data, thus
+potentially reducing decoding latency.
+
+This mode was previously only enabled, when the display delay was set to
+0. Allow the user to manually toggle the use of that mode via a module
+parameter called low_latency, which enables the mode without
+changing the display order.
+
+Signed-off-by: Ming Qian <ming.qian@oss.nxp.com>
+Reviewed-by: Nicolas Dufresne <nicolas.dufresne@collabora.com>
+Signed-off-by: Sebastian Fricke <sebastian.fricke@collabora.com>
+Signed-off-by: Hans Verkuil <hverkuil@xs4all.nl>
+Stable-dep-of: 634c2cd17bd0 ("media: amphion: Remove vpu_vb_is_codecconfig")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/media/platform/amphion/vpu_malone.c |   14 +++++++++++++-
+ 1 file changed, 13 insertions(+), 1 deletion(-)
+
+--- a/drivers/media/platform/amphion/vpu_malone.c
++++ b/drivers/media/platform/amphion/vpu_malone.c
+@@ -27,6 +27,10 @@
+ #include "vpu_imx8q.h"
+ #include "vpu_malone.h"
++static bool low_latency;
++module_param(low_latency, bool, 0644);
++MODULE_PARM_DESC(low_latency, "Set low latency frame flush mode: 0 (disable) or 1 (enable)");
++
+ #define CMD_SIZE                      25600
+ #define MSG_SIZE                      25600
+ #define CODEC_SIZE                    0x1000
+@@ -1527,7 +1531,15 @@ static int vpu_malone_input_frame_data(s
+       vpu_malone_update_wptr(str_buf, wptr);
+-      if (disp_imm && !vpu_vb_is_codecconfig(vbuf)) {
++      /*
++       * Enable the low latency flush mode if display delay is set to 0
++       * or the low latency frame flush mode if it is set to 1.
++       * The low latency flush mode requires some padding data to be appended to each frame,
++       * but there must not be any padding data between the sequence header and the frame.
++       * This module is currently only supported for the H264 and HEVC formats,
++       * for other formats, vpu_malone_add_scode() will return 0.
++       */
++      if ((disp_imm || low_latency) && !vpu_vb_is_codecconfig(vbuf)) {
+               ret = vpu_malone_add_scode(inst->core->iface,
+                                          inst->id,
+                                          &inst->stream_buffer,
diff --git a/queue-6.1/media-amphion-make-some-vpu_v4l2-functions-static.patch b/queue-6.1/media-amphion-make-some-vpu_v4l2-functions-static.patch
new file mode 100644 (file)
index 0000000..f2cefed
--- /dev/null
@@ -0,0 +1,98 @@
+From stable+bounces-204944-greg=kroah.com@vger.kernel.org Mon Jan  5 22:34:00 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon,  5 Jan 2026 16:32:23 -0500
+Subject: media: amphion: Make some vpu_v4l2 functions static
+To: stable@vger.kernel.org
+Cc: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>, Ming Qian <ming.qian@oss.nxp.com>, Hans Verkuil <hverkuil+cisco@kernel.org>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260105213224.2805653-2-sashal@kernel.org>
+
+From: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
+
+[ Upstream commit 5d1e54bb4dc6741284a3ed587e994308ddee2f16 ]
+
+Some functions defined in vpu_v4l2.c are never used outside of that
+compilation unit. Make them static.
+
+Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
+Reviewed-by: Ming Qian <ming.qian@oss.nxp.com>
+Signed-off-by: Hans Verkuil <hverkuil+cisco@kernel.org>
+Stable-dep-of: 634c2cd17bd0 ("media: amphion: Remove vpu_vb_is_codecconfig")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/media/platform/amphion/vpu_v4l2.c |   12 +++++++++---
+ drivers/media/platform/amphion/vpu_v4l2.h |    8 --------
+ 2 files changed, 9 insertions(+), 11 deletions(-)
+
+--- a/drivers/media/platform/amphion/vpu_v4l2.c
++++ b/drivers/media/platform/amphion/vpu_v4l2.c
+@@ -24,6 +24,11 @@
+ #include "vpu_msgs.h"
+ #include "vpu_helpers.h"
++static char *vpu_type_name(u32 type)
++{
++      return V4L2_TYPE_IS_OUTPUT(type) ? "output" : "capture";
++}
++
+ void vpu_inst_lock(struct vpu_inst *inst)
+ {
+       mutex_lock(&inst->lock);
+@@ -42,7 +47,7 @@ dma_addr_t vpu_get_vb_phy_addr(struct vb
+                       vb->planes[plane_no].data_offset;
+ }
+-unsigned int vpu_get_vb_length(struct vb2_buffer *vb, u32 plane_no)
++static unsigned int vpu_get_vb_length(struct vb2_buffer *vb, u32 plane_no)
+ {
+       if (plane_no >= vb->num_planes)
+               return 0;
+@@ -74,7 +79,7 @@ void vpu_v4l2_set_error(struct vpu_inst
+       vpu_inst_unlock(inst);
+ }
+-int vpu_notify_eos(struct vpu_inst *inst)
++static int vpu_notify_eos(struct vpu_inst *inst)
+ {
+       static const struct v4l2_event ev = {
+               .id = 0,
+@@ -461,7 +466,8 @@ static void vpu_vb2_buf_finish(struct vb
+               call_void_vop(inst, on_queue_empty, q->type);
+ }
+-void vpu_vb2_buffers_return(struct vpu_inst *inst, unsigned int type, enum vb2_buffer_state state)
++static void vpu_vb2_buffers_return(struct vpu_inst *inst, unsigned int type,
++                                 enum vb2_buffer_state state)
+ {
+       struct vb2_v4l2_buffer *buf;
+--- a/drivers/media/platform/amphion/vpu_v4l2.h
++++ b/drivers/media/platform/amphion/vpu_v4l2.h
+@@ -24,15 +24,12 @@ void vpu_skip_frame(struct vpu_inst *ins
+ struct vb2_v4l2_buffer *vpu_find_buf_by_sequence(struct vpu_inst *inst, u32 type, u32 sequence);
+ struct vb2_v4l2_buffer *vpu_find_buf_by_idx(struct vpu_inst *inst, u32 type, u32 idx);
+ void vpu_v4l2_set_error(struct vpu_inst *inst);
+-int vpu_notify_eos(struct vpu_inst *inst);
+ int vpu_notify_source_change(struct vpu_inst *inst);
+ int vpu_set_last_buffer_dequeued(struct vpu_inst *inst, bool eos);
+-void vpu_vb2_buffers_return(struct vpu_inst *inst, unsigned int type, enum vb2_buffer_state state);
+ int vpu_get_num_buffers(struct vpu_inst *inst, u32 type);
+ bool vpu_is_source_empty(struct vpu_inst *inst);
+ dma_addr_t vpu_get_vb_phy_addr(struct vb2_buffer *vb, u32 plane_no);
+-unsigned int vpu_get_vb_length(struct vb2_buffer *vb, u32 plane_no);
+ static inline struct vpu_format *vpu_get_format(struct vpu_inst *inst, u32 type)
+ {
+       if (V4L2_TYPE_IS_OUTPUT(type))
+@@ -41,11 +38,6 @@ static inline struct vpu_format *vpu_get
+               return &inst->cap_format;
+ }
+-static inline char *vpu_type_name(u32 type)
+-{
+-      return V4L2_TYPE_IS_OUTPUT(type) ? "output" : "capture";
+-}
+-
+ static inline int vpu_vb_is_codecconfig(struct vb2_v4l2_buffer *vbuf)
+ {
+ #ifdef V4L2_BUF_FLAG_CODECCONFIG
diff --git a/queue-6.1/media-amphion-remove-vpu_vb_is_codecconfig.patch b/queue-6.1/media-amphion-remove-vpu_vb_is_codecconfig.patch
new file mode 100644 (file)
index 0000000..2c78d83
--- /dev/null
@@ -0,0 +1,142 @@
+From stable+bounces-204945-greg=kroah.com@vger.kernel.org Mon Jan  5 22:34:06 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon,  5 Jan 2026 16:32:24 -0500
+Subject: media: amphion: Remove vpu_vb_is_codecconfig
+To: stable@vger.kernel.org
+Cc: Ming Qian <ming.qian@oss.nxp.com>, Nicolas Dufresne <nicolas.dufresne@collabora.com>, Hans Verkuil <hverkuil+cisco@kernel.org>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260105213224.2805653-3-sashal@kernel.org>
+
+From: Ming Qian <ming.qian@oss.nxp.com>
+
+[ Upstream commit 634c2cd17bd021487c57b95973bddb14be8002ff ]
+
+Currently the function vpu_vb_is_codecconfig() always returns 0.
+Delete it and its related code.
+
+Fixes: 3cd084519c6f ("media: amphion: add vpu v4l2 m2m support")
+Cc: stable@vger.kernel.org
+Signed-off-by: Ming Qian <ming.qian@oss.nxp.com>
+Signed-off-by: Nicolas Dufresne <nicolas.dufresne@collabora.com>
+Signed-off-by: Hans Verkuil <hverkuil+cisco@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/media/platform/amphion/vpu_malone.c |   23 +++--------------------
+ drivers/media/platform/amphion/vpu_v4l2.c   |   10 ----------
+ drivers/media/platform/amphion/vpu_v4l2.h   |   10 ----------
+ 3 files changed, 3 insertions(+), 40 deletions(-)
+
+--- a/drivers/media/platform/amphion/vpu_malone.c
++++ b/drivers/media/platform/amphion/vpu_malone.c
+@@ -1295,22 +1295,18 @@ static int vpu_malone_insert_scode_vc1_g
+ {
+       if (!scode->inst->total_input_count)
+               return 0;
+-      if (vpu_vb_is_codecconfig(to_vb2_v4l2_buffer(scode->vb)))
+-              scode->need_data = 0;
+       return 0;
+ }
+ static int vpu_malone_insert_scode_vc1_g_pic(struct malone_scode_t *scode)
+ {
+-      struct vb2_v4l2_buffer *vbuf;
+       u8 nal_hdr[MALONE_VC1_NAL_HEADER_LEN];
+       u32 *data = NULL;
+       int ret;
+-      vbuf = to_vb2_v4l2_buffer(scode->vb);
+       data = vb2_plane_vaddr(scode->vb, 0);
+-      if (scode->inst->total_input_count == 0 || vpu_vb_is_codecconfig(vbuf))
++      if (scode->inst->total_input_count == 0)
+               return 0;
+       if (MALONE_VC1_CONTAIN_NAL(*data))
+               return 0;
+@@ -1331,8 +1327,6 @@ static int vpu_malone_insert_scode_vc1_l
+       int size = 0;
+       u8 rcv_seqhdr[MALONE_VC1_RCV_SEQ_HEADER_LEN];
+-      if (vpu_vb_is_codecconfig(to_vb2_v4l2_buffer(scode->vb)))
+-              scode->need_data = 0;
+       if (scode->inst->total_input_count)
+               return 0;
+       scode->need_data = 0;
+@@ -1503,7 +1497,7 @@ static int vpu_malone_input_frame_data(s
+       scode.vb = vb;
+       scode.wptr = wptr;
+       scode.need_data = 1;
+-      if (vbuf->sequence == 0 || vpu_vb_is_codecconfig(vbuf))
++      if (vbuf->sequence == 0)
+               ret = vpu_malone_insert_scode(&scode, SCODE_SEQUENCE);
+       if (ret < 0)
+@@ -1539,7 +1533,7 @@ static int vpu_malone_input_frame_data(s
+        * This module is currently only supported for the H264 and HEVC formats,
+        * for other formats, vpu_malone_add_scode() will return 0.
+        */
+-      if ((disp_imm || low_latency) && !vpu_vb_is_codecconfig(vbuf)) {
++      if (disp_imm || low_latency) {
+               ret = vpu_malone_add_scode(inst->core->iface,
+                                          inst->id,
+                                          &inst->stream_buffer,
+@@ -1586,7 +1580,6 @@ int vpu_malone_input_frame(struct vpu_sh
+                          struct vpu_inst *inst, struct vb2_buffer *vb)
+ {
+       struct vpu_dec_ctrl *hc = shared->priv;
+-      struct vb2_v4l2_buffer *vbuf;
+       struct vpu_malone_str_buffer __iomem *str_buf = hc->str_buf[inst->id];
+       u32 disp_imm = hc->codec_param[inst->id].disp_imm;
+       u32 size;
+@@ -1600,16 +1593,6 @@ int vpu_malone_input_frame(struct vpu_sh
+               return ret;
+       size = ret;
+-      /*
+-       * if buffer only contain codec data, and the timestamp is invalid,
+-       * don't put the invalid timestamp to resync
+-       * merge the data to next frame
+-       */
+-      vbuf = to_vb2_v4l2_buffer(vb);
+-      if (vpu_vb_is_codecconfig(vbuf)) {
+-              inst->extra_size += size;
+-              return 0;
+-      }
+       if (inst->extra_size) {
+               size += inst->extra_size;
+               inst->extra_size = 0;
+--- a/drivers/media/platform/amphion/vpu_v4l2.c
++++ b/drivers/media/platform/amphion/vpu_v4l2.c
+@@ -257,16 +257,6 @@ struct vb2_v4l2_buffer *vpu_next_src_buf
+       if (!src_buf || vpu_get_buffer_state(src_buf) == VPU_BUF_STATE_IDLE)
+               return NULL;
+-      while (vpu_vb_is_codecconfig(src_buf)) {
+-              v4l2_m2m_src_buf_remove(inst->fh.m2m_ctx);
+-              vpu_set_buffer_state(src_buf, VPU_BUF_STATE_IDLE);
+-              v4l2_m2m_buf_done(src_buf, VB2_BUF_STATE_DONE);
+-
+-              src_buf = v4l2_m2m_next_src_buf(inst->fh.m2m_ctx);
+-              if (!src_buf || vpu_get_buffer_state(src_buf) == VPU_BUF_STATE_IDLE)
+-                      return NULL;
+-      }
+-
+       return src_buf;
+ }
+--- a/drivers/media/platform/amphion/vpu_v4l2.h
++++ b/drivers/media/platform/amphion/vpu_v4l2.h
+@@ -37,14 +37,4 @@ static inline struct vpu_format *vpu_get
+       else
+               return &inst->cap_format;
+ }
+-
+-static inline int vpu_vb_is_codecconfig(struct vb2_v4l2_buffer *vbuf)
+-{
+-#ifdef V4L2_BUF_FLAG_CODECCONFIG
+-      return (vbuf->flags & V4L2_BUF_FLAG_CODECCONFIG) ? 1 : 0;
+-#else
+-      return 0;
+-#endif
+-}
+-
+ #endif
diff --git a/queue-6.1/media-mediatek-vcodec-fix-a-reference-leak-in-mtk_vcodec_fw_vpu_init.patch b/queue-6.1/media-mediatek-vcodec-fix-a-reference-leak-in-mtk_vcodec_fw_vpu_init.patch
new file mode 100644 (file)
index 0000000..0b33296
--- /dev/null
@@ -0,0 +1,47 @@
+From stable+bounces-204956-greg=kroah.com@vger.kernel.org Tue Jan  6 00:32:09 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon,  5 Jan 2026 18:31:38 -0500
+Subject: media: mediatek: vcodec: Fix a reference leak in mtk_vcodec_fw_vpu_init()
+To: stable@vger.kernel.org
+Cc: Haoxiang Li <haoxiang_li2024@163.com>, AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>, Tzung-Bi Shih <tzungbi@kernel.org>, Nicolas Dufresne <nicolas.dufresne@collabora.com>, Hans Verkuil <hverkuil+cisco@kernel.org>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260105233138.2845766-1-sashal@kernel.org>
+
+From: Haoxiang Li <haoxiang_li2024@163.com>
+
+[ Upstream commit cdd0f118ef87db8a664fb5ea366fd1766d2df1cd ]
+
+vpu_get_plat_device() increases the reference count of the returned
+platform device. However, when devm_kzalloc() fails, the reference
+is not released, causing a reference leak.
+
+Fix this by calling put_device() on fw_pdev->dev before returning
+on the error path.
+
+Fixes: e25a89f743b1 ("media: mtk-vcodec: potential dereference of null pointer")
+Cc: stable@vger.kernel.org
+Signed-off-by: Haoxiang Li <haoxiang_li2024@163.com>
+Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
+Reviewed-by: Tzung-Bi Shih <tzungbi@kernel.org>
+Signed-off-by: Nicolas Dufresne <nicolas.dufresne@collabora.com>
+Signed-off-by: Hans Verkuil <hverkuil+cisco@kernel.org>
+[ adapted file path from common/ subdirectory and adjusted devm_kzalloc target from plat_dev->dev to dev->plat_dev->dev ]
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/media/platform/mediatek/vcodec/mtk_vcodec_fw_vpu.c |    4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+--- a/drivers/media/platform/mediatek/vcodec/mtk_vcodec_fw_vpu.c
++++ b/drivers/media/platform/mediatek/vcodec/mtk_vcodec_fw_vpu.c
+@@ -94,8 +94,10 @@ struct mtk_vcodec_fw *mtk_vcodec_fw_vpu_
+       vpu_wdt_reg_handler(fw_pdev, mtk_vcodec_vpu_reset_handler, dev, rst_id);
+       fw = devm_kzalloc(&dev->plat_dev->dev, sizeof(*fw), GFP_KERNEL);
+-      if (!fw)
++      if (!fw) {
++              put_device(&fw_pdev->dev);
+               return ERR_PTR(-ENOMEM);
++      }
+       fw->type = VPU;
+       fw->ops = &mtk_vcodec_vpu_msg;
+       fw->pdev = fw_pdev;
diff --git a/queue-6.1/media-verisilicon-fix-cpu-stalls-on-g2-bus-error.patch b/queue-6.1/media-verisilicon-fix-cpu-stalls-on-g2-bus-error.patch
new file mode 100644 (file)
index 0000000..88ba344
--- /dev/null
@@ -0,0 +1,236 @@
+From stable+bounces-204883-greg=kroah.com@vger.kernel.org Mon Jan  5 18:53:26 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon,  5 Jan 2026 12:53:07 -0500
+Subject: media: verisilicon: Fix CPU stalls on G2 bus error
+To: stable@vger.kernel.org
+Cc: Nicolas Dufresne <nicolas.dufresne@collabora.com>, Benjamin Gaignard <benjamin.gaignard@collabora.com>, Hans Verkuil <hverkuil+cisco@kernel.org>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260105175307.2700019-1-sashal@kernel.org>
+
+From: Nicolas Dufresne <nicolas.dufresne@collabora.com>
+
+[ Upstream commit 19c286b755072a22a063052f530a6b1fac8a1f63 ]
+
+In some seek stress tests, we are getting IRQ from the G2 decoder where
+the dec_bus_int and the dec_e bits are high, meaning the decoder is
+still running despite the error.
+
+Fix this by reworking the IRQ handler to only finish the job once we
+have reached completion and move the software reset to when our software
+watchdog triggers.
+
+This way, we let the hardware continue on errors when it did not self
+reset and in worse case scenario the hardware timeout will
+automatically stop it. The actual error will be fixed in a follow up
+patch.
+
+Fixes: 3385c514ecc5a ("media: hantro: Convert imx8m_vpu_g2_irq to helper")
+Cc: stable@vger.kernel.org
+Reviewed-by: Benjamin Gaignard <benjamin.gaignard@collabora.com>
+Signed-off-by: Nicolas Dufresne <nicolas.dufresne@collabora.com>
+Signed-off-by: Hans Verkuil <hverkuil+cisco@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/media/platform/verisilicon/hantro_g2.c          |   84 ++++++++++++----
+ drivers/media/platform/verisilicon/hantro_g2_hevc_dec.c |    2 
+ drivers/media/platform/verisilicon/hantro_g2_regs.h     |   13 ++
+ drivers/media/platform/verisilicon/hantro_g2_vp9_dec.c  |    2 
+ drivers/media/platform/verisilicon/hantro_hw.h          |    1 
+ drivers/media/platform/verisilicon/imx8m_vpu_hw.c       |    2 
+ 6 files changed, 83 insertions(+), 21 deletions(-)
+
+--- a/drivers/media/platform/verisilicon/hantro_g2.c
++++ b/drivers/media/platform/verisilicon/hantro_g2.c
+@@ -5,40 +5,90 @@
+  * Copyright (C) 2021 Collabora Ltd, Andrzej Pietrasiewicz <andrzej.p@collabora.com>
+  */
++#include <linux/delay.h>
+ #include "hantro_hw.h"
+ #include "hantro_g2_regs.h"
+-void hantro_g2_check_idle(struct hantro_dev *vpu)
++static bool hantro_g2_active(struct hantro_ctx *ctx)
+ {
+-      int i;
++      struct hantro_dev *vpu = ctx->dev;
++      u32 status;
++
++      status = vdpu_read(vpu, G2_REG_INTERRUPT);
++
++      return (status & G2_REG_INTERRUPT_DEC_E);
++}
+-      for (i = 0; i < 3; i++) {
+-              u32 status;
++/**
++ * hantro_g2_reset:
++ * @ctx: the hantro context
++ *
++ * Emulates a reset using Hantro abort function. Failing this procedure would
++ * results in programming a running IP which leads to CPU hang.
++ *
++ * Using a hard reset procedure instead is prefferred.
++ */
++void hantro_g2_reset(struct hantro_ctx *ctx)
++{
++      struct hantro_dev *vpu = ctx->dev;
++      u32 status;
+-              /* Make sure the VPU is idle */
+-              status = vdpu_read(vpu, G2_REG_INTERRUPT);
+-              if (status & G2_REG_INTERRUPT_DEC_E) {
+-                      dev_warn(vpu->dev, "device still running, aborting");
+-                      status |= G2_REG_INTERRUPT_DEC_ABORT_E | G2_REG_INTERRUPT_DEC_IRQ_DIS;
+-                      vdpu_write(vpu, status, G2_REG_INTERRUPT);
+-              }
++      status = vdpu_read(vpu, G2_REG_INTERRUPT);
++      if (status & G2_REG_INTERRUPT_DEC_E) {
++              dev_warn_ratelimited(vpu->dev, "device still running, aborting");
++              status |= G2_REG_INTERRUPT_DEC_ABORT_E | G2_REG_INTERRUPT_DEC_IRQ_DIS;
++              vdpu_write(vpu, status, G2_REG_INTERRUPT);
++
++              do {
++                      mdelay(1);
++              } while (hantro_g2_active(ctx));
+       }
+ }
+ irqreturn_t hantro_g2_irq(int irq, void *dev_id)
+ {
+       struct hantro_dev *vpu = dev_id;
+-      enum vb2_buffer_state state;
+       u32 status;
+       status = vdpu_read(vpu, G2_REG_INTERRUPT);
+-      state = (status & G2_REG_INTERRUPT_DEC_RDY_INT) ?
+-               VB2_BUF_STATE_DONE : VB2_BUF_STATE_ERROR;
+-      vdpu_write(vpu, 0, G2_REG_INTERRUPT);
+-      vdpu_write(vpu, G2_REG_CONFIG_DEC_CLK_GATE_E, G2_REG_CONFIG);
++      if (!(status & G2_REG_INTERRUPT_DEC_IRQ))
++              return IRQ_NONE;
++
++      hantro_reg_write(vpu, &g2_dec_irq, 0);
++      hantro_reg_write(vpu, &g2_dec_int_stat, 0);
++      hantro_reg_write(vpu, &g2_clk_gate_e, 1);
++
++      if (status & G2_REG_INTERRUPT_DEC_RDY_INT) {
++              hantro_irq_done(vpu, VB2_BUF_STATE_DONE);
++              return IRQ_HANDLED;
++      }
++
++      if (status & G2_REG_INTERRUPT_DEC_ABORT_INT) {
++              /* disabled on abort, though lets be safe and handle it */
++              dev_warn_ratelimited(vpu->dev, "decode operation aborted.");
++              return IRQ_HANDLED;
++      }
++
++      if (status & G2_REG_INTERRUPT_DEC_LAST_SLICE_INT)
++              dev_warn_ratelimited(vpu->dev, "not all macroblocks were decoded.");
++
++      if (status & G2_REG_INTERRUPT_DEC_BUS_INT)
++              dev_warn_ratelimited(vpu->dev, "bus error detected.");
++
++      if (status & G2_REG_INTERRUPT_DEC_ERROR_INT)
++              dev_warn_ratelimited(vpu->dev, "decode error detected.");
+-      hantro_irq_done(vpu, state);
++      if (status & G2_REG_INTERRUPT_DEC_TIMEOUT)
++              dev_warn_ratelimited(vpu->dev, "frame decode timed out.");
++
++      /**
++       * If the decoding haven't stopped, let it continue. The hardware timeout
++       * will trigger if it is trully stuck.
++       */
++      if (status & G2_REG_INTERRUPT_DEC_E)
++              return IRQ_HANDLED;
++      hantro_irq_done(vpu, VB2_BUF_STATE_ERROR);
+       return IRQ_HANDLED;
+ }
+--- a/drivers/media/platform/verisilicon/hantro_g2_hevc_dec.c
++++ b/drivers/media/platform/verisilicon/hantro_g2_hevc_dec.c
+@@ -592,8 +592,6 @@ int hantro_g2_hevc_dec_run(struct hantro
+       struct hantro_dev *vpu = ctx->dev;
+       int ret;
+-      hantro_g2_check_idle(vpu);
+-
+       /* Prepare HEVC decoder context. */
+       ret = hantro_hevc_dec_prepare_run(ctx);
+       if (ret)
+--- a/drivers/media/platform/verisilicon/hantro_g2_regs.h
++++ b/drivers/media/platform/verisilicon/hantro_g2_regs.h
+@@ -22,7 +22,14 @@
+ #define G2_REG_VERSION                        G2_SWREG(0)
+ #define G2_REG_INTERRUPT              G2_SWREG(1)
++#define G2_REG_INTERRUPT_DEC_LAST_SLICE_INT   BIT(19)
++#define G2_REG_INTERRUPT_DEC_TIMEOUT  BIT(18)
++#define G2_REG_INTERRUPT_DEC_ERROR_INT        BIT(16)
++#define G2_REG_INTERRUPT_DEC_BUF_INT  BIT(14)
++#define G2_REG_INTERRUPT_DEC_BUS_INT  BIT(13)
+ #define G2_REG_INTERRUPT_DEC_RDY_INT  BIT(12)
++#define G2_REG_INTERRUPT_DEC_ABORT_INT        BIT(11)
++#define G2_REG_INTERRUPT_DEC_IRQ      BIT(8)
+ #define G2_REG_INTERRUPT_DEC_ABORT_E  BIT(5)
+ #define G2_REG_INTERRUPT_DEC_IRQ_DIS  BIT(4)
+ #define G2_REG_INTERRUPT_DEC_E                BIT(0)
+@@ -35,6 +42,9 @@
+ #define BUS_WIDTH_128                 2
+ #define BUS_WIDTH_256                 3
++#define g2_dec_int_stat               G2_DEC_REG(1, 11, 0xf)
++#define g2_dec_irq            G2_DEC_REG(1, 8, 0x1)
++
+ #define g2_strm_swap          G2_DEC_REG(2, 28, 0xf)
+ #define g2_strm_swap_old      G2_DEC_REG(2, 27, 0x1f)
+ #define g2_pic_swap           G2_DEC_REG(2, 22, 0x1f)
+@@ -225,6 +235,9 @@
+ #define vp9_filt_level_seg5   G2_DEC_REG(19,  8, 0x3f)
+ #define vp9_quant_seg5                G2_DEC_REG(19,  0, 0xff)
++#define g2_timemout_override_e        G2_DEC_REG(45, 31, 0x1)
++#define g2_timemout_cycles    G2_DEC_REG(45, 0, 0x7fffffff)
++
+ #define hevc_cur_poc_00               G2_DEC_REG(46, 24, 0xff)
+ #define hevc_cur_poc_01               G2_DEC_REG(46, 16, 0xff)
+ #define hevc_cur_poc_02               G2_DEC_REG(46, 8,  0xff)
+--- a/drivers/media/platform/verisilicon/hantro_g2_vp9_dec.c
++++ b/drivers/media/platform/verisilicon/hantro_g2_vp9_dec.c
+@@ -909,8 +909,6 @@ int hantro_g2_vp9_dec_run(struct hantro_
+       struct vb2_v4l2_buffer *dst;
+       int ret;
+-      hantro_g2_check_idle(ctx->dev);
+-
+       ret = start_prepare_run(ctx, &decode_params);
+       if (ret) {
+               hantro_end_prepare_run(ctx);
+--- a/drivers/media/platform/verisilicon/hantro_hw.h
++++ b/drivers/media/platform/verisilicon/hantro_hw.h
+@@ -436,6 +436,7 @@ void hantro_g2_vp9_dec_done(struct hantr
+ int hantro_vp9_dec_init(struct hantro_ctx *ctx);
+ void hantro_vp9_dec_exit(struct hantro_ctx *ctx);
+ void hantro_g2_check_idle(struct hantro_dev *vpu);
++void hantro_g2_reset(struct hantro_ctx *ctx);
+ irqreturn_t hantro_g2_irq(int irq, void *dev_id);
+ #endif /* HANTRO_HW_H_ */
+--- a/drivers/media/platform/verisilicon/imx8m_vpu_hw.c
++++ b/drivers/media/platform/verisilicon/imx8m_vpu_hw.c
+@@ -310,11 +310,13 @@ static const struct hantro_codec_ops imx
+ static const struct hantro_codec_ops imx8mq_vpu_g2_codec_ops[] = {
+       [HANTRO_MODE_HEVC_DEC] = {
+               .run = hantro_g2_hevc_dec_run,
++              .reset = hantro_g2_reset,
+               .init = hantro_hevc_dec_init,
+               .exit = hantro_hevc_dec_exit,
+       },
+       [HANTRO_MODE_VP9_DEC] = {
+               .run = hantro_g2_vp9_dec_run,
++              .reset = hantro_g2_reset,
+               .done = hantro_g2_vp9_dec_done,
+               .init = hantro_vp9_dec_init,
+               .exit = hantro_vp9_dec_exit,
diff --git a/queue-6.1/mm-balloon_compaction-convert-balloon_page_delete-to-balloon_page_finalize.patch b/queue-6.1/mm-balloon_compaction-convert-balloon_page_delete-to-balloon_page_finalize.patch
new file mode 100644 (file)
index 0000000..e19aff1
--- /dev/null
@@ -0,0 +1,225 @@
+From stable+bounces-204887-greg=kroah.com@vger.kernel.org Mon Jan  5 19:21:09 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon,  5 Jan 2026 13:18:48 -0500
+Subject: mm/balloon_compaction: convert balloon_page_delete() to balloon_page_finalize()
+To: stable@vger.kernel.org
+Cc: "David Hildenbrand" <david@redhat.com>, "Lorenzo Stoakes" <lorenzo.stoakes@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>, "Harry Yoo" <harry.yoo@oracle.com>, "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>, "Zi Yan" <ziy@nvidia.com>, "Andrew Morton" <akpm@linux-foundation.org>, "Sasha Levin" <sashal@kernel.org>
+Message-ID: <20260105181849.2717306-2-sashal@kernel.org>
+
+From: David Hildenbrand <david@redhat.com>
+
+[ Upstream commit 15504b1163007bbfbd9a63460d5c14737c16e96d ]
+
+Let's move the removal of the page from the balloon list into the single
+caller, to remove the dependency on the PG_isolated flag and clarify
+locking requirements.
+
+Note that for now, balloon_page_delete() was used on two paths:
+
+(1) Removing a page from the balloon for deflation through
+    balloon_page_list_dequeue()
+(2) Removing an isolated page from the balloon for migration in the
+    per-driver migration handlers. Isolated pages were already removed from
+    the balloon list during isolation.
+
+So instead of relying on the flag, we can just distinguish both cases
+directly and handle it accordingly in the caller.
+
+We'll shuffle the operations a bit such that they logically make more
+sense (e.g., remove from the list before clearing flags).
+
+In balloon migration functions we can now move the balloon_page_finalize()
+out of the balloon lock and perform the finalization just before dropping
+the balloon reference.
+
+Document that the page lock is currently required when modifying the
+movability aspects of a page; hopefully we can soon decouple this from the
+page lock.
+
+Link: https://lkml.kernel.org/r/20250704102524.326966-3-david@redhat.com
+Signed-off-by: David Hildenbrand <david@redhat.com>
+Reviewed-by: Lorenzo Stoakes <lorenzo.stoakes@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: Harry Yoo <harry.yoo@oracle.com>
+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>
+Cc: Zi Yan <ziy@nvidia.com>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Stable-dep-of: 0da2ba35c0d5 ("powerpc/pseries/cmm: adjust BALLOON_MIGRATE when migrating pages")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/powerpc/platforms/pseries/cmm.c |    2 -
+ drivers/misc/vmw_balloon.c           |    3 --
+ drivers/virtio/virtio_balloon.c      |    4 ---
+ include/linux/balloon_compaction.h   |   43 +++++++++++++----------------------
+ mm/balloon_compaction.c              |    3 +-
+ 5 files changed, 21 insertions(+), 34 deletions(-)
+
+--- a/arch/powerpc/platforms/pseries/cmm.c
++++ b/arch/powerpc/platforms/pseries/cmm.c
+@@ -532,7 +532,6 @@ static int cmm_migratepage(struct balloo
+       spin_lock_irqsave(&b_dev_info->pages_lock, flags);
+       balloon_page_insert(b_dev_info, newpage);
+-      balloon_page_delete(page);
+       b_dev_info->isolated_pages--;
+       spin_unlock_irqrestore(&b_dev_info->pages_lock, flags);
+@@ -542,6 +541,7 @@ static int cmm_migratepage(struct balloo
+        */
+       plpar_page_set_active(page);
++      balloon_page_finalize(page);
+       /* balloon page list reference */
+       put_page(page);
+--- a/drivers/misc/vmw_balloon.c
++++ b/drivers/misc/vmw_balloon.c
+@@ -1789,8 +1789,7 @@ static int vmballoon_migratepage(struct
+        * @pages_lock . We keep holding @comm_lock since we will need it in a
+        * second.
+        */
+-      balloon_page_delete(page);
+-
++      balloon_page_finalize(page);
+       put_page(page);
+       /* Inflate */
+--- a/drivers/virtio/virtio_balloon.c
++++ b/drivers/virtio/virtio_balloon.c
+@@ -789,15 +789,13 @@ static int virtballoon_migratepage(struc
+       tell_host(vb, vb->inflate_vq);
+       /* balloon's page migration 2nd step -- deflate "page" */
+-      spin_lock_irqsave(&vb_dev_info->pages_lock, flags);
+-      balloon_page_delete(page);
+-      spin_unlock_irqrestore(&vb_dev_info->pages_lock, flags);
+       vb->num_pfns = VIRTIO_BALLOON_PAGES_PER_PAGE;
+       set_page_pfns(vb, vb->pfns, page);
+       tell_host(vb, vb->deflate_vq);
+       mutex_unlock(&vb->balloon_lock);
++      balloon_page_finalize(page);
+       put_page(page); /* balloon reference */
+       return MIGRATEPAGE_SUCCESS;
+--- a/include/linux/balloon_compaction.h
++++ b/include/linux/balloon_compaction.h
+@@ -98,27 +98,6 @@ static inline void balloon_page_insert(s
+ }
+ /*
+- * balloon_page_delete - delete a page from balloon's page list and clear
+- *                     the page->private assignement accordingly.
+- * @page    : page to be released from balloon's page list
+- *
+- * Caller must ensure the page is locked and the spin_lock protecting balloon
+- * pages list is held before deleting a page from the balloon device.
+- */
+-static inline void balloon_page_delete(struct page *page)
+-{
+-      __ClearPageOffline(page);
+-      __ClearPageMovable(page);
+-      set_page_private(page, 0);
+-      /*
+-       * No touch page.lru field once @page has been isolated
+-       * because VM is using the field.
+-       */
+-      if (!PageIsolated(page))
+-              list_del(&page->lru);
+-}
+-
+-/*
+  * balloon_page_device - get the b_dev_info descriptor for the balloon device
+  *                     that enqueues the given page.
+  */
+@@ -141,12 +120,6 @@ static inline void balloon_page_insert(s
+       list_add(&page->lru, &balloon->pages);
+ }
+-static inline void balloon_page_delete(struct page *page)
+-{
+-      __ClearPageOffline(page);
+-      list_del(&page->lru);
+-}
+-
+ static inline gfp_t balloon_mapping_gfp_mask(void)
+ {
+       return GFP_HIGHUSER;
+@@ -155,6 +128,22 @@ static inline gfp_t balloon_mapping_gfp_
+ #endif /* CONFIG_BALLOON_COMPACTION */
+ /*
++ * balloon_page_finalize - prepare a balloon page that was removed from the
++ *                       balloon list for release to the page allocator
++ * @page: page to be released to the page allocator
++ *
++ * Caller must ensure that the page is locked.
++ */
++static inline void balloon_page_finalize(struct page *page)
++{
++      if (IS_ENABLED(CONFIG_BALLOON_COMPACTION)) {
++              __ClearPageMovable(page);
++              set_page_private(page, 0);
++      }
++      __ClearPageOffline(page);
++}
++
++/*
+  * balloon_page_push - insert a page into a page list.
+  * @head : pointer to list
+  * @page : page to be added
+--- a/mm/balloon_compaction.c
++++ b/mm/balloon_compaction.c
+@@ -93,7 +93,8 @@ size_t balloon_page_list_dequeue(struct
+               if (!trylock_page(page))
+                       continue;
+-              balloon_page_delete(page);
++              list_del(&page->lru);
++              balloon_page_finalize(page);
+               __count_vm_event(BALLOON_DEFLATE);
+               list_add(&page->lru, pages);
+               unlock_page(page);
diff --git a/queue-6.1/mm-balloon_compaction-we-cannot-have-isolated-pages-in-the-balloon-list.patch b/queue-6.1/mm-balloon_compaction-we-cannot-have-isolated-pages-in-the-balloon-list.patch
new file mode 100644 (file)
index 0000000..d9dafd3
--- /dev/null
@@ -0,0 +1,109 @@
+From stable+bounces-204886-greg=kroah.com@vger.kernel.org Mon Jan  5 19:21:01 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon,  5 Jan 2026 13:18:47 -0500
+Subject: mm/balloon_compaction: we cannot have isolated pages in the balloon list
+To: stable@vger.kernel.org
+Cc: "David Hildenbrand" <david@redhat.com>, "Zi Yan" <ziy@nvidia.com>, "Lorenzo Stoakes" <lorenzo.stoakes@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>, "Harry Yoo" <harry.yoo@oracle.com>, "Andrew Morton" <akpm@linux-foundation.org>, "Sasha Levin" <sashal@kernel.org>
+Message-ID: <20260105181849.2717306-1-sashal@kernel.org>
+
+From: David Hildenbrand <david@redhat.com>
+
+[ Upstream commit fb05f992b6bbb4702307d96f00703ee637b24dbf ]
+
+Patch series "mm/migration: rework movable_ops page migration (part 1)",
+v2.
+
+In the future, as we decouple "struct page" from "struct folio", pages
+that support "non-lru page migration" -- movable_ops page migration such
+as memory balloons and zsmalloc -- will no longer be folios.  They will
+not have ->mapping, ->lru, and likely no refcount and no page lock.  But
+they will have a type and flags 🙂
+
+This is the first part (other parts not written yet) of decoupling
+movable_ops page migration from folio migration.
+
+In this series, we get rid of the ->mapping usage, and start cleaning up
+the code + separating it from folio migration.
+
+Migration core will have to be further reworked to not treat movable_ops
+pages like folios.  This is the first step into that direction.
+
+This patch (of 29):
+
+The core will set PG_isolated only after mops->isolate_page() was called.
+In case of the balloon, that is where we will remove it from the balloon
+list.  So we cannot have isolated pages in the balloon list.
+
+Let's drop this unnecessary check.
+
+Link: https://lkml.kernel.org/r/20250704102524.326966-2-david@redhat.com
+Signed-off-by: David Hildenbrand <david@redhat.com>
+Acked-by: Zi Yan <ziy@nvidia.com>
+Reviewed-by: Lorenzo Stoakes <lorenzo.stoakes@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>
+Cc: Harry Yoo <harry.yoo@oracle.com>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Stable-dep-of: 0da2ba35c0d5 ("powerpc/pseries/cmm: adjust BALLOON_MIGRATE when migrating pages")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ mm/balloon_compaction.c |    6 ------
+ 1 file changed, 6 deletions(-)
+
+--- a/mm/balloon_compaction.c
++++ b/mm/balloon_compaction.c
+@@ -93,12 +93,6 @@ size_t balloon_page_list_dequeue(struct
+               if (!trylock_page(page))
+                       continue;
+-              if (IS_ENABLED(CONFIG_BALLOON_COMPACTION) &&
+-                  PageIsolated(page)) {
+-                      /* raced with isolation */
+-                      unlock_page(page);
+-                      continue;
+-              }
+               balloon_page_delete(page);
+               __count_vm_event(BALLOON_DEFLATE);
+               list_add(&page->lru, pages);
diff --git a/queue-6.1/mm-consider-non-anon-swap-cache-folios-in-folio_expected_ref_count.patch b/queue-6.1/mm-consider-non-anon-swap-cache-folios-in-folio_expected_ref_count.patch
new file mode 100644 (file)
index 0000000..478266a
--- /dev/null
@@ -0,0 +1,120 @@
+From stable+bounces-206070-greg=kroah.com@vger.kernel.org Wed Jan  7 01:36:38 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue,  6 Jan 2026 19:36:27 -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: <20260107003627.3469728-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
+@@ -1823,10 +1823,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.1/mm-simplify-folio_expected_ref_count.patch b/queue-6.1/mm-simplify-folio_expected_ref_count.patch
new file mode 100644 (file)
index 0000000..d42df6e
--- /dev/null
@@ -0,0 +1,100 @@
+From stable+bounces-206069-greg=kroah.com@vger.kernel.org Wed Jan  7 01:36:36 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue,  6 Jan 2026 19:36:26 -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: <20260107003627.3469728-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
+@@ -1820,13 +1820,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.1/mptcp-avoid-deadlock-on-fallback-while-reinjecting.patch b/queue-6.1/mptcp-avoid-deadlock-on-fallback-while-reinjecting.patch
new file mode 100644 (file)
index 0000000..9c76d30
--- /dev/null
@@ -0,0 +1,117 @@
+From stable+bounces-204204-greg=kroah.com@vger.kernel.org Tue Dec 30 14:20:10 2025
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 30 Dec 2025 08:20:05 -0500
+Subject: mptcp: avoid deadlock on fallback while reinjecting
+To: stable@vger.kernel.org
+Cc: Paolo Abeni <pabeni@redhat.com>, Jakub Kicinski <kuba@kernel.org>, "Matthieu Baerts (NGI0)" <matttbe@kernel.org>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20251230132005.2177978-1-sashal@kernel.org>
+
+From: Paolo Abeni <pabeni@redhat.com>
+
+[ Upstream commit ffb8c27b0539dd90262d1021488e7817fae57c42 ]
+
+Jakub reported an MPTCP deadlock at fallback time:
+
+ WARNING: possible recursive locking detected
+ 6.18.0-rc7-virtme #1 Not tainted
+ --------------------------------------------
+ mptcp_connect/20858 is trying to acquire lock:
+ ff1100001da18b60 (&msk->fallback_lock){+.-.}-{3:3}, at: __mptcp_try_fallback+0xd8/0x280
+
+ but task is already holding lock:
+ ff1100001da18b60 (&msk->fallback_lock){+.-.}-{3:3}, at: __mptcp_retrans+0x352/0xaa0
+
+ other info that might help us debug this:
+  Possible unsafe locking scenario:
+
+        CPU0
+        ----
+   lock(&msk->fallback_lock);
+   lock(&msk->fallback_lock);
+
+  *** DEADLOCK ***
+
+  May be due to missing lock nesting notation
+
+ 3 locks held by mptcp_connect/20858:
+  #0: ff1100001da18290 (sk_lock-AF_INET){+.+.}-{0:0}, at: mptcp_sendmsg+0x114/0x1bc0
+  #1: ff1100001db40fd0 (k-sk_lock-AF_INET#2){+.+.}-{0:0}, at: __mptcp_retrans+0x2cb/0xaa0
+  #2: ff1100001da18b60 (&msk->fallback_lock){+.-.}-{3:3}, at: __mptcp_retrans+0x352/0xaa0
+
+ stack backtrace:
+ CPU: 0 UID: 0 PID: 20858 Comm: mptcp_connect Not tainted 6.18.0-rc7-virtme #1 PREEMPT(full)
+ Hardware name: Bochs, BIOS Bochs 01/01/2011
+ Call Trace:
+  <TASK>
+  dump_stack_lvl+0x6f/0xa0
+  print_deadlock_bug.cold+0xc0/0xcd
+  validate_chain+0x2ff/0x5f0
+  __lock_acquire+0x34c/0x740
+  lock_acquire.part.0+0xbc/0x260
+  _raw_spin_lock_bh+0x38/0x50
+  __mptcp_try_fallback+0xd8/0x280
+  mptcp_sendmsg_frag+0x16c2/0x3050
+  __mptcp_retrans+0x421/0xaa0
+  mptcp_release_cb+0x5aa/0xa70
+  release_sock+0xab/0x1d0
+  mptcp_sendmsg+0xd5b/0x1bc0
+  sock_write_iter+0x281/0x4d0
+  new_sync_write+0x3c5/0x6f0
+  vfs_write+0x65e/0xbb0
+  ksys_write+0x17e/0x200
+  do_syscall_64+0xbb/0xfd0
+  entry_SYSCALL_64_after_hwframe+0x4b/0x53
+ RIP: 0033:0x7fa5627cbc5e
+ Code: 4d 89 d8 e8 14 bd 00 00 4c 8b 5d f8 41 8b 93 08 03 00 00 59 5e 48 83 f8 fc 74 11 c9 c3 0f 1f 80 00 00 00 00 48 8b 45 10 0f 05 <c9> c3 83 e2 39 83 fa 08 75 e7 e8 13 ff ff ff 0f 1f 00 f3 0f 1e fa
+ RSP: 002b:00007fff1fe14700 EFLAGS: 00000202 ORIG_RAX: 0000000000000001
+ RAX: ffffffffffffffda RBX: 0000000000000005 RCX: 00007fa5627cbc5e
+ RDX: 0000000000001f9c RSI: 00007fff1fe16984 RDI: 0000000000000005
+ RBP: 00007fff1fe14710 R08: 0000000000000000 R09: 0000000000000000
+ R10: 0000000000000000 R11: 0000000000000202 R12: 00007fff1fe16920
+ R13: 0000000000002000 R14: 0000000000001f9c R15: 0000000000001f9c
+
+The packet scheduler could attempt a reinjection after receiving an
+MP_FAIL and before the infinite map has been transmitted, causing a
+deadlock since MPTCP needs to do the reinjection atomically from WRT
+fallback.
+
+Address the issue explicitly avoiding the reinjection in the critical
+scenario. Note that this is the only fallback critical section that
+could potentially send packets and hit the double-lock.
+
+Reported-by: Jakub Kicinski <kuba@kernel.org>
+Closes: https://netdev-ctrl.bots.linux.dev/logs/vmksft/mptcp-dbg/results/412720/1-mptcp-join-sh/stderr
+Fixes: f8a1d9b18c5e ("mptcp: make fallback action and fallback decision atomic")
+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/20251205-net-mptcp-misc-fixes-6-19-rc1-v1-4-9e4781a6c1b8@kernel.org
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+[ Adjust context ]
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/mptcp/protocol.c |   10 ++++++++--
+ 1 file changed, 8 insertions(+), 2 deletions(-)
+
+--- a/net/mptcp/protocol.c
++++ b/net/mptcp/protocol.c
+@@ -2715,9 +2715,15 @@ static void __mptcp_retrans(struct sock
+       info.sent = 0;
+       info.limit = READ_ONCE(msk->csum_enabled) ? dfrag->data_len : dfrag->already_sent;
+-      /* make the whole retrans decision, xmit, disallow fallback atomic */
++      /*
++       * make the whole retrans decision, xmit, disallow
++       * fallback atomic, note that we can't retrans even
++       * when an infinite fallback is in progress, i.e. new
++       * subflows are disallowed.
++       */
+       spin_lock_bh(&msk->fallback_lock);
+-      if (__mptcp_check_fallback(msk)) {
++      if (__mptcp_check_fallback(msk) ||
++          !msk->allow_subflows) {
+               spin_unlock_bh(&msk->fallback_lock);
+               release_sock(ssk);
+               return;
diff --git a/queue-6.1/mptcp-fallback-earlier-on-simult-connection.patch b/queue-6.1/mptcp-fallback-earlier-on-simult-connection.patch
new file mode 100644 (file)
index 0000000..99f0aec
--- /dev/null
@@ -0,0 +1,149 @@
+From stable+bounces-205929-greg=kroah.com@vger.kernel.org Tue Jan  6 19:51:20 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue,  6 Jan 2026 12:58:52 -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: <20260106175852.3105095-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 from two arguments to one argument ]
+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 |    5 ++---
+ net/mptcp/subflow.c  |    9 ---------
+ 3 files changed, 12 insertions(+), 12 deletions(-)
+
+--- a/net/mptcp/options.c
++++ b/net/mptcp/options.c
+@@ -403,6 +403,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
+@@ -1053,9 +1053,8 @@ static inline bool subflow_simultaneous_
+ {
+       struct mptcp_subflow_context *subflow = mptcp_subflow_ctx(sk);
+-      return sk->sk_state == TCP_ESTABLISHED &&
+-             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
+@@ -1700,15 +1700,6 @@ static void subflow_state_change(struct
+       __subflow_state_change(sk);
+       msk = mptcp_sk(parent);
+-      if (subflow_simultaneous_connect(sk)) {
+-              mptcp_propagate_sndbuf(parent, sk);
+-              WARN_ON_ONCE(!mptcp_try_fallback(sk));
+-              mptcp_rcv_space_init(msk, sk);
+-              pr_fallback(msk);
+-              subflow->conn_finished = 1;
+-              mptcp_set_connected(parent);
+-      }
+-
+       /* 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.1/mptcp-initialise-rcv_mss-before-calling-tcp_send_active_reset-in-mptcp_do_fastclose.patch b/queue-6.1/mptcp-initialise-rcv_mss-before-calling-tcp_send_active_reset-in-mptcp_do_fastclose.patch
new file mode 100644 (file)
index 0000000..7e13250
--- /dev/null
@@ -0,0 +1,95 @@
+From stable+bounces-200348-greg=kroah.com@vger.kernel.org Mon Dec  8 14:01:04 2025
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon,  8 Dec 2025 08:00:54 -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: <20251208130054.296171-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
+@@ -2806,6 +2806,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.1/mptcp-pm-ignore-unknown-endpoint-flags.patch b/queue-6.1/mptcp-pm-ignore-unknown-endpoint-flags.patch
new file mode 100644 (file)
index 0000000..7d7baa6
--- /dev/null
@@ -0,0 +1,68 @@
+From stable+bounces-204220-greg=kroah.com@vger.kernel.org Tue Dec 30 14:48:47 2025
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 30 Dec 2025 08:48:42 -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: <20251230134842.2212007-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
+@@ -1424,7 +1424,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.1/net-dsa-sja1105-fix-kasan-out-of-bounds-warning-in-sja1105_table_delete_entry.patch b/queue-6.1/net-dsa-sja1105-fix-kasan-out-of-bounds-warning-in-sja1105_table_delete_entry.patch
new file mode 100644 (file)
index 0000000..91a4ef3
--- /dev/null
@@ -0,0 +1,49 @@
+From stable+bounces-200123-greg=kroah.com@vger.kernel.org Fri Dec  5 06:56:07 2025
+From: Chen Yu <xnguchen@sina.cn>
+Date: Fri,  5 Dec 2025 13:54:48 +0800
+Subject: net: dsa: sja1105: fix kasan out-of-bounds warning in sja1105_table_delete_entry()
+To: vladimir.oltean@nxp.com, horms@kernel.org, kuba@kernel.org
+Cc: stable@vger.kernel.org
+Message-ID: <20251205055448.3030-1-xnguchen@sina.cn>
+
+From: Vladimir Oltean <vladimir.oltean@nxp.com>
+
+[ Upstream commit 5f2b28b79d2d1946ee36ad8b3dc0066f73c90481 ]
+
+There are actually 2 problems:
+- deleting the last element doesn't require the memmove of elements
+  [i + 1, end) over it. Actually, element i+1 is out of bounds.
+- The memmove itself should move size - i - 1 elements, because the last
+  element is out of bounds.
+
+The out-of-bounds element still remains out of bounds after being
+accessed, so the problem is only that we touch it, not that it becomes
+in active use. But I suppose it can lead to issues if the out-of-bounds
+element is part of an unmapped page.
+
+Fixes: 6666cebc5e30 ("net: dsa: sja1105: Add support for VLAN operations")
+Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
+Reviewed-by: Simon Horman <horms@kernel.org>
+Link: https://patch.msgid.link/20250318115716.2124395-4-vladimir.oltean@nxp.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Chen Yu <xnguchen@sina.cn>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/net/dsa/sja1105/sja1105_static_config.c |    6 ++++--
+ 1 file changed, 4 insertions(+), 2 deletions(-)
+
+--- a/drivers/net/dsa/sja1105/sja1105_static_config.c
++++ b/drivers/net/dsa/sja1105/sja1105_static_config.c
+@@ -1921,8 +1921,10 @@ int sja1105_table_delete_entry(struct sj
+       if (i > table->entry_count)
+               return -ERANGE;
+-      memmove(entries + i * entry_size, entries + (i + 1) * entry_size,
+-              (table->entry_count - i) * entry_size);
++      if (i + 1 < table->entry_count) {
++              memmove(entries + i * entry_size, entries + (i + 1) * entry_size,
++                      (table->entry_count - i - 1) * entry_size);
++      }
+       table->entry_count--;
diff --git a/queue-6.1/net-remove-rtnl-dance-for-siocbraddif-and-siocbrdelif.patch b/queue-6.1/net-remove-rtnl-dance-for-siocbraddif-and-siocbrdelif.patch
new file mode 100644 (file)
index 0000000..c929482
--- /dev/null
@@ -0,0 +1,300 @@
+From stable+bounces-206190-greg=kroah.com@vger.kernel.org Wed Jan  7 18:48:09 2026
+From: Thadeu Lima de Souza Cascardo <cascardo@igalia.com>
+Date: Wed,  7 Jan 2026 14:21:16 -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: <20260107172116.2488542-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
+@@ -63,11 +63,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
+@@ -895,8 +895,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
+@@ -315,7 +315,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;
+@@ -378,19 +377,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 SIOCSHWTSTAMP:
+               err = net_hwtstamp_validate(ifr);
+               if (err)
+@@ -575,8 +561,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
+@@ -1151,12 +1151,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);
+@@ -1165,8 +1163,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;
+@@ -1175,7 +1172,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;
+@@ -1272,7 +1269,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:
+@@ -3376,6 +3375,8 @@ static int compat_sock_ioctl_trans(struc
+       case SIOCGPGRP:
+       case SIOCBRADDBR:
+       case SIOCBRDELBR:
++      case SIOCBRADDIF:
++      case SIOCBRDELIF:
+       case SIOCGIFVLAN:
+       case SIOCSIFVLAN:
+       case SIOCGSKNS:
+@@ -3415,8 +3416,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.1/nfsd-clear-seclabel-in-the-suppattr_exclcreat-bitmap.patch b/queue-6.1/nfsd-clear-seclabel-in-the-suppattr_exclcreat-bitmap.patch
new file mode 100644 (file)
index 0000000..5614ad8
--- /dev/null
@@ -0,0 +1,57 @@
+From stable+bounces-204318-greg=kroah.com@vger.kernel.org Wed Dec 31 04:55:43 2025
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 30 Dec 2025 22:55:37 -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: <20251231035537.2722284-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
+@@ -3408,6 +3408,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.1/nfsd-nfsv4-file-creation-neglects-setting-acl.patch b/queue-6.1/nfsd-nfsv4-file-creation-neglects-setting-acl.patch
new file mode 100644 (file)
index 0000000..40b9399
--- /dev/null
@@ -0,0 +1,49 @@
+From stable+bounces-204918-greg=kroah.com@vger.kernel.org Mon Jan  5 21:33:17 2026
+From: Chuck Lever <cel@kernel.org>
+Date: Mon,  5 Jan 2026 15:33:11 -0500
+Subject: NFSD: NFSv4 file creation neglects setting ACL
+To: <stable@vger.kernel.org>
+Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>, Sasha Levin <sashal@kernel.org>, <linux-nfs@vger.kernel.org>, Chuck Lever <chuck.lever@oracle.com>, Aurelien Couderc <aurelien.couderc2002@gmail.com>
+Message-ID: <20260105203311.3562329-1-cel@kernel.org>
+
+From: Chuck Lever <chuck.lever@oracle.com>
+
+[ Upstream commit 913f7cf77bf14c13cfea70e89bcb6d0b22239562 ]
+
+An NFSv4 client that sets an ACL with a named principal during file
+creation retrieves the ACL afterwards, and finds that it is only a
+default ACL (based on the mode bits) and not the ACL that was
+requested during file creation. This violates RFC 8881 section
+6.4.1.3: "the ACL attribute is set as given".
+
+The issue occurs in nfsd_create_setattr(). On 6.1.y, the check to
+determine whether nfsd_setattr() should be called is simply
+"iap->ia_valid", which only accounts for iattr changes. When only
+an ACL is present (and no iattr fields are set), nfsd_setattr() is
+skipped and the POSIX ACL is never applied to the inode.
+
+Subsequently, when the client retrieves the ACL, the server finds
+no POSIX ACL on the inode and returns one generated from the file's
+mode bits rather than returning the originally-specified ACL.
+
+Reported-by: Aurelien Couderc <aurelien.couderc2002@gmail.com>
+Fixes: c0cbe70742f4 ("NFSD: add posix ACLs to struct nfsd_attrs")
+Cc: stable@vger.kernel.org
+[ cel: Adjust nfsd_create_setattr() instead of nfsd_attrs_valid() ]
+Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/nfsd/vfs.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/fs/nfsd/vfs.c
++++ b/fs/nfsd/vfs.c
+@@ -1320,7 +1320,7 @@ nfsd_create_setattr(struct svc_rqst *rqs
+        * Callers expect new file metadata to be committed even
+        * if the attributes have not changed.
+        */
+-      if (iap->ia_valid)
++      if (iap->ia_valid || attrs->na_pacl || attrs->na_dpacl)
+               status = nfsd_setattr(rqstp, resfhp, attrs, 0, (time64_t)0);
+       else
+               status = nfserrno(commit_metadata(resfhp));
diff --git a/queue-6.1/page_pool-fix-use-after-free-in-page_pool_recycle_in_ring.patch b/queue-6.1/page_pool-fix-use-after-free-in-page_pool_recycle_in_ring.patch
new file mode 100644 (file)
index 0000000..a2720ba
--- /dev/null
@@ -0,0 +1,146 @@
+From stable+bounces-200718-greg=kroah.com@vger.kernel.org Wed Dec 10 13:16:30 2025
+From: ruohanlan@aliyun.com
+Date: Wed, 10 Dec 2025 12:15:55 +0000
+Subject: page_pool: Fix use-after-free in page_pool_recycle_in_ring
+To: stable@vger.kernel.org
+Cc: "Dong Chenchen" <dongchenchen2@huawei.com>, "Jakub Kicinski" <kuba@kernel.org>, syzbot+204a4382fcb3311f3858@syzkaller.appspotmail.com, "Toke Høiland-Jørgensen" <toke@redhat.com>, "Mina Almasry" <almasrymina@google.com>, "Ruohan Lan" <ruohanlan@aliyun.com>
+Message-ID: <20251210121555.5106-1-ruohanlan@aliyun.com>
+
+From: Dong Chenchen <dongchenchen2@huawei.com>
+
+[ Upstream commit 271683bb2cf32e5126c592b5d5e6a756fa374fd9 ]
+
+syzbot reported a uaf in page_pool_recycle_in_ring:
+
+BUG: KASAN: slab-use-after-free in lock_release+0x151/0xa30 kernel/locking/lockdep.c:5862
+Read of size 8 at addr ffff8880286045a0 by task syz.0.284/6943
+
+CPU: 0 UID: 0 PID: 6943 Comm: syz.0.284 Not tainted 6.13.0-rc3-syzkaller-gdfa94ce54f41 #0
+Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 09/13/2024
+Call Trace:
+ <TASK>
+ __dump_stack lib/dump_stack.c:94 [inline]
+ dump_stack_lvl+0x241/0x360 lib/dump_stack.c:120
+ print_address_description mm/kasan/report.c:378 [inline]
+ print_report+0x169/0x550 mm/kasan/report.c:489
+ kasan_report+0x143/0x180 mm/kasan/report.c:602
+ lock_release+0x151/0xa30 kernel/locking/lockdep.c:5862
+ __raw_spin_unlock_bh include/linux/spinlock_api_smp.h:165 [inline]
+ _raw_spin_unlock_bh+0x1b/0x40 kernel/locking/spinlock.c:210
+ spin_unlock_bh include/linux/spinlock.h:396 [inline]
+ ptr_ring_produce_bh include/linux/ptr_ring.h:164 [inline]
+ page_pool_recycle_in_ring net/core/page_pool.c:707 [inline]
+ page_pool_put_unrefed_netmem+0x748/0xb00 net/core/page_pool.c:826
+ page_pool_put_netmem include/net/page_pool/helpers.h:323 [inline]
+ page_pool_put_full_netmem include/net/page_pool/helpers.h:353 [inline]
+ napi_pp_put_page+0x149/0x2b0 net/core/skbuff.c:1036
+ skb_pp_recycle net/core/skbuff.c:1047 [inline]
+ skb_free_head net/core/skbuff.c:1094 [inline]
+ skb_release_data+0x6c4/0x8a0 net/core/skbuff.c:1125
+ skb_release_all net/core/skbuff.c:1190 [inline]
+ __kfree_skb net/core/skbuff.c:1204 [inline]
+ sk_skb_reason_drop+0x1c9/0x380 net/core/skbuff.c:1242
+ kfree_skb_reason include/linux/skbuff.h:1263 [inline]
+ __skb_queue_purge_reason include/linux/skbuff.h:3343 [inline]
+
+root cause is:
+
+page_pool_recycle_in_ring
+  ptr_ring_produce
+    spin_lock(&r->producer_lock);
+    WRITE_ONCE(r->queue[r->producer++], ptr)
+      //recycle last page to pool
+                               page_pool_release
+                                 page_pool_scrub
+                                   page_pool_empty_ring
+                                     ptr_ring_consume
+                                     page_pool_return_page  //release all page
+                                 __page_pool_destroy
+                                    free_percpu(pool->recycle_stats);
+                                    free(pool) //free
+
+     spin_unlock(&r->producer_lock); //pool->ring uaf read
+  recycle_stat_inc(pool, ring);
+
+page_pool can be free while page pool recycle the last page in ring.
+Add producer-lock barrier to page_pool_release to prevent the page
+pool from being free before all pages have been recycled.
+
+recycle_stat_inc() is empty when CONFIG_PAGE_POOL_STATS is not
+enabled, which will trigger Wempty-body build warning. Add definition
+for pool stat macro to fix warning.
+
+Suggested-by: Jakub Kicinski <kuba@kernel.org>
+Link: https://lore.kernel.org/netdev/20250513083123.3514193-1-dongchenchen2@huawei.com
+Fixes: ff7d6b27f894 ("page_pool: refurbish version of page_pool code")
+Reported-by: syzbot+204a4382fcb3311f3858@syzkaller.appspotmail.com
+Closes: https://syzkaller.appspot.com/bug?extid=204a4382fcb3311f3858
+Signed-off-by: Dong Chenchen <dongchenchen2@huawei.com>
+Reviewed-by: Toke Høiland-Jørgensen <toke@redhat.com>
+Reviewed-by: Mina Almasry <almasrymina@google.com>
+Link: https://patch.msgid.link/20250527114152.3119109-1-dongchenchen2@huawei.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+[ Minor context change fixed. ]
+Signed-off-by: Ruohan Lan <ruohanlan@aliyun.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/core/page_pool.c |   27 ++++++++++++++-------------
+ 1 file changed, 14 insertions(+), 13 deletions(-)
+
+--- a/net/core/page_pool.c
++++ b/net/core/page_pool.c
+@@ -128,9 +128,9 @@ u64 *page_pool_ethtool_stats_get(u64 *da
+ EXPORT_SYMBOL(page_pool_ethtool_stats_get);
+ #else
+-#define alloc_stat_inc(pool, __stat)
+-#define recycle_stat_inc(pool, __stat)
+-#define recycle_stat_add(pool, __stat, val)
++#define alloc_stat_inc(...)   do { } while (0)
++#define recycle_stat_inc(...) do { } while (0)
++#define recycle_stat_add(...) do { } while (0)
+ #endif
+ static bool page_pool_producer_lock(struct page_pool *pool)
+@@ -539,19 +539,16 @@ static void page_pool_return_page(struct
+ static bool page_pool_recycle_in_ring(struct page_pool *pool, struct page *page)
+ {
+-      int ret;
+-      /* BH protection not needed if current is softirq */
+-      if (in_softirq())
+-              ret = ptr_ring_produce(&pool->ring, page);
+-      else
+-              ret = ptr_ring_produce_bh(&pool->ring, page);
++      bool in_softirq, ret;
+-      if (!ret) {
++      /* BH protection not needed if current is softirq */
++      in_softirq = page_pool_producer_lock(pool);
++      ret = !__ptr_ring_produce(&pool->ring, page);
++      if (ret)
+               recycle_stat_inc(pool, ring);
+-              return true;
+-      }
++      page_pool_producer_unlock(pool, in_softirq);
+-      return false;
++      return ret;
+ }
+ /* Only allow direct recycling in special circumstances, into the
+@@ -826,10 +823,14 @@ static void page_pool_scrub(struct page_
+ static int page_pool_release(struct page_pool *pool)
+ {
++      bool in_softirq;
+       int inflight;
+       page_pool_scrub(pool);
+       inflight = page_pool_inflight(pool);
++      /* Acquire producer lock to make sure producers have exited. */
++      in_softirq = page_pool_producer_lock(pool);
++      page_pool_producer_unlock(pool, in_softirq);
+       if (!inflight)
+               page_pool_free(pool);
diff --git a/queue-6.1/pci-brcmstb-fix-disabling-l0s-capability.patch b/queue-6.1/pci-brcmstb-fix-disabling-l0s-capability.patch
new file mode 100644 (file)
index 0000000..7dfdfea
--- /dev/null
@@ -0,0 +1,79 @@
+From stable+bounces-204893-greg=kroah.com@vger.kernel.org Mon Jan  5 20:14:47 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon,  5 Jan 2026 14:14:41 -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: <20260105191441.2731420-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
+@@ -45,7 +45,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
+@@ -869,7 +868,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;
+@@ -963,12 +962,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.1/pmdomain-imx-fix-reference-count-leak-in-imx_gpc_probe.patch b/queue-6.1/pmdomain-imx-fix-reference-count-leak-in-imx_gpc_probe.patch
new file mode 100644 (file)
index 0000000..b168292
--- /dev/null
@@ -0,0 +1,48 @@
+From stable+bounces-205127-greg=kroah.com@vger.kernel.org Tue Jan  6 19:44:43 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue,  6 Jan 2026 12:05:17 -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: <20260106170520.3081258-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/soc/imx/gpc.c |    5 ++---
+ 1 file changed, 2 insertions(+), 3 deletions(-)
+
+--- a/drivers/soc/imx/gpc.c
++++ b/drivers/soc/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.1/pmdomain-use-device_get_match_data.patch b/queue-6.1/pmdomain-use-device_get_match_data.patch
new file mode 100644 (file)
index 0000000..0835a1e
--- /dev/null
@@ -0,0 +1,134 @@
+From stable+bounces-205126-greg=kroah.com@vger.kernel.org Tue Jan  6 18:13:57 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue,  6 Jan 2026 12:05:16 -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: <20260106170520.3081258-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/soc/actions/owl-sps.c     |   16 +++++-----------
+ drivers/soc/imx/gpc.c             |    7 +++----
+ drivers/soc/rockchip/pm_domains.c |   13 ++++---------
+ 3 files changed, 12 insertions(+), 24 deletions(-)
+
+--- a/drivers/soc/actions/owl-sps.c
++++ b/drivers/soc/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/soc/imx/gpc.c
++++ b/drivers/soc/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/soc/rockchip/pm_domains.c
++++ b/drivers/soc/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>
+@@ -770,7 +772,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;
+@@ -779,13 +780,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.1/powerpc-pseries-cmm-adjust-balloon_migrate-when-migrating-pages.patch b/queue-6.1/powerpc-pseries-cmm-adjust-balloon_migrate-when-migrating-pages.patch
new file mode 100644 (file)
index 0000000..a8314af
--- /dev/null
@@ -0,0 +1,45 @@
+From stable+bounces-204888-greg=kroah.com@vger.kernel.org Mon Jan  5 19:21:13 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon,  5 Jan 2026 13:18:49 -0500
+Subject: powerpc/pseries/cmm: adjust BALLOON_MIGRATE when migrating pages
+To: stable@vger.kernel.org
+Cc: David Hildenbrand <david@redhat.com>, "Ritesh Harjani (IBM)" <ritesh.list@gmail.com>, Christophe Leroy <christophe.leroy@csgroup.eu>, Madhavan Srinivasan <maddy@linux.ibm.com>, Michael Ellerman <mpe@ellerman.id.au>, Nicholas Piggin <npiggin@gmail.com>, Andrew Morton <akpm@linux-foundation.org>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260105181849.2717306-3-sashal@kernel.org>
+
+From: David Hildenbrand <david@redhat.com>
+
+[ Upstream commit 0da2ba35c0d532ca0fe7af698b17d74c4d084b9a ]
+
+Let's properly adjust BALLOON_MIGRATE like the other drivers.
+
+Note that the INFLATE/DEFLATE events are triggered from the core when
+enqueueing/dequeueing pages.
+
+This was found by code inspection.
+
+Link: https://lkml.kernel.org/r/20251021100606.148294-3-david@redhat.com
+Fixes: fe030c9b85e6 ("powerpc/pseries/cmm: Implement balloon compaction")
+Signed-off-by: David Hildenbrand <david@redhat.com>
+Reviewed-by: Ritesh Harjani (IBM) <ritesh.list@gmail.com>
+Cc: Christophe Leroy <christophe.leroy@csgroup.eu>
+Cc: Madhavan Srinivasan <maddy@linux.ibm.com>
+Cc: Michael Ellerman <mpe@ellerman.id.au>
+Cc: Nicholas Piggin <npiggin@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>
+---
+ arch/powerpc/platforms/pseries/cmm.c |    1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/arch/powerpc/platforms/pseries/cmm.c
++++ b/arch/powerpc/platforms/pseries/cmm.c
+@@ -532,6 +532,7 @@ static int cmm_migratepage(struct balloo
+       spin_lock_irqsave(&b_dev_info->pages_lock, flags);
+       balloon_page_insert(b_dev_info, newpage);
++      __count_vm_event(BALLOON_MIGRATE);
+       b_dev_info->isolated_pages--;
+       spin_unlock_irqrestore(&b_dev_info->pages_lock, flags);
diff --git a/queue-6.1/scsi-ufs-core-add-ufshcd_update_evt_hist-for-ufs-suspend-error.patch b/queue-6.1/scsi-ufs-core-add-ufshcd_update_evt_hist-for-ufs-suspend-error.patch
new file mode 100644 (file)
index 0000000..a4b156d
--- /dev/null
@@ -0,0 +1,50 @@
+From stable+bounces-204240-greg=kroah.com@vger.kernel.org Tue Dec 30 17:02:09 2025
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 30 Dec 2025 11:01:59 -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: <20251230160159.2292887-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
+@@ -9437,7 +9437,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;
+@@ -9448,6 +9448,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;
+ }
diff --git a/queue-6.1/serial-make-uart_remove_one_port-return-void.patch b/queue-6.1/serial-make-uart_remove_one_port-return-void.patch
new file mode 100644 (file)
index 0000000..0a463cf
--- /dev/null
@@ -0,0 +1,245 @@
+From stable+bounces-204281-greg=kroah.com@vger.kernel.org Tue Dec 30 20:49:10 2025
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 30 Dec 2025 14:49:02 -0500
+Subject: serial: Make uart_remove_one_port() return void
+To: stable@vger.kernel.org
+Cc: "Uwe Kleine-König" <u.kleine-koenig@pengutronix.de>, "Greg Kroah-Hartman" <gregkh@linuxfoundation.org>, "Sasha Levin" <sashal@kernel.org>
+Message-ID: <20251230194904.2442970-1-sashal@kernel.org>
+
+From: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
+
+[ Upstream commit d5b3d02d0b107345f2a6ecb5b06f98356f5c97ab ]
+
+The return value is only ever used as a return value for remove callbacks
+of platform drivers. This return value is ignored by the driver core.
+(The only effect is an error message, but uart_remove_one_port() already
+emitted one in this case.)
+
+So the return value isn't used at all and uart_remove_one_port() can be
+changed to return void without any loss. Also this better matches the
+Linux device model as remove functions are not supposed to fail.
+
+Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
+Link: https://lore.kernel.org/r/20230512173810.131447-3-u.kleine-koenig@pengutronix.de
+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/tty/serial/atmel_serial.c           |    5 ++---
+ drivers/tty/serial/clps711x.c               |    4 +++-
+ drivers/tty/serial/cpm_uart/cpm_uart_core.c |    5 ++++-
+ drivers/tty/serial/imx.c                    |    4 +++-
+ drivers/tty/serial/lantiq.c                 |    4 +++-
+ drivers/tty/serial/serial_core.c            |    6 +-----
+ drivers/tty/serial/st-asc.c                 |    4 +++-
+ drivers/tty/serial/uartlite.c               |   12 ++++--------
+ drivers/tty/serial/xilinx_uartps.c          |    5 ++---
+ include/linux/serial_core.h                 |    2 +-
+ 10 files changed, 26 insertions(+), 25 deletions(-)
+
+--- a/drivers/tty/serial/atmel_serial.c
++++ b/drivers/tty/serial/atmel_serial.c
+@@ -3022,14 +3022,13 @@ static int atmel_serial_remove(struct pl
+ {
+       struct uart_port *port = platform_get_drvdata(pdev);
+       struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
+-      int ret = 0;
+       tasklet_kill(&atmel_port->tasklet_rx);
+       tasklet_kill(&atmel_port->tasklet_tx);
+       device_init_wakeup(&pdev->dev, 0);
+-      ret = uart_remove_one_port(&atmel_uart, port);
++      uart_remove_one_port(&atmel_uart, port);
+       kfree(atmel_port->rx_ring.buf);
+@@ -3039,7 +3038,7 @@ static int atmel_serial_remove(struct pl
+       pdev->dev.of_node = NULL;
+-      return ret;
++      return 0;
+ }
+ static SIMPLE_DEV_PM_OPS(atmel_serial_pm_ops, atmel_serial_suspend,
+--- a/drivers/tty/serial/clps711x.c
++++ b/drivers/tty/serial/clps711x.c
+@@ -515,7 +515,9 @@ static int uart_clps711x_remove(struct p
+ {
+       struct clps711x_port *s = platform_get_drvdata(pdev);
+-      return uart_remove_one_port(&clps711x_uart, &s->port);
++      uart_remove_one_port(&clps711x_uart, &s->port);
++
++      return 0;
+ }
+ static const struct of_device_id __maybe_unused clps711x_uart_dt_ids[] = {
+--- a/drivers/tty/serial/cpm_uart/cpm_uart_core.c
++++ b/drivers/tty/serial/cpm_uart/cpm_uart_core.c
+@@ -1428,7 +1428,10 @@ static int cpm_uart_probe(struct platfor
+ static int cpm_uart_remove(struct platform_device *ofdev)
+ {
+       struct uart_cpm_port *pinfo = platform_get_drvdata(ofdev);
+-      return uart_remove_one_port(&cpm_reg, &pinfo->port);
++
++      uart_remove_one_port(&cpm_reg, &pinfo->port);
++
++      return 0;
+ }
+ static const struct of_device_id cpm_uart_match[] = {
+--- a/drivers/tty/serial/imx.c
++++ b/drivers/tty/serial/imx.c
+@@ -2538,7 +2538,9 @@ static int imx_uart_remove(struct platfo
+ {
+       struct imx_port *sport = platform_get_drvdata(pdev);
+-      return uart_remove_one_port(&imx_uart_uart_driver, &sport->port);
++      uart_remove_one_port(&imx_uart_uart_driver, &sport->port);
++
++      return 0;
+ }
+ static void imx_uart_restore_context(struct imx_port *sport)
+--- a/drivers/tty/serial/lantiq.c
++++ b/drivers/tty/serial/lantiq.c
+@@ -918,7 +918,9 @@ static int lqasc_remove(struct platform_
+ {
+       struct uart_port *port = platform_get_drvdata(pdev);
+-      return uart_remove_one_port(&lqasc_reg, port);
++      uart_remove_one_port(&lqasc_reg, port);
++
++      return 0;
+ }
+ static const struct ltq_soc_data soc_data_lantiq = {
+--- a/drivers/tty/serial/serial_core.c
++++ b/drivers/tty/serial/serial_core.c
+@@ -3186,13 +3186,12 @@ EXPORT_SYMBOL(uart_add_one_port);
+  * This unhooks (and hangs up) the specified port structure from the core
+  * driver. No further calls will be made to the low-level code for this port.
+  */
+-int uart_remove_one_port(struct uart_driver *drv, struct uart_port *uport)
++void uart_remove_one_port(struct uart_driver *drv, struct uart_port *uport)
+ {
+       struct uart_state *state = drv->state + uport->line;
+       struct tty_port *port = &state->port;
+       struct uart_port *uart_port;
+       struct tty_struct *tty;
+-      int ret = 0;
+       mutex_lock(&port_mutex);
+@@ -3208,7 +3207,6 @@ int uart_remove_one_port(struct uart_dri
+       if (!uart_port) {
+               mutex_unlock(&port->mutex);
+-              ret = -EINVAL;
+               goto out;
+       }
+       uport->flags |= UPF_DEAD;
+@@ -3251,8 +3249,6 @@ int uart_remove_one_port(struct uart_dri
+       mutex_unlock(&port->mutex);
+ out:
+       mutex_unlock(&port_mutex);
+-
+-      return ret;
+ }
+ EXPORT_SYMBOL(uart_remove_one_port);
+--- a/drivers/tty/serial/st-asc.c
++++ b/drivers/tty/serial/st-asc.c
+@@ -834,7 +834,9 @@ static int asc_serial_remove(struct plat
+ {
+       struct uart_port *port = platform_get_drvdata(pdev);
+-      return uart_remove_one_port(&asc_uart_driver, port);
++      uart_remove_one_port(&asc_uart_driver, port);
++
++      return 0;
+ }
+ #ifdef CONFIG_PM_SLEEP
+--- a/drivers/tty/serial/uartlite.c
++++ b/drivers/tty/serial/uartlite.c
+@@ -686,18 +686,15 @@ static int ulite_assign(struct device *d
+  *
+  * @dev: pointer to device structure
+  */
+-static int ulite_release(struct device *dev)
++static void ulite_release(struct device *dev)
+ {
+       struct uart_port *port = dev_get_drvdata(dev);
+-      int rc = 0;
+       if (port) {
+-              rc = uart_remove_one_port(&ulite_uart_driver, port);
++              uart_remove_one_port(&ulite_uart_driver, port);
+               dev_set_drvdata(dev, NULL);
+               port->mapbase = 0;
+       }
+-
+-      return rc;
+ }
+ /**
+@@ -891,14 +888,13 @@ static int ulite_remove(struct platform_
+ {
+       struct uart_port *port = dev_get_drvdata(&pdev->dev);
+       struct uartlite_data *pdata = port->private_data;
+-      int rc;
+       clk_disable_unprepare(pdata->clk);
+-      rc = ulite_release(&pdev->dev);
++      ulite_release(&pdev->dev);
+       pm_runtime_disable(&pdev->dev);
+       pm_runtime_set_suspended(&pdev->dev);
+       pm_runtime_dont_use_autosuspend(&pdev->dev);
+-      return rc;
++      return 0;
+ }
+ /* work with hotplug and coldplug */
+--- a/drivers/tty/serial/xilinx_uartps.c
++++ b/drivers/tty/serial/xilinx_uartps.c
+@@ -1670,14 +1670,13 @@ static int cdns_uart_remove(struct platf
+ {
+       struct uart_port *port = platform_get_drvdata(pdev);
+       struct cdns_uart *cdns_uart_data = port->private_data;
+-      int rc;
+       /* Remove the cdns_uart port from the serial core */
+ #ifdef CONFIG_COMMON_CLK
+       clk_notifier_unregister(cdns_uart_data->uartclk,
+                       &cdns_uart_data->clk_rate_change_nb);
+ #endif
+-      rc = uart_remove_one_port(cdns_uart_data->cdns_uart_driver, port);
++      uart_remove_one_port(cdns_uart_data->cdns_uart_driver, port);
+       port->mapbase = 0;
+       clk_disable_unprepare(cdns_uart_data->uartclk);
+       clk_disable_unprepare(cdns_uart_data->pclk);
+@@ -1693,7 +1692,7 @@ static int cdns_uart_remove(struct platf
+       if (!--instances)
+               uart_unregister_driver(cdns_uart_data->cdns_uart_driver);
+-      return rc;
++      return 0;
+ }
+ static struct platform_driver cdns_uart_platform_driver = {
+--- a/include/linux/serial_core.h
++++ b/include/linux/serial_core.h
+@@ -847,7 +847,7 @@ void uart_console_write(struct uart_port
+ int uart_register_driver(struct uart_driver *uart);
+ void uart_unregister_driver(struct uart_driver *uart);
+ int uart_add_one_port(struct uart_driver *reg, struct uart_port *port);
+-int uart_remove_one_port(struct uart_driver *reg, struct uart_port *port);
++void uart_remove_one_port(struct uart_driver *reg, struct uart_port *port);
+ bool uart_match_port(const struct uart_port *port1,
+               const struct uart_port *port2);
index 80e5ea3f256fc7932982068aa88bcbe482e98101..625794102e407b3bc2ef95933d3dc87afaba4a43 100644 (file)
@@ -523,3 +523,84 @@ mm-damon-tests-core-kunit-handle-memory-failure-from-damon_test_target.patch
 mm-damon-tests-core-kunit-handle-alloc-failures-on-damon_test_split_regions_of.patch
 mm-damon-tests-core-kunit-handle-memory-alloc-failure-from-damon_test_aggregate.patch
 mm-damon-tests-core-kunit-handle-alloc-failures-in-damon_test_set_regions.patch
+kbuild-use-crc32-and-a-1mib-dictionary-for-xz-compressed-modules.patch
+fscache-delete-fscache_cookie_lru_timer-when-fscache-exits-to-avoid-uaf.patch
+net-dsa-sja1105-fix-kasan-out-of-bounds-warning-in-sja1105_table_delete_entry.patch
+ksmbd-fix-out-of-bounds-in-parse_sec_desc.patch
+page_pool-fix-use-after-free-in-page_pool_recycle_in_ring.patch
+kvm-x86-mmu-use-emultype-flag-to-track-write-pfs-to-shadow-pages.patch
+kvm-svm-don-t-skip-unrelated-instruction-if-int3-into-is-replaced.patch
+mptcp-initialise-rcv_mss-before-calling-tcp_send_active_reset-in-mptcp_do_fastclose.patch
+alsa-hda-cs35l41-fix-null-pointer-dereference-in-cs35l41_hda_read_acpi.patch
+alsa-wavefront-use-guard-for-spin-locks.patch
+alsa-wavefront-clear-substream-pointers-on-close.patch
+alsa-wavefront-use-standard-print-api.patch
+alsa-wavefront-fix-integer-overflow-in-sample-size-validation.patch
+can-gs_usb-gs_can_open-fix-error-handling.patch
+wifi-mt76-fix-dts-power-limits-on-little-endian-systems.patch
+btrfs-don-t-rewrite-ret-from-inode_permission.patch
+gfs2-fix-freeze-error-handling.patch
+jbd2-fix-the-inconsistency-between-checksum-and-data-in-memory-for-journal-sb.patch
+ext4-fix-string-copying-in-parse_apply_sb_mount_options.patch
+mptcp-avoid-deadlock-on-fallback-while-reinjecting.patch
+usb-ohci-nxp-use-helper-function-devm_clk_get_enabled.patch
+usb-ohci-nxp-fix-device-leak-on-probe-failure.patch
+mptcp-pm-ignore-unknown-endpoint-flags.patch
+usb-dwc3-keep-susphy-enabled-during-exit-to-avoid-controller-faults.patch
+scsi-ufs-core-add-ufshcd_update_evt_hist-for-ufs-suspend-error.patch
+f2fs-fix-to-avoid-updating-zero-sized-extent-in-extent-cache.patch
+f2fs-remove-unused-gc_failure_pin.patch
+f2fs-keep-posix_fadv_noreuse-ranges.patch
+f2fs-drop-inode-from-the-donation-list-when-the-last-file-is-closed.patch
+f2fs-fix-to-avoid-updating-compression-context-during-writeback.patch
+f2fs-fix-to-propagate-error-from-f2fs_enable_checkpoint.patch
+f2fs-use-global-inline_xattr_slab-instead-of-per-sb-slab-cache.patch
+f2fs-fix-to-detect-recoverable-inode-during-dryrun-of-find_fsync_dnodes.patch
+nfsd-clear-seclabel-in-the-suppattr_exclcreat-bitmap.patch
+sunrpc-svcauth_gss-avoid-null-deref-on-zero-length-gss_token-in-gss_read_proxy_verf.patch
+btrfs-don-t-log-conflicting-inode-if-it-s-a-dir-moved-in-the-current-transaction.patch
+crypto-af_alg-zero-initialize-memory-allocated-via-sock_kmalloc.patch
+arm-dts-microchip-sama5d2-fix-spi-flexcom-fifo-size-to-32.patch
+arm-dts-microchip-sama7g5-fix-uart-fifo-size-to-32.patch
+iommu-mediatek-improve-safety-for-mediatek-smi-property-in-larb-nodes.patch
+iommu-mediatek-fix-use-after-free-on-probe-deferral.patch
+iommu-mtk_iommu_v1-convert-to-platform-remove-callback-returning-void.patch
+iommu-mediatek-v1-fix-device-leaks-on-probe.patch
+asoc-stm32-sai-use-the-devm_clk_get_optional-helper.patch
+asoc-stm32-sai-fix-clk-prepare-imbalance-on-probe-failure.patch
+fuse-fix-readahead-reclaim-deadlock.patch
+asoc-stm-stm32_sai_sub-convert-to-platform-remove-callback-returning-void.patch
+asoc-stm32-sai-fix-of-node-leak-on-probe.patch
+media-verisilicon-fix-cpu-stalls-on-g2-bus-error.patch
+arm64-dts-ti-k3-j721e-sk-fix-pinmux-for-pin-y1-used-by-power-regulator.patch
+pci-brcmstb-fix-disabling-l0s-capability.patch
+mm-balloon_compaction-we-cannot-have-isolated-pages-in-the-balloon-list.patch
+mm-balloon_compaction-convert-balloon_page_delete-to-balloon_page_finalize.patch
+powerpc-pseries-cmm-adjust-balloon_migrate-when-migrating-pages.patch
+kvm-nvmx-immediately-refresh-apicv-controls-as-needed-on-nested-vm-exit.patch
+media-amphion-add-a-frame-flush-mode-for-decoder.patch
+media-amphion-make-some-vpu_v4l2-functions-static.patch
+media-amphion-remove-vpu_vb_is_codecconfig.patch
+media-mediatek-vcodec-fix-a-reference-leak-in-mtk_vcodec_fw_vpu_init.patch
+pmdomain-use-device_get_match_data.patch
+pmdomain-imx-fix-reference-count-leak-in-imx_gpc_probe.patch
+mptcp-fallback-earlier-on-simult-connection.patch
+lockd-fix-vfs_test_lock-calls.patch
+mm-simplify-folio_expected_ref_count.patch
+mm-consider-non-anon-swap-cache-folios-in-folio_expected_ref_count.patch
+wifi-mac80211-discard-beacon-frames-to-non-broadcast-address.patch
+drm-amdgpu-cleanup-scheduler-job-initialization-v2.patch
+drm-amdgpu-add-missing-lock-to-amdgpu_ttm_access_memory_sdma.patch
+drm-mediatek-fix-probe-memory-leak.patch
+drm-gma500-remove-unused-helper-psb_fbdev_fb_setcolreg.patch
+net-remove-rtnl-dance-for-siocbraddif-and-siocbrdelif.patch
+serial-make-uart_remove_one_port-return-void.patch
+tty-introduce-and-use-tty_port_tty_vhangup-helper.patch
+xhci-dbgtty-fix-device-unregister-fixup.patch
+nfsd-nfsv4-file-creation-neglects-setting-acl.patch
+iommu-arm-smmu-drop-if-with-an-always-false-condition.patch
+iommu-arm-smmu-convert-to-platform-remove-callback-returning-void.patch
+iommu-qcom-use-the-asid-read-from-device-tree-if-specified.patch
+iommu-qcom-index-contexts-by-asid-number-to-allow-asid-0.patch
+iommu-qcom-fix-device-leak-on-of_xlate.patch
+virtio_console-fix-order-of-fields-cols-and-rows.patch
diff --git a/queue-6.1/sunrpc-svcauth_gss-avoid-null-deref-on-zero-length-gss_token-in-gss_read_proxy_verf.patch b/queue-6.1/sunrpc-svcauth_gss-avoid-null-deref-on-zero-length-gss_token-in-gss_read_proxy_verf.patch
new file mode 100644 (file)
index 0000000..ab6161e
--- /dev/null
@@ -0,0 +1,41 @@
+From stable+bounces-204356-greg=kroah.com@vger.kernel.org Wed Dec 31 15:32:46 2025
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 31 Dec 2025 09:32:39 -0500
+Subject: SUNRPC: svcauth_gss: avoid NULL deref on zero length gss_token in gss_read_proxy_verf
+To: stable@vger.kernel.org
+Cc: Joshua Rogers <linux@joshua.hu>, Chuck Lever <chuck.lever@oracle.com>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20251231143239.3043585-1-sashal@kernel.org>
+
+From: Joshua Rogers <linux@joshua.hu>
+
+[ Upstream commit d4b69a6186b215d2dc1ebcab965ed88e8d41768d ]
+
+A zero length gss_token results in pages == 0 and in_token->pages[0]
+is NULL. The code unconditionally evaluates
+page_address(in_token->pages[0]) for the initial memcpy, which can
+dereference NULL even when the copy length is 0. Guard the first
+memcpy so it only runs when length > 0.
+
+Fixes: 5866efa8cbfb ("SUNRPC: Fix svcauth_gss_proxy_init()")
+Cc: stable@vger.kernel.org
+Signed-off-by: Joshua Rogers <linux@joshua.hu>
+Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
+[ adapted xdr buffer pointer API to older argv iov_base/iov_len API ]
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/sunrpc/auth_gss/svcauth_gss.c |    3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+--- a/net/sunrpc/auth_gss/svcauth_gss.c
++++ b/net/sunrpc/auth_gss/svcauth_gss.c
+@@ -1179,7 +1179,8 @@ static int gss_read_proxy_verf(struct sv
+       }
+       length = min_t(unsigned int, inlen, argv->iov_len);
+-      memcpy(page_address(in_token->pages[0]), argv->iov_base, length);
++      if (length)
++              memcpy(page_address(in_token->pages[0]), argv->iov_base, length);
+       inlen -= length;
+       to_offs = length;
diff --git a/queue-6.1/tty-introduce-and-use-tty_port_tty_vhangup-helper.patch b/queue-6.1/tty-introduce-and-use-tty_port_tty_vhangup-helper.patch
new file mode 100644 (file)
index 0000000..83d1595
--- /dev/null
@@ -0,0 +1,233 @@
+From stable+bounces-204282-greg=kroah.com@vger.kernel.org Tue Dec 30 20:49:12 2025
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 30 Dec 2025 14:49:03 -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: <20251230194904.2442970-2-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
+@@ -915,7 +915,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);
+@@ -928,11 +927,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
+@@ -3191,7 +3191,6 @@ void uart_remove_one_port(struct uart_dr
+       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);
+@@ -3217,11 +3216,7 @@ void uart_remove_one_port(struct uart_dr
+        */
+       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
+@@ -416,15 +416,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
+@@ -1548,7 +1548,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 */
+@@ -1575,11 +1574,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
+@@ -1179,7 +1179,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)
+@@ -1194,11 +1193,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
+@@ -234,7 +234,7 @@ int tty_port_carrier_raised(struct tty_p
+ 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);
+@@ -253,4 +253,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.1/usb-dwc3-keep-susphy-enabled-during-exit-to-avoid-controller-faults.patch b/queue-6.1/usb-dwc3-keep-susphy-enabled-during-exit-to-avoid-controller-faults.patch
new file mode 100644 (file)
index 0000000..89751d6
--- /dev/null
@@ -0,0 +1,58 @@
+From sashal@kernel.org Tue Dec 30 15:54:25 2025
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 30 Dec 2025 09:54:19 -0500
+Subject: usb: dwc3: keep susphy enabled during exit to avoid controller faults
+To: stable@vger.kernel.org
+Cc: Udipto Goswami <udipto.goswami@oss.qualcomm.com>, stable <stable@kernel.org>, Thinh Nguyen <Thinh.Nguyen@synopsys.com>, Greg Kroah-Hartman <gregkh@linuxfoundation.org>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20251230145419.2259989-1-sashal@kernel.org>
+
+From: Udipto Goswami <udipto.goswami@oss.qualcomm.com>
+
+[ Upstream commit e1003aa7ec9eccdde4c926bd64ef42816ad55f25 ]
+
+On some platforms, switching USB roles from host to device can trigger
+controller faults due to premature PHY power-down. This occurs when the
+PHY is disabled too early during teardown, causing synchronization
+issues between the PHY and controller.
+
+Keep susphy enabled during dwc3_host_exit() and dwc3_gadget_exit()
+ensures the PHY remains in a low-power state capable of handling
+required commands during role switch.
+
+Cc: stable <stable@kernel.org>
+Fixes: 6d735722063a ("usb: dwc3: core: Prevent phy suspend during init")
+Suggested-by: Thinh Nguyen <Thinh.Nguyen@synopsys.com>
+Signed-off-by: Udipto Goswami <udipto.goswami@oss.qualcomm.com>
+Acked-by: Thinh Nguyen <Thinh.Nguyen@synopsys.com>
+Link: https://patch.msgid.link/20251126054221.120638-1-udipto.goswami@oss.qualcomm.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+[ Adjust context ]
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/usb/dwc3/gadget.c |    2 +-
+ drivers/usb/dwc3/host.c   |    2 +-
+ 2 files changed, 2 insertions(+), 2 deletions(-)
+
+--- a/drivers/usb/dwc3/gadget.c
++++ b/drivers/usb/dwc3/gadget.c
+@@ -4646,7 +4646,7 @@ void dwc3_gadget_exit(struct dwc3 *dwc)
+       if (!dwc->gadget)
+               return;
+-      dwc3_enable_susphy(dwc, false);
++      dwc3_enable_susphy(dwc, true);
+       usb_del_gadget(dwc->gadget);
+       dwc3_gadget_free_endpoints(dwc);
+       usb_put_gadget(dwc->gadget);
+--- a/drivers/usb/dwc3/host.c
++++ b/drivers/usb/dwc3/host.c
+@@ -162,7 +162,7 @@ err:
+ void dwc3_host_exit(struct dwc3 *dwc)
+ {
+-      dwc3_enable_susphy(dwc, false);
++      dwc3_enable_susphy(dwc, true);
+       platform_device_unregister(dwc->xhci);
+       dwc->xhci = NULL;
+ }
diff --git a/queue-6.1/usb-ohci-nxp-fix-device-leak-on-probe-failure.patch b/queue-6.1/usb-ohci-nxp-fix-device-leak-on-probe-failure.patch
new file mode 100644 (file)
index 0000000..6bb0fec
--- /dev/null
@@ -0,0 +1,49 @@
+From stable+bounces-204213-greg=kroah.com@vger.kernel.org Tue Dec 30 14:26:44 2025
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 30 Dec 2025 08:26:34 -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: <20251230132634.2198371-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
+@@ -224,6 +224,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;
+ }
+@@ -235,6 +236,7 @@ static int ohci_hcd_nxp_remove(struct pl
+       usb_remove_hcd(hcd);
+       ohci_nxp_stop_hc();
+       usb_put_hcd(hcd);
++      put_device(&isp1301_i2c_client->dev);
+       isp1301_i2c_client = NULL;
+       return 0;
diff --git a/queue-6.1/usb-ohci-nxp-use-helper-function-devm_clk_get_enabled.patch b/queue-6.1/usb-ohci-nxp-use-helper-function-devm_clk_get_enabled.patch
new file mode 100644 (file)
index 0000000..b5698a1
--- /dev/null
@@ -0,0 +1,93 @@
+From stable+bounces-204212-greg=kroah.com@vger.kernel.org Tue Dec 30 14:26:44 2025
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 30 Dec 2025 08:26:33 -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: <20251230132634.2198371-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;
+       }
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+@@ -230,8 +223,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;
+@@ -244,7 +235,6 @@ static int ohci_hcd_nxp_remove(struct pl
+       usb_remove_hcd(hcd);
+       ohci_nxp_stop_hc();
+       usb_put_hcd(hcd);
+-      clk_disable_unprepare(usb_host_clk);
+       isp1301_i2c_client = NULL;
+       return 0;
diff --git a/queue-6.1/virtio_console-fix-order-of-fields-cols-and-rows.patch b/queue-6.1/virtio_console-fix-order-of-fields-cols-and-rows.patch
new file mode 100644 (file)
index 0000000..e0738c2
--- /dev/null
@@ -0,0 +1,36 @@
+From 5326ab737a47278dbd16ed3ee7380b26c7056ddd Mon Sep 17 00:00:00 2001
+From: Maximilian Immanuel Brandtner <maxbr@linux.ibm.com>
+Date: Mon, 24 Mar 2025 15:42:46 +0100
+Subject: virtio_console: fix order of fields cols and rows
+
+From: Maximilian Immanuel Brandtner <maxbr@linux.ibm.com>
+
+commit 5326ab737a47278dbd16ed3ee7380b26c7056ddd upstream.
+
+According to section 5.3.6.2 (Multiport Device Operation) of the virtio
+spec(version 1.2) a control buffer with the event VIRTIO_CONSOLE_RESIZE
+is followed by a virtio_console_resize struct containing cols then rows.
+The kernel implements this the wrong way around (rows then cols) resulting
+in the two values being swapped.
+
+Signed-off-by: Maximilian Immanuel Brandtner <maxbr@linux.ibm.com>
+Message-Id: <20250324144300.905535-1-maxbr@linux.ibm.com>
+Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
+Cc: Filip Hejsek <filip.hejsek@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/char/virtio_console.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/char/virtio_console.c
++++ b/drivers/char/virtio_console.c
+@@ -1615,8 +1615,8 @@ static void handle_control_message(struc
+               break;
+       case VIRTIO_CONSOLE_RESIZE: {
+               struct {
+-                      __virtio16 rows;
+                       __virtio16 cols;
++                      __virtio16 rows;
+               } size;
+               if (!is_console_port(port))
diff --git a/queue-6.1/wifi-mac80211-discard-beacon-frames-to-non-broadcast-address.patch b/queue-6.1/wifi-mac80211-discard-beacon-frames-to-non-broadcast-address.patch
new file mode 100644 (file)
index 0000000..8850d06
--- /dev/null
@@ -0,0 +1,62 @@
+From stable+bounces-206080-greg=kroah.com@vger.kernel.org Wed Jan  7 03:37:44 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue,  6 Jan 2026 21:34: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: <20260107023440.3510800-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>
+[ adapted RX_DROP return value 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
+@@ -3299,6 +3299,11 @@ ieee80211_rx_h_mgmt_check(struct ieee802
+       if (!ieee80211_is_mgmt(mgmt->frame_control))
+               return RX_DROP_MONITOR;
++      /* 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.1/wifi-mt76-fix-dts-power-limits-on-little-endian-systems.patch b/queue-6.1/wifi-mt76-fix-dts-power-limits-on-little-endian-systems.patch
new file mode 100644 (file)
index 0000000..5f35856
--- /dev/null
@@ -0,0 +1,139 @@
+From stable+bounces-204137-greg=kroah.com@vger.kernel.org Mon Dec 29 22:13:38 2025
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 29 Dec 2025 16:13:28 -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: <20251229211328.1711248-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
+@@ -189,6 +189,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)
+ {
+@@ -228,7 +241,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;
+@@ -237,15 +250,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;
+@@ -253,8 +265,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;
+@@ -269,7 +280,7 @@ mt76_apply_multi_array_limit(s8 *pwr, si
+               if (!len)
+                       break;
+-              cur = be32_to_cpu(data[0]);
++              cur = data[0];
+       }
+ }
+@@ -280,7 +291,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]);
+@@ -326,21 +337,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.1/xhci-dbgtty-fix-device-unregister-fixup.patch b/queue-6.1/xhci-dbgtty-fix-device-unregister-fixup.patch
new file mode 100644 (file)
index 0000000..1c1ade6
--- /dev/null
@@ -0,0 +1,40 @@
+From stable+bounces-204283-greg=kroah.com@vger.kernel.org Tue Dec 30 20:49:13 2025
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 30 Dec 2025 14:49:04 -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: <20251230194904.2442970-3-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
+@@ -523,7 +523,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);