]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
7.0-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 20 May 2026 14:54:21 +0000 (16:54 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 20 May 2026 14:54:21 +0000 (16:54 +0200)
added patches:
accel-rocket-fix-prep_bo-ioctl-leaking-positive-return-from-dma_resv_wait_timeout.patch
alsa-hda-realtek-add-mute-led-quirk-for-hp-pavilion-laptop-16-ag0xxx.patch
alsa-hda-realtek-add-quirk-for-samsung-galaxy-book5-360-headphone.patch
alsa-usb-audio-bound-midi-2.0-endpoint-descriptor-scans.patch
alsa-usb-audio-bound-midi-endpoint-descriptor-scans.patch
alsa-usb-audio-qcom-check-offload-mapping-failures.patch
btrfs-only-release-the-dirty-pages-io-tree-after-successful-writes.patch
ceph-fix-a-buffer-leak-in-__ceph_setxattr.patch
ceph-fix-bug_on-in-__ceph_build_xattrs_blob-due-to-stale-blob-size.patch
ceph-put-folios-not-suitable-for-writeback.patch
drm-amd-display-wrap-dcn32-phantom-plane-allocation-in-dc_run_with_preemption_enabled.patch
drm-bridge-imx8qxp-pxl2dpi-avoid-err_ptr-with-device_node-cleanup.patch
drm-i915-dp-fix-vsc-dynamic-range-signaling-for-rgb-formats.patch
drm-i915-skip-__i915_request_skip-for-already-signaled-requests.patch
drm-loongson-use-managed-kms-polling.patch
drm-panfrost-fix-wait_bo-ioctl-leaking-positive-return-from-dma_resv_wait_timeout.patch
drm-replace-old-pointer-to-new-idr.patch
drm-ttm-convert-eagain-from-dmem_cgroup_try_charge-to-enospc.patch
drm-ttm-fix-ttm_bo_shrink-infinite-lru-walk-on-backup-failure.patch
drm-ttm-fix-ttm_bo_swapout-infinite-lru-walk-on-swapout-failure.patch
drm-xe-dma-buf-fix-uaf-with-retry-loop.patch
drm-xe-dma-buf-handle-empty-bo-and-uaf-races.patch
io-wq-check-that-the-predecessor-is-hashed-in-io_wq_remove_pending.patch
iommu-amd-bounds-check-devid-in-__rlookup_amd_iommu.patch
iommu-fix-ats-invalidation-timeouts-during-__iommu_remove_group_pasid.patch
iommu-fix-nested-pci_dev_reset_iommu_prepare-done.patch
iommu-fix-null-group-domain-dereference-in-pci_dev_reset_iommu_done.patch
iommu-fix-pasid-attach-in-pci_dev_reset_iommu_prepare-done.patch
iommu-fix-warn_on-in-__iommu_group_set_domain_nofail-due-to-reset.patch
iommu-replace-per-group-resetting_domain-with-per-gdev-blocked-flag.patch
iommu-vt-d-avoid-null-pointer-dereference-or-refcount-corruption.patch
iommu-vt-d-disable-dmar-for-intel-q35-igfx.patch
iommu-vt-d-fix-oops-due-to-out-of-scope-access.patch
irqchip-gic-v5-allocate-its-parent-lpis-as-a-range.patch
irqchip-gic-v5-move-lpi-allocation-into-the-lpi-domain.patch
irqchip-gic-v5-support-range-allocation-for-lpis.patch
irqchip-meson-gpio-use-the-correct-register-in-meson_s4_gpio_irq_set_type.patch
irqchip-riscv-imsic-clear-interrupt-move-state-during-cpu-offlining.patch
libceph-fix-potential-null-ptr-deref-in-decode_choose_args.patch
libceph-fix-potential-out-of-bounds-access-in-__ceph_x_decrypt.patch
libceph-fix-potential-out-of-bounds-access-in-crush_decode.patch
libceph-fix-potential-out-of-bounds-access-in-osdmap_decode.patch
libceph-handle-rbtree-insertion-error-in-decode_choose_args.patch
netfs-fix-error-handling-in-netfs_extract_user_iter.patch
nfsd-fix-file-change-detection-in-cb_getattr.patch
nfsd-fix-get_dir_delegation-when-vfs-leases-are-disabled.patch
nfsd-update-mtime-ctime-on-clone-in-presense-of-delegated-attributes.patch
nfsd-update-mtime-ctime-on-copy-in-presence-of-delegated-attributes.patch
nvme-apple-reset-q-sq_tail-during-queue-init.patch
platform-x86-intel-move-debugfs-register-before-creating-devices.patch
platform-x86-lenovo-wmi-helpers-fix-memory-leak-in-lwmi_dev_evaluate_int.patch
platform-x86-lenovo-wmi-helpers-move-gamezone-enums-to-wmi-helpers.patch
platform-x86-lenovo-wmi-other-add-attribute-id-helper-functions.patch
platform-x86-lenovo-wmi-other-balance-component-bind-and-unbind.patch
platform-x86-lenovo-wmi-other-balance-ida-id-allocation-and-free.patch
platform-x86-lenovo-wmi-other-fix-tunable_attr_01-struct-members.patch
platform-x86-lenovo-wmi-other-limit-adding-attributes-to-supported-devices.patch
platform-x86-lenovo-wmi-other-zero-initialize-wmi-arguments.patch
powerpc-warp-fix-error-handling-in-pika_dtm_thread.patch
riscv-misaligned-make-enabling-delegation-depend-on-nonportable.patch
smb-client-fix-possible-infinite-loop-and-oob-read-in-symlink_data.patch
virt-sev-guest-do-not-use-host-controlled-page-order-in-cleanup-path.patch
x86-kexec-push-kjump-return-address-even-for-non-kjump-kexec.patch
xfs-fix-memory-leak-on-error-in-xfs_alloc_zone_info.patch

65 files changed:
queue-7.0/accel-rocket-fix-prep_bo-ioctl-leaking-positive-return-from-dma_resv_wait_timeout.patch [new file with mode: 0644]
queue-7.0/alsa-hda-realtek-add-mute-led-quirk-for-hp-pavilion-laptop-16-ag0xxx.patch [new file with mode: 0644]
queue-7.0/alsa-hda-realtek-add-quirk-for-samsung-galaxy-book5-360-headphone.patch [new file with mode: 0644]
queue-7.0/alsa-usb-audio-bound-midi-2.0-endpoint-descriptor-scans.patch [new file with mode: 0644]
queue-7.0/alsa-usb-audio-bound-midi-endpoint-descriptor-scans.patch [new file with mode: 0644]
queue-7.0/alsa-usb-audio-qcom-check-offload-mapping-failures.patch [new file with mode: 0644]
queue-7.0/btrfs-only-release-the-dirty-pages-io-tree-after-successful-writes.patch [new file with mode: 0644]
queue-7.0/ceph-fix-a-buffer-leak-in-__ceph_setxattr.patch [new file with mode: 0644]
queue-7.0/ceph-fix-bug_on-in-__ceph_build_xattrs_blob-due-to-stale-blob-size.patch [new file with mode: 0644]
queue-7.0/ceph-put-folios-not-suitable-for-writeback.patch [new file with mode: 0644]
queue-7.0/drm-amd-display-wrap-dcn32-phantom-plane-allocation-in-dc_run_with_preemption_enabled.patch [new file with mode: 0644]
queue-7.0/drm-bridge-imx8qxp-pxl2dpi-avoid-err_ptr-with-device_node-cleanup.patch [new file with mode: 0644]
queue-7.0/drm-i915-dp-fix-vsc-dynamic-range-signaling-for-rgb-formats.patch [new file with mode: 0644]
queue-7.0/drm-i915-skip-__i915_request_skip-for-already-signaled-requests.patch [new file with mode: 0644]
queue-7.0/drm-loongson-use-managed-kms-polling.patch [new file with mode: 0644]
queue-7.0/drm-panfrost-fix-wait_bo-ioctl-leaking-positive-return-from-dma_resv_wait_timeout.patch [new file with mode: 0644]
queue-7.0/drm-replace-old-pointer-to-new-idr.patch [new file with mode: 0644]
queue-7.0/drm-ttm-convert-eagain-from-dmem_cgroup_try_charge-to-enospc.patch [new file with mode: 0644]
queue-7.0/drm-ttm-fix-ttm_bo_shrink-infinite-lru-walk-on-backup-failure.patch [new file with mode: 0644]
queue-7.0/drm-ttm-fix-ttm_bo_swapout-infinite-lru-walk-on-swapout-failure.patch [new file with mode: 0644]
queue-7.0/drm-xe-dma-buf-fix-uaf-with-retry-loop.patch [new file with mode: 0644]
queue-7.0/drm-xe-dma-buf-handle-empty-bo-and-uaf-races.patch [new file with mode: 0644]
queue-7.0/io-wq-check-that-the-predecessor-is-hashed-in-io_wq_remove_pending.patch [new file with mode: 0644]
queue-7.0/iommu-amd-bounds-check-devid-in-__rlookup_amd_iommu.patch [new file with mode: 0644]
queue-7.0/iommu-fix-ats-invalidation-timeouts-during-__iommu_remove_group_pasid.patch [new file with mode: 0644]
queue-7.0/iommu-fix-nested-pci_dev_reset_iommu_prepare-done.patch [new file with mode: 0644]
queue-7.0/iommu-fix-null-group-domain-dereference-in-pci_dev_reset_iommu_done.patch [new file with mode: 0644]
queue-7.0/iommu-fix-pasid-attach-in-pci_dev_reset_iommu_prepare-done.patch [new file with mode: 0644]
queue-7.0/iommu-fix-warn_on-in-__iommu_group_set_domain_nofail-due-to-reset.patch [new file with mode: 0644]
queue-7.0/iommu-replace-per-group-resetting_domain-with-per-gdev-blocked-flag.patch [new file with mode: 0644]
queue-7.0/iommu-vt-d-avoid-null-pointer-dereference-or-refcount-corruption.patch [new file with mode: 0644]
queue-7.0/iommu-vt-d-disable-dmar-for-intel-q35-igfx.patch [new file with mode: 0644]
queue-7.0/iommu-vt-d-fix-oops-due-to-out-of-scope-access.patch [new file with mode: 0644]
queue-7.0/irqchip-gic-v5-allocate-its-parent-lpis-as-a-range.patch [new file with mode: 0644]
queue-7.0/irqchip-gic-v5-move-lpi-allocation-into-the-lpi-domain.patch [new file with mode: 0644]
queue-7.0/irqchip-gic-v5-support-range-allocation-for-lpis.patch [new file with mode: 0644]
queue-7.0/irqchip-meson-gpio-use-the-correct-register-in-meson_s4_gpio_irq_set_type.patch [new file with mode: 0644]
queue-7.0/irqchip-riscv-imsic-clear-interrupt-move-state-during-cpu-offlining.patch [new file with mode: 0644]
queue-7.0/libceph-fix-potential-null-ptr-deref-in-decode_choose_args.patch [new file with mode: 0644]
queue-7.0/libceph-fix-potential-out-of-bounds-access-in-__ceph_x_decrypt.patch [new file with mode: 0644]
queue-7.0/libceph-fix-potential-out-of-bounds-access-in-crush_decode.patch [new file with mode: 0644]
queue-7.0/libceph-fix-potential-out-of-bounds-access-in-osdmap_decode.patch [new file with mode: 0644]
queue-7.0/libceph-handle-rbtree-insertion-error-in-decode_choose_args.patch [new file with mode: 0644]
queue-7.0/netfs-fix-error-handling-in-netfs_extract_user_iter.patch [new file with mode: 0644]
queue-7.0/nfsd-fix-file-change-detection-in-cb_getattr.patch [new file with mode: 0644]
queue-7.0/nfsd-fix-get_dir_delegation-when-vfs-leases-are-disabled.patch [new file with mode: 0644]
queue-7.0/nfsd-update-mtime-ctime-on-clone-in-presense-of-delegated-attributes.patch [new file with mode: 0644]
queue-7.0/nfsd-update-mtime-ctime-on-copy-in-presence-of-delegated-attributes.patch [new file with mode: 0644]
queue-7.0/nvme-apple-reset-q-sq_tail-during-queue-init.patch [new file with mode: 0644]
queue-7.0/platform-x86-intel-move-debugfs-register-before-creating-devices.patch [new file with mode: 0644]
queue-7.0/platform-x86-lenovo-wmi-helpers-fix-memory-leak-in-lwmi_dev_evaluate_int.patch [new file with mode: 0644]
queue-7.0/platform-x86-lenovo-wmi-helpers-move-gamezone-enums-to-wmi-helpers.patch [new file with mode: 0644]
queue-7.0/platform-x86-lenovo-wmi-other-add-attribute-id-helper-functions.patch [new file with mode: 0644]
queue-7.0/platform-x86-lenovo-wmi-other-balance-component-bind-and-unbind.patch [new file with mode: 0644]
queue-7.0/platform-x86-lenovo-wmi-other-balance-ida-id-allocation-and-free.patch [new file with mode: 0644]
queue-7.0/platform-x86-lenovo-wmi-other-fix-tunable_attr_01-struct-members.patch [new file with mode: 0644]
queue-7.0/platform-x86-lenovo-wmi-other-limit-adding-attributes-to-supported-devices.patch [new file with mode: 0644]
queue-7.0/platform-x86-lenovo-wmi-other-zero-initialize-wmi-arguments.patch [new file with mode: 0644]
queue-7.0/powerpc-warp-fix-error-handling-in-pika_dtm_thread.patch [new file with mode: 0644]
queue-7.0/riscv-misaligned-make-enabling-delegation-depend-on-nonportable.patch [new file with mode: 0644]
queue-7.0/series
queue-7.0/smb-client-fix-possible-infinite-loop-and-oob-read-in-symlink_data.patch [new file with mode: 0644]
queue-7.0/virt-sev-guest-do-not-use-host-controlled-page-order-in-cleanup-path.patch [new file with mode: 0644]
queue-7.0/x86-kexec-push-kjump-return-address-even-for-non-kjump-kexec.patch [new file with mode: 0644]
queue-7.0/xfs-fix-memory-leak-on-error-in-xfs_alloc_zone_info.patch [new file with mode: 0644]

diff --git a/queue-7.0/accel-rocket-fix-prep_bo-ioctl-leaking-positive-return-from-dma_resv_wait_timeout.patch b/queue-7.0/accel-rocket-fix-prep_bo-ioctl-leaking-positive-return-from-dma_resv_wait_timeout.patch
new file mode 100644 (file)
index 0000000..728225e
--- /dev/null
@@ -0,0 +1,38 @@
+From 74570e12b4705ea11dcdfbfbd0a0b0fdaeff3059 Mon Sep 17 00:00:00 2001
+From: Gyeyoung Baek <gye976@gmail.com>
+Date: Sun, 19 Apr 2026 16:17:15 +0900
+Subject: accel/rocket: Fix prep_bo ioctl leaking positive return from dma_resv_wait_timeout()
+
+From: Gyeyoung Baek <gye976@gmail.com>
+
+commit 74570e12b4705ea11dcdfbfbd0a0b0fdaeff3059 upstream.
+
+dma_resv_wait_timeout() returns a positive 'remaining jiffies' value
+on success, 0 on timeout, and -errno on failure.
+
+rocket_ioctl_prep_bo() returns this 'long' result from an int-typed
+ioctl handler, so positive values reach userspace as bogus errors.
+Explicitly set ret to 0 on the success path.
+
+Fixes: 525ad89dd904 ("accel/rocket: Add IOCTLs for synchronizing memory accesses")
+Cc: stable@vger.kernel.org
+Signed-off-by: Gyeyoung Baek <gye976@gmail.com>
+Reviewed-by: Tomeu Vizoso <tomeu@tomeuvizoso.net>
+Link: https://patch.msgid.link/c0ebf83b345721701b22d8f5bc41c52c0ecf5e16.1776581974.git.gye976@gmail.com
+Signed-off-by: Steven Price <steven.price@arm.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/accel/rocket/rocket_gem.c |    2 ++
+ 1 file changed, 2 insertions(+)
+
+--- a/drivers/accel/rocket/rocket_gem.c
++++ b/drivers/accel/rocket/rocket_gem.c
+@@ -145,6 +145,8 @@ int rocket_ioctl_prep_bo(struct drm_devi
+       ret = dma_resv_wait_timeout(gem_obj->resv, DMA_RESV_USAGE_WRITE, true, timeout);
+       if (!ret)
+               ret = timeout ? -ETIMEDOUT : -EBUSY;
++      else if (ret > 0)
++              ret = 0;
+       shmem_obj = &to_rocket_bo(gem_obj)->base;
diff --git a/queue-7.0/alsa-hda-realtek-add-mute-led-quirk-for-hp-pavilion-laptop-16-ag0xxx.patch b/queue-7.0/alsa-hda-realtek-add-mute-led-quirk-for-hp-pavilion-laptop-16-ag0xxx.patch
new file mode 100644 (file)
index 0000000..30ed651
--- /dev/null
@@ -0,0 +1,38 @@
+From 7d1051ad68df3d584b5f24bfa1fb19f3a24db278 Mon Sep 17 00:00:00 2001
+From: Adrien Burnett <an.arctic.pigeon@gmail.com>
+Date: Thu, 14 May 2026 18:59:05 +0200
+Subject: ALSA: hda/realtek: Add mute LED quirk for HP Pavilion Laptop 16-ag0xxx
+
+From: Adrien Burnett <an.arctic.pigeon@gmail.com>
+
+commit 7d1051ad68df3d584b5f24bfa1fb19f3a24db278 upstream.
+
+Add a SND_PCI_QUIRK entry for the HP Pavilion Laptop 16-ag0xxx
+(subsystem 0x103c:0x8cbc, Realtek ALC245). The
+ALC245_FIXUP_HP_X360_MUTE_LEDS fixup is already used by the
+neighbouring HP Pavilion Aero Laptop 13-bg0xxx (0x103c:0x8cbd);
+it chains the master-mute COEF handler with the GPIO mic-mute
+LED handler, which is what this machine needs.
+
+Tested on the affected hardware: both the mute and mic-mute key
+LEDs respond correctly to the keyboard hotkeys after this change.
+
+Cc: <stable@vger.kernel.org>
+Signed-off-by: Adrien Burnett <an.arctic.pigeon@gmail.com>
+Link: https://patch.msgid.link/20260514165905.21175-1-an.arctic.pigeon@gmail.com
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ sound/hda/codecs/realtek/alc269.c |    1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/sound/hda/codecs/realtek/alc269.c
++++ b/sound/hda/codecs/realtek/alc269.c
+@@ -7146,6 +7146,7 @@ static const struct hda_quirk alc269_fix
+       SND_PCI_QUIRK(0x103c, 0x8ca4, "HP ZBook Fury", ALC245_FIXUP_CS35L41_SPI_2_HP_GPIO_LED),
+       SND_PCI_QUIRK(0x103c, 0x8ca7, "HP ZBook Fury", ALC245_FIXUP_CS35L41_SPI_2_HP_GPIO_LED),
+       SND_PCI_QUIRK(0x103c, 0x8caf, "HP Elite mt645 G8 Mobile Thin Client", ALC236_FIXUP_HP_MUTE_LED_MICMUTE_VREF),
++      SND_PCI_QUIRK(0x103c, 0x8cbc, "HP Pavilion Laptop 16-ag0xxx", ALC245_FIXUP_HP_X360_MUTE_LEDS),
+       SND_PCI_QUIRK(0x103c, 0x8cbd, "HP Pavilion Aero Laptop 13-bg0xxx", ALC245_FIXUP_HP_X360_MUTE_LEDS),
+       SND_PCI_QUIRK(0x103c, 0x8cdd, "HP Spectre", ALC245_FIXUP_HP_SPECTRE_X360_EU0XXX),
+       SND_PCI_QUIRK(0x103c, 0x8cde, "HP OmniBook Ultra Flip Laptop 14t", ALC245_FIXUP_HP_SPECTRE_X360_EU0XXX),
diff --git a/queue-7.0/alsa-hda-realtek-add-quirk-for-samsung-galaxy-book5-360-headphone.patch b/queue-7.0/alsa-hda-realtek-add-quirk-for-samsung-galaxy-book5-360-headphone.patch
new file mode 100644 (file)
index 0000000..e7b7032
--- /dev/null
@@ -0,0 +1,35 @@
+From fd87b510f5f543125ecf51e7c706a9f4bc3352be Mon Sep 17 00:00:00 2001
+From: Markus Kramer <linux@markus-kramer.de>
+Date: Thu, 14 May 2026 00:28:18 +0200
+Subject: ALSA: hda/realtek: Add quirk for Samsung Galaxy Book5 360 headphone
+
+From: Markus Kramer <linux@markus-kramer.de>
+
+commit fd87b510f5f543125ecf51e7c706a9f4bc3352be upstream.
+
+The Samsung Galaxy Book5 360 (NP750QHA, PCI subsystem ID 0x144d:0xc902)
+has severe audio distortion on the 3.5mm headphone jack. Applying
+ALC256_FIXUP_SAMSUNG_HEADPHONE_VERY_QUIET corrects the output path
+configuration, consistent with fixes already applied to other Samsung
+Galaxy Book models using the same ALC256 codec.
+
+Cc: stable@vger.kernel.org
+Link: https://github.com/thesofproject/linux/issues/5648
+Signed-off-by: Markus Kramer <linux@markus-kramer.de>
+Link: https://patch.msgid.link/20260513222818.14351-1-linux@markus-kramer.de
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ sound/hda/codecs/realtek/alc269.c |    1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/sound/hda/codecs/realtek/alc269.c
++++ b/sound/hda/codecs/realtek/alc269.c
+@@ -7448,6 +7448,7 @@ static const struct hda_quirk alc269_fix
+       SND_PCI_QUIRK(0x144d, 0xc870, "Samsung Galaxy Book2 Pro (NP950XED)", ALC298_FIXUP_SAMSUNG_AMP_V2_2_AMPS),
+       SND_PCI_QUIRK(0x144d, 0xc872, "Samsung Galaxy Book2 Pro (NP950XEE)", ALC298_FIXUP_SAMSUNG_AMP_V2_2_AMPS),
+       SND_PCI_QUIRK(0x144d, 0xc886, "Samsung Galaxy Book3 Pro (NP964XFG)", ALC298_FIXUP_SAMSUNG_AMP_V2_4_AMPS),
++      SND_PCI_QUIRK(0x144d, 0xc902, "Samsung Galaxy Book5 360 (NP750QHA)", ALC256_FIXUP_SAMSUNG_HEADPHONE_VERY_QUIET),
+       SND_PCI_QUIRK(0x144d, 0xc1ca, "Samsung Galaxy Book3 Pro 360 (NP960QFG)", ALC298_FIXUP_SAMSUNG_AMP_V2_4_AMPS),
+       SND_PCI_QUIRK(0x144d, 0xc1cb, "Samsung Galaxy Book3 Pro 360 (NP965QFG)", ALC298_FIXUP_SAMSUNG_AMP_V2_4_AMPS),
+       SND_PCI_QUIRK(0x144d, 0xc1cc, "Samsung Galaxy Book3 Ultra (NT960XFH)", ALC298_FIXUP_SAMSUNG_AMP_V2_4_AMPS),
diff --git a/queue-7.0/alsa-usb-audio-bound-midi-2.0-endpoint-descriptor-scans.patch b/queue-7.0/alsa-usb-audio-bound-midi-2.0-endpoint-descriptor-scans.patch
new file mode 100644 (file)
index 0000000..08aa6d1
--- /dev/null
@@ -0,0 +1,58 @@
+From 918be519c7876329e1b6e2ea1c59f0b75e792dca Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?C=C3=A1ssio=20Gabriel?= <cassiogabrielcontato@gmail.com>
+Date: Thu, 7 May 2026 00:40:52 -0300
+Subject: ALSA: usb-audio: Bound MIDI 2.0 endpoint descriptor scans
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Cássio Gabriel <cassiogabrielcontato@gmail.com>
+
+commit 918be519c7876329e1b6e2ea1c59f0b75e792dca upstream.
+
+The USB MIDI 2.0 endpoint parser has the same descriptor walking
+pattern as the legacy MIDI parser. It validates bLength against
+bNumGrpTrmBlock before reading baAssoGrpTrmBlkID[], but not against the
+remaining bytes in the endpoint-extra scan.
+
+A malformed device can therefore make later baAssoGrpTrmBlkID[] reads
+consume bytes past the walked descriptor.
+
+Reject zero-length and overlong descriptors while walking endpoint
+extras.
+
+Fixes: ff49d1df79ae ("ALSA: usb-audio: USB MIDI 2.0 UMP support")
+Cc: stable@vger.kernel.org
+Signed-off-by: Cássio Gabriel <cassiogabrielcontato@gmail.com>
+Link: https://patch.msgid.link/20260507-usb-midi-endpoint-scan-bounds-v1-2-329d7348160e@gmail.com
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ sound/usb/midi2.c |   12 +++++++-----
+ 1 file changed, 7 insertions(+), 5 deletions(-)
+
+--- a/sound/usb/midi2.c
++++ b/sound/usb/midi2.c
+@@ -496,15 +496,17 @@ static void *find_usb_ms_endpoint_descri
+       while (extralen > 3) {
+               struct usb_ms_endpoint_descriptor *ms_ep =
+                       (struct usb_ms_endpoint_descriptor *)extra;
++              int length = ms_ep->bLength;
+-              if (ms_ep->bLength > 3 &&
++              if (!length || length > extralen)
++                      break;
++
++              if (length > 3 &&
+                   ms_ep->bDescriptorType == USB_DT_CS_ENDPOINT &&
+                   ms_ep->bDescriptorSubtype == subtype)
+                       return ms_ep;
+-              if (!extra[0])
+-                      break;
+-              extralen -= extra[0];
+-              extra += extra[0];
++              extralen -= length;
++              extra += length;
+       }
+       return NULL;
+ }
diff --git a/queue-7.0/alsa-usb-audio-bound-midi-endpoint-descriptor-scans.patch b/queue-7.0/alsa-usb-audio-bound-midi-endpoint-descriptor-scans.patch
new file mode 100644 (file)
index 0000000..6ca3ff7
--- /dev/null
@@ -0,0 +1,58 @@
+From d6854daa67be623860f4e1873fd3d3c275aba4ed Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?C=C3=A1ssio=20Gabriel?= <cassiogabrielcontato@gmail.com>
+Date: Thu, 7 May 2026 00:40:51 -0300
+Subject: ALSA: usb-audio: Bound MIDI endpoint descriptor scans
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Cássio Gabriel <cassiogabrielcontato@gmail.com>
+
+commit d6854daa67be623860f4e1873fd3d3c275aba4ed upstream.
+
+snd_usbmidi_get_ms_info() validates the internal MIDIStreaming endpoint
+descriptor size before using baAssocJackID[], but the descriptor walker can
+still return a class-specific endpoint descriptor whose bLength exceeds the
+remaining bytes in the endpoint-extra scan.
+
+That leaves later flexible-array reads bounded by bLength, but not by the
+remaining bytes in the endpoint-extra scan.
+
+Stop walking when bLength is zero or
+extends past the remaining endpoint-extra scan.
+
+Fixes: 5c6cd7021a05 ("ALSA: usb-audio: Fix case when USB MIDI interface has more than one extra endpoint descriptor")
+Cc: stable@vger.kernel.org
+Signed-off-by: Cássio Gabriel <cassiogabrielcontato@gmail.com>
+Link: https://patch.msgid.link/20260507-usb-midi-endpoint-scan-bounds-v1-1-329d7348160e@gmail.com
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ sound/usb/midi.c |   12 +++++++-----
+ 1 file changed, 7 insertions(+), 5 deletions(-)
+
+--- a/sound/usb/midi.c
++++ b/sound/usb/midi.c
+@@ -1947,15 +1947,17 @@ static struct usb_ms_endpoint_descriptor
+       while (extralen > 3) {
+               struct usb_ms_endpoint_descriptor *ms_ep =
+                               (struct usb_ms_endpoint_descriptor *)extra;
++              int length = ms_ep->bLength;
+-              if (ms_ep->bLength > 3 &&
++              if (!length || length > extralen)
++                      break;
++
++              if (length > 3 &&
+                   ms_ep->bDescriptorType == USB_DT_CS_ENDPOINT &&
+                   ms_ep->bDescriptorSubtype == UAC_MS_GENERAL)
+                       return ms_ep;
+-              if (!extra[0])
+-                      break;
+-              extralen -= extra[0];
+-              extra += extra[0];
++              extralen -= length;
++              extra += length;
+       }
+       return NULL;
+ }
diff --git a/queue-7.0/alsa-usb-audio-qcom-check-offload-mapping-failures.patch b/queue-7.0/alsa-usb-audio-qcom-check-offload-mapping-failures.patch
new file mode 100644 (file)
index 0000000..0af6916
--- /dev/null
@@ -0,0 +1,108 @@
+From 814b2c9b30e56074e11fc0a6e5419b3fee0639bc Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?C=C3=A1ssio=20Gabriel?= <cassiogabrielcontato@gmail.com>
+Date: Mon, 11 May 2026 01:36:37 -0300
+Subject: ALSA: usb-audio: qcom: Check offload mapping failures
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Cássio Gabriel <cassiogabrielcontato@gmail.com>
+
+commit 814b2c9b30e56074e11fc0a6e5419b3fee0639bc upstream.
+
+uaudio_transfer_buffer_setup() calls dma_get_sgtable() and then passes
+the sg_table to uaudio_iommu_map_xfer_buf() without checking whether sg
+table construction succeeded. If dma_get_sgtable() fails, the sg_table
+contents are not valid.
+
+uaudio_iommu_map_pa() also ignores iommu_map() failures for the event and
+transfer rings and still returns the allocated IOVA to the QMI response.
+That can expose an unmapped IOVA to the audio DSP. For transfer rings,
+the failed mapping also leaves the IOVA allocator state marked in use.
+
+Check both operations. Free the coherent transfer buffer when sg table
+construction fails, free the sg table when transfer-buffer IOMMU mapping
+fails, and release the transfer-ring IOVA if iommu_map() fails. Also
+return the existing event-ring IOVA when the event ring is already mapped,
+matching the pre-split helper behavior.
+
+Fixes: 326bbc348298 ("ALSA: usb-audio: qcom: Introduce QC USB SND offloading support")
+Fixes: 44499ecb4f28 ("ALSA: usb: qcom: Fix false-positive address space check")
+Cc: stable@vger.kernel.org
+Signed-off-by: Cássio Gabriel <cassiogabrielcontato@gmail.com>
+Link: https://patch.msgid.link/20260511-alsa-usb-qcom-offload-map-errors-v1-1-6502695e58bc@gmail.com
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ sound/usb/qcom/qc_audio_offload.c |   31 +++++++++++++++++++++++++------
+ 1 file changed, 25 insertions(+), 6 deletions(-)
+
+--- a/sound/usb/qcom/qc_audio_offload.c
++++ b/sound/usb/qcom/qc_audio_offload.c
+@@ -565,6 +565,7 @@ static unsigned long uaudio_iommu_map_pa
+       unsigned long iova = 0;
+       bool map = true;
+       int prot = uaudio_iommu_map_prot(dma_coherent);
++      int ret;
+       switch (mtype) {
+       case MEM_EVENT_RING:
+@@ -582,10 +583,24 @@ static unsigned long uaudio_iommu_map_pa
+               dev_err(uaudio_qdev->data->dev, "unknown mem type %d\n", mtype);
+       }
+-      if (!iova || !map)
++      if (!iova)
+               return 0;
+-      iommu_map(uaudio_qdev->data->domain, iova, pa, size, prot, GFP_KERNEL);
++      if (!map)
++              return iova;
++
++      ret = iommu_map(uaudio_qdev->data->domain, iova, pa, size, prot,
++                      GFP_KERNEL);
++      if (ret) {
++              dev_err(uaudio_qdev->data->dev,
++                      "failed to map %zu bytes at iova 0x%08lx: %d\n",
++                      size, iova, ret);
++              if (mtype == MEM_XFER_RING)
++                      uaudio_put_iova(iova, size,
++                                      &uaudio_qdev->xfer_ring_list,
++                                      &uaudio_qdev->xfer_ring_iova_size);
++              return 0;
++      }
+       return iova;
+ }
+@@ -1054,15 +1069,17 @@ static int uaudio_transfer_buffer_setup(
+       if (!xfer_buf)
+               return -ENOMEM;
+-      dma_get_sgtable(subs->dev->bus->sysdev, &xfer_buf_sgt, xfer_buf,
+-                      xfer_buf_dma, len);
++      ret = dma_get_sgtable(subs->dev->bus->sysdev, &xfer_buf_sgt, xfer_buf,
++                            xfer_buf_dma, len);
++      if (ret)
++              goto free_xfer_buf;
+       /* map the physical buffer into sysdev as well */
+       xfer_buf_dma_sysdev = uaudio_iommu_map_xfer_buf(dma_coherent,
+                                                       len, &xfer_buf_sgt);
+       if (!xfer_buf_dma_sysdev) {
+               ret = -ENOMEM;
+-              goto unmap_sync;
++              goto free_sgt;
+       }
+       mem_info->dma = xfer_buf_dma;
+@@ -1073,7 +1090,9 @@ static int uaudio_transfer_buffer_setup(
+       return 0;
+-unmap_sync:
++free_sgt:
++      sg_free_table(&xfer_buf_sgt);
++free_xfer_buf:
+       usb_free_coherent(subs->dev, len, xfer_buf, xfer_buf_dma);
+       return ret;
diff --git a/queue-7.0/btrfs-only-release-the-dirty-pages-io-tree-after-successful-writes.patch b/queue-7.0/btrfs-only-release-the-dirty-pages-io-tree-after-successful-writes.patch
new file mode 100644 (file)
index 0000000..ceccb18
--- /dev/null
@@ -0,0 +1,152 @@
+From 4066c55e109475a06d18a1f127c939d551211956 Mon Sep 17 00:00:00 2001
+From: Qu Wenruo <wqu@suse.com>
+Date: Thu, 30 Apr 2026 10:37:22 +0930
+Subject: btrfs: only release the dirty pages io tree after successful writes
+
+From: Qu Wenruo <wqu@suse.com>
+
+commit 4066c55e109475a06d18a1f127c939d551211956 upstream.
+
+[WARNING]
+With extra warning on dirty extent buffers at umount (aka, the next
+patch in the series), test case generic/388 can trigger the following
+warning about dirty extent buffers at unmount time:
+
+  BTRFS critical (device dm-2 state E): emergency shutdown
+  BTRFS error (device dm-2 state E): error while writing out transaction: -30
+  BTRFS warning (device dm-2 state E): Skipping commit of aborted transaction.
+  BTRFS error (device dm-2 state EA): Transaction 9 aborted (error -30)
+  BTRFS: error (device dm-2 state EA) in cleanup_transaction:2068: errno=-30 Readonly filesystem
+  BTRFS info (device dm-2 state EA): forced readonly
+  BTRFS info (device dm-2 state EA): last unmount of filesystem 4fbf2e15-f941-49a0-bc7c-716315d2777c
+  ------------[ cut here ]------------
+  WARNING: disk-io.c:3311 at invalidate_and_check_btree_folios+0xfd/0x1ca [btrfs], CPU#8: umount/914368
+  CPU: 8 UID: 0 PID: 914368 Comm: umount Tainted: G           OE       7.1.0-rc1-custom+ #372 PREEMPT(full)  2de38db8d1deae71fde295430a0ff3ab98ccf596
+  Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS unknown 02/02/2022
+  RIP: 0010:invalidate_and_check_btree_folios+0xfd/0x1ca [btrfs]
+  Call Trace:
+   <TASK>
+   close_ctree+0x52e/0x574 [btrfs d2f0b1cd330d1287e7a9919d112eadfc0e914efd]
+   generic_shutdown_super+0x89/0x1a0
+   kill_anon_super+0x16/0x40
+   btrfs_kill_super+0x16/0x20 [btrfs d2f0b1cd330d1287e7a9919d112eadfc0e914efd]
+   deactivate_locked_super+0x2d/0xb0
+   cleanup_mnt+0xdc/0x140
+   task_work_run+0x5a/0xa0
+   exit_to_user_mode_loop+0x123/0x4b0
+   do_syscall_64+0x243/0x7c0
+   entry_SYSCALL_64_after_hwframe+0x4b/0x53
+   </TASK>
+  ---[ end trace 0000000000000000 ]---
+  BTRFS warning (device dm-2 state EA): unable to release extent buffer 30539776 owner 9 gen 9 refs 2 flags 0x7
+  BTRFS warning (device dm-2 state EA): unable to release extent buffer 30621696 owner 257 gen 9 refs 2 flags 0x7
+  BTRFS warning (device dm-2 state EA): unable to release extent buffer 30638080 owner 258 gen 9 refs 2 flags 0x7
+  BTRFS warning (device dm-2 state EA): unable to release extent buffer 30654464 owner 7 gen 9 refs 2 flags 0x7
+  BTRFS warning (device dm-2 state EA): unable to release extent buffer 30703616 owner 2 gen 9 refs 2 flags 0x7
+  BTRFS warning (device dm-2 state EA): unable to release extent buffer 30720000 owner 10 gen 9 refs 2 flags 0x7
+  BTRFS warning (device dm-2 state EA): unable to release extent buffer 30736384 owner 4 gen 9 refs 2 flags 0x7
+  BTRFS warning (device dm-2 state EA): unable to release extent buffer 30752768 owner 11 gen 9 refs 2 flags 0x7
+
+I'm using a stripped down version, which seems to trigger the warning
+more reliably:
+
+  _fsstress_pid=""
+  workload()
+  {
+       dmesg -C
+       mkfs.btrfs -f -K $dev > /dev/null
+       echo 1 > /sys/kernel/debug/clear_warn_once
+       mount $dev $mnt
+       $fsstress -w -n 1024 -p 4 -d $mnt &
+       _fsstress_pid=$!
+       sleep 0
+       $godown $mnt
+       pkill --echo -PIPE fsstress > /dev/null
+       wait $_fsstress_pid
+       unset _fsstress_pid
+       umount $mnt
+
+       if dmesg | grep -q "WARNING"; then
+               fail
+       fi
+  }
+
+  for (( i = 0; i < $runtime; i++ )); do
+       echo "=== $i/$runtime ==="
+       workload
+  done
+
+[CAUSE]
+Inside btrfs_write_and_wait_transaction(), we first try to write all
+dirty ebs, then wait for them to finish.
+
+After that we call btrfs_extent_io_tree_release() to free all
+extent states from dirty_pages io tree.
+
+However if we hit an error from btrfs_write_marked_extent(), then we
+still call btrfs_extent_io_tree_release() to clear that dirty_pages io
+tree, which may contain dirty records that we haven't yet submitted.
+
+Furthermore, the later transaction cleanup path will utilize that
+dirty_pages io tree to properly cleanup those dirty ebs, but since it's
+already empty, no dirty ebs are properly cleaned up, thus will later
+trigger the warnings inside invalidate_btree_folios().
+
+[FIX]
+Normally such dirty ebs won't cause problems, as when the iput() is
+called on the btree inode, the dirty ebs will be forcibly written back,
+and since the fs is already in an error status, such writeback will not
+reach disk and finish immediately.
+
+But it's still better to get rid of such dirty ebs, if we ended up with
+dirty ebs but the fs is not in an error status, then such writeback at
+iput() time will be too late, as all workers are already stopped but
+writeback will utilize workers, which will lead to NULL pointer
+dereferences.
+
+Instead of unconditionally calling btrfs_extent_io_tree_release(), only
+call it if btrfs_write_and_wait_transaction() finished successfully, so
+that @dirty_pages extent io tree is kept untouched for transaction
+cleanup.
+
+CC: stable@vger.kernel.org # 6.1+
+Reviewed-by: Filipe Manana <fdmanana@suse.com>
+Signed-off-by: Qu Wenruo <wqu@suse.com>
+Signed-off-by: David Sterba <dsterba@suse.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/btrfs/disk-io.c     |    1 +
+ fs/btrfs/transaction.c |    9 ++++-----
+ 2 files changed, 5 insertions(+), 5 deletions(-)
+
+--- a/fs/btrfs/disk-io.c
++++ b/fs/btrfs/disk-io.c
+@@ -4709,6 +4709,7 @@ static void btrfs_destroy_marked_extents
+                       free_extent_buffer_stale(eb);
+               }
+       }
++      btrfs_extent_io_tree_release(dirty_pages);
+ }
+ static void btrfs_destroy_pinned_extent(struct btrfs_fs_info *fs_info,
+--- a/fs/btrfs/transaction.c
++++ b/fs/btrfs/transaction.c
+@@ -1275,14 +1275,13 @@ static int btrfs_write_and_wait_transact
+       blk_finish_plug(&plug);
+       ret2 = btrfs_wait_extents(fs_info, dirty_pages);
+-      btrfs_extent_io_tree_release(&trans->transaction->dirty_pages);
+-
+       if (ret)
+               return ret;
+-      else if (ret2)
++      if (ret2)
+               return ret2;
+-      else
+-              return 0;
++
++      btrfs_extent_io_tree_release(&trans->transaction->dirty_pages);
++      return 0;
+ }
+ /*
diff --git a/queue-7.0/ceph-fix-a-buffer-leak-in-__ceph_setxattr.patch b/queue-7.0/ceph-fix-a-buffer-leak-in-__ceph_setxattr.patch
new file mode 100644 (file)
index 0000000..f8c1ae9
--- /dev/null
@@ -0,0 +1,34 @@
+From 5d3cc36b4e77a27ce7b686b7c59c7072bcb3fa8e Mon Sep 17 00:00:00 2001
+From: Viacheslav Dubeyko <Slava.Dubeyko@ibm.com>
+Date: Thu, 9 Apr 2026 12:26:02 -0700
+Subject: ceph: fix a buffer leak in __ceph_setxattr()
+
+From: Viacheslav Dubeyko <Slava.Dubeyko@ibm.com>
+
+commit 5d3cc36b4e77a27ce7b686b7c59c7072bcb3fa8e upstream.
+
+The old_blob in __ceph_setxattr() can store
+ci->i_xattrs.prealloc_blob value during the retry.
+However, it is never called the ceph_buffer_put()
+for the old_blob object. This patch fixes the issue of
+the buffer leak.
+
+Cc: stable@vger.kernel.org
+Signed-off-by: Viacheslav Dubeyko <Slava.Dubeyko@ibm.com>
+Reviewed-by: Alex Markuze <amarkuze@redhat.com>
+Signed-off-by: Ilya Dryomov <idryomov@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/ceph/xattr.c |    1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/fs/ceph/xattr.c
++++ b/fs/ceph/xattr.c
+@@ -1294,6 +1294,7 @@ retry:
+ do_sync:
+       spin_unlock(&ci->i_ceph_lock);
++      ceph_buffer_put(old_blob);
+ do_sync_unlocked:
+       if (lock_snap_rwsem)
+               up_read(&mdsc->snap_rwsem);
diff --git a/queue-7.0/ceph-fix-bug_on-in-__ceph_build_xattrs_blob-due-to-stale-blob-size.patch b/queue-7.0/ceph-fix-bug_on-in-__ceph_build_xattrs_blob-due-to-stale-blob-size.patch
new file mode 100644 (file)
index 0000000..7af007c
--- /dev/null
@@ -0,0 +1,125 @@
+From 0c22d9511cbde746622f8e4c11aaa63fe76d45f9 Mon Sep 17 00:00:00 2001
+From: Viacheslav Dubeyko <Slava.Dubeyko@ibm.com>
+Date: Thu, 9 Apr 2026 12:43:40 -0700
+Subject: ceph: fix BUG_ON in __ceph_build_xattrs_blob() due to stale blob size
+
+From: Viacheslav Dubeyko <Slava.Dubeyko@ibm.com>
+
+commit 0c22d9511cbde746622f8e4c11aaa63fe76d45f9 upstream.
+
+The generic/642 test-case can reproduce the kernel crash:
+
+[40243.605254] ------------[ cut here ]------------
+[40243.605956] kernel BUG at fs/ceph/xattr.c:918!
+[40243.607142] Oops: invalid opcode: 0000 [#1] SMP PTI
+[40243.608067] CPU: 7 UID: 0 PID: 498762 Comm: kworker/7:1 Not tainted 7.0.0-rc7+ #3 PREEMPT(full)
+[40243.609700] Hardware name: QEMU Ubuntu 25.10 PC v2 (i440FX + PIIX, + 10.1 machine, 1996), BIOS 1.16.3-debian-1.16.3-2 04/01/2014
+[40243.611820] Workqueue: ceph-msgr ceph_con_workfn
+[40243.612715] RIP: 0010:__ceph_build_xattrs_blob+0x1b8/0x1e0
+[40243.613731] Code: 0f 84 82 fe ff ff e9 cf 8e 56 ff 48 8d 65 e8 31 c0 5b 41 5c 41 5d 5d 31 d2 31 c9 31 f6 31 ff 45 31 c0 45 31 c9 c3 cc cc cc cc <0f> 0b 4c 8b 62 08 41 8b 85 24 07 00 00 49 83 c4 04 41 89 44 24 fc
+[40243.616888] RSP: 0018:ffffcc80c4d4b688 EFLAGS: 00010287
+[40243.617773] RAX: 0000000000010026 RBX: 0000000000000001 RCX: 0000000000000000
+[40243.618928] RDX: ffff8a773798dee0 RSI: 0000000000000000 RDI: 0000000000000000
+[40243.620158] RBP: ffffcc80c4d4b6a0 R08: 0000000000000000 R09: 0000000000000000
+[40243.621573] R10: 0000000000000000 R11: 0000000000000000 R12: ffff8a75f3b58000
+[40243.622907] R13: ffff8a75f3b58000 R14: 0000000000000080 R15: 000000000000bffd
+[40243.624054] FS:  0000000000000000(0000) GS:ffff8a787d1b4000(0000) knlGS:0000000000000000
+[40243.625331] CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
+[40243.626269] CR2: 000072f390b623c0 CR3: 000000011c02a003 CR4: 0000000000372ef0
+[40243.627408] Call Trace:
+[40243.627839]  <TASK>
+[40243.628188]  __prep_cap+0x3fd/0x4a0
+[40243.628789]  ? do_raw_spin_unlock+0x4e/0xe0
+[40243.629474]  ceph_check_caps+0x46a/0xc80
+[40243.630094]  ? __lock_acquire+0x4a2/0x2650
+[40243.630773]  ? find_held_lock+0x31/0x90
+[40243.631347]  ? handle_cap_grant+0x79f/0x1060
+[40243.632068]  ? lock_release+0xd9/0x300
+[40243.632696]  ? __mutex_unlock_slowpath+0x3e/0x340
+[40243.633429]  ? lock_release+0xd9/0x300
+[40243.634052]  handle_cap_grant+0xcf6/0x1060
+[40243.634745]  ceph_handle_caps+0x122b/0x2110
+[40243.635415]  mds_dispatch+0x5bd/0x2160
+[40243.636034]  ? ceph_con_process_message+0x65/0x190
+[40243.636828]  ? lock_release+0xd9/0x300
+[40243.637431]  ceph_con_process_message+0x7a/0x190
+[40243.638184]  ? kfree+0x311/0x4f0
+[40243.638749]  ? kfree+0x311/0x4f0
+[40243.639268]  process_message+0x16/0x1a0
+[40243.639915]  ? sg_free_table+0x39/0x90
+[40243.640572]  ceph_con_v2_try_read+0xf58/0x2120
+[40243.641255]  ? lock_acquire+0xc8/0x300
+[40243.641863]  ceph_con_workfn+0x151/0x820
+[40243.642493]  process_one_work+0x22f/0x630
+[40243.643093]  ? process_one_work+0x254/0x630
+[40243.643770]  worker_thread+0x1e2/0x400
+[40243.644332]  ? __pfx_worker_thread+0x10/0x10
+[40243.645020]  kthread+0x109/0x140
+[40243.645560]  ? __pfx_kthread+0x10/0x10
+[40243.646125]  ret_from_fork+0x3f8/0x480
+[40243.646752]  ? __pfx_kthread+0x10/0x10
+[40243.647316]  ? __pfx_kthread+0x10/0x10
+[40243.647919]  ret_from_fork_asm+0x1a/0x30
+[40243.648556]  </TASK>
+[40243.648902] Modules linked in: overlay hctr2 libpolyval chacha libchacha adiantum libnh libpoly1305 essiv intel_rapl_msr intel_rapl_common intel_uncore_frequency_common skx_edac_common nfit kvm_intel kvm irqbypass joydev ghash_clmulni_intel aesni_intel rapl input_leds mac_hid psmouse vga16fb serio_raw vgastate floppy i2c_piix4 pata_acpi bochs qemu_fw_cfg i2c_smbus sch_fq_codel rbd dm_crypt msr parport_pc ppdev lp parport efi_pstore
+[40243.654766] ---[ end trace 0000000000000000 ]---
+
+Commit d93231a6bc8a ("ceph: prevent a client from exceeding the MDS
+maximum xattr size") moved the required_blob_size computation to before
+the __build_xattrs() call, introducing a race.
+
+__build_xattrs() releases and reacquires i_ceph_lock during execution.
+In that window, handle_cap_grant() may update i_xattrs.blob with a
+newer MDS-provided blob and bump i_xattrs.version.  When
+__build_xattrs() detects that index_version < version, it destroys and
+rebuilds the entire xattr rb-tree from the new blob, potentially
+increasing count, names_size, and vals_size.
+
+The prealloc_blob size check that follows still uses the stale
+required_blob_size computed before the rebuild, so it passes even when
+prealloc_blob is too small for the now-larger tree. After __set_xattr()
+adds one more xattr on top, __ceph_build_xattrs_blob() is called from
+the cap flush path and hits:
+
+    BUG_ON(need > ci->i_xattrs.prealloc_blob->alloc_len);
+
+Fix this by recomputing required_blob_size after __build_xattrs()
+returns, using the current tree state. Also re-validate against
+m_max_xattr_size to fall back to the sync path if the rebuilt tree now
+exceeds the MDS limit.
+
+Cc: stable@vger.kernel.org
+Fixes: d93231a6bc8a ("ceph: prevent a client from exceeding the MDS maximum xattr size")
+Signed-off-by: Viacheslav Dubeyko <Slava.Dubeyko@ibm.com>
+Reviewed-by: Alex Markuze <amarkuze@redhat.com>
+Signed-off-by: Ilya Dryomov <idryomov@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/ceph/xattr.c |   16 ++++++++++++++++
+ 1 file changed, 16 insertions(+)
+
+--- a/fs/ceph/xattr.c
++++ b/fs/ceph/xattr.c
+@@ -1254,6 +1254,22 @@ retry:
+             ceph_vinop(inode), name, ceph_cap_string(issued));
+       __build_xattrs(inode);
++      /*
++       * __build_xattrs() may have released and reacquired i_ceph_lock,
++       * during which handle_cap_grant() could have replaced i_xattrs.blob
++       * with a newer MDS-provided blob and bumped i_xattrs.version. If that
++       * caused __build_xattrs() to rebuild the rb-tree from the new blob,
++       * count/names_size/vals_size may now be larger than when
++       * required_blob_size was computed above. Recompute it here so the
++       * prealloc_blob size check below reflects the current tree state.
++       */
++      required_blob_size = __get_required_blob_size(ci, name_len, val_len);
++      if (required_blob_size > mdsc->mdsmap->m_max_xattr_size) {
++              doutc(cl, "sync (size too large): %d > %llu\n",
++                    required_blob_size, mdsc->mdsmap->m_max_xattr_size);
++              goto do_sync;
++      }
++
+       if (!ci->i_xattrs.prealloc_blob ||
+           required_blob_size > ci->i_xattrs.prealloc_blob->alloc_len) {
+               struct ceph_buffer *blob;
diff --git a/queue-7.0/ceph-put-folios-not-suitable-for-writeback.patch b/queue-7.0/ceph-put-folios-not-suitable-for-writeback.patch
new file mode 100644 (file)
index 0000000..a4582cb
--- /dev/null
@@ -0,0 +1,42 @@
+From 544576f0f05c4a759806acddfaaeb686f14fb4b0 Mon Sep 17 00:00:00 2001
+From: Hristo Venev <hristo@venev.name>
+Date: Mon, 4 May 2026 18:54:45 +0300
+Subject: ceph: put folios not suitable for writeback
+
+From: Hristo Venev <hristo@venev.name>
+
+commit 544576f0f05c4a759806acddfaaeb686f14fb4b0 upstream.
+
+The batch holds references to the folios (see `filemap_get_folios`,
+`folio_batch_release`), so we need to `folio_put` the folios we remove.
+
+Tested on v6.18.
+
+Cc: stable@vger.kernel.org
+Link: https://tracker.ceph.com/issues/74156
+Signed-off-by: Hristo Venev <hristo@venev.name>
+Reviewed-by: Viacheslav Dubeyko <Slava.Dubeyko@ibm.com>
+Signed-off-by: Ilya Dryomov <idryomov@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/ceph/addr.c |    2 ++
+ 1 file changed, 2 insertions(+)
+
+--- a/fs/ceph/addr.c
++++ b/fs/ceph/addr.c
+@@ -1322,6 +1322,7 @@ void ceph_process_folio_batch(struct add
+                                                 ceph_wbc, folio);
+               if (rc == -ENODATA) {
+                       folio_unlock(folio);
++                      folio_put(folio);
+                       ceph_wbc->fbatch.folios[i] = NULL;
+                       continue;
+               } else if (rc == -E2BIG) {
+@@ -1332,6 +1333,7 @@ void ceph_process_folio_batch(struct add
+               if (!folio_clear_dirty_for_io(folio)) {
+                       doutc(cl, "%p !folio_clear_dirty_for_io\n", folio);
+                       folio_unlock(folio);
++                      folio_put(folio);
+                       ceph_wbc->fbatch.folios[i] = NULL;
+                       continue;
+               }
diff --git a/queue-7.0/drm-amd-display-wrap-dcn32-phantom-plane-allocation-in-dc_run_with_preemption_enabled.patch b/queue-7.0/drm-amd-display-wrap-dcn32-phantom-plane-allocation-in-dc_run_with_preemption_enabled.patch
new file mode 100644 (file)
index 0000000..5e086e6
--- /dev/null
@@ -0,0 +1,65 @@
+From 183182235f6d53bac62c6c39014738a54a68dfa6 Mon Sep 17 00:00:00 2001
+From: Mikhail Gavrilov <mikhail.v.gavrilov@gmail.com>
+Date: Tue, 5 May 2026 09:05:37 +0800
+Subject: drm/amd/display: Wrap DCN32 phantom-plane allocation in DC_RUN_WITH_PREEMPTION_ENABLED
+
+From: Mikhail Gavrilov <mikhail.v.gavrilov@gmail.com>
+
+commit 183182235f6d53bac62c6c39014738a54a68dfa6 upstream.
+
+[Why]
+dcn32_validate_bandwidth() wraps dcn32_internal_validate_bw() with
+DC_FP_START()/DC_FP_END(). In x86 non-RT, DC_FP_START takes fpregs_lock(),
+which disables local softirqs.
+
+The DML1 path through dcn32_enable_phantom_plane() calls kvzalloc() to
+allocate ~335 KiB for dc_plane_state. This triggers the vmalloc path,
+which calls BUG_ON(in_interrupt()) because it's invoked within the
+FPU-enabled (softirq disabled) region, leading to a kernel crash.
+
+[How]
+Wrap the dc_state_create_phantom_plane() call with the
+DC_RUN_WITH_PREEMPTION_ENABLED() macro to allow preemption during
+this memory allocation.
+
+Fixes: 235c67634230 ("drm/amd/display: add DCN32/321 specific files for Display Core")
+Closes: https://gitlab.freedesktop.org/drm/amd/-/work_items/4470
+Reviewed-by: Aurabindo Pillai <aurabindo.pillai@amd.com>
+Signed-off-by: Mikhail Gavrilov <mikhail.v.gavrilov@gmail.com>
+Signed-off-by: James Lin <pinglei.lin@amd.com>
+Tested-by: Daniel Wheeler <daniel.wheeler@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+(cherry picked from commit 885ccbef7b94a8b38f69c4211c679021aa27ad11)
+Cc: stable@vger.kernel.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/gpu/drm/amd/display/dc/resource/dcn32/dcn32_resource.c |    8 +++++++-
+ 1 file changed, 7 insertions(+), 1 deletion(-)
+
+--- a/drivers/gpu/drm/amd/display/dc/resource/dcn32/dcn32_resource.c
++++ b/drivers/gpu/drm/amd/display/dc/resource/dcn32/dcn32_resource.c
+@@ -92,9 +92,14 @@
+ #include "dml/dcn32/dcn32_fpu.h"
+ #include "dc_state_priv.h"
++#include "dc_fpu.h"
+ #include "dml2_0/dml2_wrapper.h"
++#if !defined(DC_RUN_WITH_PREEMPTION_ENABLED)
++#define DC_RUN_WITH_PREEMPTION_ENABLED(code) code
++#endif
++
+ #define DC_LOGGER_INIT(logger)
+ enum dcn32_clk_src_array_id {
+@@ -1684,7 +1689,8 @@ static void dcn32_enable_phantom_plane(s
+               if (curr_pipe->top_pipe && curr_pipe->top_pipe->plane_state == curr_pipe->plane_state)
+                       phantom_plane = prev_phantom_plane;
+               else
+-                      phantom_plane = dc_state_create_phantom_plane(dc, context, curr_pipe->plane_state);
++                      DC_RUN_WITH_PREEMPTION_ENABLED(phantom_plane =
++                              dc_state_create_phantom_plane(dc, context, curr_pipe->plane_state));
+               if (!phantom_plane)
+                       continue;
diff --git a/queue-7.0/drm-bridge-imx8qxp-pxl2dpi-avoid-err_ptr-with-device_node-cleanup.patch b/queue-7.0/drm-bridge-imx8qxp-pxl2dpi-avoid-err_ptr-with-device_node-cleanup.patch
new file mode 100644 (file)
index 0000000..f9f91ae
--- /dev/null
@@ -0,0 +1,120 @@
+From 53597deca0e38c30e6cd4ba2114fa42d2bcd85bb Mon Sep 17 00:00:00 2001
+From: Guangshuo Li <lgs201920130244@gmail.com>
+Date: Thu, 7 May 2026 18:06:03 +0800
+Subject: drm/bridge: imx8qxp-pxl2dpi: avoid ERR_PTR with device_node cleanup
+
+From: Guangshuo Li <lgs201920130244@gmail.com>
+
+commit 53597deca0e38c30e6cd4ba2114fa42d2bcd85bb upstream.
+
+imx8qxp_pxl2dpi_get_available_ep_from_port() returns ERR_PTR()
+on errors. imx8qxp_pxl2dpi_find_next_bridge() stores its return
+value in a __free(device_node) variable before checking IS_ERR().
+When the function returns on the error path, the cleanup action calls
+of_node_put() on the ERR_PTR() value.
+
+Do not let a device_node cleanup variable hold error pointers. Change
+imx8qxp_pxl2dpi_get_available_ep_from_port() to return an int and pass
+the endpoint node through an output argument. Initialize the output
+argument to NULL so callers hold either NULL on error paths or a valid
+device_node pointer on successful path.
+
+Fixes: ceea3f7806a10 ("drm/bridge: imx8qxp-pxl2dpi: simplify put of device_node pointers")
+Cc: stable@vger.kernel.org
+Reviewed-by: Liu Ying <victor.liu@nxp.com>
+Signed-off-by: Guangshuo Li <lgs201920130244@gmail.com>
+Link: https://patch.msgid.link/20260507100604.667731-1-lgs201920130244@gmail.com
+Signed-off-by: Liu Ying <victor.liu@nxp.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/gpu/drm/bridge/imx/imx8qxp-pxl2dpi.c |   40 +++++++++++++++------------
+ 1 file changed, 23 insertions(+), 17 deletions(-)
+
+--- a/drivers/gpu/drm/bridge/imx/imx8qxp-pxl2dpi.c
++++ b/drivers/gpu/drm/bridge/imx/imx8qxp-pxl2dpi.c
+@@ -222,52 +222,58 @@ static const struct drm_bridge_funcs imx
+                       imx8qxp_pxl2dpi_bridge_atomic_get_output_bus_fmts,
+ };
+-static struct device_node *
++static int
+ imx8qxp_pxl2dpi_get_available_ep_from_port(struct imx8qxp_pxl2dpi *p2d,
+-                                         u32 port_id)
++                                         u32 port_id,
++                                         struct device_node **ep)
+ {
+-      struct device_node *port, *ep;
++      struct device_node *port;
++      int ret = 0;
+       int ep_cnt;
++      *ep = NULL;
++
+       port = of_graph_get_port_by_id(p2d->dev->of_node, port_id);
+       if (!port) {
+               DRM_DEV_ERROR(p2d->dev, "failed to get port@%u\n", port_id);
+-              return ERR_PTR(-ENODEV);
++              return -ENODEV;
+       }
+       ep_cnt = of_get_available_child_count(port);
+       if (ep_cnt == 0) {
+               DRM_DEV_ERROR(p2d->dev, "no available endpoints of port@%u\n",
+                             port_id);
+-              ep = ERR_PTR(-ENODEV);
++              ret = -ENODEV;
+               goto out;
+       } else if (ep_cnt > 1) {
+               DRM_DEV_ERROR(p2d->dev,
+                             "invalid available endpoints of port@%u\n",
+                             port_id);
+-              ep = ERR_PTR(-EINVAL);
++              ret = -EINVAL;
+               goto out;
+       }
+-      ep = of_get_next_available_child(port, NULL);
+-      if (!ep) {
++      *ep = of_get_next_available_child(port, NULL);
++      if (!*ep) {
+               DRM_DEV_ERROR(p2d->dev,
+                             "failed to get available endpoint of port@%u\n",
+                             port_id);
+-              ep = ERR_PTR(-ENODEV);
++              ret = -ENODEV;
+               goto out;
+       }
+ out:
+       of_node_put(port);
+-      return ep;
++      return ret;
+ }
+ static int imx8qxp_pxl2dpi_find_next_bridge(struct imx8qxp_pxl2dpi *p2d)
+ {
+-      struct device_node *ep __free(device_node) =
+-              imx8qxp_pxl2dpi_get_available_ep_from_port(p2d, 1);
+-      if (IS_ERR(ep))
+-              return PTR_ERR(ep);
++      struct device_node *ep __free(device_node) = NULL;
++      int ret;
++
++      ret = imx8qxp_pxl2dpi_get_available_ep_from_port(p2d, 1, &ep);
++      if (ret)
++              return ret;
+       struct device_node *remote __free(device_node) = of_graph_get_remote_port_parent(ep);
+       if (!remote || !of_device_is_available(remote)) {
+@@ -291,9 +297,9 @@ static int imx8qxp_pxl2dpi_set_pixel_lin
+       struct of_endpoint endpoint;
+       int ret;
+-      ep = imx8qxp_pxl2dpi_get_available_ep_from_port(p2d, 0);
+-      if (IS_ERR(ep))
+-              return PTR_ERR(ep);
++      ret = imx8qxp_pxl2dpi_get_available_ep_from_port(p2d, 0, &ep);
++      if (ret)
++              return ret;
+       ret = of_graph_parse_endpoint(ep, &endpoint);
+       if (ret) {
diff --git a/queue-7.0/drm-i915-dp-fix-vsc-dynamic-range-signaling-for-rgb-formats.patch b/queue-7.0/drm-i915-dp-fix-vsc-dynamic-range-signaling-for-rgb-formats.patch
new file mode 100644 (file)
index 0000000..9d1d501
--- /dev/null
@@ -0,0 +1,55 @@
+From 1ae15b6c7965d137eef21f2cc7d367b29cb88369 Mon Sep 17 00:00:00 2001
+From: Chaitanya Kumar Borah <chaitanya.kumar.borah@intel.com>
+Date: Tue, 5 May 2026 14:39:20 +0530
+Subject: drm/i915/dp: Fix VSC dynamic range signaling for RGB formats
+
+From: Chaitanya Kumar Borah <chaitanya.kumar.borah@intel.com>
+
+commit 1ae15b6c7965d137eef21f2cc7d367b29cb88369 upstream.
+
+For RGB, set dynamic_range to CTA or VESA based on
+crtc_state->limited_color_range so sinks apply correct
+quantization. YCbCr remains limited (CTA) range.
+(DP v1.4, Table 5-1)
+
+v2:
+- Added Reported-by and Tested-by tags
+
+v3:
+- Add back YCbCr comment(Suraj)
+
+Cc: stable@vger.kernel.org #v5.8+
+Reported-by: DeepChirp <DeepChirp@outlook.com>
+Closes: https://gitlab.freedesktop.org/drm/i915/kernel/-/work_items/15874
+Tested-by: DeepChirp <DeepChirp@outlook.com>
+Fixes: 9799c4c3b76e ("drm/i915/dp: Add compute routine for DP VSC SDP")
+Assisted-by: GitHub-Copilot:GPT-5.4
+Signed-off-by: Chaitanya Kumar Borah <chaitanya.kumar.borah@intel.com>
+Reviewed-by: Suraj Kandpal <suraj.kandpal@intel.com>
+Signed-off-by: Suraj Kandpal <suraj.kandpal@intel.com>
+Link: https://patch.msgid.link/20260505090920.2479112-1-chaitanya.kumar.borah@intel.com
+(cherry picked from commit 38e10ddae6f8d42a2e8437fcd25a1cac51106c64)
+Signed-off-by: Tvrtko Ursulin <tursulin@ursulin.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/gpu/drm/i915/display/intel_dp.c |    9 +++++++--
+ 1 file changed, 7 insertions(+), 2 deletions(-)
+
+--- a/drivers/gpu/drm/i915/display/intel_dp.c
++++ b/drivers/gpu/drm/i915/display/intel_dp.c
+@@ -2981,8 +2981,13 @@ static void intel_dp_compute_vsc_colorim
+       drm_WARN_ON(display->drm,
+                   vsc->bpc == 6 && vsc->pixelformat != DP_PIXELFORMAT_RGB);
+-      /* all YCbCr are always limited range */
+-      vsc->dynamic_range = DP_DYNAMIC_RANGE_CTA;
++      /* All YCbCr formats are always limited range. */
++      if (vsc->pixelformat == DP_PIXELFORMAT_RGB)
++              vsc->dynamic_range = crtc_state->limited_color_range ?
++                      DP_DYNAMIC_RANGE_CTA : DP_DYNAMIC_RANGE_VESA;
++      else
++              vsc->dynamic_range = DP_DYNAMIC_RANGE_CTA;
++
+       vsc->content_type = DP_CONTENT_TYPE_NOT_DEFINED;
+ }
diff --git a/queue-7.0/drm-i915-skip-__i915_request_skip-for-already-signaled-requests.patch b/queue-7.0/drm-i915-skip-__i915_request_skip-for-already-signaled-requests.patch
new file mode 100644 (file)
index 0000000..a44605c
--- /dev/null
@@ -0,0 +1,61 @@
+From 4cfe4c0efbdcde742a47813180cc69b132d7598e Mon Sep 17 00:00:00 2001
+From: Sebastian Brzezinka <sebastian.brzezinka@intel.com>
+Date: Thu, 16 Apr 2026 13:31:18 +0200
+Subject: drm/i915: skip __i915_request_skip() for already signaled requests
+
+From: Sebastian Brzezinka <sebastian.brzezinka@intel.com>
+
+commit 4cfe4c0efbdcde742a47813180cc69b132d7598e upstream.
+
+After a GPU reset the HWSP is zeroed, so previously completed
+requests appear incomplete. If such a request is picked up during
+reset_rewind() and marked guilty, i915_request_set_error_once()
+returns early (fence already signaled), leaving fence.error without
+a fatal error code. The subsequent __i915_request_skip() then hits:
+```
+GEM_BUG_ON(!fatal_error(rq->fence.error))
+```
+
+Fixes a kernel BUG observed on Sandy Bridge (Gen6) during
+heartbeat-triggered engine resets.
+```
+kernel BUG at drivers/gpu/drm/i915/i915_request.c:556!
+RIP: __i915_request_skip+0x15e/0x1d0 [i915]
+...
+__i915_request_reset+0x212/0xa70 [i915]
+reset_rewind+0xe4/0x280 [i915]
+intel_gt_reset+0x30d/0x5b0 [i915]
+heartbeat+0x516/0x530 [i915]
+```
+
+Guard __i915_request_skip() with i915_request_signaled(), if the
+fence is already signaled, the ring content is committed and there
+is nothing left to skip.
+
+Fixes: 36e191f0644b ("drm/i915: Apply i915_request_skip() on submission")
+Closes: https://gitlab.freedesktop.org/drm/i915/kernel/-/work_items/13729
+Signed-off-by: Sebastian Brzezinka <sebastian.brzezinka@intel.com>
+Cc: stable@vger.kernel.org # v5.7+
+Reviewed-by: Krzysztof Karas <krzysztof.karas@intel.com>
+Reviewed-by: Andi Shyti <andi.shyti@linux.intel.com>
+Signed-off-by: Andi Shyti <andi.shyti@linux.intel.com>
+Link: https://lore.kernel.org/r/fe76921d35b6ae85aa651822726d0d9815aa5362.1776339012.git.sebastian.brzezinka@intel.com
+(cherry picked from commit 5ba54393dcd7adf75a9f39f5a933b1538349cad5)
+Signed-off-by: Tvrtko Ursulin <tursulin@ursulin.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/gpu/drm/i915/gt/intel_reset.c |    3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+--- a/drivers/gpu/drm/i915/gt/intel_reset.c
++++ b/drivers/gpu/drm/i915/gt/intel_reset.c
+@@ -132,7 +132,8 @@ void __i915_request_reset(struct i915_re
+       rcu_read_lock(); /* protect the GEM context */
+       if (guilty) {
+               i915_request_set_error_once(rq, -EIO);
+-              __i915_request_skip(rq);
++              if (!i915_request_signaled(rq))
++                      __i915_request_skip(rq);
+               banned = mark_guilty(rq);
+       } else {
+               i915_request_set_error_once(rq, -EAGAIN);
diff --git a/queue-7.0/drm-loongson-use-managed-kms-polling.patch b/queue-7.0/drm-loongson-use-managed-kms-polling.patch
new file mode 100644 (file)
index 0000000..bd4d38d
--- /dev/null
@@ -0,0 +1,46 @@
+From 0a9c56dd387605d17dabeedd9fdd2c4c1d0bab7b Mon Sep 17 00:00:00 2001
+From: Myeonghun Pak <mhun512@gmail.com>
+Date: Wed, 13 May 2026 15:57:00 +0900
+Subject: drm/loongson: Use managed KMS polling
+
+From: Myeonghun Pak <mhun512@gmail.com>
+
+commit 0a9c56dd387605d17dabeedd9fdd2c4c1d0bab7b upstream.
+
+lsdc_pci_probe() initializes KMS polling before setting up vblank support,
+requesting the IRQ and registering the DRM device. If any of those later
+steps fails, probe returns without finalizing polling. The driver also
+never finalizes polling on regular removal.
+
+Use drmm_kms_helper_poll_init() so polling is tied to the DRM device
+lifetime and automatically finalized on probe failure and device removal.
+
+This issue was identified during our ongoing static-analysis research while
+reviewing kernel code.
+
+Fixes: f39db26c5428 ("drm: Add kms driver for loongson display controller")
+Cc: stable@vger.kernel.org
+Co-developed-by: Ijae Kim <ae878000@gmail.com>
+Signed-off-by: Ijae Kim <ae878000@gmail.com>
+Reviewed-by: Thomas Zimmermann <tzimmermann@suse.de>
+Acked-by: Jianmin Lv <lvjianmin@loongson.cn>
+Reviewed-by: Huacai Chen <chenhuacai@loongson.cn>
+Signed-off-by: Myeonghun Pak <mhun512@gmail.com>
+Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
+Link: https://patch.msgid.link/20260513065706.23803-1-mhun512@gmail.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/gpu/drm/loongson/lsdc_drv.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/gpu/drm/loongson/lsdc_drv.c
++++ b/drivers/gpu/drm/loongson/lsdc_drv.c
+@@ -292,7 +292,7 @@ static int lsdc_pci_probe(struct pci_dev
+       vga_client_register(pdev, lsdc_vga_set_decode);
+-      drm_kms_helper_poll_init(ddev);
++      drmm_kms_helper_poll_init(ddev);
+       if (loongson_vblank) {
+               ret = drm_vblank_init(ddev, descp->num_of_crtc);
diff --git a/queue-7.0/drm-panfrost-fix-wait_bo-ioctl-leaking-positive-return-from-dma_resv_wait_timeout.patch b/queue-7.0/drm-panfrost-fix-wait_bo-ioctl-leaking-positive-return-from-dma_resv_wait_timeout.patch
new file mode 100644 (file)
index 0000000..2369698
--- /dev/null
@@ -0,0 +1,43 @@
+From 459d75523b71c0ec254d153d8850d0b7008af396 Mon Sep 17 00:00:00 2001
+From: Gyeyoung Baek <gye976@gmail.com>
+Date: Sun, 19 Apr 2026 16:17:16 +0900
+Subject: drm/panfrost: Fix wait_bo ioctl leaking positive return from dma_resv_wait_timeout()
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Gyeyoung Baek <gye976@gmail.com>
+
+commit 459d75523b71c0ec254d153d8850d0b7008af396 upstream.
+
+dma_resv_wait_timeout() returns a positive 'remaining jiffies' value
+on success, 0 on timeout, and -errno on failure.
+
+panfrost_ioctl_wait_bo() returns this 'long' result from an int-typed
+ioctl handler, so positive values reach userspace as bogus errors.
+Explicitly set ret to 0 on the success path.
+
+Fixes: f3ba91228e8e ("drm/panfrost: Add initial panfrost driver")
+Cc: stable@vger.kernel.org
+Signed-off-by: Gyeyoung Baek <gye976@gmail.com>
+Reviewed-by: Adrián Larumbe <adrian.larumbe@collabora.com>
+Reviewed-by: Boris Brezillon <boris.brezillon@collabora.com>
+Reviewed-by: Steven Price <steven.price@arm.com>
+Link: https://patch.msgid.link/fe33f82fded7be1c18e2e0eb2db451d5a738cf39.1776581974.git.gye976@gmail.com
+Signed-off-by: Steven Price <steven.price@arm.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/gpu/drm/panfrost/panfrost_drv.c |    2 ++
+ 1 file changed, 2 insertions(+)
+
+--- a/drivers/gpu/drm/panfrost/panfrost_drv.c
++++ b/drivers/gpu/drm/panfrost/panfrost_drv.c
+@@ -390,6 +390,8 @@ panfrost_ioctl_wait_bo(struct drm_device
+                                   true, timeout);
+       if (!ret)
+               ret = timeout ? -ETIMEDOUT : -EBUSY;
++      else if (ret > 0)
++              ret = 0;
+       drm_gem_object_put(gem_obj);
diff --git a/queue-7.0/drm-replace-old-pointer-to-new-idr.patch b/queue-7.0/drm-replace-old-pointer-to-new-idr.patch
new file mode 100644 (file)
index 0000000..57a91be
--- /dev/null
@@ -0,0 +1,72 @@
+From dc366607c41c45fd0ae6f3db090f31dd611b644a Mon Sep 17 00:00:00 2001
+From: Edward Adam Davis <eadavis@qq.com>
+Date: Wed, 13 May 2026 12:30:50 +0800
+Subject: drm: Replace old pointer to new idr
+
+From: Edward Adam Davis <eadavis@qq.com>
+
+commit dc366607c41c45fd0ae6f3db090f31dd611b644a upstream.
+
+Commit 5e28b7b94408 introduced a logical error by failing to replace the
+newly generated IDR pointer to old id's pointer at the correct location
+within the "change handle" logic; this resulted in the issue reported by
+syzbot [1].
+
+Specifically, the new IDR object pointer is intended to replace the original
+id's pointer during the normal execution flow.
+
+Additionally, an unnecessary conditional check for the ret exit path has
+been removed.
+
+[1]
+!RB_EMPTY_ROOT(&prime_fpriv->dmabufs)
+WARNING: drivers/gpu/drm/drm_prime.c:224 at drm_prime_destroy_file_private+0x48/0x60 drivers/gpu/drm/drm_prime.c:224, CPU#0: syz.0.17/5833
+Call Trace:
+ drm_file_free.part.0+0x7e6/0xcc0 drivers/gpu/drm/drm_file.c:269
+ drm_file_free drivers/gpu/drm/drm_file.c:237 [inline]
+ drm_close_helper.isra.0+0x186/0x200 drivers/gpu/drm/drm_file.c:290
+ drm_release+0x1ab/0x360 drivers/gpu/drm/drm_file.c:438
+
+Fixes: 5e28b7b94408 ("drm: Set old handle to NULL before prime swap in change_handle")
+Reported-by: syzbot+d7c9eed171647e421013@syzkaller.appspotmail.com
+Closes: https://syzkaller.appspot.com/bug?extid=d7c9eed171647e421013
+Cc: stable@vger.kernel.org
+Tested-by: syzbot+d7c9eed171647e421013@syzkaller.appspotmail.com
+Signed-off-by: Edward Adam Davis <eadavis@qq.com>
+Signed-off-by: Dave Airlie <airlied@redhat.com>
+Link: https://patch.msgid.link/tencent_C267296443AAA4567771176886DFF364A305@qq.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/gpu/drm/drm_gem.c |    7 ++-----
+ 1 file changed, 2 insertions(+), 5 deletions(-)
+
+--- a/drivers/gpu/drm/drm_gem.c
++++ b/drivers/gpu/drm/drm_gem.c
+@@ -1049,17 +1049,12 @@ int drm_gem_change_handle_ioctl(struct d
+       spin_unlock(&file_priv->table_lock);
+-      if (ret < 0)
+-              goto out_unlock;
+-
+       if (obj->dma_buf) {
+               ret = drm_prime_add_buf_handle(&file_priv->prime, obj->dma_buf,
+                                              handle);
+               if (ret < 0) {
+                       spin_lock(&file_priv->table_lock);
+                       idr_remove(&file_priv->object_idr, handle);
+-                      idrobj = idr_replace(&file_priv->object_idr, obj, handle);
+-                      WARN_ON(idrobj != NULL);
+                       spin_unlock(&file_priv->table_lock);
+                       goto out_unlock;
+               }
+@@ -1071,7 +1066,9 @@ int drm_gem_change_handle_ioctl(struct d
+       spin_lock(&file_priv->table_lock);
+       idr_remove(&file_priv->object_idr, args->handle);
++      idrobj = idr_replace(&file_priv->object_idr, obj, handle);
+       spin_unlock(&file_priv->table_lock);
++      WARN_ON(idrobj != NULL);
+ out_unlock:
+       mutex_unlock(&file_priv->prime.lock);
diff --git a/queue-7.0/drm-ttm-convert-eagain-from-dmem_cgroup_try_charge-to-enospc.patch b/queue-7.0/drm-ttm-convert-eagain-from-dmem_cgroup_try_charge-to-enospc.patch
new file mode 100644 (file)
index 0000000..e5ed4bc
--- /dev/null
@@ -0,0 +1,67 @@
+From 591711b32681a04b57d00c2a404658f8419a081c Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Thomas=20Hellstr=C3=B6m?= <thomas.hellstrom@linux.intel.com>
+Date: Fri, 8 May 2026 18:09:20 +0200
+Subject: drm/ttm: Convert -EAGAIN from dmem_cgroup_try_charge to -ENOSPC
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Thomas Hellström <thomas.hellstrom@linux.intel.com>
+
+commit 591711b32681a04b57d00c2a404658f8419a081c upstream.
+
+dmem_cgroup_try_charge() returns -EAGAIN when the cgroup limit is
+hit and the charge fails. TTM has no concept of -EAGAIN from resource
+allocation; -ENOSPC is the canonical error meaning "no space, try
+eviction". Convert at the source in ttm_resource_alloc() so no caller
+needs to handle an unexpected error code, and clean up the now-redundant
+-EAGAIN check in ttm_bo_alloc_resource().
+
+Without this, -EAGAIN escaping ttm_resource_alloc() during an eviction
+walk causes the walk to terminate early instead of continuing to the
+next candidate.
+
+Cc: Friedrich Vock <friedrich.vock@gmx.de>
+Cc: Maarten Lankhorst <dev@lankhorst.se>
+Cc: Tejun Heo <tj@kernel.org>
+Cc: Maxime Ripard <mripard@kernel.org>
+Cc: Christian Koenig <christian.koenig@amd.com>
+Cc: dri-devel@lists.freedesktop.org
+Cc: <stable@vger.kernel.org> # v6.14+
+Fixes: 2b624a2c1865 ("drm/ttm: Handle cgroup based eviction in TTM")
+Assisted-by: GitHub_Copilot:claude-sonnet-4.6
+Signed-off-by: Thomas Hellström <thomas.hellstrom@linux.intel.com>
+Reviewed-by: Maarten Lankhorst <dev@lankhrost.se>
+Link: https://patch.msgid.link/20260508160920.230339-1-thomas.hellstrom@linux.intel.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/gpu/drm/ttm/ttm_bo.c       |    2 +-
+ drivers/gpu/drm/ttm/ttm_resource.c |    5 ++++-
+ 2 files changed, 5 insertions(+), 2 deletions(-)
+
+--- a/drivers/gpu/drm/ttm/ttm_bo.c
++++ b/drivers/gpu/drm/ttm/ttm_bo.c
+@@ -740,7 +740,7 @@ static int ttm_bo_alloc_resource(struct
+               may_evict = (force_space && place->mem_type != TTM_PL_SYSTEM);
+               ret = ttm_resource_alloc(bo, place, res, force_space ? &limit_pool : NULL);
+               if (ret) {
+-                      if (ret != -ENOSPC && ret != -EAGAIN) {
++                      if (ret != -ENOSPC) {
+                               dmem_cgroup_pool_state_put(limit_pool);
+                               return ret;
+                       }
+--- a/drivers/gpu/drm/ttm/ttm_resource.c
++++ b/drivers/gpu/drm/ttm/ttm_resource.c
+@@ -398,8 +398,11 @@ int ttm_resource_alloc(struct ttm_buffer
+       if (man->cg) {
+               ret = dmem_cgroup_try_charge(man->cg, bo->base.size, &pool, ret_limit_pool);
+-              if (ret)
++              if (ret) {
++                      if (ret == -EAGAIN)
++                              ret = -ENOSPC;
+                       return ret;
++              }
+       }
+       ret = man->func->alloc(man, bo, place, res_ptr);
diff --git a/queue-7.0/drm-ttm-fix-ttm_bo_shrink-infinite-lru-walk-on-backup-failure.patch b/queue-7.0/drm-ttm-fix-ttm_bo_shrink-infinite-lru-walk-on-backup-failure.patch
new file mode 100644 (file)
index 0000000..a6812d9
--- /dev/null
@@ -0,0 +1,61 @@
+From 1d59f36e95f7f7134db0e313c9d787cb0adb2153 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Thomas=20Hellstr=C3=B6m?= <thomas.hellstrom@linux.intel.com>
+Date: Mon, 11 May 2026 18:24:43 +0200
+Subject: drm/ttm: Fix ttm_bo_shrink() infinite LRU walk on backup failure
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Thomas Hellström <thomas.hellstrom@linux.intel.com>
+
+commit 1d59f36e95f7f7134db0e313c9d787cb0adb2153 upstream.
+
+Apply the same fix as b2ed01e7ad ("drm/ttm: Fix ttm_bo_swapout()
+infinite LRU walk on swapout failure") to the ttm_bo_shrink() path.
+
+Move del_bulk_move from before the backup to after success only,
+using ttm_resource_del_bulk_move_unevictable() since the resource
+is now unevictable once fully backed up.
+
+Fixes: 70d645deac98 ("drm/ttm: Add helpers for shrinking")
+Cc: Christian König <christian.koenig@amd.com>
+Cc: Huang Rui <ray.huang@amd.com>
+Cc: Matthew Auld <matthew.auld@intel.com>
+Cc: Matthew Brost <matthew.brost@intel.com>
+Cc: Dave Airlie <airlied@redhat.com>
+Cc: dri-devel@lists.freedesktop.org
+Cc: stable@vger.kernel.org # v6.15+
+Assisted-by: GitHub_Copilot:claude-opus-4.6
+Reviewed-by: Matthew Auld <matthew.auld@intel.com>
+Link: https://patch.msgid.link/20260511162443.24352-1-thomas.hellstrom@linux.intel.com
+Signed-off-by: Thomas Hellström <thomas.hellstrom@linux.intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/gpu/drm/ttm/ttm_bo_util.c |   11 +++--------
+ 1 file changed, 3 insertions(+), 8 deletions(-)
+
+--- a/drivers/gpu/drm/ttm/ttm_bo_util.c
++++ b/drivers/gpu/drm/ttm/ttm_bo_util.c
+@@ -1112,19 +1112,14 @@ long ttm_bo_shrink(struct ttm_operation_
+       if (lret < 0)
+               return lret;
+-      if (bo->bulk_move) {
+-              spin_lock(&bdev->lru_lock);
+-              ttm_resource_del_bulk_move(bo->resource, bo);
+-              spin_unlock(&bdev->lru_lock);
+-      }
+-
+       lret = ttm_tt_backup(bdev, bo->ttm, (struct ttm_backup_flags)
+                            {.purge = flags.purge,
+                             .writeback = flags.writeback});
+-      if (lret <= 0 && bo->bulk_move) {
++      if (lret > 0) {
+               spin_lock(&bdev->lru_lock);
+-              ttm_resource_add_bulk_move(bo->resource, bo);
++              ttm_resource_del_bulk_move_unevictable(bo->resource, bo);
++              ttm_resource_move_to_lru_tail(bo->resource);
+               spin_unlock(&bdev->lru_lock);
+       }
diff --git a/queue-7.0/drm-ttm-fix-ttm_bo_swapout-infinite-lru-walk-on-swapout-failure.patch b/queue-7.0/drm-ttm-fix-ttm_bo_swapout-infinite-lru-walk-on-swapout-failure.patch
new file mode 100644 (file)
index 0000000..a3ab4ea
--- /dev/null
@@ -0,0 +1,107 @@
+From b2ed01e7ad3de80333e9b962a44024b094bc0b2b Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Thomas=20Hellstr=C3=B6m?= <thomas.hellstrom@linux.intel.com>
+Date: Tue, 28 Apr 2026 11:44:42 +0200
+Subject: drm/ttm: Fix ttm_bo_swapout() infinite LRU walk on swapout failure
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Thomas Hellström <thomas.hellstrom@linux.intel.com>
+
+commit b2ed01e7ad3de80333e9b962a44024b094bc0b2b upstream.
+
+When ttm_tt_swapout() fails, the current code calls
+ttm_resource_add_bulk_move() followed by ttm_resource_move_to_lru_tail()
+to restore the resource's bulk_move membership.
+
+However, ttm_resource_move_to_lru_tail() places the resource at the tail
+of the LRU list which, relative to the walk cursor's hitch node (placed
+immediately after the resource when it was yielded), puts the resource
+*in front of the* the hitch. The next list_for_each_entry_continue() from
+the hitch finds the same resource again, causing an infinite loop.
+
+Fix by deferring del_bulk_move to the success path only.
+
+On the success path, TTM_TT_FLAG_SWAPPED has just been set by
+ttm_tt_swapout() but the resource is still tracked in the bulk_move range,
+so ttm_resource_del_bulk_move()'s !ttm_resource_unevictable() guard would
+incorrectly skip the removal. Introduce
+ttm_resource_del_bulk_move_unevictable() which bypasses that guard.
+
+Reported-by: Jatin Kataria <jkataria@netflix.com>
+Fixes: fc5d96670eb2 ("drm/ttm: Move swapped objects off the manager's LRU list")
+Cc: Christian König <christian.koenig@amd.com>
+Cc: Matthew Brost <matthew.brost@intel.com>
+Cc: <dri-devel@lists.freedesktop.org>
+Cc: <stable@vger.kernel.org> # v6.13+
+Assisted-by: GitHub_Copilot:claude-sonnet-4.6
+Signed-off-by: Thomas Hellström <thomas.hellstrom@linux.intel.com>
+Reviewed-by: Christian König <christian.koenig@amd.com>
+Tested-by: Boqun Feng <boqun@kernel.org>
+Link: https://patch.msgid.link/20260428094442.16985-1-thomas.hellstrom@linux.intel.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/gpu/drm/ttm/ttm_bo.c       |   16 ++++++----------
+ drivers/gpu/drm/ttm/ttm_resource.c |   13 +++++++++++++
+ include/drm/ttm/ttm_resource.h     |    2 ++
+ 3 files changed, 21 insertions(+), 10 deletions(-)
+
+--- a/drivers/gpu/drm/ttm/ttm_bo.c
++++ b/drivers/gpu/drm/ttm/ttm_bo.c
+@@ -1178,17 +1178,13 @@ ttm_bo_swapout_cb(struct ttm_lru_walk *w
+               bdev->funcs->swap_notify(bo);
+       if (ttm_tt_is_populated(tt)) {
+-              spin_lock(&bdev->lru_lock);
+-              ttm_resource_del_bulk_move(bo->resource, bo);
+-              spin_unlock(&bdev->lru_lock);
+-
+               ret = ttm_tt_swapout(bdev, tt, swapout_walk->gfp_flags);
+-
+-              spin_lock(&bdev->lru_lock);
+-              if (ret)
+-                      ttm_resource_add_bulk_move(bo->resource, bo);
+-              ttm_resource_move_to_lru_tail(bo->resource);
+-              spin_unlock(&bdev->lru_lock);
++              if (!ret) {
++                      spin_lock(&bdev->lru_lock);
++                      ttm_resource_del_bulk_move_unevictable(bo->resource, bo);
++                      ttm_resource_move_to_lru_tail(bo->resource);
++                      spin_unlock(&bdev->lru_lock);
++              }
+       }
+ out:
+--- a/drivers/gpu/drm/ttm/ttm_resource.c
++++ b/drivers/gpu/drm/ttm/ttm_resource.c
+@@ -292,6 +292,19 @@ void ttm_resource_del_bulk_move(struct t
+               ttm_lru_bulk_move_del(bo->bulk_move, res);
+ }
++/*
++ * Remove a resource from its bulk_move, bypassing the unevictable check.
++ * Use only when the resource is known to still be tracked in the range despite
++ * the BO having just become unevictable; asserts that this is the case.
++ */
++void ttm_resource_del_bulk_move_unevictable(struct ttm_resource *res,
++                                          struct ttm_buffer_object *bo)
++{
++      WARN_ON_ONCE(!ttm_resource_unevictable(res, bo));
++      if (bo->bulk_move)
++              ttm_lru_bulk_move_del(bo->bulk_move, res);
++}
++
+ /* Move a resource to the LRU or bulk tail */
+ void ttm_resource_move_to_lru_tail(struct ttm_resource *res)
+ {
+--- a/include/drm/ttm/ttm_resource.h
++++ b/include/drm/ttm/ttm_resource.h
+@@ -448,6 +448,8 @@ void ttm_resource_add_bulk_move(struct t
+                               struct ttm_buffer_object *bo);
+ void ttm_resource_del_bulk_move(struct ttm_resource *res,
+                               struct ttm_buffer_object *bo);
++void ttm_resource_del_bulk_move_unevictable(struct ttm_resource *res,
++                                          struct ttm_buffer_object *bo);
+ void ttm_resource_move_to_lru_tail(struct ttm_resource *res);
+ void ttm_resource_init(struct ttm_buffer_object *bo,
diff --git a/queue-7.0/drm-xe-dma-buf-fix-uaf-with-retry-loop.patch b/queue-7.0/drm-xe-dma-buf-fix-uaf-with-retry-loop.patch
new file mode 100644 (file)
index 0000000..2758d40
--- /dev/null
@@ -0,0 +1,139 @@
+From 155a372a1cc50fa93387c5d3cdfd614a61e1afd1 Mon Sep 17 00:00:00 2001
+From: Matthew Auld <matthew.auld@intel.com>
+Date: Fri, 8 May 2026 11:26:37 +0100
+Subject: drm/xe/dma-buf: fix UAF with retry loop
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Matthew Auld <matthew.auld@intel.com>
+
+commit 155a372a1cc50fa93387c5d3cdfd614a61e1afd1 upstream.
+
+Retry doesn't work here, since bo will be freed on error, leading to
+UAF. However, now that we do the alloc & init before the attach, we can
+now combine this as one unit and have the init do the alloc for us. This
+should make the retry safe.
+
+Reported by Sashiko.
+
+v2: Fix up the error unwind (CI)
+
+Closes: https://sashiko.dev/#/patchset/20260506184332.86743-2-matthew.auld%40intel.com
+Fixes: eb289a5f6cc6 ("drm/xe: Convert xe_dma_buf.c for exhaustive eviction")
+Signed-off-by: Matthew Auld <matthew.auld@intel.com>
+Cc: Thomas Hellström <thomas.hellstrom@linux.intel.com>
+Cc: Matthew Brost <matthew.brost@intel.com>
+Cc: <stable@vger.kernel.org> # v6.18+
+Reviewed-by: Thomas Hellström <thomas.hellstrom@linux.intel.com>
+Link: https://patch.msgid.link/20260508102635.149172-4-matthew.auld@intel.com
+(cherry picked from commit 479669418253e0f27f8cf5db01a731352ea592e7)
+Signed-off-by: Rodrigo Vivi <rodrigo.vivi@intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/gpu/drm/xe/xe_dma_buf.c |   49 +++++++++-------------------------------
+ 1 file changed, 12 insertions(+), 37 deletions(-)
+
+--- a/drivers/gpu/drm/xe/xe_dma_buf.c
++++ b/drivers/gpu/drm/xe/xe_dma_buf.c
+@@ -238,16 +238,8 @@ struct dma_buf *xe_gem_prime_export(stru
+       return buf;
+ }
+-/*
+- * Takes ownership of @storage: on success it is transferred to the returned
+- * drm_gem_object; on failure it is freed before returning the error.
+- * This matches the contract of xe_bo_init_locked() which frees @storage on
+- * its error paths, so callers need not (and must not) free @storage after
+- * this call.
+- */
+ static struct drm_gem_object *
+-xe_dma_buf_init_obj(struct drm_device *dev, struct xe_bo *storage,
+-                  struct dma_buf *dma_buf)
++xe_dma_buf_create_obj(struct drm_device *dev, struct dma_buf *dma_buf)
+ {
+       struct dma_resv *resv = dma_buf->resv;
+       struct xe_device *xe = to_xe_device(dev);
+@@ -258,10 +250,8 @@ xe_dma_buf_init_obj(struct drm_device *d
+       int ret = 0;
+       dummy_obj = drm_gpuvm_resv_object_alloc(&xe->drm);
+-      if (!dummy_obj) {
+-              xe_bo_free(storage);
++      if (!dummy_obj)
+               return ERR_PTR(-ENOMEM);
+-      }
+       dummy_obj->resv = resv;
+       xe_validation_guard(&ctx, &xe->val, &exec, (struct xe_val_flags) {}, ret) {
+@@ -270,8 +260,7 @@ xe_dma_buf_init_obj(struct drm_device *d
+               if (ret)
+                       break;
+-              /* xe_bo_init_locked() frees storage on error */
+-              bo = xe_bo_init_locked(xe, storage, NULL, resv, NULL, dma_buf->size,
++              bo = xe_bo_init_locked(xe, NULL, NULL, resv, NULL, dma_buf->size,
+                                      0, /* Will require 1way or 2way for vm_bind */
+                                      ttm_bo_type_sg, XE_BO_FLAG_SYSTEM, &exec);
+               drm_exec_retry_on_contention(&exec);
+@@ -322,7 +311,6 @@ struct drm_gem_object *xe_gem_prime_impo
+       const struct dma_buf_attach_ops *attach_ops;
+       struct dma_buf_attachment *attach;
+       struct drm_gem_object *obj;
+-      struct xe_bo *bo;
+       if (dma_buf->ops == &xe_dmabuf_ops) {
+               obj = dma_buf->priv;
+@@ -337,22 +325,14 @@ struct drm_gem_object *xe_gem_prime_impo
+               }
+       }
+-      bo = xe_bo_alloc();
+-      if (IS_ERR(bo))
+-              return ERR_CAST(bo);
+-
+       /*
+-       * xe_dma_buf_init_obj() takes ownership of the raw bo, so do not touch
+-       * on fail, since it will already take care of cleanup. On success we
+-       * still need to drop the ref, if something later fails.
+-       *
+-       * In addition this needs to happen before the attach, since
+-       * it will create a new attachment for this, and add it to the list of
+-       * attachments, at which point it is globally visible, and at any point
+-       * the export side can call into on invalidate_mappings callback, which
+-       * require a working object.
++       * This needs to happen before the attach, since it will create a new
++       * attachment for this, and add it to the list of attachments, at which
++       * point it is globally visible, and at any point the export side can
++       * call into on invalidate_mappings callback, which require a working
++       * object.
+        */
+-      obj = xe_dma_buf_init_obj(dev, bo, dma_buf);
++      obj = xe_dma_buf_create_obj(dev, dma_buf);
+       if (IS_ERR(obj))
+               return obj;
+@@ -362,20 +342,15 @@ struct drm_gem_object *xe_gem_prime_impo
+               attach_ops = test->attach_ops;
+ #endif
+-      attach = dma_buf_dynamic_attach(dma_buf, dev->dev, attach_ops, &bo->ttm.base);
++      attach = dma_buf_dynamic_attach(dma_buf, dev->dev, attach_ops, obj);
+       if (IS_ERR(attach)) {
+-              obj = ERR_CAST(attach);
+-              goto out_err;
++              xe_bo_put(gem_to_xe_bo(obj));
++              return ERR_CAST(attach);
+       }
+       get_dma_buf(dma_buf);
+       obj->import_attach = attach;
+       return obj;
+-
+-out_err:
+-      xe_bo_put(bo);
+-
+-      return obj;
+ }
+ #if IS_ENABLED(CONFIG_DRM_XE_KUNIT_TEST)
diff --git a/queue-7.0/drm-xe-dma-buf-handle-empty-bo-and-uaf-races.patch b/queue-7.0/drm-xe-dma-buf-handle-empty-bo-and-uaf-races.patch
new file mode 100644 (file)
index 0000000..d1be2dc
--- /dev/null
@@ -0,0 +1,117 @@
+From 981bedbbe61364fcc3a3b87ebaf648a66cd07108 Mon Sep 17 00:00:00 2001
+From: Matthew Auld <matthew.auld@intel.com>
+Date: Fri, 8 May 2026 11:26:36 +0100
+Subject: drm/xe/dma-buf: handle empty bo and UAF races
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Matthew Auld <matthew.auld@intel.com>
+
+commit 981bedbbe61364fcc3a3b87ebaf648a66cd07108 upstream.
+
+There look to be some nasty races here when triggering the
+invalidate_mappings hook:
+
+1) We do xe_bo_alloc() followed by the attach, before the actual full bo
+   init step in xe_dma_buf_init_obj(). However the bo is visible on the
+   attachments list after the attach.  This is bad since exporter driver,
+   say amdgpu, can at any time call back into our invalidate_mappings hook,
+   with an empty/bogus bo, leading to potential bugs/crashes.
+
+2) Similar to 1) but here we get a UAF, when the invalidate_mappings
+   hook is triggered. For example, we get as far as xe_bo_init_locked()
+   but this fails in some way. But here the bo will be freed on error, but
+   we still have it attached from dma-buf pov, so if the
+   invalidate_mappings is now triggered then the bo we access is gone and
+   we trigger UAF and more bugs/crashes.
+
+To fix this, move the attach step until after we actually have a fully
+set up buffer object. Note that the bo is not published to userspace
+until later, so not sure what the comment "Don't publish the bo
+until we have a valid attachment", is referring to.
+
+We have at least two different customers reporting hitting a NULL ptr
+deref in evict_flags when importing something from amdgpu, followed by
+triggering the evict flow. Hit rate is also pretty low, which would
+hint at some kind of race, so something like 1) or 2) might explain
+this.
+
+v2:
+  - Shuffle the order of the ops slightly (no functional change)
+  - Improve the comment to better explain the ordering (Matt B)
+
+Assisted-by: Gemini:gemini-3 #debug
+Link: https://gitlab.freedesktop.org/drm/xe/kernel/-/work_items/7903
+Link: https://gitlab.freedesktop.org/drm/xe/kernel/-/work_items/4055
+Fixes: dd08ebf6c352 ("drm/xe: Introduce a new DRM driver for Intel GPUs")
+Signed-off-by: Matthew Auld <matthew.auld@intel.com>
+Cc: Thomas Hellström <thomas.hellstrom@linux.intel.com>
+Cc: Matthew Brost <matthew.brost@intel.com>
+Cc: <stable@vger.kernel.org> # v6.8+
+Reviewed-by: Matthew Brost <matthew.brost@intel.com>
+Acked-by: Thomas Hellström <thomas.hellstrom@linux.intel.com>
+Link: https://patch.msgid.link/20260508102635.149172-3-matthew.auld@intel.com
+(cherry picked from commit af1f2ad0c59fe4e2f924c526f66e968289d77971)
+Signed-off-by: Rodrigo Vivi <rodrigo.vivi@intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/gpu/drm/xe/xe_dma_buf.c |   31 ++++++++++++++++---------------
+ 1 file changed, 16 insertions(+), 15 deletions(-)
+
+--- a/drivers/gpu/drm/xe/xe_dma_buf.c
++++ b/drivers/gpu/drm/xe/xe_dma_buf.c
+@@ -337,15 +337,25 @@ struct drm_gem_object *xe_gem_prime_impo
+               }
+       }
+-      /*
+-       * Don't publish the bo until we have a valid attachment, and a
+-       * valid attachment needs the bo address. So pre-create a bo before
+-       * creating the attachment and publish.
+-       */
+       bo = xe_bo_alloc();
+       if (IS_ERR(bo))
+               return ERR_CAST(bo);
++      /*
++       * xe_dma_buf_init_obj() takes ownership of the raw bo, so do not touch
++       * on fail, since it will already take care of cleanup. On success we
++       * still need to drop the ref, if something later fails.
++       *
++       * In addition this needs to happen before the attach, since
++       * it will create a new attachment for this, and add it to the list of
++       * attachments, at which point it is globally visible, and at any point
++       * the export side can call into on invalidate_mappings callback, which
++       * require a working object.
++       */
++      obj = xe_dma_buf_init_obj(dev, bo, dma_buf);
++      if (IS_ERR(obj))
++              return obj;
++
+       attach_ops = &xe_dma_buf_attach_ops;
+ #if IS_ENABLED(CONFIG_DRM_XE_KUNIT_TEST)
+       if (test)
+@@ -358,21 +368,12 @@ struct drm_gem_object *xe_gem_prime_impo
+               goto out_err;
+       }
+-      /*
+-       * xe_dma_buf_init_obj() takes ownership of bo on both success
+-       * and failure, so we must not touch bo after this call.
+-       */
+-      obj = xe_dma_buf_init_obj(dev, bo, dma_buf);
+-      if (IS_ERR(obj)) {
+-              dma_buf_detach(dma_buf, attach);
+-              return obj;
+-      }
+       get_dma_buf(dma_buf);
+       obj->import_attach = attach;
+       return obj;
+ out_err:
+-      xe_bo_free(bo);
++      xe_bo_put(bo);
+       return obj;
+ }
diff --git a/queue-7.0/io-wq-check-that-the-predecessor-is-hashed-in-io_wq_remove_pending.patch b/queue-7.0/io-wq-check-that-the-predecessor-is-hashed-in-io_wq_remove_pending.patch
new file mode 100644 (file)
index 0000000..badb1a3
--- /dev/null
@@ -0,0 +1,52 @@
+From d6a2d7b04b5a093021a7a0e2e69e9d5237dfa8cc Mon Sep 17 00:00:00 2001
+From: Nicholas Carlini <nicholas@carlini.com>
+Date: Mon, 11 May 2026 18:02:16 +0000
+Subject: io-wq: check that the predecessor is hashed in io_wq_remove_pending()
+
+From: Nicholas Carlini <nicholas@carlini.com>
+
+commit d6a2d7b04b5a093021a7a0e2e69e9d5237dfa8cc upstream.
+
+io_wq_remove_pending() needs to fix up wq->hash_tail[] if the cancelled
+work was the tail of its hash bucket. When doing this, it checks whether
+the preceding entry in acct->work_list has the same hash value, but
+never checks that the predecessor is hashed at all. io_get_work_hash()
+is simply atomic_read(&work->flags) >> IO_WQ_HASH_SHIFT, and the hash
+bits are never set for non-hashed work, so it returns 0. Thus, when a
+hashed bucket-0 work is cancelled while a non-hashed work is its list
+predecessor, the check spuriously passes and a pointer to the non-hashed
+io_kiocb is stored in wq->hash_tail[0].
+
+Because non-hashed work is dequeued via the fast path in
+io_get_next_work(), which never touches hash_tail[], the stale pointer
+is never cleared. Therefore, after the non-hashed io_kiocb completes and
+is freed back to req_cachep, wq->hash_tail[0] is a dangling pointer. The
+io_wq is per-task (tctx->io_wq) and survives ring open/close, so the
+dangling pointer persists for the lifetime of the task; the next hashed
+bucket-0 enqueue dereferences it in io_wq_insert_work() and
+wq_list_add_after() writes through freed memory.
+
+Add the missing io_wq_is_hashed() check so a non-hashed predecessor
+never inherits a hash_tail[] slot.
+
+Cc: stable@vger.kernel.org
+Fixes: 204361a77f40 ("io-wq: fix hang after cancelling pending hashed work")
+Signed-off-by: Nicholas Carlini <nicholas@carlini.com>
+Signed-off-by: Jens Axboe <axboe@kernel.dk>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ io_uring/io-wq.c |    3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+--- a/io_uring/io-wq.c
++++ b/io_uring/io-wq.c
+@@ -1124,7 +1124,8 @@ static inline void io_wq_remove_pending(
+       if (io_wq_is_hashed(work) && work == wq->hash_tail[hash]) {
+               if (prev)
+                       prev_work = container_of(prev, struct io_wq_work, list);
+-              if (prev_work && io_get_work_hash(prev_work) == hash)
++              if (prev_work && io_wq_is_hashed(prev_work) &&
++                  io_get_work_hash(prev_work) == hash)
+                       wq->hash_tail[hash] = prev_work;
+               else
+                       wq->hash_tail[hash] = NULL;
diff --git a/queue-7.0/iommu-amd-bounds-check-devid-in-__rlookup_amd_iommu.patch b/queue-7.0/iommu-amd-bounds-check-devid-in-__rlookup_amd_iommu.patch
new file mode 100644 (file)
index 0000000..de5e4d5
--- /dev/null
@@ -0,0 +1,82 @@
+From 07d0f496fe7ec5abe3bee7e38be709521567bb33 Mon Sep 17 00:00:00 2001
+From: "Jose Fernandez (Anthropic)" <jose.fernandez@linux.dev>
+Date: Tue, 21 Apr 2026 19:26:13 +0000
+Subject: iommu/amd: Bounds-check devid in __rlookup_amd_iommu()
+
+From: Jose Fernandez (Anthropic) <jose.fernandez@linux.dev>
+
+commit 07d0f496fe7ec5abe3bee7e38be709521567bb33 upstream.
+
+iommu_device_register() walks every device on the PCI bus via
+bus_for_each_dev() and calls amd_iommu_probe_device() for each. The
+inlined check_device() path computes the device's sbdf, calls
+rlookup_amd_iommu() to find the owning IOMMU, and only afterwards
+verifies devid <= pci_seg->last_bdf. __rlookup_amd_iommu() indexes
+rlookup_table[devid] with no bounds check of its own, so for a PCI
+device whose BDF is not described by the IVRS, the lookup reads past
+the end of the allocation before the caller's bounds check can run.
+
+This was harmless before commit e874c666b15b ("iommu/amd: Change
+rlookup, irq_lookup, and alias to use kvalloc()"): the table was a
+zeroed page-order allocation, so the over-read returned NULL and the
+caller's NULL check skipped the device. After that commit the table is
+a tight kvcalloc() and the over-read returns adjacent slab contents,
+which check_device() then dereferences as a struct amd_iommu *,
+causing a boot-time GPF.
+
+Seen on Google Compute Engine ct6e VMs, where the virtualized IVRS
+describes only the four TPU endpoints 00:04.0-07.0; the gVNIC at
+00:08.0 (devid 0x40) indexes 56 bytes past the 456-byte allocation,
+into the adjacent kmalloc-512 slab object:
+
+  pci 0000:00:04.0: Adding to iommu group 0
+  pci 0000:00:05.0: Adding to iommu group 1
+  pci 0000:00:06.0: Adding to iommu group 2
+  pci 0000:00:07.0: Adding to iommu group 3
+  Oops: general protection fault, probably for non-canonical address 0x3a64695f78746382: 0000 [#1] SMP NOPTI
+  CPU: 0 UID: 0 PID: 1 Comm: swapper/0 Not tainted 6.18.22 #1
+  Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 12/06/2025
+  RIP: 0010:amd_iommu_probe_device+0x54/0x3a0
+  Call Trace:
+   __iommu_probe_device+0x107/0x520
+   probe_iommu_group+0x29/0x50
+   bus_for_each_dev+0x7e/0xe0
+   iommu_device_register+0xc9/0x240
+   iommu_go_to_state+0x9c0/0x1c60
+   amd_iommu_init+0x14/0x40
+   pci_iommu_init+0x16/0x60
+   do_one_initcall+0x47/0x2f0
+
+Guard the array access in __rlookup_amd_iommu(). With the fix applied
+on 6.18.22, the gVNIC at 00:08.0 is skipped cleanly and the VM boots.
+
+Fixes: e874c666b15b ("iommu/amd: Change rlookup, irq_lookup, and alias to use kvalloc()")
+Cc: stable@vger.kernel.org
+Reported-by: Ziyuan Chen <zc@anthropic.com>
+Tested-by: Ziyuan Chen <zc@anthropic.com>
+Reviewed-by: Josef Bacik <josef@toxicpanda.com>
+Assisted-by: Claude:unspecified
+Signed-off-by: Jose Fernandez (Anthropic) <jose.fernandez@linux.dev>
+Signed-off-by: Joerg Roedel <joerg.roedel@amd.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/iommu/amd/iommu.c |    8 ++++++--
+ 1 file changed, 6 insertions(+), 2 deletions(-)
+
+--- a/drivers/iommu/amd/iommu.c
++++ b/drivers/iommu/amd/iommu.c
+@@ -351,8 +351,12 @@ static struct amd_iommu *__rlookup_amd_i
+       struct amd_iommu_pci_seg *pci_seg;
+       for_each_pci_segment(pci_seg) {
+-              if (pci_seg->id == seg)
+-                      return pci_seg->rlookup_table[devid];
++              if (pci_seg->id != seg)
++                      continue;
++              /* IVRS may not describe every device on the bus */
++              if (devid > pci_seg->last_bdf)
++                      return NULL;
++              return pci_seg->rlookup_table[devid];
+       }
+       return NULL;
+ }
diff --git a/queue-7.0/iommu-fix-ats-invalidation-timeouts-during-__iommu_remove_group_pasid.patch b/queue-7.0/iommu-fix-ats-invalidation-timeouts-during-__iommu_remove_group_pasid.patch
new file mode 100644 (file)
index 0000000..6fe3afd
--- /dev/null
@@ -0,0 +1,43 @@
+From fc3523b16d2b4b88e61e69504b0ae0b18b869c8f Mon Sep 17 00:00:00 2001
+From: Nicolin Chen <nicolinc@nvidia.com>
+Date: Fri, 24 Apr 2026 18:15:25 -0700
+Subject: iommu: Fix ATS invalidation timeouts during __iommu_remove_group_pasid()
+
+From: Nicolin Chen <nicolinc@nvidia.com>
+
+commit fc3523b16d2b4b88e61e69504b0ae0b18b869c8f upstream.
+
+If a device is blocked, its PASID domains are already detached. Repeating
+iommu_remove_dev_pasid() is unnecessary and might trigger ATS invalidation
+timeouts.
+
+Skip the iommu_remove_dev_pasid() call upon gdev->blocked.
+
+Fixes: c279e83953d9 ("iommu: Introduce pci_dev_reset_iommu_prepare/done()")
+Cc: stable@vger.kernel.org
+Closes: https://sashiko.dev/#/patchset/20260407194644.171304-1-nicolinc%40nvidia.com
+Reviewed-by: Kevin Tian <kevin.tian@intel.com>
+Signed-off-by: Nicolin Chen <nicolinc@nvidia.com>
+Reviewed-by: Lu Baolu <baolu.lu@linux.intel.com>
+Signed-off-by: Joerg Roedel <joerg.roedel@amd.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/iommu/iommu.c |    7 ++++++-
+ 1 file changed, 6 insertions(+), 1 deletion(-)
+
+--- a/drivers/iommu/iommu.c
++++ b/drivers/iommu/iommu.c
+@@ -3572,7 +3572,12 @@ static void __iommu_remove_group_pasid(s
+       struct group_device *device;
+       for_each_group_device(group, device) {
+-              if (device->dev->iommu->max_pasids > 0)
++              /*
++               * A group-level detach cannot fail, even if there is a blocked
++               * device. In fact, blocked devices must be already detached for
++               * a pending device recovery.
++               */
++              if (!device->blocked && device->dev->iommu->max_pasids > 0)
+                       iommu_remove_dev_pasid(device->dev, pasid, domain);
+       }
+ }
diff --git a/queue-7.0/iommu-fix-nested-pci_dev_reset_iommu_prepare-done.patch b/queue-7.0/iommu-fix-nested-pci_dev_reset_iommu_prepare-done.patch
new file mode 100644 (file)
index 0000000..ed8b08d
--- /dev/null
@@ -0,0 +1,93 @@
+From 0d5fd7a9323ce6bedd170e21e1e90b8904917c75 Mon Sep 17 00:00:00 2001
+From: Nicolin Chen <nicolinc@nvidia.com>
+Date: Fri, 24 Apr 2026 18:15:24 -0700
+Subject: iommu: Fix nested pci_dev_reset_iommu_prepare/done()
+
+From: Nicolin Chen <nicolinc@nvidia.com>
+
+commit 0d5fd7a9323ce6bedd170e21e1e90b8904917c75 upstream.
+
+Shuai found that cxl_reset_bus_function() calls pci_reset_bus_function()
+internally while both are calling pci_dev_reset_iommu_prepare/done().
+
+As pci_dev_reset_iommu_prepare() doesn't support re-entry, the inner call
+will trigger a WARN_ON and return -EBUSY, resulting in failing the entire
+device reset.
+
+On the other hand, removing the outer calls in the PCI callers is unsafe.
+As pointed out by Kevin, device-specific quirks like reset_hinic_vf_dev()
+execute custom firmware waits after their inner pcie_flr() completes. If
+the IOMMU protection relies solely on the inner reset, the IOMMU will be
+unblocked prematurely while the device is still resetting.
+
+Instead, fix this by making pci_dev_reset_iommu_prepare/done() reentrant.
+
+Introduce gdev->reset_depth to handle the re-entries on the same device.
+
+Fixes: c279e83953d9 ("iommu: Introduce pci_dev_reset_iommu_prepare/done()")
+Cc: stable@vger.kernel.org
+Reported-by: Shuai Xue <xueshuai@linux.alibaba.com>
+Closes: https://lore.kernel.org/all/absKsk7qQOwzhpzv@Asurada-Nvidia/
+Suggested-by: Kevin Tian <kevin.tian@intel.com>
+Reviewed-by: Shuai Xue <xueshuai@linux.alibaba.com>
+Reviewed-by: Jason Gunthorpe <jgg@nvidia.com>
+Reviewed-by: Kevin Tian <kevin.tian@intel.com>
+Reviewed-by: Lu Baolu <baolu.lu@linux.intel.com>
+Signed-off-by: Nicolin Chen <nicolinc@nvidia.com>
+Signed-off-by: Joerg Roedel <joerg.roedel@amd.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/iommu/iommu.c |   19 +++++++++++++------
+ 1 file changed, 13 insertions(+), 6 deletions(-)
+
+--- a/drivers/iommu/iommu.c
++++ b/drivers/iommu/iommu.c
+@@ -82,6 +82,7 @@ struct group_device {
+        *  - Device is undergoing a reset
+        */
+       bool blocked;
++      unsigned int reset_depth;
+ };
+ /* Iterate over each struct group_device in a struct iommu_group */
+@@ -4015,20 +4016,23 @@ int pci_dev_reset_iommu_prepare(struct p
+       if (WARN_ON(!gdev))
+               return -ENODEV;
+-      /* Re-entry is not allowed */
+-      if (WARN_ON(gdev->blocked))
+-              return -EBUSY;
++      if (gdev->reset_depth++)
++              return 0;
+       ret = __iommu_group_alloc_blocking_domain(group);
+-      if (ret)
++      if (ret) {
++              gdev->reset_depth--;
+               return ret;
++      }
+       /* Stage RID domain at blocking_domain while retaining group->domain */
+       if (group->domain != group->blocking_domain) {
+               ret = __iommu_attach_device(group->blocking_domain, &pdev->dev,
+                                           group->domain);
+-              if (ret)
++              if (ret) {
++                      gdev->reset_depth--;
+                       return ret;
++              }
+       }
+       /*
+@@ -4088,7 +4092,10 @@ void pci_dev_reset_iommu_done(struct pci
+       if (WARN_ON(!gdev))
+               return;
+-      if (!gdev->blocked)
++      /* Unbalanced done() calls would underflow the counter */
++      if (WARN_ON(gdev->reset_depth == 0))
++              return;
++      if (--gdev->reset_depth)
+               return;
+       if (WARN_ON(!group->blocking_domain))
diff --git a/queue-7.0/iommu-fix-null-group-domain-dereference-in-pci_dev_reset_iommu_done.patch b/queue-7.0/iommu-fix-null-group-domain-dereference-in-pci_dev_reset_iommu_done.patch
new file mode 100644 (file)
index 0000000..239c5a4
--- /dev/null
@@ -0,0 +1,46 @@
+From d769711fcddd005f1e654b3bde547140917fe696 Mon Sep 17 00:00:00 2001
+From: Nicolin Chen <nicolinc@nvidia.com>
+Date: Fri, 24 Apr 2026 18:15:20 -0700
+Subject: iommu: Fix NULL group->domain dereference in pci_dev_reset_iommu_done()
+
+From: Nicolin Chen <nicolinc@nvidia.com>
+
+commit d769711fcddd005f1e654b3bde547140917fe696 upstream.
+
+Local sashiko review pointed it out that group->domain could be NULL when
+a default domain fails to allocate during the first probe, which can crash
+at domain->ops->attach_dev dereference in __iommu_attach_device() invoked
+by pci_dev_reset_iommu_done().
+
+pci_dev_reset_iommu_prepare() is fine as an old_domain pointer can be NULL.
+
+Skip the re-attach in pci_dev_reset_iommu_done() to fix the bug.
+
+Fixes: c279e83953d9 ("iommu: Introduce pci_dev_reset_iommu_prepare/done()")
+Cc: stable@vger.kernel.org
+Signed-off-by: Nicolin Chen <nicolinc@nvidia.com>
+Reviewed-by: Lu Baolu <baolu.lu@linux.intel.com>
+Signed-off-by: Joerg Roedel <joerg.roedel@amd.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/iommu/iommu.c |    9 +++++++--
+ 1 file changed, 7 insertions(+), 2 deletions(-)
+
+--- a/drivers/iommu/iommu.c
++++ b/drivers/iommu/iommu.c
+@@ -4035,8 +4035,13 @@ void pci_dev_reset_iommu_done(struct pci
+       if (WARN_ON(!group->blocking_domain))
+               return;
+-      /* Re-attach RID domain back to group->domain */
+-      if (group->domain != group->blocking_domain) {
++      /*
++       * Re-attach RID domain back to group->domain
++       *
++       * Leave the device parked in the blocking_domain if group->domain isn't
++       * initialized yet
++       */
++      if (group->domain && group->domain != group->blocking_domain) {
+               WARN_ON(__iommu_attach_device(group->domain, &pdev->dev,
+                                             group->blocking_domain));
+       }
diff --git a/queue-7.0/iommu-fix-pasid-attach-in-pci_dev_reset_iommu_prepare-done.patch b/queue-7.0/iommu-fix-pasid-attach-in-pci_dev_reset_iommu_prepare-done.patch
new file mode 100644 (file)
index 0000000..17e6ba0
--- /dev/null
@@ -0,0 +1,70 @@
+From 1615e8896a8f6d7b2adf6495e538a81bf6cea3e0 Mon Sep 17 00:00:00 2001
+From: Nicolin Chen <nicolinc@nvidia.com>
+Date: Fri, 24 Apr 2026 18:15:23 -0700
+Subject: iommu: Fix pasid attach in pci_dev_reset_iommu_prepare/done()
+
+From: Nicolin Chen <nicolinc@nvidia.com>
+
+commit 1615e8896a8f6d7b2adf6495e538a81bf6cea3e0 upstream.
+
+Now the helpers handle per-gdev resets. Replace __iommu_set_group_pasid()
+with set_dev_pasid() accordingly, in the pci_dev_reset_iommu_done().
+
+Also add max_pasids check as other callers.
+
+Fixes: c279e83953d9 ("iommu: Introduce pci_dev_reset_iommu_prepare/done()")
+Cc: stable@vger.kernel.org
+Reported-by: Shuai Xue <xueshuai@linux.alibaba.com>
+Closes: https://lore.kernel.org/all/ad858513-09fc-455e-bbc5-fe38a225cc78@linux.alibaba.com/
+Reviewed-by: Shuai Xue <xueshuai@linux.alibaba.com>
+Reviewed-by: Jason Gunthorpe <jgg@nvidia.com>
+Reviewed-by: Kevin Tian <kevin.tian@intel.com>
+Signed-off-by: Nicolin Chen <nicolinc@nvidia.com>
+Reviewed-by: Lu Baolu <baolu.lu@linux.intel.com>
+Signed-off-by: Joerg Roedel <joerg.roedel@amd.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/iommu/iommu.c |   25 ++++++++++++++++++-------
+ 1 file changed, 18 insertions(+), 7 deletions(-)
+
+--- a/drivers/iommu/iommu.c
++++ b/drivers/iommu/iommu.c
+@@ -4044,9 +4044,14 @@ int pci_dev_reset_iommu_prepare(struct p
+        * The pasid_array is mostly fenced by group->mutex, except one reader
+        * in iommu_attach_handle_get(), so it's safe to read without xa_lock.
+        */
+-      xa_for_each_start(&group->pasid_array, pasid, entry, 1)
+-              iommu_remove_dev_pasid(&pdev->dev, pasid,
+-                                     pasid_array_entry_to_domain(entry));
++      if (pdev->dev.iommu->max_pasids > 0) {
++              xa_for_each_start(&group->pasid_array, pasid, entry, 1) {
++                      struct iommu_domain *pasid_dom =
++                              pasid_array_entry_to_domain(entry);
++
++                      iommu_remove_dev_pasid(&pdev->dev, pasid, pasid_dom);
++              }
++      }
+       group->recovery_cnt++;
+       return ret;
+@@ -4113,10 +4118,16 @@ void pci_dev_reset_iommu_done(struct pci
+        * The pasid_array is mostly fenced by group->mutex, except one reader
+        * in iommu_attach_handle_get(), so it's safe to read without xa_lock.
+        */
+-      xa_for_each_start(&group->pasid_array, pasid, entry, 1)
+-              WARN_ON(__iommu_set_group_pasid(
+-                      pasid_array_entry_to_domain(entry), group, pasid,
+-                      group->blocking_domain));
++      if (pdev->dev.iommu->max_pasids > 0) {
++              xa_for_each_start(&group->pasid_array, pasid, entry, 1) {
++                      struct iommu_domain *pasid_dom =
++                              pasid_array_entry_to_domain(entry);
++
++                      WARN_ON(pasid_dom->ops->set_dev_pasid(
++                              pasid_dom, &pdev->dev, pasid,
++                              group->blocking_domain));
++              }
++      }
+       if (!WARN_ON(group->recovery_cnt == 0))
+               group->recovery_cnt--;
diff --git a/queue-7.0/iommu-fix-warn_on-in-__iommu_group_set_domain_nofail-due-to-reset.patch b/queue-7.0/iommu-fix-warn_on-in-__iommu_group_set_domain_nofail-due-to-reset.patch
new file mode 100644 (file)
index 0000000..9e71952
--- /dev/null
@@ -0,0 +1,67 @@
+From 5474e6e17a262db45c60575c73f70210f5c7001f Mon Sep 17 00:00:00 2001
+From: Nicolin Chen <nicolinc@nvidia.com>
+Date: Fri, 24 Apr 2026 18:15:26 -0700
+Subject: iommu: Fix WARN_ON in __iommu_group_set_domain_nofail() due to reset
+
+From: Nicolin Chen <nicolinc@nvidia.com>
+
+commit 5474e6e17a262db45c60575c73f70210f5c7001f upstream.
+
+In __iommu_group_set_domain_internal(), concurrent domain attachments are
+rejected when any device in the group is recovering. This is necessary to
+fence concurrent attachments to a multi-device group where devices might
+share the same RID due to PCI DMA alias quirks, but triggers the WARN_ON in
+__iommu_group_set_domain_nofail().
+
+Other IOMMU_SET_DOMAIN_MUST_SUCCEED callers in detach/teardown paths, such
+as __iommu_group_set_core_domain and __iommu_release_dma_ownership, should
+not be rejected, as the domain would be freed anyway in these nofail paths
+while group->domain is still pointing to it. So pci_dev_reset_iommu_done()
+could trigger a UAF when re-attaching group->domain.
+
+Honor the IOMMU_SET_DOMAIN_MUST_SUCCEED flag, allowing the callers through
+the group->recovery_cnt fence, so as to update the group->domain pointer.
+Instead add a gdev->blocked check in the device iteration loop, to prevent
+any concurrent per-device detachment.
+
+Fixes: c279e83953d9 ("iommu: Introduce pci_dev_reset_iommu_prepare/done()")
+Cc: stable@vger.kernel.org
+Closes: https://sashiko.dev/#/patchset/20260407194644.171304-1-nicolinc%40nvidia.com
+Reviewed-by: Kevin Tian <kevin.tian@intel.com>
+Reviewed-by: Lu Baolu <baolu.lu@linux.intel.com>
+Signed-off-by: Nicolin Chen <nicolinc@nvidia.com>
+Signed-off-by: Joerg Roedel <joerg.roedel@amd.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/iommu/iommu.c |   12 ++++++++++--
+ 1 file changed, 10 insertions(+), 2 deletions(-)
+
+--- a/drivers/iommu/iommu.c
++++ b/drivers/iommu/iommu.c
+@@ -2472,9 +2472,10 @@ static int __iommu_group_set_domain_inte
+       /*
+        * This is a concurrent attach during device recovery. Reject it until
+-       * pci_dev_reset_iommu_done() attaches the device to group->domain.
++       * pci_dev_reset_iommu_done() attaches the device to group->domain, if
++       * IOMMU_SET_DOMAIN_MUST_SUCCEED is not set.
+        */
+-      if (group->recovery_cnt)
++      if (group->recovery_cnt && !(flags & IOMMU_SET_DOMAIN_MUST_SUCCEED))
+               return -EBUSY;
+       /*
+@@ -2485,6 +2486,13 @@ static int __iommu_group_set_domain_inte
+        */
+       result = 0;
+       for_each_group_device(group, gdev) {
++              /*
++               * Device under recovery is attached to group->blocking_domain.
++               * Don't change that. pci_dev_reset_iommu_done() will re-attach
++               * its domain to the updated group->domain, after the recovery.
++               */
++              if (gdev->blocked)
++                      continue;
+               ret = __iommu_device_set_domain(group, gdev->dev, new_domain,
+                                               group->domain, flags);
+               if (ret) {
diff --git a/queue-7.0/iommu-replace-per-group-resetting_domain-with-per-gdev-blocked-flag.patch b/queue-7.0/iommu-replace-per-group-resetting_domain-with-per-gdev-blocked-flag.patch
new file mode 100644 (file)
index 0000000..22c1bcb
--- /dev/null
@@ -0,0 +1,303 @@
+From b296ca1fb43aa435edd86131f5230f70c03b2829 Mon Sep 17 00:00:00 2001
+From: Nicolin Chen <nicolinc@nvidia.com>
+Date: Fri, 24 Apr 2026 18:15:22 -0700
+Subject: iommu: Replace per-group resetting_domain with per-gdev blocked flag
+
+From: Nicolin Chen <nicolinc@nvidia.com>
+
+commit b296ca1fb43aa435edd86131f5230f70c03b2829 upstream.
+
+The core tracks device resetting states with a per-group resetting_domain,
+while a reset is actually per group-device. Such a mismatch might lead to
+confusion and even difficulty to untangle per-gdev handling requirement.
+
+Shuai found that cxl_reset_bus_function() calls pci_reset_bus_function()
+internally while both are calling pci_dev_reset_iommu_prepare/done(). And
+the solution requires the core to track at the group_device level as well.
+
+Introduce a 'blocked' flag to struct group_device, to allow a multi-device
+group to isolate concurrent device resets independently.
+
+As the reset routine is per gdev, it cannot clear group->resetting_domain
+without iterating over the device list to ensure no other device is being
+reset. Simplify it by replacing the resetting_domain with a 'recovery_cnt'
+in the struct iommu_group.
+
+No functional change. But this is essential to apply following bug fixes.
+
+Fixes: c279e83953d9 ("iommu: Introduce pci_dev_reset_iommu_prepare/done()")
+Cc: stable@vger.kernel.org
+Reported-by: Shuai Xue <xueshuai@linux.alibaba.com>
+Closes: https://lore.kernel.org/all/absKsk7qQOwzhpzv@Asurada-Nvidia/
+Reviewed-by: Shuai Xue <xueshuai@linux.alibaba.com>
+Reviewed-by: Jason Gunthorpe <jgg@nvidia.com>
+Reviewed-by: Kevin Tian <kevin.tian@intel.com>
+Reviewed-by: Lu Baolu <baolu.lu@linux.intel.com>
+Signed-off-by: Nicolin Chen <nicolinc@nvidia.com>
+Signed-off-by: Joerg Roedel <joerg.roedel@amd.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/iommu/iommu.c |  102 ++++++++++++++++++++++++++++++++++++++------------
+ 1 file changed, 78 insertions(+), 24 deletions(-)
+
+--- a/drivers/iommu/iommu.c
++++ b/drivers/iommu/iommu.c
+@@ -61,14 +61,14 @@ struct iommu_group {
+       int id;
+       struct iommu_domain *default_domain;
+       struct iommu_domain *blocking_domain;
+-      /*
+-       * During a group device reset, @resetting_domain points to the physical
+-       * domain, while @domain points to the attached domain before the reset.
+-       */
+-      struct iommu_domain *resetting_domain;
+       struct iommu_domain *domain;
+       struct list_head entry;
+       unsigned int owner_cnt;
++      /*
++       * Number of devices in the group undergoing or awaiting recovery.
++       * If non-zero, concurrent domain attachments are rejected.
++       */
++      unsigned int recovery_cnt;
+       void *owner;
+ };
+@@ -76,12 +76,32 @@ struct group_device {
+       struct list_head list;
+       struct device *dev;
+       char *name;
++      /*
++       * Device is blocked for a pending recovery while its group->domain is
++       * retained. This can happen when:
++       *  - Device is undergoing a reset
++       */
++      bool blocked;
+ };
+ /* Iterate over each struct group_device in a struct iommu_group */
+ #define for_each_group_device(group, pos) \
+       list_for_each_entry(pos, &(group)->devices, list)
++static struct group_device *__dev_to_gdev(struct device *dev)
++{
++      struct iommu_group *group = dev->iommu_group;
++      struct group_device *gdev;
++
++      lockdep_assert_held(&group->mutex);
++
++      for_each_group_device(group, gdev) {
++              if (gdev->dev == dev)
++                      return gdev;
++      }
++      return NULL;
++}
++
+ struct iommu_group_attribute {
+       struct attribute attr;
+       ssize_t (*show)(struct iommu_group *group, char *buf);
+@@ -2195,6 +2215,8 @@ EXPORT_SYMBOL_GPL(iommu_attach_device);
+ int iommu_deferred_attach(struct device *dev, struct iommu_domain *domain)
+ {
++      struct group_device *gdev;
++
+       /*
+        * This is called on the dma mapping fast path so avoid locking. This is
+        * racy, but we have an expectation that the driver will setup its DMAs
+@@ -2205,14 +2227,18 @@ int iommu_deferred_attach(struct device
+       guard(mutex)(&dev->iommu_group->mutex);
++      gdev = __dev_to_gdev(dev);
++      if (WARN_ON(!gdev))
++              return -ENODEV;
++
+       /*
+-       * This is a concurrent attach during a device reset. Reject it until
++       * This is a concurrent attach during device recovery. Reject it until
+        * pci_dev_reset_iommu_done() attaches the device to group->domain.
+        *
+        * Note that this might fail the iommu_dma_map(). But there's nothing
+        * more we can do here.
+        */
+-      if (dev->iommu_group->resetting_domain)
++      if (gdev->blocked)
+               return -EBUSY;
+       return __iommu_attach_device(domain, dev, NULL);
+ }
+@@ -2269,19 +2295,24 @@ EXPORT_SYMBOL_GPL(iommu_get_domain_for_d
+ struct iommu_domain *iommu_driver_get_domain_for_dev(struct device *dev)
+ {
+       struct iommu_group *group = dev->iommu_group;
++      struct group_device *gdev;
+       lockdep_assert_held(&group->mutex);
++      gdev = __dev_to_gdev(dev);
++      if (WARN_ON(!gdev))
++              return NULL;
++
+       /*
+        * Driver handles the low-level __iommu_attach_device(), including the
+        * one invoked by pci_dev_reset_iommu_done() re-attaching the device to
+        * the cached group->domain. In this case, the driver must get the old
+-       * domain from group->resetting_domain rather than group->domain. This
++       * domain from group->blocking_domain rather than group->domain. This
+        * prevents it from re-attaching the device from group->domain (old) to
+        * group->domain (new).
+        */
+-      if (group->resetting_domain)
+-              return group->resetting_domain;
++      if (gdev->blocked)
++              return group->blocking_domain;
+       return group->domain;
+ }
+@@ -2440,10 +2471,10 @@ static int __iommu_group_set_domain_inte
+               return -EINVAL;
+       /*
+-       * This is a concurrent attach during a device reset. Reject it until
++       * This is a concurrent attach during device recovery. Reject it until
+        * pci_dev_reset_iommu_done() attaches the device to group->domain.
+        */
+-      if (group->resetting_domain)
++      if (group->recovery_cnt)
+               return -EBUSY;
+       /*
+@@ -3577,10 +3608,10 @@ int iommu_attach_device_pasid(struct iom
+       mutex_lock(&group->mutex);
+       /*
+-       * This is a concurrent attach during a device reset. Reject it until
++       * This is a concurrent attach during device recovery. Reject it until
+        * pci_dev_reset_iommu_done() attaches the device to group->domain.
+        */
+-      if (group->resetting_domain) {
++      if (group->recovery_cnt) {
+               ret = -EBUSY;
+               goto out_unlock;
+       }
+@@ -3670,10 +3701,10 @@ int iommu_replace_device_pasid(struct io
+       mutex_lock(&group->mutex);
+       /*
+-       * This is a concurrent attach during a device reset. Reject it until
++       * This is a concurrent attach during device recovery. Reject it until
+        * pci_dev_reset_iommu_done() attaches the device to group->domain.
+        */
+-      if (group->resetting_domain) {
++      if (group->recovery_cnt) {
+               ret = -EBUSY;
+               goto out_unlock;
+       }
+@@ -3944,12 +3975,12 @@ EXPORT_SYMBOL_NS_GPL(iommu_replace_group
+  * routine wants to block any IOMMU activity: translation and ATS invalidation.
+  *
+  * This function attaches the device's RID/PASID(s) the group->blocking_domain,
+- * setting the group->resetting_domain. This allows the IOMMU driver pausing any
++ * incrementing the group->recovery_cnt, to allow the IOMMU driver pausing any
+  * IOMMU activity while leaving the group->domain pointer intact. Later when the
+  * reset is finished, pci_dev_reset_iommu_done() can restore everything.
+  *
+  * Caller must use pci_dev_reset_iommu_prepare() with pci_dev_reset_iommu_done()
+- * before/after the core-level reset routine, to unset the resetting_domain.
++ * before/after the core-level reset routine, to decrement the recovery_cnt.
+  *
+  * Return: 0 on success or negative error code if the preparation failed.
+  *
+@@ -3962,6 +3993,7 @@ EXPORT_SYMBOL_NS_GPL(iommu_replace_group
+ int pci_dev_reset_iommu_prepare(struct pci_dev *pdev)
+ {
+       struct iommu_group *group = pdev->dev.iommu_group;
++      struct group_device *gdev;
+       unsigned long pasid;
+       void *entry;
+       int ret;
+@@ -3971,8 +4003,12 @@ int pci_dev_reset_iommu_prepare(struct p
+       guard(mutex)(&group->mutex);
++      gdev = __dev_to_gdev(&pdev->dev);
++      if (WARN_ON(!gdev))
++              return -ENODEV;
++
+       /* Re-entry is not allowed */
+-      if (WARN_ON(group->resetting_domain))
++      if (WARN_ON(gdev->blocked))
+               return -EBUSY;
+       ret = __iommu_group_alloc_blocking_domain(group);
+@@ -3988,6 +4024,13 @@ int pci_dev_reset_iommu_prepare(struct p
+       }
+       /*
++       * Update gdev->blocked upon the domain change, as it is used to return
++       * the correct domain in iommu_driver_get_domain_for_dev() that might be
++       * called in a set_dev_pasid callback function.
++       */
++      gdev->blocked = true;
++
++      /*
+        * Stage PASID domains at blocking_domain while retaining pasid_array.
+        *
+        * The pasid_array is mostly fenced by group->mutex, except one reader
+@@ -3997,7 +4040,7 @@ int pci_dev_reset_iommu_prepare(struct p
+               iommu_remove_dev_pasid(&pdev->dev, pasid,
+                                      pasid_array_entry_to_domain(entry));
+-      group->resetting_domain = group->blocking_domain;
++      group->recovery_cnt++;
+       return ret;
+ }
+ EXPORT_SYMBOL_GPL(pci_dev_reset_iommu_prepare);
+@@ -4019,6 +4062,7 @@ EXPORT_SYMBOL_GPL(pci_dev_reset_iommu_pr
+ void pci_dev_reset_iommu_done(struct pci_dev *pdev)
+ {
+       struct iommu_group *group = pdev->dev.iommu_group;
++      struct group_device *gdev;
+       unsigned long pasid;
+       void *entry;
+@@ -4027,11 +4071,13 @@ void pci_dev_reset_iommu_done(struct pci
+       guard(mutex)(&group->mutex);
+-      /* pci_dev_reset_iommu_prepare() was bypassed for the device */
+-      if (!group->resetting_domain)
++      gdev = __dev_to_gdev(&pdev->dev);
++      if (WARN_ON(!gdev))
++              return;
++
++      if (!gdev->blocked)
+               return;
+-      /* pci_dev_reset_iommu_prepare() was not successfully called */
+       if (WARN_ON(!group->blocking_domain))
+               return;
+@@ -4047,6 +4093,13 @@ void pci_dev_reset_iommu_done(struct pci
+       }
+       /*
++       * Update gdev->blocked upon the domain change, as it is used to return
++       * the correct domain in iommu_driver_get_domain_for_dev() that might be
++       * called in a set_dev_pasid callback function.
++       */
++      gdev->blocked = false;
++
++      /*
+        * Re-attach PASID domains back to the domains retained in pasid_array.
+        *
+        * The pasid_array is mostly fenced by group->mutex, except one reader
+@@ -4057,7 +4110,8 @@ void pci_dev_reset_iommu_done(struct pci
+                       pasid_array_entry_to_domain(entry), group, pasid,
+                       group->blocking_domain));
+-      group->resetting_domain = NULL;
++      if (!WARN_ON(group->recovery_cnt == 0))
++              group->recovery_cnt--;
+ }
+ EXPORT_SYMBOL_GPL(pci_dev_reset_iommu_done);
diff --git a/queue-7.0/iommu-vt-d-avoid-null-pointer-dereference-or-refcount-corruption.patch b/queue-7.0/iommu-vt-d-avoid-null-pointer-dereference-or-refcount-corruption.patch
new file mode 100644 (file)
index 0000000..2b94d6a
--- /dev/null
@@ -0,0 +1,63 @@
+From 79ea2feb917b05366b49d85573c9c5331f043b2c Mon Sep 17 00:00:00 2001
+From: Zhenzhong Duan <zhenzhong.duan@intel.com>
+Date: Sat, 9 May 2026 10:43:46 +0800
+Subject: iommu/vt-d: Avoid NULL pointer dereference or refcount corruption
+
+From: Zhenzhong Duan <zhenzhong.duan@intel.com>
+
+commit 79ea2feb917b05366b49d85573c9c5331f043b2c upstream.
+
+Commit 60f030f7418d ("iommu/vt-d: Avoid use of NULL after WARN_ON_ONCE")
+fixed a NULL pointer dereference in an unlikely situation partly.
+
+If dev_pasid is not found in the dev_pasids list, it remains NULL.
+However, the teardown operations are executed unconditionally, this lead
+to a NULL pointer dereference or refcount corruption.
+
+If the domain was never attached to this IOMMU, info will be NULL, which
+would cause an immediate dereference when checking --info->refcnt.
+
+Even if info is not NULL, decrementing the refcount without having removed
+a valid PASID might unbalance the count. This could lead to premature
+dropping of the refcount to 0, potentially causing a use-after-free for the
+remaining active devices sharing the domain.
+
+Fix it by returning early if dev_pasid is NULL, before executing the
+teardown operations.
+
+Issue found by AI review and suggested by Kevin Tian.
+https://sashiko.dev/#/patchset/20260421031347.1408890-1-zhenzhong.duan%40intel.com
+
+Fixes: 60f030f7418d ("iommu/vt-d: Avoid use of NULL after WARN_ON_ONCE")
+Cc: stable@vger.kernel.org
+Suggested-by: Kevin Tian <kevin.tian@intel.com>
+Signed-off-by: Zhenzhong Duan <zhenzhong.duan@intel.com>
+Reviewed-by: Kevin Tian <kevin.tian@intel.com>
+Link: https://lore.kernel.org/r/20260422033538.95000-1-zhenzhong.duan@intel.com
+Signed-off-by: Lu Baolu <baolu.lu@linux.intel.com>
+Signed-off-by: Joerg Roedel <joerg.roedel@amd.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/iommu/intel/iommu.c |    9 +++++----
+ 1 file changed, 5 insertions(+), 4 deletions(-)
+
+--- a/drivers/iommu/intel/iommu.c
++++ b/drivers/iommu/intel/iommu.c
+@@ -3544,12 +3544,13 @@ void domain_remove_dev_pasid(struct iomm
+       }
+       spin_unlock_irqrestore(&dmar_domain->lock, flags);
++      if (WARN_ON_ONCE(!dev_pasid))
++              return;
++
+       cache_tag_unassign_domain(dmar_domain, dev, pasid);
+       domain_detach_iommu(dmar_domain, iommu);
+-      if (!WARN_ON_ONCE(!dev_pasid)) {
+-              intel_iommu_debugfs_remove_dev_pasid(dev_pasid);
+-              kfree(dev_pasid);
+-      }
++      intel_iommu_debugfs_remove_dev_pasid(dev_pasid);
++      kfree(dev_pasid);
+ }
+ static int blocking_domain_set_dev_pasid(struct iommu_domain *domain,
diff --git a/queue-7.0/iommu-vt-d-disable-dmar-for-intel-q35-igfx.patch b/queue-7.0/iommu-vt-d-disable-dmar-for-intel-q35-igfx.patch
new file mode 100644 (file)
index 0000000..e5a5401
--- /dev/null
@@ -0,0 +1,47 @@
+From 2cda2e10dc8343ae01eae9e999a876b7e7d37861 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Naval=20Alcal=C3=A1?= <ari@naval.cat>
+Date: Sat, 9 May 2026 10:43:44 +0800
+Subject: iommu/vt-d: Disable DMAR for Intel Q35 IGFX
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Naval Alcalá <ari@naval.cat>
+
+commit 2cda2e10dc8343ae01eae9e999a876b7e7d37861 upstream.
+
+Intel Q35 integrated graphics (8086:29b2) exhibits broken DMAR
+behaviour similar to other G4x/GM45 devices for which DMAR is
+already disabled via quirks.
+
+When DMAR is enabled, the system may hard lock up during boot or
+early device initialization, requiring a reset.
+
+Add the missing PCI ID to the existing quirk list to disable
+DMAR for this device.
+
+Fixes: 1f76249cc3be ("iommu/vt-d: Declare Broadwell igfx dmar support snafu")
+Cc: stable@vger.kernel.org
+Closes: https://bugzilla.kernel.org/show_bug.cgi?id=201185
+Closes: https://bugzilla.kernel.org/show_bug.cgi?id=216064
+Signed-off-by: Naval Alcalá <ari@naval.cat>
+Link: https://lore.kernel.org/r/20260410161622.13549-1-ari@naval.cat
+Signed-off-by: Lu Baolu <baolu.lu@linux.intel.com>
+Signed-off-by: Joerg Roedel <joerg.roedel@amd.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/iommu/intel/iommu.c |    3 +++
+ 1 file changed, 3 insertions(+)
+
+--- a/drivers/iommu/intel/iommu.c
++++ b/drivers/iommu/intel/iommu.c
+@@ -3933,6 +3933,9 @@ static void quirk_iommu_igfx(struct pci_
+       disable_igfx_iommu = 1;
+ }
++/* Q35 integrated gfx dmar support is totally busted. */
++DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x29b2, quirk_iommu_igfx);
++
+ /* G4x/GM45 integrated gfx dmar support is totally busted. */
+ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2a40, quirk_iommu_igfx);
+ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2e00, quirk_iommu_igfx);
diff --git a/queue-7.0/iommu-vt-d-fix-oops-due-to-out-of-scope-access.patch b/queue-7.0/iommu-vt-d-fix-oops-due-to-out-of-scope-access.patch
new file mode 100644 (file)
index 0000000..bcd8bae
--- /dev/null
@@ -0,0 +1,66 @@
+From a6dea58d8625c06b9654c0555f101742481335c3 Mon Sep 17 00:00:00 2001
+From: Zhenzhong Duan <zhenzhong.duan@intel.com>
+Date: Sat, 9 May 2026 10:43:45 +0800
+Subject: iommu/vt-d: Fix oops due to out of scope access
+
+From: Zhenzhong Duan <zhenzhong.duan@intel.com>
+
+commit a6dea58d8625c06b9654c0555f101742481335c3 upstream.
+
+Below oops triggers when kill QEMU process:
+
+  Oops: general protection fault, probably for non-canonical address 0x7fffffff844eaaa7: 0000 [#1] SMP NOPTI
+  Call Trace:
+   <TASK>
+   do_raw_spin_lock+0xaa/0xc0
+   _raw_spin_lock_irqsave+0x21/0x40
+   domain_remove_dev_pasid+0x52/0x160
+   intel_nested_set_dev_pasid+0x1b9/0x1e0
+   __iommu_set_group_pasid+0x56/0x120
+   pci_dev_reset_iommu_done+0xe3/0x180
+   pcie_flr+0x65/0x160
+   __pci_reset_function_locked+0x5b/0x120
+   vfio_pci_core_close_device+0x63/0xe0 [vfio_pci_core]
+   vfio_df_close+0x4f/0xa0
+   vfio_df_unbind_iommufd+0x2d/0x60
+   vfio_device_fops_release+0x3e/0x40
+   __fput+0xe5/0x2c0
+   task_work_run+0x58/0xa0
+   do_exit+0x2c8/0x600
+   do_group_exit+0x2f/0xa0
+   get_signal+0x863/0x8c0
+   arch_do_signal_or_restart+0x24/0x100
+   exit_to_user_mode_loop+0x87/0x380
+   do_syscall_64+0x2ff/0x11e0
+   entry_SYSCALL_64_after_hwframe+0x76/0x7e
+
+The global static blocked domain is a dummy domain without corresponding
+dmar_domain structure, accessing beyond iommu_domain structure triggers
+oops easily. Fix it by return early in domain_remove_dev_pasid() like
+identity domain.
+
+Fixes: 7d0c9da6c150 ("iommu/vt-d: Add set_dev_pasid callback for dma domain")
+Cc: stable@vger.kernel.org
+Signed-off-by: Zhenzhong Duan <zhenzhong.duan@intel.com>
+Reviewed-by: Kevin Tian <kevin.tian@intel.com>
+Link: https://lore.kernel.org/r/20260421031347.1408890-1-zhenzhong.duan@intel.com
+Signed-off-by: Lu Baolu <baolu.lu@linux.intel.com>
+Signed-off-by: Joerg Roedel <joerg.roedel@amd.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/iommu/intel/iommu.c |    4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+--- a/drivers/iommu/intel/iommu.c
++++ b/drivers/iommu/intel/iommu.c
+@@ -3529,8 +3529,8 @@ void domain_remove_dev_pasid(struct iomm
+       if (!domain)
+               return;
+-      /* Identity domain has no meta data for pasid. */
+-      if (domain->type == IOMMU_DOMAIN_IDENTITY)
++      /* Identity domain and blocked domain have no meta data for pasid. */
++      if (domain->type == IOMMU_DOMAIN_IDENTITY || domain->type == IOMMU_DOMAIN_BLOCKED)
+               return;
+       dmar_domain = to_dmar_domain(domain);
diff --git a/queue-7.0/irqchip-gic-v5-allocate-its-parent-lpis-as-a-range.patch b/queue-7.0/irqchip-gic-v5-allocate-its-parent-lpis-as-a-range.patch
new file mode 100644 (file)
index 0000000..a9f22ed
--- /dev/null
@@ -0,0 +1,94 @@
+From a7c7e42654b6a8676610ee09d22901432c4851af Mon Sep 17 00:00:00 2001
+From: Sascha Bischoff <Sascha.Bischoff@arm.com>
+Date: Wed, 6 May 2026 09:37:43 +0000
+Subject: irqchip/gic-v5: Allocate ITS parent LPIs as a range
+
+From: Sascha Bischoff <Sascha.Bischoff@arm.com>
+
+commit a7c7e42654b6a8676610ee09d22901432c4851af upstream.
+
+The ITS MSI domain no longer manages LPI allocation directly. LPIs are
+allocated and freed by the parent LPI domain, which can now handle a
+full range of interrupts and unwind partial allocations internally.
+
+Make the ITS domain request and release the parent IRQs as a single
+range instead of iterating over each interrupt. The ITS allocation
+path then only needs to reserve EventIDs, allocate the parent range,
+and fill in the ITS irq_data for each MSI. Since no operation in the
+per-MSI loop can fail, the partial parent-free unwind becomes
+unnecessary.
+
+On teardown, reset the ITS irq_data for the range and then release the
+parent range in one call, leaving LPI teardown to the LPI domain.
+
+Fixes: 0f0101325876 ("irqchip/gic-v5: Add GICv5 LPI/IPI support")
+Signed-off-by: Sascha Bischoff <sascha.bischoff@arm.com>
+Signed-off-by: Thomas Gleixner <tglx@kernel.org>
+Reviewed-by: Marc Zyngier <maz@kernel.org>
+Reviewed-by: Lorenzo Pieralisi <lpieralisi@kernel.org>
+Cc: stable@vger.kernel.org
+Link: https://patch.msgid.link/20260506093634.382062-4-sascha.bischoff@arm.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/irqchip/irq-gic-v5-its.c |   22 +++++++---------------
+ 1 file changed, 7 insertions(+), 15 deletions(-)
+
+--- a/drivers/irqchip/irq-gic-v5-its.c
++++ b/drivers/irqchip/irq-gic-v5-its.c
+@@ -937,6 +937,7 @@ static int gicv5_its_irq_domain_alloc(st
+       int ret, i;
+       its_dev = info->scratchpad[0].ptr;
++      device_id = its_dev->device_id;
+       ret = gicv5_its_alloc_eventid(its_dev, info, nr_irqs, &event_id_base);
+       if (ret)
+@@ -946,14 +947,11 @@ static int gicv5_its_irq_domain_alloc(st
+       if (ret)
+               goto out_eventid;
+-      device_id = its_dev->device_id;
++      ret = irq_domain_alloc_irqs_parent(domain, virq, nr_irqs, NULL);
++      if (ret)
++              goto out_eventid;
+       for (i = 0; i < nr_irqs; i++) {
+-              ret = irq_domain_alloc_irqs_parent(domain, virq + i, 1, NULL);
+-              if (ret) {
+-                      goto out_free_irqs;
+-              }
+-
+               /*
+                * Store eventid and deviceid into the hwirq for later use.
+                *
+@@ -972,12 +970,6 @@ static int gicv5_its_irq_domain_alloc(st
+       return 0;
+-out_free_irqs:
+-      while (--i >= 0) {
+-              irqd = irq_domain_get_irq_data(domain, virq + i);
+-              irq_domain_reset_irq_data(irqd);
+-              irq_domain_free_irqs_parent(domain, virq + i, 1);
+-      }
+ out_eventid:
+       gicv5_its_free_eventid(its_dev, event_id_base, nr_irqs);
+       return ret;
+@@ -1000,14 +992,14 @@ static void gicv5_its_irq_domain_free(st
+       bitmap_release_region(its_dev->event_map, event_id_base,
+                             get_count_order(nr_irqs));
+-      /*  Hierarchically free irq data */
+       for (i = 0; i < nr_irqs; i++) {
+               d = irq_domain_get_irq_data(domain, virq + i);
+-
+               irq_domain_reset_irq_data(d);
+-              irq_domain_free_irqs_parent(domain, virq + i, 1);
+       }
++      /*  Hierarchically free irq data */
++      irq_domain_free_irqs_parent(domain, virq, nr_irqs);
++
+       gicv5_its_syncr(its, its_dev);
+       gicv5_irs_syncr();
+ }
diff --git a/queue-7.0/irqchip-gic-v5-move-lpi-allocation-into-the-lpi-domain.patch b/queue-7.0/irqchip-gic-v5-move-lpi-allocation-into-the-lpi-domain.patch
new file mode 100644 (file)
index 0000000..2999460
--- /dev/null
@@ -0,0 +1,210 @@
+From dec85d2fbd20de3711a71e65397dfdb40c3fa953 Mon Sep 17 00:00:00 2001
+From: Sascha Bischoff <Sascha.Bischoff@arm.com>
+Date: Wed, 6 May 2026 09:37:02 +0000
+Subject: irqchip/gic-v5: Move LPI allocation into the LPI domain
+
+From: Sascha Bischoff <Sascha.Bischoff@arm.com>
+
+commit dec85d2fbd20de3711a71e65397dfdb40c3fa953 upstream.
+
+The IPI and ITS MSI domains currently allocate and release LPIs
+directly, then pass the selected LPI ID to the parent LPI domain. This
+leaks the LPI domain's allocation policy into its child domains and
+forces each child to duplicate part of the parent domain's teardown.
+
+Make the LPI domain allocate LPIs in its .alloc() callback and release
+them in a matching .free() callback. Child domains can then request a
+parent interrupt without passing an implementation-specific LPI ID,
+and the LPI lifetime is tied to the domain that owns the LPI
+namespace.
+
+Remove the gicv5_alloc_lpi() and gicv5_free_lpi() wrappers now that no
+external caller needs to manage LPIs directly.
+
+This is a preparatory change for an actual leakage problem in the
+allocation code and therefore tagged with the same Fixes tag.
+
+Fixes: 0f0101325876 ("irqchip/gic-v5: Add GICv5 LPI/IPI support")
+Signed-off-by: Sascha Bischoff <sascha.bischoff@arm.com>
+Signed-off-by: Thomas Gleixner <tglx@kernel.org>
+Reviewed-by: Marc Zyngier <maz@kernel.org>
+Reviewed-by: Lorenzo Pieralisi <lpieralisi@kernel.org>
+Cc: stable@vger.kernel.org
+Link: https://patch.msgid.link/20260506093634.382062-2-sascha.bischoff@arm.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/irqchip/irq-gic-v5-its.c   |   14 +--------
+ drivers/irqchip/irq-gic-v5.c       |   53 ++++++++++++++++++-------------------
+ include/linux/irqchip/arm-gic-v5.h |    3 --
+ 3 files changed, 28 insertions(+), 42 deletions(-)
+
+--- a/drivers/irqchip/irq-gic-v5-its.c
++++ b/drivers/irqchip/irq-gic-v5-its.c
+@@ -929,8 +929,8 @@ static void gicv5_its_free_eventid(struc
+ static int gicv5_its_irq_domain_alloc(struct irq_domain *domain, unsigned int virq,
+                                     unsigned int nr_irqs, void *arg)
+ {
+-      u32 device_id, event_id_base, lpi;
+       struct gicv5_its_dev *its_dev;
++      u32 device_id, event_id_base;
+       msi_alloc_info_t *info = arg;
+       irq_hw_number_t hwirq;
+       struct irq_data *irqd;
+@@ -949,16 +949,8 @@ static int gicv5_its_irq_domain_alloc(st
+       device_id = its_dev->device_id;
+       for (i = 0; i < nr_irqs; i++) {
+-              ret = gicv5_alloc_lpi();
+-              if (ret < 0) {
+-                      pr_debug("Failed to find free LPI!\n");
+-                      goto out_free_irqs;
+-              }
+-              lpi = ret;
+-
+-              ret = irq_domain_alloc_irqs_parent(domain, virq + i, 1, &lpi);
++              ret = irq_domain_alloc_irqs_parent(domain, virq + i, 1, NULL);
+               if (ret) {
+-                      gicv5_free_lpi(lpi);
+                       goto out_free_irqs;
+               }
+@@ -983,7 +975,6 @@ static int gicv5_its_irq_domain_alloc(st
+ out_free_irqs:
+       while (--i >= 0) {
+               irqd = irq_domain_get_irq_data(domain, virq + i);
+-              gicv5_free_lpi(irqd->parent_data->hwirq);
+               irq_domain_reset_irq_data(irqd);
+               irq_domain_free_irqs_parent(domain, virq + i, 1);
+       }
+@@ -1013,7 +1004,6 @@ static void gicv5_its_irq_domain_free(st
+       for (i = 0; i < nr_irqs; i++) {
+               d = irq_domain_get_irq_data(domain, virq + i);
+-              gicv5_free_lpi(d->parent_data->hwirq);
+               irq_domain_reset_irq_data(d);
+               irq_domain_free_irqs_parent(domain, virq + i, 1);
+       }
+--- a/drivers/irqchip/irq-gic-v5.c
++++ b/drivers/irqchip/irq-gic-v5.c
+@@ -59,16 +59,6 @@ static void release_lpi(u32 lpi)
+       ida_free(&lpi_ida, lpi);
+ }
+-int gicv5_alloc_lpi(void)
+-{
+-      return alloc_lpi();
+-}
+-
+-void gicv5_free_lpi(u32 lpi)
+-{
+-      release_lpi(lpi);
+-}
+-
+ static void gicv5_ppi_priority_init(void)
+ {
+       write_sysreg_s(REPEAT_BYTE(GICV5_IRQ_PRI_MI), SYS_ICC_PPI_PRIORITYR0_EL1);
+@@ -788,18 +778,36 @@ static void gicv5_lpi_config_reset(struc
+       gicv5_lpi_irq_write_pending_state(d, false);
+ }
++static void gicv5_irq_lpi_domain_free(struct irq_domain *domain, unsigned int virq,
++                                    unsigned int nr_irqs)
++{
++      struct irq_data *d;
++
++      if (WARN_ON_ONCE(nr_irqs != 1))
++              return;
++
++      d = irq_domain_get_irq_data(domain, virq);
++
++      release_lpi(d->hwirq);
++
++      irq_set_handler(virq, NULL);
++      irq_domain_reset_irq_data(d);
++}
++
+ static int gicv5_irq_lpi_domain_alloc(struct irq_domain *domain, unsigned int virq,
+                                     unsigned int nr_irqs, void *arg)
+ {
+       irq_hw_number_t hwirq;
+       struct irq_data *irqd;
+-      u32 *lpi = arg;
+       int ret;
+       if (WARN_ON_ONCE(nr_irqs != 1))
+               return -EINVAL;
+-      hwirq = *lpi;
++      ret = alloc_lpi();
++      if (ret < 0)
++              return ret;
++      hwirq = ret;
+       irqd = irq_domain_get_irq_data(domain, virq);
+@@ -808,8 +816,10 @@ static int gicv5_irq_lpi_domain_alloc(st
+       irqd_set_single_target(irqd);
+       ret = gicv5_irs_iste_alloc(hwirq);
+-      if (ret < 0)
++      if (ret < 0) {
++              release_lpi(hwirq);
+               return ret;
++      }
+       gicv5_hwirq_init(hwirq, GICV5_IRQ_PRI_MI, GICV5_HWIRQ_TYPE_LPI);
+       gicv5_lpi_config_reset(irqd);
+@@ -819,7 +829,7 @@ static int gicv5_irq_lpi_domain_alloc(st
+ static const struct irq_domain_ops gicv5_irq_lpi_domain_ops = {
+       .alloc  = gicv5_irq_lpi_domain_alloc,
+-      .free   = gicv5_irq_domain_free,
++      .free   = gicv5_irq_lpi_domain_free,
+ };
+ void __init gicv5_init_lpi_domain(void)
+@@ -841,21 +851,12 @@ static int gicv5_irq_ipi_domain_alloc(st
+ {
+       struct irq_data *irqd;
+       int ret, i;
+-      u32 lpi;
+       for (i = 0; i < nr_irqs; i++) {
+-              ret = gicv5_alloc_lpi();
+-              if (ret < 0)
++              ret = irq_domain_alloc_irqs_parent(domain, virq + i, 1, NULL);
++              if (ret)
+                       return ret;
+-              lpi = ret;
+-
+-              ret = irq_domain_alloc_irqs_parent(domain, virq + i, 1, &lpi);
+-              if (ret) {
+-                      gicv5_free_lpi(lpi);
+-                      return ret;
+-              }
+-
+               irqd = irq_domain_get_irq_data(domain, virq + i);
+               irq_domain_set_hwirq_and_chip(domain, virq + i, i,
+@@ -881,8 +882,6 @@ static void gicv5_irq_ipi_domain_free(st
+               if (!d)
+                       return;
+-              gicv5_free_lpi(d->parent_data->hwirq);
+-
+               irq_set_handler(virq + i, NULL);
+               irq_domain_reset_irq_data(d);
+               irq_domain_free_irqs_parent(domain, virq + i, 1);
+--- a/include/linux/irqchip/arm-gic-v5.h
++++ b/include/linux/irqchip/arm-gic-v5.h
+@@ -398,9 +398,6 @@ struct gicv5_its_itt_cfg {
+ void gicv5_init_lpis(u32 max);
+ void gicv5_deinit_lpis(void);
+-int gicv5_alloc_lpi(void);
+-void gicv5_free_lpi(u32 lpi);
+-
+ void __init gicv5_its_of_probe(struct device_node *parent);
+ void __init gicv5_its_acpi_probe(void);
+ #endif
diff --git a/queue-7.0/irqchip-gic-v5-support-range-allocation-for-lpis.patch b/queue-7.0/irqchip-gic-v5-support-range-allocation-for-lpis.patch
new file mode 100644 (file)
index 0000000..58c186e
--- /dev/null
@@ -0,0 +1,161 @@
+From eb6f6d523813ead9dc2799194a2839d42c049734 Mon Sep 17 00:00:00 2001
+From: Sascha Bischoff <Sascha.Bischoff@arm.com>
+Date: Wed, 6 May 2026 09:37:23 +0000
+Subject: irqchip/gic-v5: Support range allocation for LPIs
+
+From: Sascha Bischoff <Sascha.Bischoff@arm.com>
+
+commit eb6f6d523813ead9dc2799194a2839d42c049734 upstream.
+
+The per-IPI parent allocation loop returns immediately on failure and leaks
+any parent interrupts allocated by earlier iterations.
+
+The GICv5 LPI domain now owns LPI allocation and teardown internally,
+but its irq_domain callbacks still reject requests where nr_irqs is
+greater than one. This forces child domains to allocate and free LPIs
+one at a time even when the interrupt core requests a contiguous
+range.
+
+Handle multi-interrupt allocation and teardown in the LPI domain by
+iterating over the requested range and unwinding any partially
+allocated state on failure.
+
+Allocate the parent LPIs for the IPI domain with a single range
+request as well, which cures the leakage problem.
+
+Fixes: 0f0101325876 ("irqchip/gic-v5: Add GICv5 LPI/IPI support")
+Signed-off-by: Sascha Bischoff <sascha.bischoff@arm.com>
+Signed-off-by: Thomas Gleixner <tglx@kernel.org>
+Reviewed-by: Marc Zyngier <maz@kernel.org>
+Reviewed-by: Lorenzo Pieralisi <lpieralisi@kernel.org>
+Cc: stable@vger.kernel.org
+Link: https://patch.msgid.link/20260506093634.382062-3-sascha.bischoff@arm.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/irqchip/irq-gic-v5.c |   77 +++++++++++++++++++++++--------------------
+ 1 file changed, 42 insertions(+), 35 deletions(-)
+
+--- a/drivers/irqchip/irq-gic-v5.c
++++ b/drivers/irqchip/irq-gic-v5.c
+@@ -783,15 +783,14 @@ static void gicv5_irq_lpi_domain_free(st
+ {
+       struct irq_data *d;
+-      if (WARN_ON_ONCE(nr_irqs != 1))
+-              return;
++      for (unsigned int i = 0; i < nr_irqs; i++, virq++) {
++              d = irq_domain_get_irq_data(domain, virq);
+-      d = irq_domain_get_irq_data(domain, virq);
++              release_lpi(d->hwirq);
+-      release_lpi(d->hwirq);
+-
+-      irq_set_handler(virq, NULL);
+-      irq_domain_reset_irq_data(d);
++              irq_set_handler(virq, NULL);
++              irq_domain_reset_irq_data(d);
++      }
+ }
+ static int gicv5_irq_lpi_domain_alloc(struct irq_domain *domain, unsigned int virq,
+@@ -799,32 +798,39 @@ static int gicv5_irq_lpi_domain_alloc(st
+ {
+       irq_hw_number_t hwirq;
+       struct irq_data *irqd;
++      unsigned int i;
+       int ret;
+-      if (WARN_ON_ONCE(nr_irqs != 1))
+-              return -EINVAL;
+-
+-      ret = alloc_lpi();
+-      if (ret < 0)
+-              return ret;
+-      hwirq = ret;
++      for (i = 0; i < nr_irqs; i++) {
++              ret = alloc_lpi();
++              if (ret < 0)
++                      goto out_free_lpis;
++              hwirq = ret;
++
++              ret = gicv5_irs_iste_alloc(hwirq);
++              if (ret < 0) {
++                      /* Undo partial state first, then clean up the rest */
++                      release_lpi(hwirq);
++                      goto out_free_lpis;
++              }
+-      irqd = irq_domain_get_irq_data(domain, virq);
++              irqd = irq_domain_get_irq_data(domain, virq + i);
+-      irq_domain_set_info(domain, virq, hwirq, &gicv5_lpi_irq_chip, NULL,
+-                          handle_fasteoi_irq, NULL, NULL);
+-      irqd_set_single_target(irqd);
++              irq_domain_set_info(domain, virq + i, hwirq, &gicv5_lpi_irq_chip,
++                                  NULL, handle_fasteoi_irq, NULL, NULL);
++              irqd_set_single_target(irqd);
+-      ret = gicv5_irs_iste_alloc(hwirq);
+-      if (ret < 0) {
+-              release_lpi(hwirq);
+-              return ret;
++              gicv5_hwirq_init(hwirq, GICV5_IRQ_PRI_MI, GICV5_HWIRQ_TYPE_LPI);
++              gicv5_lpi_config_reset(irqd);
+       }
+-      gicv5_hwirq_init(hwirq, GICV5_IRQ_PRI_MI, GICV5_HWIRQ_TYPE_LPI);
+-      gicv5_lpi_config_reset(irqd);
+-
+       return 0;
++
++out_free_lpis:
++      if (i)
++              gicv5_irq_lpi_domain_free(domain, virq, i);
++
++      return ret;
+ }
+ static const struct irq_domain_ops gicv5_irq_lpi_domain_ops = {
+@@ -850,21 +856,21 @@ static int gicv5_irq_ipi_domain_alloc(st
+                                     unsigned int nr_irqs, void *arg)
+ {
+       struct irq_data *irqd;
+-      int ret, i;
++      int ret;
+-      for (i = 0; i < nr_irqs; i++) {
+-              ret = irq_domain_alloc_irqs_parent(domain, virq + i, 1, NULL);
+-              if (ret)
+-                      return ret;
++      ret = irq_domain_alloc_irqs_parent(domain, virq, nr_irqs, arg);
++      if (ret)
++              return ret;
+-              irqd = irq_domain_get_irq_data(domain, virq + i);
++      for (unsigned int i = 0; i < nr_irqs; i++, virq++) {
++              irqd = irq_domain_get_irq_data(domain, virq);
+-              irq_domain_set_hwirq_and_chip(domain, virq + i, i,
+-                              &gicv5_ipi_irq_chip, NULL);
++              irq_domain_set_hwirq_and_chip(domain, virq, i,
++                                            &gicv5_ipi_irq_chip, NULL);
+               irqd_set_single_target(irqd);
+-              irq_set_handler(virq + i, handle_percpu_irq);
++              irq_set_handler(virq, handle_percpu_irq);
+       }
+       return 0;
+@@ -884,8 +890,9 @@ static void gicv5_irq_ipi_domain_free(st
+               irq_set_handler(virq + i, NULL);
+               irq_domain_reset_irq_data(d);
+-              irq_domain_free_irqs_parent(domain, virq + i, 1);
+       }
++
++      irq_domain_free_irqs_parent(domain, virq, nr_irqs);
+ }
+ static const struct irq_domain_ops gicv5_irq_ipi_domain_ops = {
diff --git a/queue-7.0/irqchip-meson-gpio-use-the-correct-register-in-meson_s4_gpio_irq_set_type.patch b/queue-7.0/irqchip-meson-gpio-use-the-correct-register-in-meson_s4_gpio_irq_set_type.patch
new file mode 100644 (file)
index 0000000..e767717
--- /dev/null
@@ -0,0 +1,37 @@
+From 5363b67ac8ebcc3e227dbf59fc8061949109841d Mon Sep 17 00:00:00 2001
+From: Xianwei Zhao <xianwei.zhao@amlogic.com>
+Date: Fri, 8 May 2026 07:36:54 +0000
+Subject: irqchip/meson-gpio: Use the correct register in meson_s4_gpio_irq_set_type()
+
+From: Xianwei Zhao <xianwei.zhao@amlogic.com>
+
+commit 5363b67ac8ebcc3e227dbf59fc8061949109841d upstream.
+
+meson_s4_gpio_irq_set_type() uses the both-edge trigger register for
+configuring level type and single edge mode interrupts, which is not
+correct.
+
+Use REG_EDGE_POL instead.
+
+Fixes: bbd6fcc76b39 ("irqchip: Add support for Amlogic A4 and A5 SoCs")
+Signed-off-by: Xianwei Zhao <xianwei.zhao@amlogic.com>
+Signed-off-by: Thomas Gleixner <tglx@kernel.org>
+Cc: stable@vger.kernel.org
+Link: https://patch.msgid.link/20260508-a9-gpio-irqchip-v1-1-9dc5f3e022e0@amlogic.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/irqchip/irq-meson-gpio.c |    3 +--
+ 1 file changed, 1 insertion(+), 2 deletions(-)
+
+--- a/drivers/irqchip/irq-meson-gpio.c
++++ b/drivers/irqchip/irq-meson-gpio.c
+@@ -415,8 +415,7 @@ static int meson_s4_gpio_irq_set_type(st
+       if (type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING))
+               val |= BIT(ctl->params->edge_single_offset + idx);
+-      meson_gpio_irq_update_bits(ctl, params->edge_pol_reg,
+-                                 BIT(idx) | BIT(12 + idx), val);
++      meson_gpio_irq_update_bits(ctl, REG_EDGE_POL, BIT(idx) | BIT(12 + idx), val);
+       return 0;
+ };
diff --git a/queue-7.0/irqchip-riscv-imsic-clear-interrupt-move-state-during-cpu-offlining.patch b/queue-7.0/irqchip-riscv-imsic-clear-interrupt-move-state-during-cpu-offlining.patch
new file mode 100644 (file)
index 0000000..19857e0
--- /dev/null
@@ -0,0 +1,53 @@
+From cefafbd561402b0fe6447449364a30315b9b1570 Mon Sep 17 00:00:00 2001
+From: Yong-Xuan Wang <yongxuan.wang@sifive.com>
+Date: Fri, 8 May 2026 02:31:21 -0700
+Subject: irqchip/riscv-imsic: Clear interrupt move state during CPU offlining
+
+From: Yong-Xuan Wang <yongxuan.wang@sifive.com>
+
+commit cefafbd561402b0fe6447449364a30315b9b1570 upstream.
+
+Affinity changes of IMSIC interrupts have to be careful to not lose an
+interrupt in the process. Each vector keeps track of an affinity change in
+progress with two pointers in struct imsic_vector.
+
+imsic_vector::move_prev points to the previous CPU target data and
+imsic_vector::move_next to the designated new CPU target data.
+
+imsic_vector::move_prev on the new CPU can only be cleared after the
+previous CPU has cleared imsic_vector::move_next, which ususally happens in
+__imsic_remote_sync().
+
+In case of CPU hot-unplug __imsic_remote_sync() is not invoked because the
+CPU is already marked offline. That means imsic_vector::move_prev becomes
+stale until the CPU is onlined again.
+
+The stale pointer prevents further affinity changes for the affected
+interrupts.
+
+Solve this by clearing the imsic_vector::move_prev pointers in the CPU
+hotplug offline path.
+
+[ tglx: Replace word salad in change log ]
+
+Fixes: 0f67911e821c ("irqchip/riscv-imsic: Separate next and previous pointers in IMSIC vector")
+Signed-off-by: Yong-Xuan Wang <yongxuan.wang@sifive.com>
+Signed-off-by: Thomas Gleixner <tglx@kernel.org>
+Cc: stable@vger.kernel.org
+Link: https://patch.msgid.link/20260508-imsic-v2-1-e9f08dd46cf5@sifive.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/irqchip/irq-riscv-imsic-early.c |    2 ++
+ 1 file changed, 2 insertions(+)
+
+--- a/drivers/irqchip/irq-riscv-imsic-early.c
++++ b/drivers/irqchip/irq-riscv-imsic-early.c
+@@ -158,6 +158,8 @@ static int imsic_dying_cpu(unsigned int
+       /* Cleanup IPIs */
+       imsic_ipi_dying_cpu();
++      imsic_local_sync_all(false);
++
+       /* Mark per-CPU IMSIC state as offline */
+       imsic_state_offline();
diff --git a/queue-7.0/libceph-fix-potential-null-ptr-deref-in-decode_choose_args.patch b/queue-7.0/libceph-fix-potential-null-ptr-deref-in-decode_choose_args.patch
new file mode 100644 (file)
index 0000000..83fe4a1
--- /dev/null
@@ -0,0 +1,47 @@
+From 28b0a2ab8c82d0bbdeb8013029c67c978ce6e4bf Mon Sep 17 00:00:00 2001
+From: Raphael Zimmer <raphael.zimmer@tu-ilmenau.de>
+Date: Tue, 12 May 2026 18:16:40 +0200
+Subject: libceph: Fix potential null-ptr-deref in decode_choose_args()
+
+From: Raphael Zimmer <raphael.zimmer@tu-ilmenau.de>
+
+commit 28b0a2ab8c82d0bbdeb8013029c67c978ce6e4bf upstream.
+
+A message of type CEPH_MSG_OSD_MAP contains an OSD map that itself
+contains a CRUSH map. When decoding this CRUSH map in crush_decode(), an
+array of max_buckets CRUSH buckets is decoded, where some indices may
+not refer to actual buckets and are therefore set to NULL. The received
+CRUSH map may optionally contain choose_args that get decoded in
+decode_choose_args(). When decoding a crush_choose_arg_map, a series of
+choose_args for different buckets is decoded, with the bucket_index
+being read from the incoming message. It is only checked that the bucket
+index does not exceed max_buckets, but not that it doesn't point to an
+index with a NULL bucket. If a (potentially corrupted) message contains
+a crush_choose_arg_map including such a bucket_index, a null pointer
+dereference may occur in the subsequent processing when attempting to
+access the bucket with the given index.
+
+This patch fixes the issue by extending the affected check. Now, it is
+only attempted to access the bucket if it is not NULL.
+
+Cc: stable@vger.kernel.org
+Signed-off-by: Raphael Zimmer <raphael.zimmer@tu-ilmenau.de>
+Reviewed-by: Ilya Dryomov <idryomov@gmail.com>
+Signed-off-by: Ilya Dryomov <idryomov@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/ceph/osdmap.c |    3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+--- a/net/ceph/osdmap.c
++++ b/net/ceph/osdmap.c
+@@ -389,7 +389,8 @@ static int decode_choose_args(void **p,
+                               goto fail;
+                       if (arg->ids_size &&
+-                          arg->ids_size != c->buckets[bucket_index]->size)
++                          (!c->buckets[bucket_index] ||
++                           arg->ids_size != c->buckets[bucket_index]->size))
+                               goto e_inval;
+               }
diff --git a/queue-7.0/libceph-fix-potential-out-of-bounds-access-in-__ceph_x_decrypt.patch b/queue-7.0/libceph-fix-potential-out-of-bounds-access-in-__ceph_x_decrypt.patch
new file mode 100644 (file)
index 0000000..2850986
--- /dev/null
@@ -0,0 +1,47 @@
+From 821365487aa58d06bda65c676ba215d506ba9768 Mon Sep 17 00:00:00 2001
+From: Raphael Zimmer <raphael.zimmer@tu-ilmenau.de>
+Date: Tue, 28 Apr 2026 14:15:46 +0200
+Subject: libceph: Fix potential out-of-bounds access in __ceph_x_decrypt()
+
+From: Raphael Zimmer <raphael.zimmer@tu-ilmenau.de>
+
+commit 821365487aa58d06bda65c676ba215d506ba9768 upstream.
+
+In __ceph_x_decrypt(), a part of the buffer p is interpreted as a
+ceph_x_encrypt_header, and the magic field of this struct is accessed.
+This happens without any guarantee that the buffer is large enough to
+hold this struct. The function parameter ciphertext_len represents the
+length of the ciphertext to decrypt and is guaranteed to be at most the
+remaining size of the allocated buffer p. However, this value is not
+necessarily greater than sizeof(ceph_x_encrypt_header). E.g., a message
+frame of type FRAME_TAG_AUTH_REPLY_MORE, that is just as long to hold
+the ciphertext at its end with a ciphertext_len of 8 or less, can
+trigger an out-of-bounds memory access when accessing hdr->magic.
+
+This patch fixes the issue by adding a check to ensure that the
+decrypted plaintext in the buffer is large enough to represent at least
+the ceph_x_encrypt_header.
+
+Cc: stable@vger.kernel.org
+Signed-off-by: Raphael Zimmer <raphael.zimmer@tu-ilmenau.de>
+Reviewed-by: Ilya Dryomov <idryomov@gmail.com>
+Signed-off-by: Ilya Dryomov <idryomov@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/ceph/auth_x.c |    5 +++++
+ 1 file changed, 5 insertions(+)
+
+--- a/net/ceph/auth_x.c
++++ b/net/ceph/auth_x.c
+@@ -115,6 +115,11 @@ static int __ceph_x_decrypt(const struct
+       if (ret)
+               return ret;
++      if (plaintext_len < sizeof(*hdr)) {
++              pr_err("%s plaintext too small %d\n", __func__, plaintext_len);
++              return -EINVAL;
++      }
++
+       hdr = p + ceph_crypt_data_offset(key);
+       if (le64_to_cpu(hdr->magic) != CEPHX_ENC_MAGIC) {
+               pr_err("%s bad magic\n", __func__);
diff --git a/queue-7.0/libceph-fix-potential-out-of-bounds-access-in-crush_decode.patch b/queue-7.0/libceph-fix-potential-out-of-bounds-access-in-crush_decode.patch
new file mode 100644 (file)
index 0000000..8c80dcc
--- /dev/null
@@ -0,0 +1,98 @@
+From 4c79fc2d598694bda845b46229c9d48b65042970 Mon Sep 17 00:00:00 2001
+From: Raphael Zimmer <raphael.zimmer@tu-ilmenau.de>
+Date: Wed, 22 Apr 2026 10:47:13 +0200
+Subject: libceph: Fix potential out-of-bounds access in crush_decode()
+
+From: Raphael Zimmer <raphael.zimmer@tu-ilmenau.de>
+
+commit 4c79fc2d598694bda845b46229c9d48b65042970 upstream.
+
+A message of type CEPH_MSG_OSD_MAP containing a crush map with at least
+one bucket has two fields holding the bucket algorithm. If the values
+in these two fields differ, an out-of-bounds access can occur. This is
+the case because the first algorithm field (alg) is used to allocate
+the correct amount of memory for a bucket of this type, while the second
+algorithm field inside the bucket (b->alg) is used in the subsequent
+processing.
+
+This patch fixes the issue by adding a check that compares alg and
+b->alg and aborts the processing in case they differ. Furthermore,
+b->alg is set to 0 in this case, because the destruction of the crush
+map also uses this field to determine the bucket type, which can again
+result in an out-of-bounds access when trying to free the memory pointed
+to by the fields of the bucket. To correctly free the memory allocated
+for the bucket in such a case, the corresponding call to kfree is moved
+from the algorithm-specific crush_destroy_bucket functions to the
+generic crush_destroy_bucket().
+
+Cc: stable@vger.kernel.org
+Signed-off-by: Raphael Zimmer <raphael.zimmer@tu-ilmenau.de>
+Reviewed-by: Ilya Dryomov <idryomov@gmail.com>
+Signed-off-by: Ilya Dryomov <idryomov@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/ceph/crush/crush.c |    6 +-----
+ net/ceph/osdmap.c      |    4 ++++
+ 2 files changed, 5 insertions(+), 5 deletions(-)
+
+--- a/net/ceph/crush/crush.c
++++ b/net/ceph/crush/crush.c
+@@ -47,7 +47,6 @@ int crush_get_bucket_item_weight(const s
+ void crush_destroy_bucket_uniform(struct crush_bucket_uniform *b)
+ {
+       kfree(b->h.items);
+-      kfree(b);
+ }
+ void crush_destroy_bucket_list(struct crush_bucket_list *b)
+@@ -55,14 +54,12 @@ void crush_destroy_bucket_list(struct cr
+       kfree(b->item_weights);
+       kfree(b->sum_weights);
+       kfree(b->h.items);
+-      kfree(b);
+ }
+ void crush_destroy_bucket_tree(struct crush_bucket_tree *b)
+ {
+       kfree(b->h.items);
+       kfree(b->node_weights);
+-      kfree(b);
+ }
+ void crush_destroy_bucket_straw(struct crush_bucket_straw *b)
+@@ -70,14 +67,12 @@ void crush_destroy_bucket_straw(struct c
+       kfree(b->straws);
+       kfree(b->item_weights);
+       kfree(b->h.items);
+-      kfree(b);
+ }
+ void crush_destroy_bucket_straw2(struct crush_bucket_straw2 *b)
+ {
+       kfree(b->item_weights);
+       kfree(b->h.items);
+-      kfree(b);
+ }
+ void crush_destroy_bucket(struct crush_bucket *b)
+@@ -99,6 +94,7 @@ void crush_destroy_bucket(struct crush_b
+               crush_destroy_bucket_straw2((struct crush_bucket_straw2 *)b);
+               break;
+       }
++      kfree(b);
+ }
+ /**
+--- a/net/ceph/osdmap.c
++++ b/net/ceph/osdmap.c
+@@ -517,6 +517,10 @@ static struct crush_map *crush_decode(vo
+               b->id = ceph_decode_32(p);
+               b->type = ceph_decode_16(p);
+               b->alg = ceph_decode_8(p);
++              if (b->alg != alg) {
++                      b->alg = 0;
++                      goto bad;
++              }
+               b->hash = ceph_decode_8(p);
+               b->weight = ceph_decode_32(p);
+               b->size = ceph_decode_32(p);
diff --git a/queue-7.0/libceph-fix-potential-out-of-bounds-access-in-osdmap_decode.patch b/queue-7.0/libceph-fix-potential-out-of-bounds-access-in-osdmap_decode.patch
new file mode 100644 (file)
index 0000000..d58d850
--- /dev/null
@@ -0,0 +1,41 @@
+From 35d0ed82d03e5ee77ea4f31f20e29562a7721649 Mon Sep 17 00:00:00 2001
+From: Raphael Zimmer <raphael.zimmer@tu-ilmenau.de>
+Date: Tue, 5 May 2026 11:08:12 +0200
+Subject: libceph: Fix potential out-of-bounds access in osdmap_decode()
+
+From: Raphael Zimmer <raphael.zimmer@tu-ilmenau.de>
+
+commit 35d0ed82d03e5ee77ea4f31f20e29562a7721649 upstream.
+
+When decoding osd_state and osd_weight from an incoming osdmap in
+osdmap_decode(), both are decoded for each osd, i.e., map->max_osd
+times. The ceph_decode_need() check only accounts for
+sizeof(*map->osd_weight) once. This can potentially result in an
+out-of-bounds memory access if the incoming message is corrupted such
+that the max_osd value exceeds the actual content of the osdmap message.
+
+This patch fixes the issue by changing the corresponding part in the
+ceph_decode_need() check to account for
+map->max_osd*sizeof(*map->osd_weight).
+
+Cc: stable@vger.kernel.org
+Fixes: dcbc919a5dc8 ("libceph: switch osdmap decoding to use ceph_decode_entity_addr")
+Signed-off-by: Raphael Zimmer <raphael.zimmer@tu-ilmenau.de>
+Reviewed-by: Ilya Dryomov <idryomov@gmail.com>
+Signed-off-by: Ilya Dryomov <idryomov@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/ceph/osdmap.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/net/ceph/osdmap.c
++++ b/net/ceph/osdmap.c
+@@ -1702,7 +1702,7 @@ static int osdmap_decode(void **p, void
+       ceph_decode_need(p, end, 3*sizeof(u32) +
+                        map->max_osd*(struct_v >= 5 ? sizeof(u32) :
+                                                      sizeof(u8)) +
+-                                     sizeof(*map->osd_weight), e_inval);
++                       map->max_osd*sizeof(*map->osd_weight), e_inval);
+       if (ceph_decode_32(p) != map->max_osd)
+               goto e_inval;
diff --git a/queue-7.0/libceph-handle-rbtree-insertion-error-in-decode_choose_args.patch b/queue-7.0/libceph-handle-rbtree-insertion-error-in-decode_choose_args.patch
new file mode 100644 (file)
index 0000000..2ce34db
--- /dev/null
@@ -0,0 +1,48 @@
+From d289478cfc0bcf81c7914200d6abdcb78bd04ded Mon Sep 17 00:00:00 2001
+From: Raphael Zimmer <raphael.zimmer@tu-ilmenau.de>
+Date: Tue, 12 May 2026 09:29:30 +0200
+Subject: libceph: handle rbtree insertion error in decode_choose_args()
+
+From: Raphael Zimmer <raphael.zimmer@tu-ilmenau.de>
+
+commit d289478cfc0bcf81c7914200d6abdcb78bd04ded upstream.
+
+A message of type CEPH_MSG_OSD_MAP contains an OSD map that itself
+contains a CRUSH map. The received CRUSH map may optionally contain
+choose_args that get decoded in decode_choose_args(). In this function,
+num_choose_arg_maps is read from the message, and a corresponding number
+of crush_choose_arg_maps gets decoded afterwards. Each
+crush_choose_arg_map has a choose_args_index, which serves as the key
+when inserting it into the choose_args rbtree of the decoded crush_map.
+If a (potentially corrupted) message contains two crush_choose_arg_maps
+with the same index, the assertion in insert_choose_arg_map() triggers a
+kernel BUG when trying to insert the second crush_choose_arg_map.
+
+This patch fixes the issue by switching to the non-asserting rbtree
+insertion function and rejecting the message if the insertion fails.
+
+[ idryomov: changelog ]
+
+Cc: stable@vger.kernel.org
+Signed-off-by: Raphael Zimmer <raphael.zimmer@tu-ilmenau.de>
+Reviewed-by: Ilya Dryomov <idryomov@gmail.com>
+Signed-off-by: Ilya Dryomov <idryomov@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/ceph/osdmap.c |    5 ++++-
+ 1 file changed, 4 insertions(+), 1 deletion(-)
+
+--- a/net/ceph/osdmap.c
++++ b/net/ceph/osdmap.c
+@@ -394,7 +394,10 @@ static int decode_choose_args(void **p,
+                               goto e_inval;
+               }
+-              insert_choose_arg_map(&c->choose_args, arg_map);
++              if (!__insert_choose_arg_map(&c->choose_args, arg_map)) {
++                      ret = -EEXIST;
++                      goto fail;
++              }
+       }
+       return 0;
diff --git a/queue-7.0/netfs-fix-error-handling-in-netfs_extract_user_iter.patch b/queue-7.0/netfs-fix-error-handling-in-netfs_extract_user_iter.patch
new file mode 100644 (file)
index 0000000..bcb36f1
--- /dev/null
@@ -0,0 +1,67 @@
+From 0aad5704c6b4d14007d4eab15883e8524e4310f4 Mon Sep 17 00:00:00 2001
+From: Paulo Alcantara <pc@manguebit.org>
+Date: Tue, 12 May 2026 13:33:46 +0100
+Subject: netfs: fix error handling in netfs_extract_user_iter()
+
+From: Paulo Alcantara <pc@manguebit.org>
+
+commit 0aad5704c6b4d14007d4eab15883e8524e4310f4 upstream.
+
+In netfs_extract_user_iter(), if iov_iter_extract_pages() failed to
+extract user pages, bail out on -ENOMEM, otherwise return the error
+code only if @npages == 0, allowing short DIO reads and writes to be
+issued.
+
+This fixes mmapstress02 from LTP tests against CIFS.
+
+Fixes: 85dd2c8ff368 ("netfs: Add a function to extract a UBUF or IOVEC into a BVEC iterator")
+Reported-by: Xiaoli Feng <xifeng@redhat.com>
+Signed-off-by: Paulo Alcantara (Red Hat) <pc@manguebit.org>
+Signed-off-by: David Howells <dhowells@redhat.com>
+Link: https://patch.msgid.link/20260512123404.719402-10-dhowells@redhat.com
+Cc: netfs@lists.linux.dev
+Cc: stable@vger.kernel.org
+Cc: linux-cifs@vger.kernel.org
+Cc: linux-fsdevel@vger.kernel.org
+Signed-off-by: Christian Brauner <brauner@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/netfs/iterator.c |   13 ++++++++++---
+ 1 file changed, 10 insertions(+), 3 deletions(-)
+
+--- a/fs/netfs/iterator.c
++++ b/fs/netfs/iterator.c
+@@ -22,7 +22,7 @@
+  *
+  * Extract the page fragments from the given amount of the source iterator and
+  * build up a second iterator that refers to all of those bits.  This allows
+- * the original iterator to disposed of.
++ * the original iterator to be disposed of.
+  *
+  * @extraction_flags can have ITER_ALLOW_P2PDMA set to request peer-to-peer DMA be
+  * allowed on the pages extracted.
+@@ -67,8 +67,8 @@ ssize_t netfs_extract_user_iter(struct i
+               ret = iov_iter_extract_pages(orig, &pages, count,
+                                            max_pages - npages, extraction_flags,
+                                            &offset);
+-              if (ret < 0) {
+-                      pr_err("Couldn't get user pages (rc=%zd)\n", ret);
++              if (unlikely(ret <= 0)) {
++                      ret = ret ?: -EIO;
+                       break;
+               }
+@@ -97,6 +97,13 @@ ssize_t netfs_extract_user_iter(struct i
+               npages += cur_npages;
+       }
++      if (ret < 0 && (ret == -ENOMEM || npages == 0)) {
++              for (i = 0; i < npages; i++)
++                      unpin_user_page(bv[i].bv_page);
++              kvfree(bv);
++              return ret;
++      }
++
+       iov_iter_bvec(new, orig->data_source, bv, npages, orig_len - count);
+       return npages;
+ }
diff --git a/queue-7.0/nfsd-fix-file-change-detection-in-cb_getattr.patch b/queue-7.0/nfsd-fix-file-change-detection-in-cb_getattr.patch
new file mode 100644 (file)
index 0000000..dfa6caa
--- /dev/null
@@ -0,0 +1,77 @@
+From 304d81a2fbf2b454def4debcb38ea173911b72cd Mon Sep 17 00:00:00 2001
+From: Scott Mayhew <smayhew@redhat.com>
+Date: Tue, 7 Apr 2026 18:08:57 -0400
+Subject: nfsd: fix file change detection in CB_GETATTR
+
+From: Scott Mayhew <smayhew@redhat.com>
+
+commit 304d81a2fbf2b454def4debcb38ea173911b72cd upstream.
+
+RFC 8881, section 10.4.3 doesn't say anything about caching the file
+size in the delegation record, nor does it say anything about comparing
+a cached file size with the size reported by the client in the
+CB_GETATTR reply for the purpose of determining if the client holds
+modified data for the file.
+
+What section 10.4.3 of RFC 8881 does say is that the server should
+compare the *current* file size with the size reported by the client
+holding the delegation in the CB_GETATTR reply, and if they differ to
+treat it as a modification regardless of the change attribute retrieved
+via the CB_GETATTR.
+
+Doing otherwise would cause the server to believe the client holding the
+delegation has a modified version of the file, even if the client
+flushed the modifications to the server prior to the CB_GETATTR.  This
+would have the added side effect of subsequent CB_GETATTRs causing
+updates to the mtime, ctime, and change attribute even if the client
+holding the delegation makes no further updates to the file.
+
+Modify nfsd4_deleg_getattr_conflict() to obtain the current file size
+via i_size_read().  Retain the ncf_cur_fsize field, since it's a
+convenient way to return the file size back to nfsd4_encode_fattr4(),
+but don't use it for the purpose of detecting file changes.  Remove the
+unnecessary initialization of ncf_cur_fsize in nfs4_open_delegation().
+
+Also, if we recall the delegation (because the client didn't respond to
+the CB_GETATTR), then skip the logic that checks the nfs4_cb_fattr
+fields.
+
+Fixes: c5967721e106 ("NFSD: handle GETATTR conflict with write delegation")
+Cc: stable@vger.kernel.org
+Signed-off-by: Scott Mayhew <smayhew@redhat.com>
+Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/nfsd/nfs4state.c |   13 ++++++++-----
+ 1 file changed, 8 insertions(+), 5 deletions(-)
+
+--- a/fs/nfsd/nfs4state.c
++++ b/fs/nfsd/nfs4state.c
+@@ -6368,7 +6368,6 @@ nfs4_open_delegation(struct svc_rqst *rq
+               }
+               open->op_delegate_type = deleg_ts ? OPEN_DELEGATE_WRITE_ATTRS_DELEG :
+                                                   OPEN_DELEGATE_WRITE;
+-              dp->dl_cb_fattr.ncf_cur_fsize = stat.size;
+               dp->dl_cb_fattr.ncf_initial_cinfo = nfsd4_change_attribute(&stat);
+               dp->dl_atime = stat.atime;
+               dp->dl_ctime = stat.ctime;
+@@ -9417,11 +9416,15 @@ nfsd4_deleg_getattr_conflict(struct svc_
+               if (status != nfserr_jukebox ||
+                   !nfsd_wait_for_delegreturn(rqstp, inode))
+                       goto out_status;
++              status = nfs_ok;
++              goto out_status;
++      }
++      if (!ncf->ncf_file_modified) {
++              if (ncf->ncf_initial_cinfo != ncf->ncf_cb_change)
++                      ncf->ncf_file_modified = true;
++              else if (i_size_read(inode) != ncf->ncf_cb_fsize)
++                      ncf->ncf_file_modified = true;
+       }
+-      if (!ncf->ncf_file_modified &&
+-          (ncf->ncf_initial_cinfo != ncf->ncf_cb_change ||
+-           ncf->ncf_cur_fsize != ncf->ncf_cb_fsize))
+-              ncf->ncf_file_modified = true;
+       if (ncf->ncf_file_modified) {
+               int err;
diff --git a/queue-7.0/nfsd-fix-get_dir_delegation-when-vfs-leases-are-disabled.patch b/queue-7.0/nfsd-fix-get_dir_delegation-when-vfs-leases-are-disabled.patch
new file mode 100644 (file)
index 0000000..b72c51f
--- /dev/null
@@ -0,0 +1,46 @@
+From b0bf14546bcefa4ea49f5efcd7db2a99f0cabde9 Mon Sep 17 00:00:00 2001
+From: Olga Kornievskaia <okorniev@redhat.com>
+Date: Fri, 3 Apr 2026 11:20:55 -0400
+Subject: nfsd: fix GET_DIR_DELEGATION when VFS leases are disabled
+
+From: Olga Kornievskaia <okorniev@redhat.com>
+
+commit b0bf14546bcefa4ea49f5efcd7db2a99f0cabde9 upstream.
+
+When leases are disabled on the server, running xfstest generic/309 leads
+to an error because GET_DIR_DELEGATION returns EINVAL.
+
+nfsd_get_dir_deleg() can fail in several ways: like memory allocation and
+unable to get a lease because either leases are disable or it's already
+held. Currently only the condition "already held" is translated to
+returning directory-delegation-is-unavailable error. However, other failure
+conditions are likely temporary and thus should result in the same kind
+of error.
+
+Fixes: 8b99f6a8c116 ("nfsd: wire up GET_DIR_DELEGATION handling")
+Cc: stable@vger.kernel.org
+Signed-off-by: Olga Kornievskaia <okorniev@redhat.com>
+Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/nfsd/nfs4proc.c | 4 ----
+ 1 file changed, 4 deletions(-)
+
+diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c
+index 85e94c30285a..2797da8cc950 100644
+--- a/fs/nfsd/nfs4proc.c
++++ b/fs/nfsd/nfs4proc.c
+@@ -2535,10 +2535,6 @@ nfsd4_get_dir_delegation(struct svc_rqst *rqstp,
+       dd = nfsd_get_dir_deleg(cstate, gdd, nf);
+       nfsd_file_put(nf);
+       if (IS_ERR(dd)) {
+-              int err = PTR_ERR(dd);
+-
+-              if (err != -EAGAIN)
+-                      return nfserrno(err);
+               gdd->gddrnf_status = GDD4_UNAVAIL;
+               return nfs_ok;
+       }
+-- 
+2.54.0
+
diff --git a/queue-7.0/nfsd-update-mtime-ctime-on-clone-in-presense-of-delegated-attributes.patch b/queue-7.0/nfsd-update-mtime-ctime-on-clone-in-presense-of-delegated-attributes.patch
new file mode 100644 (file)
index 0000000..368b0cd
--- /dev/null
@@ -0,0 +1,112 @@
+From 2863bac7f49c4acd80a048ce52506a2b9c8db015 Mon Sep 17 00:00:00 2001
+From: Olga Kornievskaia <okorniev@redhat.com>
+Date: Fri, 10 Apr 2026 12:09:19 -0400
+Subject: nfsd: update mtime/ctime on CLONE in presense of delegated attributes
+
+From: Olga Kornievskaia <okorniev@redhat.com>
+
+commit 2863bac7f49c4acd80a048ce52506a2b9c8db015 upstream.
+
+When delegated attributes are given on open, the file is opened with
+NOCMTIME and modifying operations do not update mtime/ctime as to not get
+out-of-sync with the client's delegated view. However, for CLONE operation,
+the server should update its view of mtime/ctime and reflect that in any
+GETATTR queries.
+
+Fixes: e5e9b24ab8fa ("nfsd: freeze c/mtime updates with outstanding WRITE_ATTRS delegation")
+Cc: stable@vger.kernel.org
+Signed-off-by: Olga Kornievskaia <okorniev@redhat.com>
+Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/nfsd/nfs4proc.c  |    3 +++
+ fs/nfsd/nfs4state.c |   44 +++++++++++++++++++++++++++++---------------
+ fs/nfsd/state.h     |    1 +
+ 3 files changed, 33 insertions(+), 15 deletions(-)
+
+--- a/fs/nfsd/nfs4proc.c
++++ b/fs/nfsd/nfs4proc.c
+@@ -1413,6 +1413,9 @@ nfsd4_clone(struct svc_rqst *rqstp, stru
+                       dst, clone->cl_dst_pos, clone->cl_count,
+                       EX_ISSYNC(cstate->current_fh.fh_export));
++      if (!status && (READ_ONCE(dst->nf_file->f_mode) & FMODE_NOCMTIME) != 0)
++              nfsd_update_cmtime_attr(dst->nf_file, 0);
++
+       nfsd_file_put(dst);
+       nfsd_file_put(src);
+ out:
+--- a/fs/nfsd/nfs4state.c
++++ b/fs/nfsd/nfs4state.c
+@@ -1226,10 +1226,6 @@ static void put_deleg_file(struct nfs4_f
+ static void nfsd4_finalize_deleg_timestamps(struct nfs4_delegation *dp, struct file *f)
+ {
+-      struct iattr ia = { .ia_valid = ATTR_ATIME | ATTR_CTIME | ATTR_MTIME | ATTR_DELEG };
+-      struct inode *inode = file_inode(f);
+-      int ret;
+-
+       /* don't do anything if FMODE_NOCMTIME isn't set */
+       if ((READ_ONCE(f->f_mode) & FMODE_NOCMTIME) == 0)
+               return;
+@@ -1247,17 +1243,7 @@ static void nfsd4_finalize_deleg_timesta
+               return;
+       /* Stamp everything to "now" */
+-      inode_lock(inode);
+-      ret = notify_change(&nop_mnt_idmap, f->f_path.dentry, &ia, NULL);
+-      inode_unlock(inode);
+-      if (ret) {
+-              struct inode *inode = file_inode(f);
+-
+-              pr_notice_ratelimited("nfsd: Unable to update timestamps on inode %02x:%02x:%lu: %d\n",
+-                                      MAJOR(inode->i_sb->s_dev),
+-                                      MINOR(inode->i_sb->s_dev),
+-                                      inode->i_ino, ret);
+-      }
++      nfsd_update_cmtime_attr(f, ATTR_ATIME);
+ }
+ static void nfs4_unlock_deleg_lease(struct nfs4_delegation *dp)
+@@ -9550,3 +9536,31 @@ out_delegees:
+       put_nfs4_file(fp);
+       return ERR_PTR(status);
+ }
++
++/**
++ * nfsd_update_cmtime_attr - update file's delegated ctime/mtime,
++ *                           and optionally other attributes (ie ATTR_ATIME).
++ * @f: pointer to an opened file
++ * @flags: any additional flags that should be updated
++ *
++ * Given upon opening a file delegated attributes were issues, update
++ * @f attributes to current times.
++ */
++void nfsd_update_cmtime_attr(struct file *f, unsigned int flags)
++{
++      int ret;
++      struct inode *inode = file_inode(f);
++      struct iattr attr = {
++              .ia_valid = ATTR_CTIME | ATTR_MTIME | ATTR_DELEG | flags,
++      };
++
++      inode_lock(inode);
++      ret = notify_change(&nop_mnt_idmap, f->f_path.dentry, &attr, NULL);
++      inode_unlock(inode);
++      if (ret)
++              pr_notice_ratelimited("nfsd: Unable to update timestamps on "
++                                    "inode %02x:%02x:%lu: %d\n",
++                                    MAJOR(inode->i_sb->s_dev),
++                                    MINOR(inode->i_sb->s_dev),
++                                    inode->i_ino, ret);
++}
+--- a/fs/nfsd/state.h
++++ b/fs/nfsd/state.h
+@@ -834,6 +834,7 @@ extern void nfsd4_shutdown_copy(struct n
+ void nfsd4_put_client(struct nfs4_client *clp);
+ void nfsd4_async_copy_reaper(struct nfsd_net *nn);
+ bool nfsd4_has_active_async_copies(struct nfs4_client *clp);
++void nfsd_update_cmtime_attr(struct file *f, unsigned int flags);
+ extern struct nfs4_client_reclaim *nfs4_client_to_reclaim(struct xdr_netobj name,
+                               struct xdr_netobj princhash, struct nfsd_net *nn);
+ extern bool nfs4_has_reclaimed_state(struct xdr_netobj name, struct nfsd_net *nn);
diff --git a/queue-7.0/nfsd-update-mtime-ctime-on-copy-in-presence-of-delegated-attributes.patch b/queue-7.0/nfsd-update-mtime-ctime-on-copy-in-presence-of-delegated-attributes.patch
new file mode 100644 (file)
index 0000000..fd59f9d
--- /dev/null
@@ -0,0 +1,70 @@
+From 4183cf383b6faec17a0882b84cd2d901dba62b16 Mon Sep 17 00:00:00 2001
+From: Olga Kornievskaia <okorniev@redhat.com>
+Date: Fri, 10 Apr 2026 12:09:20 -0400
+Subject: nfsd: update mtime/ctime on COPY in presence of delegated attributes
+
+From: Olga Kornievskaia <okorniev@redhat.com>
+
+commit 4183cf383b6faec17a0882b84cd2d901dba62b16 upstream.
+
+When delegated attributes are given on open, the file is opened with
+NOCMTIME and modifying operations do not update mtime/ctime as to not get
+out-of-sync with the client's delegated view. However, for COPY operation,
+the server should update its view of mtime/ctime and reflect that in any
+GETATTR queries.
+
+Fixes: e5e9b24ab8fa ("nfsd: freeze c/mtime updates with outstanding WRITE_ATTRS delegation")
+Cc: stable@vger.kernel.org
+Signed-off-by: Olga Kornievskaia <okorniev@redhat.com>
+Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/nfsd/nfs4proc.c |   11 ++++++++++-
+ fs/nfsd/xdr4.h     |    1 +
+ 2 files changed, 11 insertions(+), 1 deletion(-)
+
+--- a/fs/nfsd/nfs4proc.c
++++ b/fs/nfsd/nfs4proc.c
+@@ -2121,8 +2121,10 @@ do_callback:
+       set_bit(NFSD4_COPY_F_COMPLETED, &copy->cp_flags);
+       trace_nfsd_copy_async_done(copy);
+-      nfsd4_send_cb_offload(copy);
+       atomic_dec(&copy->cp_nn->pending_async_copies);
++      if (copy->cp_res.wr_bytes_written > 0 && copy->attr_update)
++              nfsd_update_cmtime_attr(copy->nf_dst->nf_file, 0);
++      nfsd4_send_cb_offload(copy);
+       return 0;
+ }
+@@ -2182,6 +2184,9 @@ nfsd4_copy(struct svc_rqst *rqstp, struc
+               memcpy(&result->cb_stateid, &copy->cp_stateid.cs_stid,
+                       sizeof(result->cb_stateid));
+               dup_copy_fields(copy, async_copy);
++              if ((READ_ONCE(copy->nf_dst->nf_file->f_mode) &
++                             FMODE_NOCMTIME) != 0)
++                      async_copy->attr_update = true;
+               memcpy(async_copy->cp_cb_offload.co_referring_sessionid.data,
+                      cstate->session->se_sessionid.data,
+                      NFS4_MAX_SESSIONID_LEN);
+@@ -2200,6 +2205,10 @@ nfsd4_copy(struct svc_rqst *rqstp, struc
+       } else {
+               status = nfsd4_do_copy(copy, copy->nf_src->nf_file,
+                                      copy->nf_dst->nf_file, true);
++              if ((READ_ONCE(copy->nf_dst->nf_file->f_mode) &
++                             FMODE_NOCMTIME) != 0 &&
++                              copy->cp_res.wr_bytes_written > 0)
++                      nfsd_update_cmtime_attr(copy->nf_dst->nf_file, 0);
+       }
+ out:
+       trace_nfsd_copy_done(copy, status);
+--- a/fs/nfsd/xdr4.h
++++ b/fs/nfsd/xdr4.h
+@@ -752,6 +752,7 @@ struct nfsd4_copy {
+       struct nfsd_file        *nf_src;
+       struct nfsd_file        *nf_dst;
++      bool                    attr_update;
+       copy_stateid_t          cp_stateid;
diff --git a/queue-7.0/nvme-apple-reset-q-sq_tail-during-queue-init.patch b/queue-7.0/nvme-apple-reset-q-sq_tail-during-queue-init.patch
new file mode 100644 (file)
index 0000000..50cb39f
--- /dev/null
@@ -0,0 +1,35 @@
+From a6ab75639e23169a741b0b2e12191fd8acb32c73 Mon Sep 17 00:00:00 2001
+From: Nick Chan <towinchenmi@gmail.com>
+Date: Thu, 14 May 2026 21:16:01 +0800
+Subject: nvme-apple: Reset q->sq_tail during queue init
+
+From: Nick Chan <towinchenmi@gmail.com>
+
+commit a6ab75639e23169a741b0b2e12191fd8acb32c73 upstream.
+
+Fixes a "duplicate tag error for tag 0" firmware crash during controller
+reset while setting up a  queue on Apple A11 / T8015 caused by stale
+entries in the submission queue due to an invalid sq_tail offset after
+reset.
+
+Fixes: 04d8ecf37b5e ("nvme: apple: Add Apple A11 support")
+Cc: stable@vger.kernel.org
+Suggested-by: Yuriy Havrylyuk <yhavry@gmail.com>
+Reviewed-by: Sven Peter <sven@kernel.org>
+Signed-off-by: Nick Chan <towinchenmi@gmail.com>
+Signed-off-by: Keith Busch <kbusch@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/nvme/host/apple.c |    1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/drivers/nvme/host/apple.c
++++ b/drivers/nvme/host/apple.c
+@@ -1009,6 +1009,7 @@ static void apple_nvme_init_queue(struct
+       unsigned int depth = apple_nvme_queue_depth(q);
+       struct apple_nvme *anv = queue_to_apple_nvme(q);
++      q->sq_tail = 0;
+       q->cq_head = 0;
+       q->cq_phase = 1;
+       if (anv->hw->has_lsq_nvmmu)
diff --git a/queue-7.0/platform-x86-intel-move-debugfs-register-before-creating-devices.patch b/queue-7.0/platform-x86-intel-move-debugfs-register-before-creating-devices.patch
new file mode 100644 (file)
index 0000000..d69890a
--- /dev/null
@@ -0,0 +1,55 @@
+From ad3bff944c0f4f2e913298a9664391af32f87491 Mon Sep 17 00:00:00 2001
+From: Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>
+Date: Thu, 30 Apr 2026 08:11:01 -0700
+Subject: platform/x86: intel: Move debugfs register before creating devices
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>
+
+commit ad3bff944c0f4f2e913298a9664391af32f87491 upstream.
+
+It is possible that the driver handling device is enumerated before
+registering debugfs. If the driver wants to access debugfs by calling
+tpmi_get_debugfs_dir(), this will return error in this case.
+
+Hence register debugfs before creating devices.
+
+Fixes: 811f67c51636 ("platform/x86/intel/tpmi: Add new auxiliary driver for performance limits")
+Signed-off-by: Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>
+Cc: Stable@vger.kernel.org
+Link: https://patch.msgid.link/20260430151103.1549733-2-srinivas.pandruvada@linux.intel.com
+Reviewed-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
+Signed-off-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/platform/x86/intel/vsec_tpmi.c |   10 ++++++----
+ 1 file changed, 6 insertions(+), 4 deletions(-)
+
+--- a/drivers/platform/x86/intel/vsec_tpmi.c
++++ b/drivers/platform/x86/intel/vsec_tpmi.c
+@@ -813,10 +813,6 @@ static int intel_vsec_tpmi_init(struct a
+       auxiliary_set_drvdata(auxdev, tpmi_info);
+-      ret = tpmi_create_devices(tpmi_info);
+-      if (ret)
+-              return ret;
+-
+       /*
+        * Allow debugfs when security policy allows. Everything this debugfs
+        * interface provides, can also be done via /dev/mem access. If
+@@ -826,6 +822,12 @@ static int intel_vsec_tpmi_init(struct a
+       if (!security_locked_down(LOCKDOWN_DEV_MEM) && capable(CAP_SYS_RAWIO))
+               tpmi_dbgfs_register(tpmi_info);
++      ret = tpmi_create_devices(tpmi_info);
++      if (ret) {
++              debugfs_remove_recursive(tpmi_info->dbgfs_dir);
++              return ret;
++      }
++
+       return 0;
+ }
diff --git a/queue-7.0/platform-x86-lenovo-wmi-helpers-fix-memory-leak-in-lwmi_dev_evaluate_int.patch b/queue-7.0/platform-x86-lenovo-wmi-helpers-fix-memory-leak-in-lwmi_dev_evaluate_int.patch
new file mode 100644 (file)
index 0000000..b4f8be0
--- /dev/null
@@ -0,0 +1,55 @@
+From 0c3887a134f191723b53e2a47e501b534c8723ee Mon Sep 17 00:00:00 2001
+From: Rong Zhang <i@rong.moe>
+Date: Sun, 10 May 2026 04:25:31 +0000
+Subject: platform/x86: lenovo-wmi-helpers: Fix memory leak in lwmi_dev_evaluate_int()
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Rong Zhang <i@rong.moe>
+
+commit 0c3887a134f191723b53e2a47e501b534c8723ee upstream.
+
+lwmi_dev_evaluate_int() leaks output.pointer when retval == NULL (found
+by sashiko.dev [1]).
+
+Fix it by moving `ret_obj = output.pointer' outside of the `if (retval)'
+block so that it is always freed by the __free cleanup callback.
+
+No functional change intended.
+
+Reviewed-by: Mark Pearson <mpearson-lenovo@squebb.ca>
+Fixes: e521d16e76cd ("platform/x86: Add lenovo-wmi-helpers")
+Cc: stable@vger.kernel.org
+Link: https://sashiko.dev/#/patchset/20260331181208.421552-1-derekjohn.clark%40gmail.com [1]
+Signed-off-by: Rong Zhang <i@rong.moe>
+Signed-off-by: Derek J. Clark <derekjohn.clark@gmail.com>
+Link: https://patch.msgid.link/20260510042546.436874-2-derekjohn.clark@gmail.com
+Reviewed-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
+Signed-off-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/platform/x86/lenovo/wmi-helpers.c |    4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+--- a/drivers/platform/x86/lenovo/wmi-helpers.c
++++ b/drivers/platform/x86/lenovo/wmi-helpers.c
+@@ -46,7 +46,6 @@ int lwmi_dev_evaluate_int(struct wmi_dev
+                         unsigned char *buf, size_t size, u32 *retval)
+ {
+       struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL };
+-      union acpi_object *ret_obj __free(kfree) = NULL;
+       struct acpi_buffer input = { size, buf };
+       acpi_status status;
+@@ -55,8 +54,9 @@ int lwmi_dev_evaluate_int(struct wmi_dev
+       if (ACPI_FAILURE(status))
+               return -EIO;
++      union acpi_object *ret_obj __free(kfree) = output.pointer;
++
+       if (retval) {
+-              ret_obj = output.pointer;
+               if (!ret_obj)
+                       return -ENODATA;
diff --git a/queue-7.0/platform-x86-lenovo-wmi-helpers-move-gamezone-enums-to-wmi-helpers.patch b/queue-7.0/platform-x86-lenovo-wmi-helpers-move-gamezone-enums-to-wmi-helpers.patch
new file mode 100644 (file)
index 0000000..0947bbe
--- /dev/null
@@ -0,0 +1,119 @@
+From 7e27896e16a1c450085c3fe020eeb1b223880f37 Mon Sep 17 00:00:00 2001
+From: "Derek J. Clark" <derekjohn.clark@gmail.com>
+Date: Sun, 10 May 2026 04:25:37 +0000
+Subject: platform/x86: lenovo-wmi-helpers: Move gamezone enums to wmi-helpers
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Derek J. Clark <derekjohn.clark@gmail.com>
+
+commit 7e27896e16a1c450085c3fe020eeb1b223880f37 upstream.
+
+In a later patch in the series the thermal mode enum will be accessed
+across three separate drivers (wmi-capdata, wmi-gamezonem and wmi-other).
+An additional patch in the series will also add a function prototype that
+needs to reference this enum in wmi-helpers.h. To avoid having all these
+drivers begin to import each others headers, and to avoid declaring an
+opaque enum to hande the second case, move the thermal mode enum to
+helpers where it can be safely accessed by everything that needs it from
+a single import.
+
+While at it, since the gamezone_events_type enum is the only remaining
+item in the header, move that as well and remove the gamezone header
+entirely.
+
+Cc: stable@vger.kernel.org
+Reviewed-by: Mark Pearson <mpearson-lenovo@squebb.ca>
+Reviewed-by: Rong Zhang <i@rong.moe>
+Tested-by: Rong Zhang <i@rong.moe>
+Signed-off-by: Derek J. Clark <derekjohn.clark@gmail.com>
+Link: https://patch.msgid.link/20260510042546.436874-8-derekjohn.clark@gmail.com
+Reviewed-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
+Signed-off-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/platform/x86/lenovo/wmi-events.c   |    2 +-
+ drivers/platform/x86/lenovo/wmi-gamezone.c |    1 -
+ drivers/platform/x86/lenovo/wmi-gamezone.h |   20 --------------------
+ drivers/platform/x86/lenovo/wmi-helpers.h  |   13 +++++++++++++
+ drivers/platform/x86/lenovo/wmi-other.c    |    1 -
+ 5 files changed, 14 insertions(+), 23 deletions(-)
+ delete mode 100644 drivers/platform/x86/lenovo/wmi-gamezone.h
+
+--- a/drivers/platform/x86/lenovo/wmi-events.c
++++ b/drivers/platform/x86/lenovo/wmi-events.c
+@@ -17,7 +17,7 @@
+ #include <linux/wmi.h>
+ #include "wmi-events.h"
+-#include "wmi-gamezone.h"
++#include "wmi-helpers.h"
+ #define THERMAL_MODE_EVENT_GUID "D320289E-8FEA-41E0-86F9-911D83151B5F"
+--- a/drivers/platform/x86/lenovo/wmi-gamezone.c
++++ b/drivers/platform/x86/lenovo/wmi-gamezone.c
+@@ -21,7 +21,6 @@
+ #include <linux/wmi.h>
+ #include "wmi-events.h"
+-#include "wmi-gamezone.h"
+ #include "wmi-helpers.h"
+ #include "wmi-other.h"
+--- a/drivers/platform/x86/lenovo/wmi-gamezone.h
++++ /dev/null
+@@ -1,20 +0,0 @@
+-/* SPDX-License-Identifier: GPL-2.0-or-later */
+-
+-/* Copyright (C) 2025 Derek J. Clark <derekjohn.clark@gmail.com> */
+-
+-#ifndef _LENOVO_WMI_GAMEZONE_H_
+-#define _LENOVO_WMI_GAMEZONE_H_
+-
+-enum gamezone_events_type {
+-      LWMI_GZ_GET_THERMAL_MODE = 1,
+-};
+-
+-enum thermal_mode {
+-      LWMI_GZ_THERMAL_MODE_QUIET =       0x01,
+-      LWMI_GZ_THERMAL_MODE_BALANCED =    0x02,
+-      LWMI_GZ_THERMAL_MODE_PERFORMANCE = 0x03,
+-      LWMI_GZ_THERMAL_MODE_EXTREME =     0xE0, /* Ver 6+ */
+-      LWMI_GZ_THERMAL_MODE_CUSTOM =      0xFF,
+-};
+-
+-#endif /* !_LENOVO_WMI_GAMEZONE_H_ */
+--- a/drivers/platform/x86/lenovo/wmi-helpers.h
++++ b/drivers/platform/x86/lenovo/wmi-helpers.h
+@@ -14,6 +14,19 @@ struct wmi_method_args_32 {
+       u32 arg1;
+ };
++enum lwmi_event_type {
++      LWMI_GZ_GET_THERMAL_MODE = 0x01,
++};
++
++enum thermal_mode {
++      LWMI_GZ_THERMAL_MODE_NONE =        0x00,
++      LWMI_GZ_THERMAL_MODE_QUIET =       0x01,
++      LWMI_GZ_THERMAL_MODE_BALANCED =    0x02,
++      LWMI_GZ_THERMAL_MODE_PERFORMANCE = 0x03,
++      LWMI_GZ_THERMAL_MODE_EXTREME =     0xE0, /* Ver 6+ */
++      LWMI_GZ_THERMAL_MODE_CUSTOM =      0xFF,
++};
++
+ int lwmi_dev_evaluate_int(struct wmi_device *wdev, u8 instance, u32 method_id,
+                         unsigned char *buf, size_t size, u32 *retval);
+--- a/drivers/platform/x86/lenovo/wmi-other.c
++++ b/drivers/platform/x86/lenovo/wmi-other.c
+@@ -47,7 +47,6 @@
+ #include "wmi-capdata.h"
+ #include "wmi-events.h"
+-#include "wmi-gamezone.h"
+ #include "wmi-helpers.h"
+ #include "wmi-other.h"
+ #include "../firmware_attributes_class.h"
diff --git a/queue-7.0/platform-x86-lenovo-wmi-other-add-attribute-id-helper-functions.patch b/queue-7.0/platform-x86-lenovo-wmi-other-add-attribute-id-helper-functions.patch
new file mode 100644 (file)
index 0000000..993fbaf
--- /dev/null
@@ -0,0 +1,226 @@
+From 30a4ad208a7f7bdb790cd31d368595890045334f Mon Sep 17 00:00:00 2001
+From: "Derek J. Clark" <derekjohn.clark@gmail.com>
+Date: Sun, 10 May 2026 04:25:38 +0000
+Subject: platform/x86: lenovo-wmi-other: Add Attribute ID helper functions
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Derek J. Clark <derekjohn.clark@gmail.com>
+
+commit 30a4ad208a7f7bdb790cd31d368595890045334f upstream.
+
+Adds lwmi_attr_id() function. In the same vein as LWMI_ATTR_ID_FAN_RPM(),
+but as a generic, to de-duplicate attribute_id assignment boilerplate.
+
+Adds tunable_attr_01_id() function that breaks out the members of a
+tunable_attr_01 struct and passes them to lwmi_attr_id().
+
+No functional change intended.
+
+Cc: stable@vger.kernel.org
+Reviewed-by: Rong Zhang <i@rong.moe>
+Tested-by: Rong Zhang <i@rong.moe>
+Reviewed-by: Mark Pearson <mpearson-lenovo@squebb.ca>
+Signed-off-by: Derek J. Clark <derekjohn.clark@gmail.com>
+Link: https://patch.msgid.link/20260510042546.436874-9-derekjohn.clark@gmail.com
+Reviewed-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
+Signed-off-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/platform/x86/lenovo/wmi-capdata.c |    8 ++--
+ drivers/platform/x86/lenovo/wmi-capdata.h |   20 ++++++++++++
+ drivers/platform/x86/lenovo/wmi-other.c   |   49 ++++++++++++------------------
+ 3 files changed, 44 insertions(+), 33 deletions(-)
+
+--- a/drivers/platform/x86/lenovo/wmi-capdata.c
++++ b/drivers/platform/x86/lenovo/wmi-capdata.c
+@@ -27,7 +27,6 @@
+ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+ #include <linux/acpi.h>
+-#include <linux/bitfield.h>
+ #include <linux/bug.h>
+ #include <linux/cleanup.h>
+ #include <linux/component.h>
+@@ -48,6 +47,7 @@
+ #include <linux/wmi.h>
+ #include "wmi-capdata.h"
++#include "wmi-helpers.h"
+ #define LENOVO_CAPABILITY_DATA_00_GUID "362A3AFE-3D96-4665-8530-96DAD5BB300E"
+ #define LENOVO_CAPABILITY_DATA_01_GUID "7A8F5407-CB67-4D6E-B547-39B3BE018154"
+@@ -58,9 +58,9 @@
+ #define LWMI_FEATURE_ID_FAN_TEST 0x05
+-#define LWMI_ATTR_ID_FAN_TEST                                                 \
+-      (FIELD_PREP(LWMI_ATTR_DEV_ID_MASK, LWMI_DEVICE_ID_FAN) |                \
+-       FIELD_PREP(LWMI_ATTR_FEAT_ID_MASK, LWMI_FEATURE_ID_FAN_TEST))
++#define LWMI_ATTR_ID_FAN_TEST                                      \
++      lwmi_attr_id(LWMI_DEVICE_ID_FAN, LWMI_FEATURE_ID_FAN_TEST, \
++                   LWMI_GZ_THERMAL_MODE_NONE, LWMI_TYPE_ID_NONE)
+ enum lwmi_cd_type {
+       LENOVO_CAPABILITY_DATA_00,
+--- a/drivers/platform/x86/lenovo/wmi-capdata.h
++++ b/drivers/platform/x86/lenovo/wmi-capdata.h
+@@ -6,6 +6,7 @@
+ #define _LENOVO_WMI_CAPDATA_H_
+ #include <linux/bits.h>
++#include <linux/bitfield.h>
+ #include <linux/types.h>
+ #define LWMI_SUPP_VALID               BIT(0)
+@@ -19,6 +20,8 @@
+ #define LWMI_DEVICE_ID_FAN    0x04
++#define LWMI_TYPE_ID_NONE 0x00
++
+ struct component_match;
+ struct device;
+ struct cd_list;
+@@ -57,6 +60,23 @@ struct lwmi_cd_binder {
+       cd_list_cb_t cd_fan_list_cb;
+ };
++/**
++ * lwmi_attr_id() - Formats a capability data attribute ID
++ * @dev_id: The u8 corresponding to the device ID.
++ * @feat_id: The u8 corresponding to the feature ID on the device.
++ * @mode_id: The u8 corresponding to the wmi-gamezone mode for set/get.
++ * @type_id: The u8 corresponding to the sub-device.
++ *
++ * Return: encoded capability data attribute ID.
++ */
++static inline u32 lwmi_attr_id(u8 dev_id, u8 feat_id, u8 mode_id, u8 type_id)
++{
++      return (FIELD_PREP(LWMI_ATTR_DEV_ID_MASK, dev_id)   |
++              FIELD_PREP(LWMI_ATTR_FEAT_ID_MASK, feat_id) |
++              FIELD_PREP(LWMI_ATTR_MODE_ID_MASK, mode_id) |
++              FIELD_PREP(LWMI_ATTR_TYPE_ID_MASK, type_id));
++}
++
+ void lwmi_cd_match_add_all(struct device *master, struct component_match **matchptr);
+ int lwmi_cd00_get_data(struct cd_list *list, u32 attribute_id, struct capdata00 *output);
+ int lwmi_cd01_get_data(struct cd_list *list, u32 attribute_id, struct capdata01 *output);
+--- a/drivers/platform/x86/lenovo/wmi-other.c
++++ b/drivers/platform/x86/lenovo/wmi-other.c
+@@ -61,8 +61,6 @@
+ #define LWMI_FEATURE_ID_FAN_RPM 0x03
+-#define LWMI_TYPE_ID_NONE 0x00
+-
+ #define LWMI_FEATURE_VALUE_GET 17
+ #define LWMI_FEATURE_VALUE_SET 18
+@@ -70,13 +68,12 @@
+ #define LWMI_FAN_NR 4
+ #define LWMI_FAN_ID(x) ((x) + LWMI_FAN_ID_BASE)
+-#define LWMI_ATTR_ID_FAN_RPM(x)                                               \
+-      (FIELD_PREP(LWMI_ATTR_DEV_ID_MASK, LWMI_DEVICE_ID_FAN) |        \
+-       FIELD_PREP(LWMI_ATTR_FEAT_ID_MASK, LWMI_FEATURE_ID_FAN_RPM) |  \
+-       FIELD_PREP(LWMI_ATTR_TYPE_ID_MASK, LWMI_FAN_ID(x)))
+-
+ #define LWMI_FAN_DIV 100
++#define LWMI_ATTR_ID_FAN_RPM(x)                                   \
++      lwmi_attr_id(LWMI_DEVICE_ID_FAN, LWMI_FEATURE_ID_FAN_RPM, \
++                   LWMI_GZ_THERMAL_MODE_NONE, LWMI_FAN_ID(x))
++
+ #define LWMI_OM_FW_ATTR_BASE_PATH "lenovo-wmi-other"
+ #define LWMI_OM_HWMON_NAME "lenovo_wmi_other"
+@@ -551,6 +548,18 @@ struct tunable_attr_01 {
+       u8 type_id;
+ };
++/**
++ * tunable_attr_01_id() - Formats a tunable_attr_01 to a capdata attribute ID
++ * @attr: The tunable_attr_01 to format.
++ * @mode: The u8 corresponding to the wmi-gamezone mode for set/get.
++ *
++ * Return: encoded capability data attribute ID.
++ */
++static u32 tunable_attr_01_id(struct tunable_attr_01 *attr, u8 mode)
++{
++      return lwmi_attr_id(attr->device_id, attr->feature_id, mode, attr->type_id);
++}
++
+ static struct tunable_attr_01 ppt_pl1_spl = {
+       .device_id = LWMI_DEVICE_ID_CPU,
+       .feature_id = LWMI_FEATURE_ID_CPU_SPL,
+@@ -714,12 +723,7 @@ static ssize_t attr_capdata01_show(struc
+       u32 attribute_id;
+       int value, ret;
+-      attribute_id =
+-              FIELD_PREP(LWMI_ATTR_DEV_ID_MASK, tunable_attr->device_id) |
+-              FIELD_PREP(LWMI_ATTR_FEAT_ID_MASK, tunable_attr->feature_id) |
+-              FIELD_PREP(LWMI_ATTR_MODE_ID_MASK,
+-                         LWMI_GZ_THERMAL_MODE_CUSTOM) |
+-              FIELD_PREP(LWMI_ATTR_TYPE_ID_MASK, tunable_attr->type_id);
++      attribute_id = tunable_attr_01_id(tunable_attr, LWMI_GZ_THERMAL_MODE_CUSTOM);
+       ret = lwmi_cd01_get_data(priv->cd01_list, attribute_id, &capdata);
+       if (ret)
+@@ -774,7 +778,6 @@ static ssize_t attr_current_value_store(
+       struct wmi_method_args_32 args = {};
+       struct capdata01 capdata;
+       enum thermal_mode mode;
+-      u32 attribute_id;
+       u32 value;
+       int ret;
+@@ -785,13 +788,9 @@ static ssize_t attr_current_value_store(
+       if (mode != LWMI_GZ_THERMAL_MODE_CUSTOM)
+               return -EBUSY;
+-      attribute_id =
+-              FIELD_PREP(LWMI_ATTR_DEV_ID_MASK, tunable_attr->device_id) |
+-              FIELD_PREP(LWMI_ATTR_FEAT_ID_MASK, tunable_attr->feature_id) |
+-              FIELD_PREP(LWMI_ATTR_MODE_ID_MASK, mode) |
+-              FIELD_PREP(LWMI_ATTR_TYPE_ID_MASK, tunable_attr->type_id);
++      args.arg0 = tunable_attr_01_id(tunable_attr, mode);
+-      ret = lwmi_cd01_get_data(priv->cd01_list, attribute_id, &capdata);
++      ret = lwmi_cd01_get_data(priv->cd01_list, args.arg0, &capdata);
+       if (ret)
+               return ret;
+@@ -802,7 +801,6 @@ static ssize_t attr_current_value_store(
+       if (value < capdata.min_value || value > capdata.max_value)
+               return -EINVAL;
+-      args.arg0 = attribute_id;
+       args.arg1 = value;
+       ret = lwmi_dev_evaluate_int(priv->wdev, 0x0, LWMI_FEATURE_VALUE_SET,
+@@ -836,7 +834,6 @@ static ssize_t attr_current_value_show(s
+       struct lwmi_om_priv *priv = dev_get_drvdata(tunable_attr->dev);
+       struct wmi_method_args_32 args = {};
+       enum thermal_mode mode;
+-      u32 attribute_id;
+       int retval;
+       int ret;
+@@ -844,13 +841,7 @@ static ssize_t attr_current_value_show(s
+       if (ret)
+               return ret;
+-      attribute_id =
+-              FIELD_PREP(LWMI_ATTR_DEV_ID_MASK, tunable_attr->device_id) |
+-              FIELD_PREP(LWMI_ATTR_FEAT_ID_MASK, tunable_attr->feature_id) |
+-              FIELD_PREP(LWMI_ATTR_MODE_ID_MASK, mode) |
+-              FIELD_PREP(LWMI_ATTR_TYPE_ID_MASK, tunable_attr->type_id);
+-
+-      args.arg0 = attribute_id;
++      args.arg0 = tunable_attr_01_id(tunable_attr, mode);
+       ret = lwmi_dev_evaluate_int(priv->wdev, 0x0, LWMI_FEATURE_VALUE_GET,
+                                   (unsigned char *)&args, sizeof(args),
diff --git a/queue-7.0/platform-x86-lenovo-wmi-other-balance-component-bind-and-unbind.patch b/queue-7.0/platform-x86-lenovo-wmi-other-balance-component-bind-and-unbind.patch
new file mode 100644 (file)
index 0000000..29b6008
--- /dev/null
@@ -0,0 +1,50 @@
+From 2fe2504abcfa4f82a4208e8d0c21ec0f22baca43 Mon Sep 17 00:00:00 2001
+From: Rong Zhang <i@rong.moe>
+Date: Sun, 10 May 2026 04:25:33 +0000
+Subject: platform/x86: lenovo-wmi-other: Balance component bind and unbind
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Rong Zhang <i@rong.moe>
+
+commit 2fe2504abcfa4f82a4208e8d0c21ec0f22baca43 upstream.
+
+When lwmi_om_master_bind() fails, the master device's components are
+left bound, with the aggregate device destroyed due to the failure
+(found by sashiko.dev [1]).
+
+Balance calls to component_bind_all() and component_unbind_all() when an
+error is propagated to the component framework.
+
+No functional change intended.
+
+Reviewed-by: Mark Pearson <mpearson-lenovo@squebb.ca>
+Reviewed-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
+Fixes: edc4b183b794 ("platform/x86: Add Lenovo Other Mode WMI Driver")
+Cc: stable@vger.kernel.org
+Link: https://sashiko.dev/#/patchset/20260331181208.421552-1-derekjohn.clark%40gmail.com [1]
+Signed-off-by: Rong Zhang <i@rong.moe>
+Signed-off-by: Derek J. Clark <derekjohn.clark@gmail.com>
+Link: https://patch.msgid.link/20260510042546.436874-4-derekjohn.clark@gmail.com
+Signed-off-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/platform/x86/lenovo/wmi-other.c |    5 ++++-
+ 1 file changed, 4 insertions(+), 1 deletion(-)
+
+--- a/drivers/platform/x86/lenovo/wmi-other.c
++++ b/drivers/platform/x86/lenovo/wmi-other.c
+@@ -1067,8 +1067,11 @@ static int lwmi_om_master_bind(struct de
+       priv->cd00_list = binder.cd00_list;
+       priv->cd01_list = binder.cd01_list;
+-      if (!priv->cd00_list || !priv->cd01_list)
++      if (!priv->cd00_list || !priv->cd01_list) {
++              component_unbind_all(dev, NULL);
++
+               return -ENODEV;
++      }
+       lwmi_om_fan_info_collect_cd00(priv);
diff --git a/queue-7.0/platform-x86-lenovo-wmi-other-balance-ida-id-allocation-and-free.patch b/queue-7.0/platform-x86-lenovo-wmi-other-balance-ida-id-allocation-and-free.patch
new file mode 100644 (file)
index 0000000..8ba6245
--- /dev/null
@@ -0,0 +1,138 @@
+From 55a279ae819adaea99a94c609f31970b70e0ec0c Mon Sep 17 00:00:00 2001
+From: Rong Zhang <i@rong.moe>
+Date: Sun, 10 May 2026 04:25:32 +0000
+Subject: platform/x86: lenovo-wmi-other: Balance IDA id allocation and free
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Rong Zhang <i@rong.moe>
+
+commit 55a279ae819adaea99a94c609f31970b70e0ec0c upstream.
+
+Currently, the IDA id is only freed on wmi-other device removal or
+failure to create firmware-attributes device, kset, or attributes. It
+leaks IDA ids if the wmi-other device is bound multiple times, as the
+unbind callback never frees the previously allocated IDA id.
+Additionally, if the wmi-other device has failed to create a
+firmware-attributes device before it gets removed, the wmi-device
+removal callback double frees the same IDA id.
+
+These bugs were found by sashiko.dev [1].
+
+Fix them by moving ida_free() into lwmi_om_fw_attr_remove() so it is
+balanced with ida_alloc() in lwmi_om_fw_attr_add(). With them fixed,
+properly set and utilize the validity of priv->ida_id to balance
+firmware-attributes registration and removal, without relying on
+propagating the registration error to the component framework, which is
+more reliable and aligns with the hwmon device registration and removal
+sequences.
+
+No functional change intended.
+
+Reviewed-by: Mark Pearson <mpearson-lenovo@squebb.ca>
+Fixes: edc4b183b794 ("platform/x86: Add Lenovo Other Mode WMI Driver")
+Cc: stable@vger.kernel.org
+Link: https://sashiko.dev/#/patchset/20260331181208.421552-1-derekjohn.clark%40gmail.com [1]
+Signed-off-by: Rong Zhang <i@rong.moe>
+Signed-off-by: Derek J. Clark <derekjohn.clark@gmail.com>
+Link: https://patch.msgid.link/20260510042546.436874-3-derekjohn.clark@gmail.com
+Reviewed-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
+Signed-off-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/platform/x86/lenovo/wmi-other.c |   36 ++++++++++++++++++--------------
+ 1 file changed, 21 insertions(+), 15 deletions(-)
+
+--- a/drivers/platform/x86/lenovo/wmi-other.c
++++ b/drivers/platform/x86/lenovo/wmi-other.c
+@@ -956,17 +956,17 @@ static struct capdata01_attr_group cd01_
+ /**
+  * lwmi_om_fw_attr_add() - Register all firmware_attributes_class members
+  * @priv: The Other Mode driver data.
+- *
+- * Return: Either 0, or an error code.
+  */
+-static int lwmi_om_fw_attr_add(struct lwmi_om_priv *priv)
++static void lwmi_om_fw_attr_add(struct lwmi_om_priv *priv)
+ {
+       unsigned int i;
+       int err;
+-      priv->ida_id = ida_alloc(&lwmi_om_ida, GFP_KERNEL);
+-      if (priv->ida_id < 0)
+-              return priv->ida_id;
++      err = ida_alloc(&lwmi_om_ida, GFP_KERNEL);
++      if (err < 0)
++              goto err_no_ida;
++
++      priv->ida_id = err;
+       priv->fw_attr_dev = device_create(&firmware_attributes_class, NULL,
+                                         MKDEV(0, 0), NULL, "%s-%u",
+@@ -992,7 +992,7 @@ static int lwmi_om_fw_attr_add(struct lw
+               cd01_attr_groups[i].tunable_attr->dev = &priv->wdev->dev;
+       }
+-      return 0;
++      return;
+ err_remove_groups:
+       while (i--)
+@@ -1006,7 +1006,12 @@ err_destroy_classdev:
+ err_free_ida:
+       ida_free(&lwmi_om_ida, priv->ida_id);
+-      return err;
++
++err_no_ida:
++      priv->ida_id = -EIDRM;
++
++      dev_warn(&priv->wdev->dev,
++               "failed to register firmware-attributes device: %d\n", err);
+ }
+ /**
+@@ -1015,12 +1020,17 @@ err_free_ida:
+  */
+ static void lwmi_om_fw_attr_remove(struct lwmi_om_priv *priv)
+ {
++      if (priv->ida_id < 0)
++              return;
++
+       for (unsigned int i = 0; i < ARRAY_SIZE(cd01_attr_groups) - 1; i++)
+               sysfs_remove_group(&priv->fw_attr_kset->kobj,
+                                  cd01_attr_groups[i].attr_group);
+       kset_unregister(priv->fw_attr_kset);
+       device_unregister(priv->fw_attr_dev);
++      ida_free(&lwmi_om_ida, priv->ida_id);
++      priv->ida_id = -EIDRM;
+ }
+ /* ======== Self (master: lenovo-wmi-other) ======== */
+@@ -1062,7 +1072,9 @@ static int lwmi_om_master_bind(struct de
+       lwmi_om_fan_info_collect_cd00(priv);
+-      return lwmi_om_fw_attr_add(priv);
++      lwmi_om_fw_attr_add(priv);
++
++      return 0;
+ }
+ /**
+@@ -1114,13 +1126,7 @@ static int lwmi_other_probe(struct wmi_d
+ static void lwmi_other_remove(struct wmi_device *wdev)
+ {
+-      struct lwmi_om_priv *priv = dev_get_drvdata(&wdev->dev);
+-
+       component_master_del(&wdev->dev, &lwmi_om_master_ops);
+-
+-      /* No IDA to free if the driver is never bound to its components. */
+-      if (priv->ida_id >= 0)
+-              ida_free(&lwmi_om_ida, priv->ida_id);
+ }
+ static const struct wmi_device_id lwmi_other_id_table[] = {
diff --git a/queue-7.0/platform-x86-lenovo-wmi-other-fix-tunable_attr_01-struct-members.patch b/queue-7.0/platform-x86-lenovo-wmi-other-fix-tunable_attr_01-struct-members.patch
new file mode 100644 (file)
index 0000000..42f9567
--- /dev/null
@@ -0,0 +1,48 @@
+From 71f3843e0f81e3c097a088c1121154bb9a44da0a Mon Sep 17 00:00:00 2001
+From: "Derek J. Clark" <derekjohn.clark@gmail.com>
+Date: Sun, 10 May 2026 04:25:35 +0000
+Subject: platform/x86: lenovo-wmi-other: Fix tunable_attr_01 struct members
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Derek J. Clark <derekjohn.clark@gmail.com>
+
+commit 71f3843e0f81e3c097a088c1121154bb9a44da0a upstream.
+
+In struct tunable_attr_01 the capdata pointer is unused and the size of
+the id members is u32 when it should be u8. Fix these prior to adding
+additional members.
+
+No functional change intended.
+
+Reviewed-by: Mark Pearson <mpearson-lenovo@squebb.ca>
+Cc: stable@vger.kernel.org
+Reviewed-by: Rong Zhang <i@rong.moe>
+Tested-by: Rong Zhang <i@rong.moe>
+Signed-off-by: Derek J. Clark <derekjohn.clark@gmail.com>
+Link: https://patch.msgid.link/20260510042546.436874-6-derekjohn.clark@gmail.com
+Reviewed-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
+Signed-off-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/platform/x86/lenovo/wmi-other.c |    7 +++----
+ 1 file changed, 3 insertions(+), 4 deletions(-)
+
+--- a/drivers/platform/x86/lenovo/wmi-other.c
++++ b/drivers/platform/x86/lenovo/wmi-other.c
+@@ -545,11 +545,10 @@ out:
+ /* ======== fw_attributes (component: lenovo-wmi-capdata 01) ======== */
+ struct tunable_attr_01 {
+-      struct capdata01 *capdata;
+       struct device *dev;
+-      u32 feature_id;
+-      u32 device_id;
+-      u32 type_id;
++      u8 feature_id;
++      u8 device_id;
++      u8 type_id;
+ };
+ static struct tunable_attr_01 ppt_pl1_spl = {
diff --git a/queue-7.0/platform-x86-lenovo-wmi-other-limit-adding-attributes-to-supported-devices.patch b/queue-7.0/platform-x86-lenovo-wmi-other-limit-adding-attributes-to-supported-devices.patch
new file mode 100644 (file)
index 0000000..4973999
--- /dev/null
@@ -0,0 +1,196 @@
+From 03bb5147da083cb91e5c8c2599fcb2f8fd05cb8f Mon Sep 17 00:00:00 2001
+From: "Derek J. Clark" <derekjohn.clark@gmail.com>
+Date: Sun, 10 May 2026 04:25:39 +0000
+Subject: platform/x86: lenovo-wmi-other: Limit adding attributes to supported devices
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Derek J. Clark <derekjohn.clark@gmail.com>
+
+commit 03bb5147da083cb91e5c8c2599fcb2f8fd05cb8f upstream.
+
+Adds lwmi_is_attr_01_supported, and only creates the attribute subfolder
+if the attribute is supported by the hardware. Due to some poorly
+implemented BIOS this is a multi-step sequence of events. This is
+because:
+- Some BIOS support getting the capability data from custom mode (0xff),
+  while others only support it in no-mode (0x00).
+- Some BIOS support get/set for the current value from custom mode (0xff),
+  while others only support it in no-mode (0x00).
+- Some BIOS report capability data for a method that is not fully
+  implemented.
+- Some BIOS have methods fully implemented, but no complimentary
+  capability data.
+
+To ensure we only expose fully implemented methods with corresponding
+capability data, we check each outcome before reporting that an
+attribute can be supported.
+
+Checking for lwmi_is_attr_01_supported during remove is not done to
+ensure that we don't attempt to call cd01 or send WMI events if one of
+the interfaces being removed was the cause of the driver unloading.
+
+Fixes: edc4b183b794 ("platform/x86: Add Lenovo Other Mode WMI Driver")
+Reported-by: Kurt Borja <kuurtb@gmail.com>
+Closes: https://lore.kernel.org/platform-driver-x86/DG60P3SHXR8H.3NSEHMZ6J7XRC@gmail.com/
+Cc: stable@vger.kernel.org
+Reviewed-by: Rong Zhang <i@rong.moe>
+Tested-by: Rong Zhang <i@rong.moe>
+Reviewed-by: Mark Pearson <mpearson-lenovo@squebb.ca>
+Signed-off-by: Derek J. Clark <derekjohn.clark@gmail.com>
+Link: https://patch.msgid.link/20260510042546.436874-10-derekjohn.clark@gmail.com
+Reviewed-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
+Signed-off-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/platform/x86/lenovo/wmi-other.c |   92 ++++++++++++++++++++++++++++++--
+ 1 file changed, 88 insertions(+), 4 deletions(-)
+
+--- a/drivers/platform/x86/lenovo/wmi-other.c
++++ b/drivers/platform/x86/lenovo/wmi-other.c
+@@ -546,6 +546,8 @@ struct tunable_attr_01 {
+       u8 feature_id;
+       u8 device_id;
+       u8 type_id;
++      u8 cd_mode_id; /* mode arg for searching capdata */
++      u8 cv_mode_id; /* mode arg for set/get current_value */
+ };
+ /**
+@@ -723,7 +725,7 @@ static ssize_t attr_capdata01_show(struc
+       u32 attribute_id;
+       int value, ret;
+-      attribute_id = tunable_attr_01_id(tunable_attr, LWMI_GZ_THERMAL_MODE_CUSTOM);
++      attribute_id = tunable_attr_01_id(tunable_attr, tunable_attr->cd_mode_id);
+       ret = lwmi_cd01_get_data(priv->cd01_list, attribute_id, &capdata);
+       if (ret)
+@@ -788,7 +790,7 @@ static ssize_t attr_current_value_store(
+       if (mode != LWMI_GZ_THERMAL_MODE_CUSTOM)
+               return -EBUSY;
+-      args.arg0 = tunable_attr_01_id(tunable_attr, mode);
++      args.arg0 = tunable_attr_01_id(tunable_attr, tunable_attr->cd_mode_id);
+       ret = lwmi_cd01_get_data(priv->cd01_list, args.arg0, &capdata);
+       if (ret)
+@@ -801,6 +803,7 @@ static ssize_t attr_current_value_store(
+       if (value < capdata.min_value || value > capdata.max_value)
+               return -EINVAL;
++      args.arg0 = tunable_attr_01_id(tunable_attr, tunable_attr->cv_mode_id);
+       args.arg1 = value;
+       ret = lwmi_dev_evaluate_int(priv->wdev, 0x0, LWMI_FEATURE_VALUE_SET,
+@@ -841,6 +844,10 @@ static ssize_t attr_current_value_show(s
+       if (ret)
+               return ret;
++      /* If "no-mode" is the supported mode, ensure we never send current mode */
++      if (tunable_attr->cv_mode_id == LWMI_GZ_THERMAL_MODE_NONE)
++              mode = tunable_attr->cv_mode_id;
++
+       args.arg0 = tunable_attr_01_id(tunable_attr, mode);
+       ret = lwmi_dev_evaluate_int(priv->wdev, 0x0, LWMI_FEATURE_VALUE_GET,
+@@ -852,6 +859,81 @@ static ssize_t attr_current_value_show(s
+       return sysfs_emit(buf, "%d\n", retval);
+ }
++/**
++ * lwmi_attr_01_is_supported() - Determine if the given attribute is supported.
++ * @tunable_attr: The attribute to verify.
++ *
++ * For an attribute to be supported it must have a functional get/set method,
++ * as well as associated capability data stored in the capdata01 table.
++ *
++ * First check if the attribute has a corresponding data table under custom mode
++ * (0xff), then under no mode (0x00). If either of those passes, check if the
++ * supported field of the capdata struct is > 0. If it is supported, store the
++ * successful mode in the cd_mode_id field of tunable_attr.
++ *
++ * If the attribute capdata shows it is supported, attempt to determine the mode
++ * for the current value property get/set methods using a similar pattern to the
++ * capdata table check. If the value returned by either mode is 0 or an error,
++ * assume that mode is not supported. Otherwise, store the successful mode in the
++ * cv_mode_id field of tunable_attr.
++ *
++ * If any of the above checks fail then the attribute is not fully supported.
++ *
++ * Return: true if capdata and set/get modes are found, otherwise false.
++ */
++static bool lwmi_attr_01_is_supported(struct tunable_attr_01 *tunable_attr)
++{
++      u8 modes[2] = { LWMI_GZ_THERMAL_MODE_CUSTOM, LWMI_GZ_THERMAL_MODE_NONE };
++      struct lwmi_om_priv *priv = dev_get_drvdata(tunable_attr->dev);
++      struct wmi_method_args_32 args = {};
++      bool cd_mode_found = false;
++      bool cv_mode_found = false;
++      struct capdata01 capdata;
++      int retval, ret, i;
++
++      /* Determine tunable_attr->cd_mode_id */
++      for (i = 0; i < ARRAY_SIZE(modes); i++) {
++              args.arg0 = tunable_attr_01_id(tunable_attr, modes[i]);
++
++              ret = lwmi_cd01_get_data(priv->cd01_list, args.arg0, &capdata);
++              if (ret || !capdata.supported)
++                      continue;
++
++              tunable_attr->cd_mode_id = modes[i];
++              cd_mode_found = true;
++              break;
++      }
++
++      if (!cd_mode_found)
++              return cd_mode_found;
++
++      dev_dbg(tunable_attr->dev,
++              "cd_mode_id: %#010x\n", args.arg0);
++
++      /* Determine tunable_attr->cv_mode_id, returns 1 if supported */
++      for (i = 0; i < ARRAY_SIZE(modes); i++) {
++              args.arg0 = tunable_attr_01_id(tunable_attr, modes[i]);
++
++              ret = lwmi_dev_evaluate_int(priv->wdev, 0x0, LWMI_FEATURE_VALUE_GET,
++                                          (u8 *)&args, sizeof(args),
++                                          &retval);
++              if (ret || !retval)
++                      continue;
++
++              tunable_attr->cv_mode_id = modes[i];
++              cv_mode_found = true;
++              break;
++      }
++
++      if (!cv_mode_found)
++              return cv_mode_found;
++
++      dev_dbg(tunable_attr->dev, "cv_mode_id: %#010x, attribute support level: %#010x\n",
++              args.arg0, capdata.supported);
++
++      return capdata.supported > 0;
++}
++
+ /* Lenovo WMI Other Mode Attribute macros */
+ #define __LWMI_ATTR_RO(_func, _name)                                  \
+       {                                                             \
+@@ -975,12 +1057,14 @@ static void lwmi_om_fw_attr_add(struct l
+       }
+       for (i = 0; i < ARRAY_SIZE(cd01_attr_groups) - 1; i++) {
++              cd01_attr_groups[i].tunable_attr->dev = &priv->wdev->dev;
++              if (!lwmi_attr_01_is_supported(cd01_attr_groups[i].tunable_attr))
++                      continue;
++
+               err = sysfs_create_group(&priv->fw_attr_kset->kobj,
+                                        cd01_attr_groups[i].attr_group);
+               if (err)
+                       goto err_remove_groups;
+-
+-              cd01_attr_groups[i].tunable_attr->dev = &priv->wdev->dev;
+       }
+       return;
diff --git a/queue-7.0/platform-x86-lenovo-wmi-other-zero-initialize-wmi-arguments.patch b/queue-7.0/platform-x86-lenovo-wmi-other-zero-initialize-wmi-arguments.patch
new file mode 100644 (file)
index 0000000..80d2871
--- /dev/null
@@ -0,0 +1,76 @@
+From 816fbd5dacee977ca56bab79bf97f71f2f7ac24e Mon Sep 17 00:00:00 2001
+From: "Derek J. Clark" <derekjohn.clark@gmail.com>
+Date: Sun, 10 May 2026 04:25:34 +0000
+Subject: platform/x86: lenovo-wmi-other: Zero initialize WMI arguments
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Derek J. Clark <derekjohn.clark@gmail.com>
+
+commit 816fbd5dacee977ca56bab79bf97f71f2f7ac24e upstream.
+
+Adds explicit initialization of wmi_method_args_32 declarations with
+zero values to prevent uninitialized data from being sent to the device
+BIOS when passed.
+
+No functional change intended.
+
+Reviewed-by: Mark Pearson <mpearson-lenovo@squebb.ca>
+Fixes: 22024ac5366f ("platform/x86: Add Lenovo Gamezone WMI Driver")
+Fixes: edc4b183b794 ("platform/x86: Add Lenovo Other Mode WMI Driver")
+Reported-by: Rong Zhang <i@rong.moe>
+Closes: https://lore.kernel.org/platform-driver-x86/95c7e7b539dd0af41189c754fcd35cec5b6fe182.camel@rong.moe/
+Cc: stable@vger.kernel.org
+Reviewed-by: Rong Zhang <i@rong.moe>
+Tested-by: Rong Zhang <i@rong.moe>
+Signed-off-by: Derek J. Clark <derekjohn.clark@gmail.com>
+Link: https://patch.msgid.link/20260510042546.436874-5-derekjohn.clark@gmail.com
+Reviewed-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
+Signed-off-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/platform/x86/lenovo/wmi-gamezone.c |    2 +-
+ drivers/platform/x86/lenovo/wmi-other.c    |    6 +++---
+ 2 files changed, 4 insertions(+), 4 deletions(-)
+
+--- a/drivers/platform/x86/lenovo/wmi-gamezone.c
++++ b/drivers/platform/x86/lenovo/wmi-gamezone.c
+@@ -200,7 +200,7 @@ static int lwmi_gz_profile_set(struct de
+                              enum platform_profile_option profile)
+ {
+       struct lwmi_gz_priv *priv = dev_get_drvdata(dev);
+-      struct wmi_method_args_32 args;
++      struct wmi_method_args_32 args = {};
+       enum thermal_mode mode;
+       int ret;
+--- a/drivers/platform/x86/lenovo/wmi-other.c
++++ b/drivers/platform/x86/lenovo/wmi-other.c
+@@ -165,7 +165,7 @@ MODULE_PARM_DESC(relax_fan_constraint,
+  */
+ static int lwmi_om_fan_get_set(struct lwmi_om_priv *priv, int channel, u32 *val, bool set)
+ {
+-      struct wmi_method_args_32 args;
++      struct wmi_method_args_32 args = {};
+       u32 method_id, retval;
+       int err;
+@@ -772,7 +772,7 @@ static ssize_t attr_current_value_store(
+                                       struct tunable_attr_01 *tunable_attr)
+ {
+       struct lwmi_om_priv *priv = dev_get_drvdata(tunable_attr->dev);
+-      struct wmi_method_args_32 args;
++      struct wmi_method_args_32 args = {};
+       struct capdata01 capdata;
+       enum thermal_mode mode;
+       u32 attribute_id;
+@@ -835,7 +835,7 @@ static ssize_t attr_current_value_show(s
+                                      struct tunable_attr_01 *tunable_attr)
+ {
+       struct lwmi_om_priv *priv = dev_get_drvdata(tunable_attr->dev);
+-      struct wmi_method_args_32 args;
++      struct wmi_method_args_32 args = {};
+       enum thermal_mode mode;
+       u32 attribute_id;
+       int retval;
diff --git a/queue-7.0/powerpc-warp-fix-error-handling-in-pika_dtm_thread.patch b/queue-7.0/powerpc-warp-fix-error-handling-in-pika_dtm_thread.patch
new file mode 100644 (file)
index 0000000..a46dda1
--- /dev/null
@@ -0,0 +1,39 @@
+From 108d7f951271cbd36ca36efc5e5d106966f5180c Mon Sep 17 00:00:00 2001
+From: Ma Ke <make24@iscas.ac.cn>
+Date: Sun, 16 Nov 2025 10:44:11 +0800
+Subject: powerpc/warp: Fix error handling in pika_dtm_thread
+
+From: Ma Ke <make24@iscas.ac.cn>
+
+commit 108d7f951271cbd36ca36efc5e5d106966f5180c upstream.
+
+pika_dtm_thread() acquires client through of_find_i2c_device_by_node()
+but fails to release it in error handling path. This could result in a
+reference count leak, preventing proper cleanup and potentially
+leading to resource exhaustion. Add put_device() to release the
+reference in the error handling path.
+
+Found by code review.
+
+Cc: stable@vger.kernel.org
+Fixes: 3984114f0562 ("powerpc/warp: Platform fix for i2c change")
+Signed-off-by: Ma Ke <make24@iscas.ac.cn>
+Reviewed-by: Christophe Leroy <christophe.leroy@csgroup.eu>
+Signed-off-by: Madhavan Srinivasan <maddy@linux.ibm.com>
+Link: https://patch.msgid.link/20251116024411.21968-1-make24@iscas.ac.cn
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/powerpc/platforms/44x/warp.c |    2 ++
+ 1 file changed, 2 insertions(+)
+
+--- a/arch/powerpc/platforms/44x/warp.c
++++ b/arch/powerpc/platforms/44x/warp.c
+@@ -293,6 +293,8 @@ static int pika_dtm_thread(void __iomem
+               schedule_timeout(HZ);
+       }
++      put_device(&client->dev);
++
+       return 0;
+ }
diff --git a/queue-7.0/riscv-misaligned-make-enabling-delegation-depend-on-nonportable.patch b/queue-7.0/riscv-misaligned-make-enabling-delegation-depend-on-nonportable.patch
new file mode 100644 (file)
index 0000000..e712c38
--- /dev/null
@@ -0,0 +1,83 @@
+From b69bcb13ed7024a84d6cd8ad330f1e32782fcf28 Mon Sep 17 00:00:00 2001
+From: Vivian Wang <wangruikang@iscas.ac.cn>
+Date: Wed, 1 Apr 2026 09:53:17 +0800
+Subject: riscv: misaligned: Make enabling delegation depend on NONPORTABLE
+
+From: Vivian Wang <wangruikang@iscas.ac.cn>
+
+commit b69bcb13ed7024a84d6cd8ad330f1e32782fcf28 upstream.
+
+The unaligned access emulation code in Linux has various deficiencies.
+For example, it doesn't emulate vector instructions [1] [2], and doesn't
+emulate KVM guest accesses. Therefore, requesting misaligned exception
+delegation with SBI FWFT actually regresses vector instructions' and KVM
+guests' behavior.
+
+Until Linux can handle it properly, guard these sbi_fwft_set() calls
+behind RISCV_SBI_FWFT_DELEGATE_MISALIGNED, which in turn depends on
+NONPORTABLE. Those who are sure that this wouldn't be a problem can
+enable this option, perhaps getting better performance.
+
+The rest of the existing code proceeds as before, except as if
+SBI_FWFT_MISALIGNED_EXC_DELEG is not available, to handle any remaining
+address misaligned exceptions on a best-effort basis. The KVM SBI FWFT
+implementation is also not touched, but it is disabled if the firmware
+emulates unaligned accesses.
+
+Cc: stable@vger.kernel.org
+Fixes: cf5a8abc6560 ("riscv: misaligned: request misaligned exception from SBI")
+Reported-by: Songsong Zhang <U2FsdGVkX1@gmail.com> # KVM
+Link: https://lore.kernel.org/linux-riscv/38ce44c1-08cf-4e3f-8ade-20da224f529c@iscas.ac.cn/ [1]
+Link: https://lore.kernel.org/linux-riscv/b3cfcdac-0337-4db0-a611-258f2868855f@iscas.ac.cn/ [2]
+Signed-off-by: Vivian Wang <wangruikang@iscas.ac.cn>
+Acked-by: Conor Dooley <conor.dooley@microchip.com>
+Link: https://patch.msgid.link/20260401-riscv-misaligned-dont-delegate-v2-1-5014a288c097@iscas.ac.cn
+Signed-off-by: Paul Walmsley <pjw@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/riscv/Kconfig                   |   22 ++++++++++++++++++++++
+ arch/riscv/kernel/traps_misaligned.c |    2 +-
+ 2 files changed, 23 insertions(+), 1 deletion(-)
+
+--- a/arch/riscv/Kconfig
++++ b/arch/riscv/Kconfig
+@@ -941,6 +941,28 @@ config RISCV_VECTOR_MISALIGNED
+       help
+         Enable detecting support for vector misaligned loads and stores.
++config RISCV_SBI_FWFT_DELEGATE_MISALIGNED
++      bool "Request firmware delegation of unaligned access exceptions"
++      depends on RISCV_SBI
++      depends on NONPORTABLE
++      help
++        Use SBI FWFT to request delegation of load address misaligned and
++        store address misaligned exceptions, if possible, and prefer Linux
++        kernel emulation of these accesses to firmware emulation.
++
++        Unfortunately, Linux's emulation is still incomplete. Namely, it
++        currently does not handle vector instructions and KVM guest accesses.
++        On platforms where these accesses would have been handled by firmware,
++        enabling this causes unexpected kernel oopses, userspaces crashes and
++        KVM guest crashes. If you are sure that these are not a problem for
++        your platform, you can say Y here, which may improve performance.
++
++        Saying N here will not worsen emulation support for unaligned accesses
++        even in the case where the firmware also has incomplete support. It
++        simply keeps the firmware's emulation enabled.
++
++        If you don't know what to do here, say N.
++
+ choice
+       prompt "Unaligned Accesses Support"
+       default RISCV_PROBE_UNALIGNED_ACCESS
+--- a/arch/riscv/kernel/traps_misaligned.c
++++ b/arch/riscv/kernel/traps_misaligned.c
+@@ -584,7 +584,7 @@ static int cpu_online_check_unaligned_ac
+ static bool misaligned_traps_delegated;
+-#ifdef CONFIG_RISCV_SBI
++#if defined(CONFIG_RISCV_SBI_FWFT_DELEGATE_MISALIGNED)
+ static int cpu_online_sbi_unaligned_setup(unsigned int cpu)
+ {
index c66d03568ce770a8fe763ba19969ba71d2e837ef..6d98396fbad4c79c60e6890e16217d27ecf01dfc 100644 (file)
@@ -1067,3 +1067,67 @@ hid-core-fix-size_t-specifier-in-hid_report_raw_even.patch
 ata-libata-scsi-fix-requeue-of-deferred-ata-pass-thr.patch
 media-staging-imx-configure-src_mux-in-csi_start.patch
 bluetooth-btmtk-accept-too-short-wmt-func_ctrl-events.patch
+nvme-apple-reset-q-sq_tail-during-queue-init.patch
+smb-client-fix-possible-infinite-loop-and-oob-read-in-symlink_data.patch
+drm-loongson-use-managed-kms-polling.patch
+drm-replace-old-pointer-to-new-idr.patch
+drm-bridge-imx8qxp-pxl2dpi-avoid-err_ptr-with-device_node-cleanup.patch
+drm-i915-dp-fix-vsc-dynamic-range-signaling-for-rgb-formats.patch
+drm-amd-display-wrap-dcn32-phantom-plane-allocation-in-dc_run_with_preemption_enabled.patch
+drm-ttm-fix-ttm_bo_swapout-infinite-lru-walk-on-swapout-failure.patch
+platform-x86-intel-move-debugfs-register-before-creating-devices.patch
+platform-x86-lenovo-wmi-helpers-move-gamezone-enums-to-wmi-helpers.patch
+platform-x86-lenovo-wmi-helpers-fix-memory-leak-in-lwmi_dev_evaluate_int.patch
+platform-x86-lenovo-wmi-other-balance-ida-id-allocation-and-free.patch
+platform-x86-lenovo-wmi-other-balance-component-bind-and-unbind.patch
+platform-x86-lenovo-wmi-other-zero-initialize-wmi-arguments.patch
+platform-x86-lenovo-wmi-other-fix-tunable_attr_01-struct-members.patch
+platform-x86-lenovo-wmi-other-add-attribute-id-helper-functions.patch
+platform-x86-lenovo-wmi-other-limit-adding-attributes-to-supported-devices.patch
+accel-rocket-fix-prep_bo-ioctl-leaking-positive-return-from-dma_resv_wait_timeout.patch
+alsa-hda-realtek-add-mute-led-quirk-for-hp-pavilion-laptop-16-ag0xxx.patch
+alsa-hda-realtek-add-quirk-for-samsung-galaxy-book5-360-headphone.patch
+alsa-usb-audio-bound-midi-2.0-endpoint-descriptor-scans.patch
+alsa-usb-audio-bound-midi-endpoint-descriptor-scans.patch
+alsa-usb-audio-qcom-check-offload-mapping-failures.patch
+btrfs-only-release-the-dirty-pages-io-tree-after-successful-writes.patch
+ceph-fix-a-buffer-leak-in-__ceph_setxattr.patch
+ceph-fix-bug_on-in-__ceph_build_xattrs_blob-due-to-stale-blob-size.patch
+ceph-put-folios-not-suitable-for-writeback.patch
+io-wq-check-that-the-predecessor-is-hashed-in-io_wq_remove_pending.patch
+iommu-amd-bounds-check-devid-in-__rlookup_amd_iommu.patch
+x86-kexec-push-kjump-return-address-even-for-non-kjump-kexec.patch
+xfs-fix-memory-leak-on-error-in-xfs_alloc_zone_info.patch
+virt-sev-guest-do-not-use-host-controlled-page-order-in-cleanup-path.patch
+riscv-misaligned-make-enabling-delegation-depend-on-nonportable.patch
+powerpc-warp-fix-error-handling-in-pika_dtm_thread.patch
+netfs-fix-error-handling-in-netfs_extract_user_iter.patch
+nfsd-fix-get_dir_delegation-when-vfs-leases-are-disabled.patch
+nfsd-fix-file-change-detection-in-cb_getattr.patch
+nfsd-update-mtime-ctime-on-clone-in-presense-of-delegated-attributes.patch
+nfsd-update-mtime-ctime-on-copy-in-presence-of-delegated-attributes.patch
+irqchip-riscv-imsic-clear-interrupt-move-state-during-cpu-offlining.patch
+irqchip-meson-gpio-use-the-correct-register-in-meson_s4_gpio_irq_set_type.patch
+irqchip-gic-v5-move-lpi-allocation-into-the-lpi-domain.patch
+irqchip-gic-v5-support-range-allocation-for-lpis.patch
+irqchip-gic-v5-allocate-its-parent-lpis-as-a-range.patch
+libceph-fix-potential-out-of-bounds-access-in-osdmap_decode.patch
+libceph-fix-potential-null-ptr-deref-in-decode_choose_args.patch
+libceph-fix-potential-out-of-bounds-access-in-__ceph_x_decrypt.patch
+libceph-fix-potential-out-of-bounds-access-in-crush_decode.patch
+libceph-handle-rbtree-insertion-error-in-decode_choose_args.patch
+iommu-vt-d-disable-dmar-for-intel-q35-igfx.patch
+iommu-vt-d-fix-oops-due-to-out-of-scope-access.patch
+iommu-vt-d-avoid-null-pointer-dereference-or-refcount-corruption.patch
+iommu-fix-null-group-domain-dereference-in-pci_dev_reset_iommu_done.patch
+iommu-replace-per-group-resetting_domain-with-per-gdev-blocked-flag.patch
+iommu-fix-warn_on-in-__iommu_group_set_domain_nofail-due-to-reset.patch
+iommu-fix-pasid-attach-in-pci_dev_reset_iommu_prepare-done.patch
+iommu-fix-nested-pci_dev_reset_iommu_prepare-done.patch
+iommu-fix-ats-invalidation-timeouts-during-__iommu_remove_group_pasid.patch
+drm-i915-skip-__i915_request_skip-for-already-signaled-requests.patch
+drm-panfrost-fix-wait_bo-ioctl-leaking-positive-return-from-dma_resv_wait_timeout.patch
+drm-xe-dma-buf-handle-empty-bo-and-uaf-races.patch
+drm-xe-dma-buf-fix-uaf-with-retry-loop.patch
+drm-ttm-fix-ttm_bo_shrink-infinite-lru-walk-on-backup-failure.patch
+drm-ttm-convert-eagain-from-dmem_cgroup_try_charge-to-enospc.patch
diff --git a/queue-7.0/smb-client-fix-possible-infinite-loop-and-oob-read-in-symlink_data.patch b/queue-7.0/smb-client-fix-possible-infinite-loop-and-oob-read-in-symlink_data.patch
new file mode 100644 (file)
index 0000000..0d5bc4b
--- /dev/null
@@ -0,0 +1,44 @@
+From 7d9a7f1f96cd617ee9e75bb22217c709038e26b8 Mon Sep 17 00:00:00 2001
+From: Ye Bin <yebin10@huawei.com>
+Date: Thu, 14 May 2026 21:14:18 +0800
+Subject: smb/client: fix possible infinite loop and oob read in symlink_data()
+
+From: Ye Bin <yebin10@huawei.com>
+
+commit 7d9a7f1f96cd617ee9e75bb22217c709038e26b8 upstream.
+
+On 32-bit architectures, the infinite loop is as follows:
+
+  len = p->ErrorDataLength == 0xfffffff8
+  u8 *next = p->ErrorContextData + len
+  next == p
+
+On 32-bit architectures, the out-of-bounds read is as follows:
+
+  len = p->ErrorDataLength == 0xfffffff0
+  u8 *next = p->ErrorContextData + len
+  next == (u8 *)p - 8
+
+Reported-by: ChenXiaoSong <chenxiaosong@kylinos.cn>
+Fixes: 76894f3e2f71 ("cifs: improve symlink handling for smb2+")
+Cc: stable@vger.kernel.org
+Signed-off-by: Ye Bin <yebin10@huawei.com>
+Reviewed-by: ChenXiaoSong <chenxiaosong@kylinos.cn>
+Signed-off-by: Steve French <stfrench@microsoft.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/smb/client/smb2file.c |    3 +++
+ 1 file changed, 3 insertions(+)
+
+--- a/fs/smb/client/smb2file.c
++++ b/fs/smb/client/smb2file.c
+@@ -49,6 +49,9 @@ static struct smb2_symlink_err_rsp *syml
+                                __func__, le32_to_cpu(p->ErrorId));
+                       len = ALIGN(le32_to_cpu(p->ErrorDataLength), 8);
++                      if (len > end - ((u8 *)p + sizeof(*p)))
++                              return ERR_PTR(-EINVAL);
++
+                       p = (struct smb2_error_context_rsp *)(p->ErrorContextData + len);
+               }
+       } else if (le32_to_cpu(err->ByteCount) >= sizeof(*sym) &&
diff --git a/queue-7.0/virt-sev-guest-do-not-use-host-controlled-page-order-in-cleanup-path.patch b/queue-7.0/virt-sev-guest-do-not-use-host-controlled-page-order-in-cleanup-path.patch
new file mode 100644 (file)
index 0000000..f00d6a5
--- /dev/null
@@ -0,0 +1,80 @@
+From 23e6a1ca04ae44806439a5a446e62e4d42e80bb4 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Carlos=20L=C3=B3pez?= <clopez@suse.de>
+Date: Tue, 12 May 2026 12:00:41 +0200
+Subject: virt: sev-guest: Do not use host-controlled page order in cleanup path
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Carlos López <clopez@suse.de>
+
+commit 23e6a1ca04ae44806439a5a446e62e4d42e80bb4 upstream.
+
+When issuing an extended guest request (SVM_VMGEXIT_EXT_GUEST_REQUEST),
+get_ext_report() allocates a buffer to retrieve a certificate blob from the
+host, keeping track of its size in report_req->certs_len.
+
+However, the host may return SNP_GUEST_VMM_ERR_INVALID_LEN, indicating
+an invalid buffer size, as well as the expected length of such buffer.
+get_ext_report() subsequently updates report_req->certs_len with the
+host-controlled value, and cleans up the buffer by computing a page order
+from such value. This is incorrect, as the host-provided length may not
+match the page order of the original allocation, potentially resulting
+in corruption in the page allocator.
+
+Fix this by using alloc_pages_exact() instead, and reusing @npages to
+compute the size passed to free_pages_exact(). For consistency, also
+use @npages to compute the size when allocating the pages, even though
+this last change has no functional effect.
+
+Fixes: 3e385c0d6ce8 ("virt: sev-guest: Move SNP Guest Request data pages handling under snp_cmd_mutex")
+Signed-off-by: Carlos López <clopez@suse.de>
+Signed-off-by: Borislav Petkov (AMD) <bp@alien8.de>
+Tested-by: Michael Roth <michael.roth@amd.com>
+Cc: stable@kernel.org
+Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/virt/coco/sev-guest/sev-guest.c |   12 +++++-------
+ 1 file changed, 5 insertions(+), 7 deletions(-)
+
+--- a/drivers/virt/coco/sev-guest/sev-guest.c
++++ b/drivers/virt/coco/sev-guest/sev-guest.c
+@@ -176,7 +176,6 @@ static int get_ext_report(struct snp_gue
+       struct snp_guest_req req = {};
+       int ret, npages = 0, resp_len;
+       sockptr_t certs_address;
+-      struct page *page;
+       if (sockptr_is_null(io->req_data) || sockptr_is_null(io->resp_data))
+               return -EINVAL;
+@@ -211,16 +210,15 @@ static int get_ext_report(struct snp_gue
+        * zeros to indicate that certificate data was not provided.
+        */
+       npages = report_req->certs_len >> PAGE_SHIFT;
+-      page = alloc_pages(GFP_KERNEL_ACCOUNT | __GFP_ZERO,
+-                         get_order(report_req->certs_len));
+-      if (!page)
++      req.certs_data = alloc_pages_exact(npages << PAGE_SHIFT,
++                                         GFP_KERNEL_ACCOUNT | __GFP_ZERO);
++      if (!req.certs_data)
+               return -ENOMEM;
+-      req.certs_data = page_address(page);
+       ret = set_memory_decrypted((unsigned long)req.certs_data, npages);
+       if (ret) {
+               pr_err("failed to mark page shared, ret=%d\n", ret);
+-              __free_pages(page, get_order(report_req->certs_len));
++              free_pages_exact(req.certs_data, npages << PAGE_SHIFT);
+               return -EFAULT;
+       }
+@@ -277,7 +275,7 @@ e_free_data:
+               if (set_memory_encrypted((unsigned long)req.certs_data, npages))
+                       WARN_ONCE(ret, "failed to restore encryption mask (leak it)\n");
+               else
+-                      __free_pages(page, get_order(report_req->certs_len));
++                      free_pages_exact(req.certs_data, npages << PAGE_SHIFT);
+       }
+       return ret;
+ }
diff --git a/queue-7.0/x86-kexec-push-kjump-return-address-even-for-non-kjump-kexec.patch b/queue-7.0/x86-kexec-push-kjump-return-address-even-for-non-kjump-kexec.patch
new file mode 100644 (file)
index 0000000..8b1bde4
--- /dev/null
@@ -0,0 +1,52 @@
+From 786a45757dcdf8f2beb9d4a6db605db16c18b2b4 Mon Sep 17 00:00:00 2001
+From: David Woodhouse <dwmw@amazon.co.uk>
+Date: Tue, 28 Apr 2026 21:59:52 +0100
+Subject: x86/kexec: Push kjump return address even for non-kjump kexec
+
+From: David Woodhouse <dwmw@amazon.co.uk>
+
+commit 786a45757dcdf8f2beb9d4a6db605db16c18b2b4 upstream.
+
+The version of purgatory code shipped by kexec-tools attempts to look above
+the top of its stack to find a return address for a kjump, even in a non-kjump
+kexec.
+
+After the commit in Fixes: the word above the stack might not be there,
+leading to a fault (which is at least now caught by my exception-handling code
+in kexec).
+
+That commit fixed things for the actual kjump path, but no longer
+"gratuitously" pushes the unused return address to the stack in the non-kjump
+path. Put that *back* in the non-kjump path, to prevent purgatory from
+crashing when trying to access it.
+
+Fixes: 2cacf7f23a02 ("x86/kexec: Fix stack and handling of re-entry point for ::preserve_context")
+Reported-by: Rohan Kakulawaram <rohanka@google.com>
+Signed-off-by: David Woodhouse <dwmw@amazon.co.uk>
+Signed-off-by: Borislav Petkov (AMD) <bp@alien8.de>
+Acked-by: Dave Hansen <dave.hansen@linux.intel.com>
+Tested-by: Rohan Kakulawaram <rohanka@google.com>
+Cc: <stable@kernel.org>
+Link: https://patch.msgid.link/32d627134143ffd957891cb697138e839c623211.camel@infradead.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/x86/kernel/relocate_kernel_64.S |    8 ++++++++
+ 1 file changed, 8 insertions(+)
+
+--- a/arch/x86/kernel/relocate_kernel_64.S
++++ b/arch/x86/kernel/relocate_kernel_64.S
+@@ -136,6 +136,14 @@ SYM_CODE_START_LOCAL_NOALIGN(identity_ma
+        * %r13 original CR4 when relocate_kernel() was invoked
+        */
++      /*
++       * Set return address to 0 if not preserving context. The purgatory
++       * shipped in kexec-tools will unconditionally look for the return
++       * address on the stack and set a kexec_jump_back_entry= command
++       * line option if it's non-zero. There's no other way that it can
++       * tell a preserve-context (kjump) kexec from a normal one.
++       */
++      pushq   $0
+       /* store the start address on the stack */
+       pushq   %rdx
diff --git a/queue-7.0/xfs-fix-memory-leak-on-error-in-xfs_alloc_zone_info.patch b/queue-7.0/xfs-fix-memory-leak-on-error-in-xfs_alloc_zone_info.patch
new file mode 100644 (file)
index 0000000..0e35951
--- /dev/null
@@ -0,0 +1,39 @@
+From 592975da8c3ca87b043077e6eafa37665eae7936 Mon Sep 17 00:00:00 2001
+From: Wilfred Mallawa <wilfred.mallawa@wdc.com>
+Date: Wed, 15 Apr 2026 09:45:14 +1000
+Subject: xfs: fix memory leak on error in xfs_alloc_zone_info()
+
+From: Wilfred Mallawa <wilfred.mallawa@wdc.com>
+
+commit 592975da8c3ca87b043077e6eafa37665eae7936 upstream.
+
+Currently, the 0th index of the zi_used_bucket_bitmap array is not freed
+on error due to the pre-decrement then evaluate semantic of the while
+loop used in xfs_alloc_zone_info(). Fix it by allowing for the i == 0
+case to be covered.
+
+Fixes: 080d01c41d44 ("xfs: implement zoned garbage collection")
+Cc: stable@vger.kernel.org # v6.15
+Reviewed-by: Damien Le Moal <dlemoal@kernel.org>
+Reviewed-by: Carlos Maiolino <cmaiolino@redhat.com>
+Signed-off-by: Wilfred Mallawa <wilfred.mallawa@wdc.com>
+Reviewed-by: Hans Holmberg <hans.holmberg@wdc.com>
+Reviewed-by: Christoph Hellwig <hch@lst.de>
+Reviewed-by: Darrick J. Wong <djwong@kernel.org>
+Signed-off-by: Carlos Maiolino <cem@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/xfs/xfs_zone_alloc.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/fs/xfs/xfs_zone_alloc.c
++++ b/fs/xfs/xfs_zone_alloc.c
+@@ -1214,7 +1214,7 @@ xfs_alloc_zone_info(
+       return zi;
+ out_free_bitmaps:
+-      while (--i > 0)
++      while (--i >= 0)
+               kvfree(zi->zi_used_bucket_bitmap[i]);
+       kfree(zi);
+       return NULL;