]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
5.15-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 8 Jan 2026 13:56:24 +0000 (14:56 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 8 Jan 2026 13:56:24 +0000 (14:56 +0100)
added patches:
alsa-wavefront-clear-substream-pointers-on-close.patch
alsa-wavefront-fix-integer-overflow-in-sample-size-validation.patch
alsa-wavefront-use-standard-print-api.patch
arm-dts-microchip-sama5d2-fix-spi-flexcom-fifo-size-to-32.patch
arm-dts-microchip-sama7g5-fix-uart-fifo-size-to-32.patch
asoc-stm-stm32_sai_sub-convert-to-platform-remove-callback-returning-void.patch
asoc-stm-use-dev_err_probe-helper.patch
asoc-stm32-sai-fix-clk-prepare-imbalance-on-probe-failure.patch
asoc-stm32-sai-fix-of-node-leak-on-probe.patch
asoc-stm32-sai-use-the-devm_clk_get_optional-helper.patch
btrfs-don-t-rewrite-ret-from-inode_permission.patch
crypto-af_alg-zero-initialize-memory-allocated-via-sock_kmalloc.patch
drm-gma500-remove-unused-helper-psb_fbdev_fb_setcolreg.patch
drm-i915-selftests-fix-subtraction-overflow-bug.patch
drm-mediatek-fix-probe-memory-leak.patch
f2fs-fix-to-avoid-updating-zero-sized-extent-in-extent-cache.patch
f2fs-fix-to-detect-recoverable-inode-during-dryrun-of-find_fsync_dnodes.patch
f2fs-fix-to-propagate-error-from-f2fs_enable_checkpoint.patch
f2fs-use-global-inline_xattr_slab-instead-of-per-sb-slab-cache.patch
fuse-fix-readahead-reclaim-deadlock.patch
hid-core-harden-s32ton-against-conversion-to-0-bits.patch
iommu-qcom-fix-device-leak-on-of_xlate.patch
jbd2-fix-the-inconsistency-between-checksum-and-data-in-memory-for-journal-sb.patch
kvm-nvmx-immediately-refresh-apicv-controls-as-needed-on-nested-vm-exit.patch
kvm-svm-mark-vmcb_npt-as-dirty-on-nested-vmrun.patch
kvm-x86-acquire-kvm-srcu-when-handling-kvm_set_vcpu_events.patch
lockd-fix-vfs_test_lock-calls.patch
media-mediatek-vcodec-fix-a-reference-leak-in-mtk_vcodec_fw_vpu_init.patch
media-renesas-rcar_drif-fix-device-node-reference-leak-in-rcar_drif_bond_enabled.patch
media-samsung-exynos4-is-fix-potential-abba-deadlock-on-init.patch
media-verisilicon-protect-g2-hevc-decoder-against-invalid-dpb-index.patch
media-vpif_capture-fix-section-mismatch.patch
mm-balloon_compaction-convert-balloon_page_delete-to-balloon_page_finalize.patch
mm-balloon_compaction-make-balloon-page-compaction-callbacks-static.patch
mm-balloon_compaction-we-cannot-have-isolated-pages-in-the-balloon-list.patch
mm-mprotect-delete-pmd_none_or_clear_bad_unless_trans_huge.patch
mm-mprotect-use-long-for-page-accountings-and-retval.patch
mmc-core-use-sysfs_emit-instead-of-sprintf.patch
mptcp-pm-ignore-unknown-endpoint-flags.patch
net-remove-rtnl-dance-for-siocbraddif-and-siocbrdelif.patch
nfsd-clear-seclabel-in-the-suppattr_exclcreat-bitmap.patch
nfsd-nfsv4-file-creation-neglects-setting-acl.patch
page_pool-fix-use-after-free-in-page_pool_recycle_in_ring.patch
pci-brcmstb-fix-disabling-l0s-capability.patch
pmdomain-imx-fix-reference-count-leak-in-imx_gpc_probe.patch
pmdomain-use-device_get_match_data.patch
powerpc-64s-slb-fix-slb-multihit-issue-during-slb-preload.patch
powerpc-pseries-cmm-adjust-balloon_migrate-when-migrating-pages.patch
powerpc-pseries-cmm-call-balloon_devinfo_init-also-without-config_balloon_compaction.patch
r8169-fix-rtl8117-wake-on-lan-in-dash-mode.patch
soc-rockchip-power-domain-manage-resource-conflicts-with-firmware.patch
sunrpc-svcauth_gss-avoid-null-deref-on-zero-length-gss_token-in-gss_read_proxy_verf.patch
svcrdma-bound-check-rq_pages-index-in-inline-path.patch
tpm-cap-the-number-of-pcr-banks.patch
usb-dwc3-keep-susphy-enabled-during-exit-to-avoid-controller-faults.patch
usb-gadget-udc-fix-use-after-free-in-usb_gadget_state_work.patch
usb-ohci-nxp-fix-device-leak-on-probe-failure.patch
usb-ohci-nxp-use-helper-function-devm_clk_get_enabled.patch
wifi-mac80211-discard-beacon-frames-to-non-broadcast-address.patch
wifi-mt76-fix-dts-power-limits-on-little-endian-systems.patch
xfs-fix-a-memory-leak-in-xfs_buf_item_init.patch
xhci-dbgtty-fix-device-unregister.patch
xhci-dbgtty-use-idr-to-support-several-dbc-instances.patch

64 files changed:
queue-5.15/alsa-wavefront-clear-substream-pointers-on-close.patch [new file with mode: 0644]
queue-5.15/alsa-wavefront-fix-integer-overflow-in-sample-size-validation.patch [new file with mode: 0644]
queue-5.15/alsa-wavefront-use-standard-print-api.patch [new file with mode: 0644]
queue-5.15/arm-dts-microchip-sama5d2-fix-spi-flexcom-fifo-size-to-32.patch [new file with mode: 0644]
queue-5.15/arm-dts-microchip-sama7g5-fix-uart-fifo-size-to-32.patch [new file with mode: 0644]
queue-5.15/asoc-stm-stm32_sai_sub-convert-to-platform-remove-callback-returning-void.patch [new file with mode: 0644]
queue-5.15/asoc-stm-use-dev_err_probe-helper.patch [new file with mode: 0644]
queue-5.15/asoc-stm32-sai-fix-clk-prepare-imbalance-on-probe-failure.patch [new file with mode: 0644]
queue-5.15/asoc-stm32-sai-fix-of-node-leak-on-probe.patch [new file with mode: 0644]
queue-5.15/asoc-stm32-sai-use-the-devm_clk_get_optional-helper.patch [new file with mode: 0644]
queue-5.15/btrfs-don-t-rewrite-ret-from-inode_permission.patch [new file with mode: 0644]
queue-5.15/crypto-af_alg-zero-initialize-memory-allocated-via-sock_kmalloc.patch [new file with mode: 0644]
queue-5.15/drm-gma500-remove-unused-helper-psb_fbdev_fb_setcolreg.patch [new file with mode: 0644]
queue-5.15/drm-i915-selftests-fix-subtraction-overflow-bug.patch [new file with mode: 0644]
queue-5.15/drm-mediatek-fix-probe-memory-leak.patch [new file with mode: 0644]
queue-5.15/f2fs-fix-to-avoid-updating-zero-sized-extent-in-extent-cache.patch [new file with mode: 0644]
queue-5.15/f2fs-fix-to-detect-recoverable-inode-during-dryrun-of-find_fsync_dnodes.patch [new file with mode: 0644]
queue-5.15/f2fs-fix-to-propagate-error-from-f2fs_enable_checkpoint.patch [new file with mode: 0644]
queue-5.15/f2fs-use-global-inline_xattr_slab-instead-of-per-sb-slab-cache.patch [new file with mode: 0644]
queue-5.15/fuse-fix-readahead-reclaim-deadlock.patch [new file with mode: 0644]
queue-5.15/hid-core-harden-s32ton-against-conversion-to-0-bits.patch [new file with mode: 0644]
queue-5.15/iommu-qcom-fix-device-leak-on-of_xlate.patch [new file with mode: 0644]
queue-5.15/jbd2-fix-the-inconsistency-between-checksum-and-data-in-memory-for-journal-sb.patch [new file with mode: 0644]
queue-5.15/kvm-nvmx-immediately-refresh-apicv-controls-as-needed-on-nested-vm-exit.patch [new file with mode: 0644]
queue-5.15/kvm-svm-mark-vmcb_npt-as-dirty-on-nested-vmrun.patch [new file with mode: 0644]
queue-5.15/kvm-x86-acquire-kvm-srcu-when-handling-kvm_set_vcpu_events.patch [new file with mode: 0644]
queue-5.15/lockd-fix-vfs_test_lock-calls.patch [new file with mode: 0644]
queue-5.15/media-mediatek-vcodec-fix-a-reference-leak-in-mtk_vcodec_fw_vpu_init.patch [new file with mode: 0644]
queue-5.15/media-renesas-rcar_drif-fix-device-node-reference-leak-in-rcar_drif_bond_enabled.patch [new file with mode: 0644]
queue-5.15/media-samsung-exynos4-is-fix-potential-abba-deadlock-on-init.patch [new file with mode: 0644]
queue-5.15/media-verisilicon-protect-g2-hevc-decoder-against-invalid-dpb-index.patch [new file with mode: 0644]
queue-5.15/media-vpif_capture-fix-section-mismatch.patch [new file with mode: 0644]
queue-5.15/mm-balloon_compaction-convert-balloon_page_delete-to-balloon_page_finalize.patch [new file with mode: 0644]
queue-5.15/mm-balloon_compaction-make-balloon-page-compaction-callbacks-static.patch [new file with mode: 0644]
queue-5.15/mm-balloon_compaction-we-cannot-have-isolated-pages-in-the-balloon-list.patch [new file with mode: 0644]
queue-5.15/mm-mprotect-delete-pmd_none_or_clear_bad_unless_trans_huge.patch [new file with mode: 0644]
queue-5.15/mm-mprotect-use-long-for-page-accountings-and-retval.patch [new file with mode: 0644]
queue-5.15/mmc-core-use-sysfs_emit-instead-of-sprintf.patch [new file with mode: 0644]
queue-5.15/mptcp-pm-ignore-unknown-endpoint-flags.patch [new file with mode: 0644]
queue-5.15/net-remove-rtnl-dance-for-siocbraddif-and-siocbrdelif.patch [new file with mode: 0644]
queue-5.15/nfsd-clear-seclabel-in-the-suppattr_exclcreat-bitmap.patch [new file with mode: 0644]
queue-5.15/nfsd-nfsv4-file-creation-neglects-setting-acl.patch [new file with mode: 0644]
queue-5.15/page_pool-fix-use-after-free-in-page_pool_recycle_in_ring.patch [new file with mode: 0644]
queue-5.15/pci-brcmstb-fix-disabling-l0s-capability.patch [new file with mode: 0644]
queue-5.15/pmdomain-imx-fix-reference-count-leak-in-imx_gpc_probe.patch [new file with mode: 0644]
queue-5.15/pmdomain-use-device_get_match_data.patch [new file with mode: 0644]
queue-5.15/powerpc-64s-slb-fix-slb-multihit-issue-during-slb-preload.patch [new file with mode: 0644]
queue-5.15/powerpc-pseries-cmm-adjust-balloon_migrate-when-migrating-pages.patch [new file with mode: 0644]
queue-5.15/powerpc-pseries-cmm-call-balloon_devinfo_init-also-without-config_balloon_compaction.patch [new file with mode: 0644]
queue-5.15/r8169-fix-rtl8117-wake-on-lan-in-dash-mode.patch [new file with mode: 0644]
queue-5.15/series
queue-5.15/soc-rockchip-power-domain-manage-resource-conflicts-with-firmware.patch [new file with mode: 0644]
queue-5.15/sunrpc-svcauth_gss-avoid-null-deref-on-zero-length-gss_token-in-gss_read_proxy_verf.patch [new file with mode: 0644]
queue-5.15/svcrdma-bound-check-rq_pages-index-in-inline-path.patch [new file with mode: 0644]
queue-5.15/tpm-cap-the-number-of-pcr-banks.patch [new file with mode: 0644]
queue-5.15/usb-dwc3-keep-susphy-enabled-during-exit-to-avoid-controller-faults.patch [new file with mode: 0644]
queue-5.15/usb-gadget-udc-fix-use-after-free-in-usb_gadget_state_work.patch [new file with mode: 0644]
queue-5.15/usb-ohci-nxp-fix-device-leak-on-probe-failure.patch [new file with mode: 0644]
queue-5.15/usb-ohci-nxp-use-helper-function-devm_clk_get_enabled.patch [new file with mode: 0644]
queue-5.15/wifi-mac80211-discard-beacon-frames-to-non-broadcast-address.patch [new file with mode: 0644]
queue-5.15/wifi-mt76-fix-dts-power-limits-on-little-endian-systems.patch [new file with mode: 0644]
queue-5.15/xfs-fix-a-memory-leak-in-xfs_buf_item_init.patch [new file with mode: 0644]
queue-5.15/xhci-dbgtty-fix-device-unregister.patch [new file with mode: 0644]
queue-5.15/xhci-dbgtty-use-idr-to-support-several-dbc-instances.patch [new file with mode: 0644]

diff --git a/queue-5.15/alsa-wavefront-clear-substream-pointers-on-close.patch b/queue-5.15/alsa-wavefront-clear-substream-pointers-on-close.patch
new file mode 100644 (file)
index 0000000..92b7981
--- /dev/null
@@ -0,0 +1,48 @@
+From stable+bounces-202048-greg=kroah.com@vger.kernel.org Tue Dec 16 13:22:57 2025
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 16 Dec 2025 07:03:55 -0500
+Subject: ALSA: wavefront: Clear substream pointers on close
+To: stable@vger.kernel.org
+Cc: Junrui Luo <moonafterrain@outlook.com>, Yuhao Jiang <danisjiang@gmail.com>, Takashi Iwai <tiwai@suse.de>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20251216120355.2790532-1-sashal@kernel.org>
+
+From: Junrui Luo <moonafterrain@outlook.com>
+
+[ Upstream commit e11c5c13ce0ab2325d38fe63500be1dd88b81e38 ]
+
+Clear substream pointers in close functions to avoid leaving dangling
+pointers, helping to improve code safety and
+prevents potential issues.
+
+Reported-by: Yuhao Jiang <danisjiang@gmail.com>
+Reported-by: Junrui Luo <moonafterrain@outlook.com>
+Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
+Cc: stable@vger.kernel.org
+Signed-off-by: Junrui Luo <moonafterrain@outlook.com>
+Link: https://patch.msgid.link/SYBPR01MB7881DF762CAB45EE42F6D812AFC2A@SYBPR01MB7881.ausprd01.prod.outlook.com
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+[ No guard() in older trees ]
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ sound/isa/wavefront/wavefront_midi.c |    2 ++
+ 1 file changed, 2 insertions(+)
+
+--- a/sound/isa/wavefront/wavefront_midi.c
++++ b/sound/isa/wavefront/wavefront_midi.c
+@@ -294,6 +294,7 @@ static int snd_wavefront_midi_input_clos
+               return -EIO;
+       spin_lock_irqsave (&midi->open, flags);
++      midi->substream_input[mpu] = NULL;
+       midi->mode[mpu] &= ~MPU401_MODE_INPUT;
+       spin_unlock_irqrestore (&midi->open, flags);
+@@ -318,6 +319,7 @@ static int snd_wavefront_midi_output_clo
+               return -EIO;
+       spin_lock_irqsave (&midi->open, flags);
++      midi->substream_output[mpu] = NULL;
+       midi->mode[mpu] &= ~MPU401_MODE_OUTPUT;
+       spin_unlock_irqrestore (&midi->open, flags);
+       return 0;
diff --git a/queue-5.15/alsa-wavefront-fix-integer-overflow-in-sample-size-validation.patch b/queue-5.15/alsa-wavefront-fix-integer-overflow-in-sample-size-validation.patch
new file mode 100644 (file)
index 0000000..9479ebf
--- /dev/null
@@ -0,0 +1,43 @@
+From stable+bounces-201186-greg=kroah.com@vger.kernel.org Tue Dec 16 12:13:42 2025
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 16 Dec 2025 06:06:27 -0500
+Subject: ALSA: wavefront: Fix integer overflow in sample size validation
+To: stable@vger.kernel.org
+Cc: Junrui Luo <moonafterrain@outlook.com>, Takashi Iwai <tiwai@suse.de>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20251216110628.2753962-2-sashal@kernel.org>
+
+From: Junrui Luo <moonafterrain@outlook.com>
+
+[ Upstream commit 0c4a13ba88594fd4a27292853e736c6b4349823d ]
+
+The wavefront_send_sample() function has an integer overflow issue
+when validating sample size. The header->size field is u32 but gets
+cast to int for comparison with dev->freemem
+
+Fix by using unsigned comparison to avoid integer overflow.
+
+Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
+Cc: stable@vger.kernel.org
+Signed-off-by: Junrui Luo <moonafterrain@outlook.com>
+Link: https://patch.msgid.link/SYBPR01MB7881B47789D1B060CE8BF4C3AFC2A@SYBPR01MB7881.ausprd01.prod.outlook.com
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ sound/isa/wavefront/wavefront_synth.c |    4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+--- a/sound/isa/wavefront/wavefront_synth.c
++++ b/sound/isa/wavefront/wavefront_synth.c
+@@ -952,9 +952,9 @@ wavefront_send_sample (snd_wavefront_t *
+       if (header->size) {
+               dev->freemem = wavefront_freemem (dev);
+-              if (dev->freemem < (int)header->size) {
++              if (dev->freemem < 0 || dev->freemem < header->size) {
+                       dev_err(dev->card->dev,
+-                              "insufficient memory to load %d byte sample.\n",
++                              "insufficient memory to load %u byte sample.\n",
+                               header->size);
+                       return -ENOMEM;
+               }
diff --git a/queue-5.15/alsa-wavefront-use-standard-print-api.patch b/queue-5.15/alsa-wavefront-use-standard-print-api.patch
new file mode 100644 (file)
index 0000000..f271d62
--- /dev/null
@@ -0,0 +1,1000 @@
+From stable+bounces-201185-greg=kroah.com@vger.kernel.org Tue Dec 16 12:14:05 2025
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 16 Dec 2025 06:06:26 -0500
+Subject: ALSA: wavefront: Use standard print API
+To: stable@vger.kernel.org
+Cc: Takashi Iwai <tiwai@suse.de>, Jaroslav Kysela <perex@perex.cz>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20251216110628.2753962-1-sashal@kernel.org>
+
+From: Takashi Iwai <tiwai@suse.de>
+
+[ Upstream commit 8b4ac5429938dd5f1fbf2eea0687f08cbcccb6be ]
+
+Use the standard print API with dev_*() instead of the old house-baked
+one.  It gives better information and allows dynamically control of
+debug prints.
+
+Reviewed-by: Jaroslav Kysela <perex@perex.cz>
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Link: https://patch.msgid.link/20240807133452.9424-36-tiwai@suse.de
+Stable-dep-of: 0c4a13ba8859 ("ALSA: wavefront: Fix integer overflow in sample size validation")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ include/sound/snd_wavefront.h         |    4 
+ sound/isa/wavefront/wavefront.c       |   61 +++++-----
+ sound/isa/wavefront/wavefront_fx.c    |   36 +++---
+ sound/isa/wavefront/wavefront_midi.c  |   15 +-
+ sound/isa/wavefront/wavefront_synth.c |  196 +++++++++++++++++-----------------
+ 5 files changed, 158 insertions(+), 154 deletions(-)
+
+--- a/include/sound/snd_wavefront.h
++++ b/include/sound/snd_wavefront.h
+@@ -137,8 +137,4 @@ extern int  snd_wavefront_fx_ioctl  (str
+ extern int snd_wavefront_fx_open    (struct snd_hwdep *, struct file *);
+ extern int snd_wavefront_fx_release (struct snd_hwdep *, struct file *);
+-/* prefix in all snd_printk() delivered messages */
+-
+-#define LOGNAME "WaveFront: "
+-
+ #endif  /* __SOUND_SND_WAVEFRONT_H__ */
+--- a/sound/isa/wavefront/wavefront.c
++++ b/sound/isa/wavefront/wavefront.c
+@@ -140,7 +140,7 @@ snd_wavefront_pnp (int dev, snd_wavefron
+       err = pnp_activate_dev(pdev);
+       if (err < 0) {
+-              snd_printk(KERN_ERR "PnP WSS pnp configure failure\n");
++              dev_err(&pdev->dev, "PnP WSS pnp configure failure\n");
+               return err;
+       }
+@@ -156,7 +156,7 @@ snd_wavefront_pnp (int dev, snd_wavefron
+       
+       err = pnp_activate_dev(pdev);
+       if (err < 0) {
+-              snd_printk(KERN_ERR "PnP ICS2115 pnp configure failure\n");
++              dev_err(&pdev->dev, "PnP ICS2115 pnp configure failure\n");
+               return err;
+       }
+@@ -174,26 +174,27 @@ snd_wavefront_pnp (int dev, snd_wavefron
+               err = pnp_activate_dev(pdev);
+               if (err < 0) {
+-                      snd_printk(KERN_ERR "PnP MPU401 pnp configure failure\n");
++                      dev_err(&pdev->dev, "PnP MPU401 pnp configure failure\n");
+                       cs4232_mpu_port[dev] = SNDRV_AUTO_PORT;
+               } else {
+                       cs4232_mpu_port[dev] = pnp_port_start(pdev, 0);
+                       cs4232_mpu_irq[dev] = pnp_irq(pdev, 0);
+               }
+-              snd_printk (KERN_INFO "CS4232 MPU: port=0x%lx, irq=%i\n", 
+-                          cs4232_mpu_port[dev], 
+-                          cs4232_mpu_irq[dev]);
++              dev_info(&pdev->dev, "CS4232 MPU: port=0x%lx, irq=%i\n",
++                       cs4232_mpu_port[dev],
++                       cs4232_mpu_irq[dev]);
+       }
+-      snd_printdd ("CS4232: pcm port=0x%lx, fm port=0x%lx, dma1=%i, dma2=%i, irq=%i\nICS2115: port=0x%lx, irq=%i\n", 
+-                  cs4232_pcm_port[dev], 
+-                  fm_port[dev],
+-                  dma1[dev], 
+-                  dma2[dev], 
+-                  cs4232_pcm_irq[dev],
+-                  ics2115_port[dev], 
+-                  ics2115_irq[dev]);
++      dev_dbg(&pdev->dev,
++              "CS4232: pcm port=0x%lx, fm port=0x%lx, dma1=%i, dma2=%i, irq=%i\nICS2115: port=0x%lx, irq=%i\n",
++              cs4232_pcm_port[dev],
++              fm_port[dev],
++              dma1[dev],
++              dma2[dev],
++              cs4232_pcm_irq[dev],
++              ics2115_port[dev],
++              ics2115_irq[dev]);
+       
+       return 0;
+ }
+@@ -251,7 +252,7 @@ static struct snd_hwdep *snd_wavefront_n
+       struct snd_hwdep *fx_processor;
+       if (snd_wavefront_fx_start (&acard->wavefront)) {
+-              snd_printk (KERN_ERR "cannot initialize YSS225 FX processor");
++              dev_err(card->dev, "cannot initialize YSS225 FX processor");
+               return NULL;
+       }
+@@ -282,7 +283,7 @@ static struct snd_rawmidi *snd_wavefront
+               first = 0;
+               acard->wavefront.midi.base = port;
+               if (snd_wavefront_midi_start (acard)) {
+-                      snd_printk (KERN_ERR "cannot initialize MIDI interface\n");
++                      dev_err(card->dev, "cannot initialize MIDI interface\n");
+                       return NULL;
+               }
+       }
+@@ -349,7 +350,7 @@ snd_wavefront_probe (struct snd_card *ca
+                            cs4232_pcm_irq[dev], dma1[dev], dma2[dev],
+                            WSS_HW_DETECT, 0, &chip);
+       if (err < 0) {
+-              snd_printk(KERN_ERR "can't allocate WSS device\n");
++              dev_err(card->dev, "can't allocate WSS device\n");
+               return err;
+       }
+@@ -369,7 +370,7 @@ snd_wavefront_probe (struct snd_card *ca
+               err = snd_opl3_create(card, fm_port[dev], fm_port[dev] + 2,
+                                     OPL3_HW_OPL3_CS, 0, &opl3);
+               if (err < 0) {
+-                      snd_printk (KERN_ERR "can't allocate or detect OPL3 synth\n");
++                      dev_err(card->dev, "can't allocate or detect OPL3 synth\n");
+                       return err;
+               }
+@@ -385,14 +386,14 @@ snd_wavefront_probe (struct snd_card *ca
+               devm_request_region(card->dev, ics2115_port[dev], 16,
+                                   "ICS2115");
+       if (acard->wavefront.res_base == NULL) {
+-              snd_printk(KERN_ERR "unable to grab ICS2115 i/o region 0x%lx-0x%lx\n",
+-                         ics2115_port[dev], ics2115_port[dev] + 16 - 1);
++              dev_err(card->dev, "unable to grab ICS2115 i/o region 0x%lx-0x%lx\n",
++                      ics2115_port[dev], ics2115_port[dev] + 16 - 1);
+               return -EBUSY;
+       }
+       if (devm_request_irq(card->dev, ics2115_irq[dev],
+                            snd_wavefront_ics2115_interrupt,
+                            0, "ICS2115", acard)) {
+-              snd_printk(KERN_ERR "unable to use ICS2115 IRQ %d\n", ics2115_irq[dev]);
++              dev_err(card->dev, "unable to use ICS2115 IRQ %d\n", ics2115_irq[dev]);
+               return -EBUSY;
+       }
+       
+@@ -402,7 +403,7 @@ snd_wavefront_probe (struct snd_card *ca
+       wavefront_synth = snd_wavefront_new_synth(card, hw_dev, acard);
+       if (wavefront_synth == NULL) {
+-              snd_printk (KERN_ERR "can't create WaveFront synth device\n");
++              dev_err(card->dev, "can't create WaveFront synth device\n");
+               return -ENOMEM;
+       }
+@@ -414,7 +415,7 @@ snd_wavefront_probe (struct snd_card *ca
+       err = snd_wss_mixer(chip);
+       if (err < 0) {
+-              snd_printk (KERN_ERR "can't allocate mixer device\n");
++              dev_err(card->dev, "can't allocate mixer device\n");
+               return err;
+       }
+@@ -425,7 +426,7 @@ snd_wavefront_probe (struct snd_card *ca
+                                         cs4232_mpu_port[dev], 0,
+                                         cs4232_mpu_irq[dev], NULL);
+               if (err < 0) {
+-                      snd_printk (KERN_ERR "can't allocate CS4232 MPU-401 device\n");
++                      dev_err(card->dev, "can't allocate CS4232 MPU-401 device\n");
+                       return err;
+               }
+               midi_dev++;
+@@ -441,7 +442,7 @@ snd_wavefront_probe (struct snd_card *ca
+                                               ics2115_port[dev],
+                                               internal_mpu);
+               if (ics2115_internal_rmidi == NULL) {
+-                      snd_printk (KERN_ERR "can't setup ICS2115 internal MIDI device\n");
++                      dev_err(card->dev, "can't setup ICS2115 internal MIDI device\n");
+                       return -ENOMEM;
+               }
+               midi_dev++;
+@@ -457,7 +458,7 @@ snd_wavefront_probe (struct snd_card *ca
+                                               ics2115_port[dev],
+                                               external_mpu);
+               if (ics2115_external_rmidi == NULL) {
+-                      snd_printk (KERN_ERR "can't setup ICS2115 external MIDI device\n");
++                      dev_err(card->dev, "can't setup ICS2115 external MIDI device\n");
+                       return -ENOMEM;
+               }
+               midi_dev++;
+@@ -471,7 +472,7 @@ snd_wavefront_probe (struct snd_card *ca
+                                                    acard,
+                                                    ics2115_port[dev]);
+               if (fx_processor == NULL) {
+-                      snd_printk (KERN_ERR "can't setup FX device\n");
++                      dev_err(card->dev, "can't setup FX device\n");
+                       return -ENOMEM;
+               }
+@@ -525,11 +526,11 @@ static int snd_wavefront_isa_match(struc
+               return 0;
+ #endif
+       if (cs4232_pcm_port[dev] == SNDRV_AUTO_PORT) {
+-              snd_printk(KERN_ERR "specify CS4232 port\n");
++              dev_err(pdev, "specify CS4232 port\n");
+               return 0;
+       }
+       if (ics2115_port[dev] == SNDRV_AUTO_PORT) {
+-              snd_printk(KERN_ERR "specify ICS2115 port\n");
++              dev_err(pdev, "specify ICS2115 port\n");
+               return 0;
+       }
+       return 1;
+@@ -585,7 +586,7 @@ static int snd_wavefront_pnp_detect(stru
+       if (snd_wavefront_pnp (dev, card->private_data, pcard, pid) < 0) {
+               if (cs4232_pcm_port[dev] == SNDRV_AUTO_PORT) {
+-                      snd_printk (KERN_ERR "isapnp detection failed\n");
++                      dev_err(card->dev, "isapnp detection failed\n");
+                       return -ENODEV;
+               }
+       }
+--- a/sound/isa/wavefront/wavefront_fx.c
++++ b/sound/isa/wavefront/wavefront_fx.c
+@@ -38,7 +38,7 @@ wavefront_fx_idle (snd_wavefront_t *dev)
+       }
+       if (x & 0x80) {
+-              snd_printk ("FX device never idle.\n");
++              dev_err(dev->card->dev, "FX device never idle.\n");
+               return 0;
+       }
+@@ -64,14 +64,14 @@ wavefront_fx_memset (snd_wavefront_t *de
+                    unsigned short *data)
+ {
+       if (page < 0 || page > 7) {
+-              snd_printk ("FX memset: "
+-                      "page must be >= 0 and <= 7\n");
++              dev_err(dev->card->dev,
++                      "FX memset: page must be >= 0 and <= 7\n");
+               return -EINVAL;
+       }
+       if (addr < 0 || addr > 0x7f) {
+-              snd_printk ("FX memset: "
+-                      "addr must be >= 0 and <= 7f\n");
++              dev_err(dev->card->dev,
++                      "FX memset: addr must be >= 0 and <= 7f\n");
+               return -EINVAL;
+       }
+@@ -83,7 +83,7 @@ wavefront_fx_memset (snd_wavefront_t *de
+               outb ((data[0] >> 8), dev->fx_dsp_msb);
+               outb ((data[0] & 0xff), dev->fx_dsp_lsb);
+-              snd_printk ("FX: addr %d:%x set to 0x%x\n",
++              dev_err(dev->card->dev, "FX: addr %d:%x set to 0x%x\n",
+                       page, addr, data[0]);
+       } else {
+@@ -102,9 +102,9 @@ wavefront_fx_memset (snd_wavefront_t *de
+               }
+               if (i != cnt) {
+-                      snd_printk ("FX memset "
+-                                  "(0x%x, 0x%x, 0x%lx, %d) incomplete\n",
+-                                  page, addr, (unsigned long) data, cnt);
++                      dev_err(dev->card->dev,
++                              "FX memset (0x%x, 0x%x, 0x%lx, %d) incomplete\n",
++                              page, addr, (unsigned long) data, cnt);
+                       return -EIO;
+               }
+       }
+@@ -123,7 +123,7 @@ snd_wavefront_fx_detect (snd_wavefront_t
+       */
+       if (inb (dev->fx_status) & 0x80) {
+-              snd_printk ("Hmm, probably a Maui or Tropez.\n");
++              dev_err(dev->card->dev, "Hmm, probably a Maui or Tropez.\n");
+               return -1;
+       }
+@@ -180,15 +180,15 @@ snd_wavefront_fx_ioctl (struct snd_hwdep
+       case WFFX_MEMSET:
+               if (r.data[2] <= 0) {
+-                      snd_printk ("cannot write "
+-                              "<= 0 bytes to FX\n");
++                      dev_err(dev->card->dev,
++                              "cannot write <= 0 bytes to FX\n");
+                       return -EIO;
+               } else if (r.data[2] == 1) {
+                       pd = (unsigned short *) &r.data[3];
+               } else {
+                       if (r.data[2] > 256) {
+-                              snd_printk ("cannot write "
+-                                          "> 512 bytes to FX\n");
++                              dev_err(dev->card->dev,
++                                      "cannot write > 512 bytes to FX\n");
+                               return -EIO;
+                       }
+                       page_data = memdup_user((unsigned char __user *)
+@@ -208,8 +208,8 @@ snd_wavefront_fx_ioctl (struct snd_hwdep
+               break;
+       default:
+-              snd_printk ("FX: ioctl %d not yet supported\n",
+-                          r.request);
++              dev_err(dev->card->dev, "FX: ioctl %d not yet supported\n",
++                      r.request);
+               return -ENOTTY;
+       }
+       return err;
+@@ -254,8 +254,8 @@ snd_wavefront_fx_start (snd_wavefront_t
+                               goto out;
+                       }
+               } else {
+-                      snd_printk(KERN_ERR "invalid address"
+-                                 " in register data\n");
++                      dev_err(dev->card->dev,
++                              "invalid address in register data\n");
+                       err = -1;
+                       goto out;
+               }
+--- a/sound/isa/wavefront/wavefront_midi.c
++++ b/sound/isa/wavefront/wavefront_midi.c
+@@ -503,7 +503,8 @@ snd_wavefront_midi_start (snd_wavefront_
+       for (i = 0; i < 30000 && !output_ready (midi); i++);
+       if (!output_ready (midi)) {
+-              snd_printk ("MIDI interface not ready for command\n");
++              dev_err(card->wavefront.card->dev,
++                      "MIDI interface not ready for command\n");
+               return -1;
+       }
+@@ -525,7 +526,8 @@ snd_wavefront_midi_start (snd_wavefront_
+       }
+       if (!ok) {
+-              snd_printk ("cannot set UART mode for MIDI interface");
++              dev_err(card->wavefront.card->dev,
++                      "cannot set UART mode for MIDI interface");
+               dev->interrupts_are_midi = 0;
+               return -1;
+       }
+@@ -533,7 +535,8 @@ snd_wavefront_midi_start (snd_wavefront_
+       /* Route external MIDI to WaveFront synth (by default) */
+     
+       if (snd_wavefront_cmd (dev, WFC_MISYNTH_ON, rbuf, wbuf)) {
+-              snd_printk ("can't enable MIDI-IN-2-synth routing.\n");
++              dev_warn(card->wavefront.card->dev,
++                       "can't enable MIDI-IN-2-synth routing.\n");
+               /* XXX error ? */
+       }
+@@ -549,14 +552,16 @@ snd_wavefront_midi_start (snd_wavefront_
+       */
+       if (snd_wavefront_cmd (dev, WFC_VMIDI_OFF, rbuf, wbuf)) { 
+-              snd_printk ("virtual MIDI mode not disabled\n");
++              dev_warn(card->wavefront.card->dev,
++                       "virtual MIDI mode not disabled\n");
+               return 0; /* We're OK, but missing the external MIDI dev */
+       }
+       snd_wavefront_midi_enable_virtual (card);
+       if (snd_wavefront_cmd (dev, WFC_VMIDI_ON, rbuf, wbuf)) {
+-              snd_printk ("cannot enable virtual MIDI mode.\n");
++              dev_warn(card->wavefront.card->dev,
++                       "cannot enable virtual MIDI mode.\n");
+               snd_wavefront_midi_disable_virtual (card);
+       } 
+       return 0;
+--- a/sound/isa/wavefront/wavefront_synth.c
++++ b/sound/isa/wavefront/wavefront_synth.c
+@@ -116,7 +116,7 @@ MODULE_PARM_DESC(osrun_time, "how many s
+ #define DPRINT(cond, ...) \
+        if ((dev->debug & (cond)) == (cond)) { \
+-           snd_printk (__VA_ARGS__); \
++           pr_debug(__VA_ARGS__); \
+        }
+ #else
+ #define DPRINT(cond, args...)
+@@ -341,7 +341,7 @@ snd_wavefront_cmd (snd_wavefront_t *dev,
+       wfcmd = wavefront_get_command(cmd);
+       if (!wfcmd) {
+-              snd_printk ("command 0x%x not supported.\n",
++              dev_err(dev->card->dev, "command 0x%x not supported.\n",
+                       cmd);
+               return 1;
+       }
+@@ -625,7 +625,7 @@ wavefront_get_sample_status (snd_wavefro
+       /* check sample status */
+     
+       if (snd_wavefront_cmd (dev, WFC_GET_NSAMPLES, rbuf, wbuf)) {
+-              snd_printk ("cannot request sample count.\n");
++              dev_err(dev->card->dev, "cannot request sample count.\n");
+               return -1;
+       } 
+     
+@@ -637,8 +637,8 @@ wavefront_get_sample_status (snd_wavefro
+               wbuf[1] = i >> 7;
+               if (snd_wavefront_cmd (dev, WFC_IDENTIFY_SAMPLE_TYPE, rbuf, wbuf)) {
+-                      snd_printk(KERN_WARNING "cannot identify sample "
+-                                 "type of slot %d\n", i);
++                      dev_warn(dev->card->dev,
++                               "cannot identify sample type of slot %d\n", i);
+                       dev->sample_status[i] = WF_ST_EMPTY;
+                       continue;
+               }
+@@ -663,9 +663,9 @@ wavefront_get_sample_status (snd_wavefro
+                       break;
+               default:
+-                      snd_printk ("unknown sample type for "
+-                                  "slot %d (0x%x)\n", 
+-                                  i, rbuf[0]);
++                      dev_err(dev->card->dev,
++                              "unknown sample type for slot %d (0x%x)\n",
++                              i, rbuf[0]);
+               }
+               if (rbuf[0] != WF_ST_EMPTY) {
+@@ -673,9 +673,10 @@ wavefront_get_sample_status (snd_wavefro
+               } 
+       }
+-      snd_printk ("%d samples used (%d real, %d aliases, %d multi), "
+-                  "%d empty\n", dev->samples_used, sc_real, sc_alias, sc_multi,
+-                  WF_MAX_SAMPLE - dev->samples_used);
++      dev_info(dev->card->dev,
++               "%d samples used (%d real, %d aliases, %d multi), %d empty\n",
++               dev->samples_used, sc_real, sc_alias, sc_multi,
++               WF_MAX_SAMPLE - dev->samples_used);
+       return (0);
+@@ -708,8 +709,8 @@ wavefront_get_patch_status (snd_wavefron
+               } else if (x == 3) { /* Bad patch number */
+                       dev->patch_status[i] = 0;
+               } else {
+-                      snd_printk ("upload patch "
+-                                  "error 0x%x\n", x);
++                      dev_err(dev->card->dev,
++                              "upload patch error 0x%x\n", x);
+                       dev->patch_status[i] = 0;
+                       return 1;
+               }
+@@ -726,7 +727,8 @@ wavefront_get_patch_status (snd_wavefron
+               }
+       
+       }
+-      snd_printk ("%d patch slots filled, %d in use\n", cnt, cnt2);
++      dev_info(dev->card->dev, "%d patch slots filled, %d in use\n",
++               cnt, cnt2);
+       return (0);
+ }
+@@ -762,8 +764,8 @@ wavefront_get_program_status (snd_wavefr
+               } else if (x == 1) { /* Bad program number */
+                       dev->prog_status[i] = 0;
+               } else {
+-                      snd_printk ("upload program "
+-                                  "error 0x%x\n", x);
++                      dev_err(dev->card->dev,
++                              "upload program error 0x%x\n", x);
+                       dev->prog_status[i] = 0;
+               }
+       }
+@@ -774,7 +776,7 @@ wavefront_get_program_status (snd_wavefr
+               }
+       }
+-      snd_printk ("%d programs slots in use\n", cnt);
++      dev_info(dev->card->dev, "%d programs slots in use\n", cnt);
+       return (0);
+ }
+@@ -798,7 +800,7 @@ wavefront_send_patch (snd_wavefront_t *d
+       munge_buf ((unsigned char *)&header->hdr.p, bptr, WF_PATCH_BYTES);
+     
+       if (snd_wavefront_cmd (dev, WFC_DOWNLOAD_PATCH, NULL, buf)) {
+-              snd_printk ("download patch failed\n");
++              dev_err(dev->card->dev, "download patch failed\n");
+               return -EIO;
+       }
+@@ -839,7 +841,7 @@ wavefront_send_program (snd_wavefront_t
+       munge_buf ((unsigned char *)&header->hdr.pr, &buf[1], WF_PROGRAM_BYTES);
+     
+       if (snd_wavefront_cmd (dev, WFC_DOWNLOAD_PROGRAM, NULL, buf)) {
+-              snd_printk ("download patch failed\n"); 
++              dev_err(dev->card->dev, "download patch failed\n");
+               return -EIO;
+       }
+@@ -853,7 +855,7 @@ wavefront_freemem (snd_wavefront_t *dev)
+       char rbuf[8];
+       if (snd_wavefront_cmd (dev, WFC_REPORT_FREE_MEMORY, rbuf, NULL)) {
+-              snd_printk ("can't get memory stats.\n");
++              dev_err(dev->card->dev, "can't get memory stats.\n");
+               return -1;
+       } else {
+               return demunge_int32 (rbuf, 4);
+@@ -903,7 +905,7 @@ wavefront_send_sample (snd_wavefront_t *
+               x = wavefront_find_free_sample(dev);
+               if (x < 0)
+                       return -ENOMEM;
+-              snd_printk ("unspecified sample => %d\n", x);
++              dev_info(dev->card->dev, "unspecified sample => %d\n", x);
+               header->number = x;
+       }
+@@ -937,9 +939,9 @@ wavefront_send_sample (snd_wavefront_t *
+               if (dev->rom_samples_rdonly) {
+                       if (dev->sample_status[header->number] & WF_SLOT_ROM) {
+-                              snd_printk ("sample slot %d "
+-                                          "write protected\n",
+-                                          header->number);
++                              dev_err(dev->card->dev,
++                                      "sample slot %d write protected\n",
++                                      header->number);
+                               return -EACCES;
+                       }
+               }
+@@ -951,9 +953,9 @@ wavefront_send_sample (snd_wavefront_t *
+               dev->freemem = wavefront_freemem (dev);
+               if (dev->freemem < (int)header->size) {
+-                      snd_printk ("insufficient memory to "
+-                                  "load %d byte sample.\n",
+-                                  header->size);
++                      dev_err(dev->card->dev,
++                              "insufficient memory to load %d byte sample.\n",
++                              header->size);
+                       return -ENOMEM;
+               }
+       
+@@ -962,8 +964,8 @@ wavefront_send_sample (snd_wavefront_t *
+       skip = WF_GET_CHANNEL(&header->hdr.s);
+       if (skip > 0 && header->hdr.s.SampleResolution != LINEAR_16BIT) {
+-              snd_printk ("channel selection only "
+-                          "possible on 16-bit samples");
++              dev_err(dev->card->dev,
++                      "channel selection only possible on 16-bit samples");
+               return -EINVAL;
+       }
+@@ -1059,8 +1061,8 @@ wavefront_send_sample (snd_wavefront_t *
+                          header->size ?
+                          WFC_DOWNLOAD_SAMPLE : WFC_DOWNLOAD_SAMPLE_HEADER,
+                          NULL, sample_hdr)) {
+-              snd_printk ("sample %sdownload refused.\n",
+-                          header->size ? "" : "header ");
++              dev_err(dev->card->dev, "sample %sdownload refused.\n",
++                      header->size ? "" : "header ");
+               return -EIO;
+       }
+@@ -1085,8 +1087,8 @@ wavefront_send_sample (snd_wavefront_t *
+               }
+               if (snd_wavefront_cmd (dev, WFC_DOWNLOAD_BLOCK, NULL, NULL)) {
+-                      snd_printk ("download block "
+-                                  "request refused.\n");
++                      dev_err(dev->card->dev,
++                              "download block request refused.\n");
+                       return -EIO;
+               }
+@@ -1147,13 +1149,13 @@ wavefront_send_sample (snd_wavefront_t *
+               dma_ack = wavefront_read(dev);
+               if (dma_ack != WF_DMA_ACK) {
+                       if (dma_ack == -1) {
+-                              snd_printk ("upload sample "
+-                                          "DMA ack timeout\n");
++                              dev_err(dev->card->dev,
++                                      "upload sample DMA ack timeout\n");
+                               return -EIO;
+                       } else {
+-                              snd_printk ("upload sample "
+-                                          "DMA ack error 0x%x\n",
+-                                          dma_ack);
++                              dev_err(dev->card->dev,
++                                      "upload sample DMA ack error 0x%x\n",
++                                      dma_ack);
+                               return -EIO;
+                       }
+               }
+@@ -1197,7 +1199,7 @@ wavefront_send_alias (snd_wavefront_t *d
+       munge_int32 (*(&header->hdr.a.FrequencyBias+1), &alias_hdr[23], 2);
+       if (snd_wavefront_cmd (dev, WFC_DOWNLOAD_SAMPLE_ALIAS, NULL, alias_hdr)) {
+-              snd_printk ("download alias failed.\n");
++              dev_err(dev->card->dev, "download alias failed.\n");
+               return -EIO;
+       }
+@@ -1250,7 +1252,7 @@ wavefront_send_multisample (snd_wavefron
+       if (snd_wavefront_cmd (dev, WFC_DOWNLOAD_MULTISAMPLE, 
+                          (unsigned char *) (long) ((num_samples*2)+3),
+                          msample_hdr)) {
+-              snd_printk ("download of multisample failed.\n");
++              dev_err(dev->card->dev, "download of multisample failed.\n");
+               kfree(msample_hdr);
+               return -EIO;
+       }
+@@ -1273,7 +1275,7 @@ wavefront_fetch_multisample (snd_wavefro
+       munge_int32 (header->number, number, 2);
+     
+       if (snd_wavefront_cmd (dev, WFC_UPLOAD_MULTISAMPLE, log_ns, number)) {
+-              snd_printk ("upload multisample failed.\n");
++              dev_err(dev->card->dev, "upload multisample failed.\n");
+               return -EIO;
+       }
+     
+@@ -1292,16 +1294,16 @@ wavefront_fetch_multisample (snd_wavefro
+       
+               val = wavefront_read(dev);
+               if (val == -1) {
+-                      snd_printk ("upload multisample failed "
+-                                  "during sample loop.\n");
++                      dev_err(dev->card->dev,
++                              "upload multisample failed during sample loop.\n");
+                       return -EIO;
+               }
+               d[0] = val;
+               val = wavefront_read(dev);
+               if (val == -1) {
+-                      snd_printk ("upload multisample failed "
+-                                  "during sample loop.\n");
++                      dev_err(dev->card->dev,
++                              "upload multisample failed during sample loop.\n");
+                       return -EIO;
+               }
+               d[1] = val;
+@@ -1336,7 +1338,7 @@ wavefront_send_drum (snd_wavefront_t *de
+       }
+       if (snd_wavefront_cmd (dev, WFC_DOWNLOAD_EDRUM_PROGRAM, NULL, drumbuf)) {
+-              snd_printk ("download drum failed.\n");
++              dev_err(dev->card->dev, "download drum failed.\n");
+               return -EIO;
+       }
+@@ -1354,7 +1356,7 @@ wavefront_find_free_sample (snd_wavefron
+                       return i;
+               }
+       }
+-      snd_printk ("no free sample slots!\n");
++      dev_err(dev->card->dev, "no free sample slots!\n");
+       return -1;
+ }
+@@ -1370,7 +1372,7 @@ wavefront_find_free_patch (snd_wavefront
+                       return i;
+               }
+       }
+-      snd_printk ("no free patch slots!\n");
++      dev_err(dev->card->dev, "no free patch slots!\n");
+       return -1;
+ }
+ #endif
+@@ -1387,7 +1389,7 @@ wavefront_load_patch (snd_wavefront_t *d
+       if (copy_from_user (header, addr, sizeof(wavefront_patch_info) -
+                           sizeof(wavefront_any))) {
+-              snd_printk ("bad address for load patch.\n");
++              dev_err(dev->card->dev, "bad address for load patch.\n");
+               err = -EFAULT;
+               goto __error;
+       }
+@@ -1465,8 +1467,8 @@ wavefront_load_patch (snd_wavefront_t *d
+               break;
+       default:
+-              snd_printk ("unknown patch type %d.\n",
+-                          header->subkey);
++              dev_err(dev->card->dev, "unknown patch type %d.\n",
++                      header->subkey);
+               err = -EINVAL;
+               break;
+       }
+@@ -1529,13 +1531,13 @@ wavefront_synth_control (snd_wavefront_c
+       switch (wc->cmd) {
+               
+       case WFC_DISABLE_INTERRUPTS:
+-              snd_printk ("interrupts disabled.\n");
++              dev_dbg(dev->card->dev, "interrupts disabled.\n");
+               outb (0x80|0x20, dev->control_port);
+               dev->interrupts_are_midi = 1;
+               return 0;
+       case WFC_ENABLE_INTERRUPTS:
+-              snd_printk ("interrupts enabled.\n");
++              dev_dbg(dev->card->dev, "interrupts enabled.\n");
+               outb (0x80|0x40|0x20, dev->control_port);
+               dev->interrupts_are_midi = 1;
+               return 0;
+@@ -1552,7 +1554,7 @@ wavefront_synth_control (snd_wavefront_c
+       case WFC_IDENTIFY_SLOT_TYPE:
+               i = wc->wbuf[0] | (wc->wbuf[1] << 7);
+               if (i <0 || i >= WF_MAX_SAMPLE) {
+-                      snd_printk ("invalid slot ID %d\n",
++                      dev_err(dev->card->dev, "invalid slot ID %d\n",
+                               i);
+                       wc->status = EINVAL;
+                       return -EINVAL;
+@@ -1563,7 +1565,7 @@ wavefront_synth_control (snd_wavefront_c
+       case WFC_DEBUG_DRIVER:
+               dev->debug = wc->wbuf[0];
+-              snd_printk ("debug = 0x%x\n", dev->debug);
++              dev_dbg(dev->card->dev, "debug = 0x%x\n", dev->debug);
+               return 0;
+       case WFC_UPLOAD_PATCH:
+@@ -1580,8 +1582,8 @@ wavefront_synth_control (snd_wavefront_c
+               return 0;
+       case WFC_UPLOAD_SAMPLE_ALIAS:
+-              snd_printk ("support for sample alias upload "
+-                      "being considered.\n");
++              dev_err(dev->card->dev,
++                      "support for sample alias upload being considered.\n");
+               wc->status = EINVAL;
+               return -EINVAL;
+       }
+@@ -1622,9 +1624,8 @@ wavefront_synth_control (snd_wavefront_c
+                       break;
+               case WFC_UPLOAD_SAMPLE_ALIAS:
+-                      snd_printk ("support for "
+-                                  "sample aliases still "
+-                                  "being considered.\n");
++                      dev_err(dev->card->dev,
++                              "support for sample aliases still being considered.\n");
+                       break;
+               case WFC_VMIDI_OFF:
+@@ -1762,7 +1763,7 @@ snd_wavefront_internal_interrupt (snd_wa
+ */
+ static int
+-snd_wavefront_interrupt_bits (int irq)
++snd_wavefront_interrupt_bits(snd_wavefront_t *dev, int irq)
+ {
+       int bits;
+@@ -1782,7 +1783,7 @@ snd_wavefront_interrupt_bits (int irq)
+               break;
+       
+       default:
+-              snd_printk ("invalid IRQ %d\n", irq);
++              dev_err(dev->card->dev, "invalid IRQ %d\n", irq);
+               bits = -1;
+       }
+@@ -1817,7 +1818,7 @@ wavefront_reset_to_cleanliness (snd_wave
+       /* IRQ already checked */
+-      bits = snd_wavefront_interrupt_bits (dev->irq);
++      bits = snd_wavefront_interrupt_bits(dev, dev->irq);
+       /* try reset of port */
+@@ -1887,7 +1888,7 @@ wavefront_reset_to_cleanliness (snd_wave
+        */
+       if (!dev->irq_ok) {
+-              snd_printk ("intr not received after h/w un-reset.\n");
++              dev_err(dev->card->dev, "intr not received after h/w un-reset.\n");
+               goto gone_bad;
+       } 
+@@ -1911,18 +1912,18 @@ wavefront_reset_to_cleanliness (snd_wave
+                                        dev->data_port, ramcheck_time*HZ);
+       if (!dev->irq_ok) {
+-              snd_printk ("post-RAM-check interrupt not received.\n");
++              dev_err(dev->card->dev, "post-RAM-check interrupt not received.\n");
+               goto gone_bad;
+       } 
+       if (!wavefront_wait (dev, STAT_CAN_READ)) {
+-              snd_printk ("no response to HW version cmd.\n");
++              dev_err(dev->card->dev, "no response to HW version cmd.\n");
+               goto gone_bad;
+       }
+       
+       hwv[0] = wavefront_read(dev);
+       if (hwv[0] == -1) {
+-              snd_printk ("board not responding correctly.\n");
++              dev_err(dev->card->dev, "board not responding correctly.\n");
+               goto gone_bad;
+       }
+@@ -1934,11 +1935,11 @@ wavefront_reset_to_cleanliness (snd_wave
+               
+               hwv[0] = wavefront_read(dev);
+               if (hwv[0] == -1) {
+-                      snd_printk ("on-board RAM test failed "
+-                                  "(bad error code).\n");
++                      dev_err(dev->card->dev,
++                              "on-board RAM test failed (bad error code).\n");
+               } else {
+-                      snd_printk ("on-board RAM test failed "
+-                                  "(error code: 0x%x).\n",
++                      dev_err(dev->card->dev,
++                              "on-board RAM test failed (error code: 0x%x).\n",
+                               hwv[0]);
+               }
+               goto gone_bad;
+@@ -1948,12 +1949,12 @@ wavefront_reset_to_cleanliness (snd_wave
+       hwv[1] = wavefront_read(dev);
+       if (hwv[1] == -1) {
+-              snd_printk ("incorrect h/w response.\n");
++              dev_err(dev->card->dev, "incorrect h/w response.\n");
+               goto gone_bad;
+       }
+-      snd_printk ("hardware version %d.%d\n",
+-                  hwv[0], hwv[1]);
++      dev_info(dev->card->dev, "hardware version %d.%d\n",
++               hwv[0], hwv[1]);
+       return 0;
+@@ -1973,7 +1974,7 @@ wavefront_download_firmware (snd_wavefro
+       err = request_firmware(&firmware, path, dev->card->dev);
+       if (err < 0) {
+-              snd_printk(KERN_ERR "firmware (%s) download failed!!!\n", path);
++              dev_err(dev->card->dev, "firmware (%s) download failed!!!\n", path);
+               return 1;
+       }
+@@ -1984,16 +1985,16 @@ wavefront_download_firmware (snd_wavefro
+               if (section_length == 0)
+                       break;
+               if (section_length < 0 || section_length > WF_SECTION_MAX) {
+-                      snd_printk(KERN_ERR
+-                                 "invalid firmware section length %d\n",
+-                                 section_length);
++                      dev_err(dev->card->dev,
++                              "invalid firmware section length %d\n",
++                              section_length);
+                       goto failure;
+               }
+               buf++;
+               len++;
+               if (firmware->size < len + section_length) {
+-                      snd_printk(KERN_ERR "firmware section read error.\n");
++                      dev_err(dev->card->dev, "firmware section read error.\n");
+                       goto failure;
+               }
+@@ -2010,15 +2011,14 @@ wavefront_download_firmware (snd_wavefro
+       
+               /* get ACK */
+               if (!wavefront_wait(dev, STAT_CAN_READ)) {
+-                      snd_printk(KERN_ERR "time out for firmware ACK.\n");
++                      dev_err(dev->card->dev, "time out for firmware ACK.\n");
+                       goto failure;
+               }
+               err = inb(dev->data_port);
+               if (err != WF_ACK) {
+-                      snd_printk(KERN_ERR
+-                                 "download of section #%d not "
+-                                 "acknowledged, ack = 0x%x\n",
+-                                 section_cnt_downloaded + 1, err);
++                      dev_err(dev->card->dev,
++                              "download of section #%d not acknowledged, ack = 0x%x\n",
++                              section_cnt_downloaded + 1, err);
+                       goto failure;
+               }
+@@ -2030,7 +2030,7 @@ wavefront_download_firmware (snd_wavefro
+  failure:
+       release_firmware(firmware);
+-      snd_printk(KERN_ERR "firmware download failed!!!\n");
++      dev_err(dev->card->dev, "firmware download failed!!!\n");
+       return 1;
+ }
+@@ -2042,7 +2042,7 @@ wavefront_do_reset (snd_wavefront_t *dev
+       char voices[1];
+       if (wavefront_reset_to_cleanliness (dev)) {
+-              snd_printk ("hw reset failed.\n");
++              dev_err(dev->card->dev, "hw reset failed.\n");
+               goto gone_bad;
+       }
+@@ -2066,7 +2066,7 @@ wavefront_do_reset (snd_wavefront_t *dev
+                                                 (osrun_time*HZ));
+               if (!dev->irq_ok) {
+-                      snd_printk ("no post-OS interrupt.\n");
++                      dev_err(dev->card->dev, "no post-OS interrupt.\n");
+                       goto gone_bad;
+               }
+               
+@@ -2076,7 +2076,7 @@ wavefront_do_reset (snd_wavefront_t *dev
+                                                 dev->data_port, (10*HZ));
+               
+               if (!dev->irq_ok) {
+-                      snd_printk ("no post-OS interrupt(2).\n");
++                      dev_err(dev->card->dev, "no post-OS interrupt(2).\n");
+                       goto gone_bad;
+               }
+@@ -2096,20 +2096,20 @@ wavefront_do_reset (snd_wavefront_t *dev
+       if (dev->freemem < 0)
+               goto gone_bad;
+               
+-      snd_printk ("available DRAM %dk\n", dev->freemem / 1024);
++      dev_info(dev->card->dev, "available DRAM %dk\n", dev->freemem / 1024);
+       if (wavefront_write (dev, 0xf0) ||
+           wavefront_write (dev, 1) ||
+           (wavefront_read (dev) < 0)) {
+               dev->debug = 0;
+-              snd_printk ("MPU emulation mode not set.\n");
++              dev_err(dev->card->dev, "MPU emulation mode not set.\n");
+               goto gone_bad;
+       }
+       voices[0] = 32;
+       if (snd_wavefront_cmd (dev, WFC_SET_NVOICES, NULL, voices)) {
+-              snd_printk ("cannot set number of voices to 32.\n");
++              dev_err(dev->card->dev, "cannot set number of voices to 32.\n");
+               goto gone_bad;
+       }
+@@ -2189,8 +2189,8 @@ snd_wavefront_detect (snd_wavefront_card
+               dev->fw_version[0] = rbuf[0];
+               dev->fw_version[1] = rbuf[1];
+-              snd_printk ("firmware %d.%d already loaded.\n",
+-                          rbuf[0], rbuf[1]);
++              dev_info(dev->card->dev, "firmware %d.%d already loaded.\n",
++                       rbuf[0], rbuf[1]);
+               /* check that a command actually works */
+       
+@@ -2199,22 +2199,24 @@ snd_wavefront_detect (snd_wavefront_card
+                       dev->hw_version[0] = rbuf[0];
+                       dev->hw_version[1] = rbuf[1];
+               } else {
+-                      snd_printk ("not raw, but no "
+-                                  "hardware version!\n");
++                      dev_err(dev->card->dev,
++                              "not raw, but no hardware version!\n");
+                       return -1;
+               }
+               if (!wf_raw) {
+                       return 0;
+               } else {
+-                      snd_printk ("reloading firmware as you requested.\n");
++                      dev_info(dev->card->dev,
++                               "reloading firmware as you requested.\n");
+                       dev->israw = 1;
+               }
+       } else {
+               dev->israw = 1;
+-              snd_printk ("no response to firmware probe, assume raw.\n");
++              dev_info(dev->card->dev,
++                       "no response to firmware probe, assume raw.\n");
+       }
diff --git a/queue-5.15/arm-dts-microchip-sama5d2-fix-spi-flexcom-fifo-size-to-32.patch b/queue-5.15/arm-dts-microchip-sama5d2-fix-spi-flexcom-fifo-size-to-32.patch
new file mode 100644 (file)
index 0000000..13d4bcc
--- /dev/null
@@ -0,0 +1,73 @@
+From stable+bounces-204391-greg=kroah.com@vger.kernel.org Wed Dec 31 22:21:02 2025
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 31 Dec 2025 16:20:57 -0500
+Subject: ARM: dts: microchip: sama5d2: fix spi flexcom fifo size to 32
+To: stable@vger.kernel.org
+Cc: Nicolas Ferre <nicolas.ferre@microchip.com>, Claudiu Beznea <claudiu.beznea@tuxon.dev>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20251231212057.3505425-1-sashal@kernel.org>
+
+From: Nicolas Ferre <nicolas.ferre@microchip.com>
+
+[ Upstream commit 7d5864dc5d5ea6a35983dd05295fb17f2f2f44ce ]
+
+Unlike standalone spi peripherals, on sama5d2, the flexcom spi have fifo
+size of 32 data. Fix flexcom/spi nodes where this property is wrong.
+
+Fixes: 6b9a3584c7ed ("ARM: dts: at91: sama5d2: Add missing flexcom definitions")
+Cc: stable@vger.kernel.org # 5.8+
+Signed-off-by: Nicolas Ferre <nicolas.ferre@microchip.com>
+Link: https://lore.kernel.org/r/20251114140225.30372-1-nicolas.ferre@microchip.com
+Signed-off-by: Claudiu Beznea <claudiu.beznea@tuxon.dev>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/arm/boot/dts/sama5d2.dtsi |   10 +++++-----
+ 1 file changed, 5 insertions(+), 5 deletions(-)
+
+--- a/arch/arm/boot/dts/sama5d2.dtsi
++++ b/arch/arm/boot/dts/sama5d2.dtsi
+@@ -555,7 +555,7 @@
+                                                AT91_XDMAC_DT_PER_IF(1) |
+                                                AT91_XDMAC_DT_PERID(12))>;
+                                       dma-names = "tx", "rx";
+-                                      atmel,fifo-size = <16>;
++                                      atmel,fifo-size = <32>;
+                                       status = "disabled";
+                               };
+@@ -625,7 +625,7 @@
+                                                AT91_XDMAC_DT_PER_IF(1) |
+                                                AT91_XDMAC_DT_PERID(14))>;
+                                       dma-names = "tx", "rx";
+-                                      atmel,fifo-size = <16>;
++                                      atmel,fifo-size = <32>;
+                                       status = "disabled";
+                               };
+@@ -835,7 +835,7 @@
+                                                AT91_XDMAC_DT_PER_IF(1) |
+                                                AT91_XDMAC_DT_PERID(16))>;
+                                       dma-names = "tx", "rx";
+-                                      atmel,fifo-size = <16>;
++                                      atmel,fifo-size = <32>;
+                                       status = "disabled";
+                               };
+@@ -925,7 +925,7 @@
+                                                AT91_XDMAC_DT_PER_IF(1) |
+                                                AT91_XDMAC_DT_PERID(18))>;
+                                       dma-names = "tx", "rx";
+-                                      atmel,fifo-size = <16>;
++                                      atmel,fifo-size = <32>;
+                                       status = "disabled";
+                               };
+@@ -976,7 +976,7 @@
+                                                AT91_XDMAC_DT_PER_IF(1) |
+                                                AT91_XDMAC_DT_PERID(20))>;
+                                       dma-names = "tx", "rx";
+-                                      atmel,fifo-size = <16>;
++                                      atmel,fifo-size = <32>;
+                                       status = "disabled";
+                               };
diff --git a/queue-5.15/arm-dts-microchip-sama7g5-fix-uart-fifo-size-to-32.patch b/queue-5.15/arm-dts-microchip-sama7g5-fix-uart-fifo-size-to-32.patch
new file mode 100644 (file)
index 0000000..bcf508b
--- /dev/null
@@ -0,0 +1,46 @@
+From stable+bounces-204398-greg=kroah.com@vger.kernel.org Wed Dec 31 23:44:37 2025
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 31 Dec 2025 17:44:27 -0500
+Subject: ARM: dts: microchip: sama7g5: fix uart fifo size to 32
+To: stable@vger.kernel.org
+Cc: Nicolas Ferre <nicolas.ferre@microchip.com>, Claudiu Beznea <claudiu.beznea@tuxon.dev>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20251231224427.3631376-1-sashal@kernel.org>
+
+From: Nicolas Ferre <nicolas.ferre@microchip.com>
+
+[ Upstream commit 5654889a94b0de5ad6ceae3793e7f5e0b61b50b6 ]
+
+On some flexcom nodes related to uart, the fifo sizes were wrong: fix
+them to 32 data.
+
+Fixes: 7540629e2fc7 ("ARM: dts: at91: add sama7g5 SoC DT and sama7g5-ek")
+Cc: stable@vger.kernel.org # 5.15+
+Signed-off-by: Nicolas Ferre <nicolas.ferre@microchip.com>
+Link: https://lore.kernel.org/r/20251114103313.20220-2-nicolas.ferre@microchip.com
+Signed-off-by: Claudiu Beznea <claudiu.beznea@tuxon.dev>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/arm/boot/dts/sama7g5.dtsi |    4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+--- a/arch/arm/boot/dts/sama7g5.dtsi
++++ b/arch/arm/boot/dts/sama7g5.dtsi
+@@ -375,7 +375,7 @@
+                               dma-names = "tx", "rx";
+                               atmel,use-dma-rx;
+                               atmel,use-dma-tx;
+-                              atmel,fifo-size = <16>;
++                              atmel,fifo-size = <32>;
+                               status = "disabled";
+                       };
+               };
+@@ -400,7 +400,7 @@
+                               dma-names = "tx", "rx";
+                               atmel,use-dma-rx;
+                               atmel,use-dma-tx;
+-                              atmel,fifo-size = <16>;
++                              atmel,fifo-size = <32>;
+                               status = "disabled";
+                       };
+               };
diff --git a/queue-5.15/asoc-stm-stm32_sai_sub-convert-to-platform-remove-callback-returning-void.patch b/queue-5.15/asoc-stm-stm32_sai_sub-convert-to-platform-remove-callback-returning-void.patch
new file mode 100644 (file)
index 0000000..2800069
--- /dev/null
@@ -0,0 +1,64 @@
+From stable+bounces-204830-greg=kroah.com@vger.kernel.org Mon Jan  5 16:12:47 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon,  5 Jan 2026 10:10:29 -0500
+Subject: ASoC: stm: stm32_sai_sub: Convert to platform remove callback returning void
+To: stable@vger.kernel.org
+Cc: "Uwe Kleine-König" <u.kleine-koenig@pengutronix.de>, "Takashi Iwai" <tiwai@suse.de>, "Nicolas Ferre" <nicolas.ferre@microchip.com>, "Mark Brown" <broonie@kernel.org>, "Sasha Levin" <sashal@kernel.org>
+Message-ID: <20260105151034.2625317-2-sashal@kernel.org>
+
+From: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
+
+[ Upstream commit a3bd37e2e2bce4fb1757a940fa985d556662ba80 ]
+
+The .remove() callback for a platform driver returns an int which makes
+many driver authors wrongly assume it's possible to do error handling by
+returning an error code. However the value returned is (mostly) ignored
+and this typically results in resource leaks. To improve here there is a
+quest to make the remove callback return void. In the first step of this
+quest all drivers are converted to .remove_new() which already returns
+void.
+
+Trivially convert this driver from always returning zero in the remove
+callback to the void returning variant.
+
+Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
+Acked-by: Takashi Iwai <tiwai@suse.de>
+Acked-by: Nicolas Ferre <nicolas.ferre@microchip.com>
+Link: https://lore.kernel.org/r/20230315150745.67084-139-u.kleine-koenig@pengutronix.de
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Stable-dep-of: 23261f0de094 ("ASoC: stm32: sai: fix OF node leak on probe")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ sound/soc/stm/stm32_sai_sub.c |    6 ++----
+ 1 file changed, 2 insertions(+), 4 deletions(-)
+
+--- a/sound/soc/stm/stm32_sai_sub.c
++++ b/sound/soc/stm/stm32_sai_sub.c
+@@ -1571,7 +1571,7 @@ err_unprepare_pclk:
+       return ret;
+ }
+-static int stm32_sai_sub_remove(struct platform_device *pdev)
++static void stm32_sai_sub_remove(struct platform_device *pdev)
+ {
+       struct stm32_sai_sub_data *sai = dev_get_drvdata(&pdev->dev);
+@@ -1579,8 +1579,6 @@ static int stm32_sai_sub_remove(struct p
+       snd_dmaengine_pcm_unregister(&pdev->dev);
+       snd_soc_unregister_component(&pdev->dev);
+       pm_runtime_disable(&pdev->dev);
+-
+-      return 0;
+ }
+ #ifdef CONFIG_PM_SLEEP
+@@ -1630,7 +1628,7 @@ static struct platform_driver stm32_sai_
+               .pm = &stm32_sai_sub_pm_ops,
+       },
+       .probe = stm32_sai_sub_probe,
+-      .remove = stm32_sai_sub_remove,
++      .remove_new = stm32_sai_sub_remove,
+ };
+ module_platform_driver(stm32_sai_sub_driver);
diff --git a/queue-5.15/asoc-stm-use-dev_err_probe-helper.patch b/queue-5.15/asoc-stm-use-dev_err_probe-helper.patch
new file mode 100644 (file)
index 0000000..add8842
--- /dev/null
@@ -0,0 +1,307 @@
+From stable+bounces-204809-greg=kroah.com@vger.kernel.org Mon Jan  5 15:31:23 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon,  5 Jan 2026 09:27:26 -0500
+Subject: ASoC: stm: Use dev_err_probe() helper
+To: stable@vger.kernel.org
+Cc: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>, Mark Brown <broonie@kernel.org>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260105142728.2602716-1-sashal@kernel.org>
+
+From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
+
+[ Upstream commit efc162cbd480f1fb47d439c193ec9731bcc6c749 ]
+
+Use the dev_err_probe() helper, instead of open-coding the same
+operation.
+
+Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
+Link: https://lore.kernel.org/r/20211214020843.2225831-22-kuninori.morimoto.gx@renesas.com
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Stable-dep-of: 312ec2f0d9d1 ("ASoC: stm32: sai: fix clk prepare imbalance on probe failure")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ sound/soc/stm/stm32_i2s.c     |   62 ++++++++++++++----------------------------
+ sound/soc/stm/stm32_sai.c     |   37 ++++++++-----------------
+ sound/soc/stm/stm32_sai_sub.c |   25 +++++-----------
+ sound/soc/stm/stm32_spdifrx.c |   44 ++++++++++-------------------
+ 4 files changed, 57 insertions(+), 111 deletions(-)
+
+--- a/sound/soc/stm/stm32_i2s.c
++++ b/sound/soc/stm/stm32_i2s.c
+@@ -1044,36 +1044,24 @@ static int stm32_i2s_parse_dt(struct pla
+       /* Get clocks */
+       i2s->pclk = devm_clk_get(&pdev->dev, "pclk");
+-      if (IS_ERR(i2s->pclk)) {
+-              if (PTR_ERR(i2s->pclk) != -EPROBE_DEFER)
+-                      dev_err(&pdev->dev, "Could not get pclk: %ld\n",
+-                              PTR_ERR(i2s->pclk));
+-              return PTR_ERR(i2s->pclk);
+-      }
++      if (IS_ERR(i2s->pclk))
++              return dev_err_probe(&pdev->dev, PTR_ERR(i2s->pclk),
++                                   "Could not get pclk\n");
+       i2s->i2sclk = devm_clk_get(&pdev->dev, "i2sclk");
+-      if (IS_ERR(i2s->i2sclk)) {
+-              if (PTR_ERR(i2s->i2sclk) != -EPROBE_DEFER)
+-                      dev_err(&pdev->dev, "Could not get i2sclk: %ld\n",
+-                              PTR_ERR(i2s->i2sclk));
+-              return PTR_ERR(i2s->i2sclk);
+-      }
++      if (IS_ERR(i2s->i2sclk))
++              return dev_err_probe(&pdev->dev, PTR_ERR(i2s->i2sclk),
++                                   "Could not get i2sclk\n");
+       i2s->x8kclk = devm_clk_get(&pdev->dev, "x8k");
+-      if (IS_ERR(i2s->x8kclk)) {
+-              if (PTR_ERR(i2s->x8kclk) != -EPROBE_DEFER)
+-                      dev_err(&pdev->dev, "Could not get x8k parent clock: %ld\n",
+-                              PTR_ERR(i2s->x8kclk));
+-              return PTR_ERR(i2s->x8kclk);
+-      }
++      if (IS_ERR(i2s->x8kclk))
++              return dev_err_probe(&pdev->dev, PTR_ERR(i2s->x8kclk),
++                                   "Could not get x8k parent clock\n");
+       i2s->x11kclk = devm_clk_get(&pdev->dev, "x11k");
+-      if (IS_ERR(i2s->x11kclk)) {
+-              if (PTR_ERR(i2s->x11kclk) != -EPROBE_DEFER)
+-                      dev_err(&pdev->dev, "Could not get x11k parent clock: %ld\n",
+-                              PTR_ERR(i2s->x11kclk));
+-              return PTR_ERR(i2s->x11kclk);
+-      }
++      if (IS_ERR(i2s->x11kclk))
++              return dev_err_probe(&pdev->dev, PTR_ERR(i2s->x11kclk),
++                                   "Could not get x11k parent clock\n");
+       /* Register mclk provider if requested */
+       if (of_find_property(np, "#clock-cells", NULL)) {
+@@ -1096,12 +1084,10 @@ static int stm32_i2s_parse_dt(struct pla
+       /* Reset */
+       rst = devm_reset_control_get_optional_exclusive(&pdev->dev, NULL);
+-      if (IS_ERR(rst)) {
+-              if (PTR_ERR(rst) != -EPROBE_DEFER)
+-                      dev_err(&pdev->dev, "Reset controller error %ld\n",
+-                              PTR_ERR(rst));
+-              return PTR_ERR(rst);
+-      }
++      if (IS_ERR(rst))
++              return dev_err_probe(&pdev->dev, PTR_ERR(rst),
++                                   "Reset controller error\n");
++
+       reset_control_assert(rst);
+       udelay(2);
+       reset_control_deassert(rst);
+@@ -1143,19 +1129,13 @@ static int stm32_i2s_probe(struct platfo
+       i2s->regmap = devm_regmap_init_mmio_clk(&pdev->dev, "pclk",
+                                               i2s->base, i2s->regmap_conf);
+-      if (IS_ERR(i2s->regmap)) {
+-              if (PTR_ERR(i2s->regmap) != -EPROBE_DEFER)
+-                      dev_err(&pdev->dev, "Regmap init error %ld\n",
+-                              PTR_ERR(i2s->regmap));
+-              return PTR_ERR(i2s->regmap);
+-      }
++      if (IS_ERR(i2s->regmap))
++              return dev_err_probe(&pdev->dev, PTR_ERR(i2s->regmap),
++                                   "Regmap init error\n");
+       ret = snd_dmaengine_pcm_register(&pdev->dev, &stm32_i2s_pcm_config, 0);
+-      if (ret) {
+-              if (ret != -EPROBE_DEFER)
+-                      dev_err(&pdev->dev, "PCM DMA register error %d\n", ret);
+-              return ret;
+-      }
++      if (ret)
++              return dev_err_probe(&pdev->dev, ret, "PCM DMA register error\n");
+       ret = snd_soc_register_component(&pdev->dev, &stm32_i2s_component,
+                                        i2s->dai_drv, 1);
+--- a/sound/soc/stm/stm32_sai.c
++++ b/sound/soc/stm/stm32_sai.c
+@@ -173,29 +173,20 @@ static int stm32_sai_probe(struct platfo
+       if (!STM_SAI_IS_F4(sai)) {
+               sai->pclk = devm_clk_get(&pdev->dev, "pclk");
+-              if (IS_ERR(sai->pclk)) {
+-                      if (PTR_ERR(sai->pclk) != -EPROBE_DEFER)
+-                              dev_err(&pdev->dev, "missing bus clock pclk: %ld\n",
+-                                      PTR_ERR(sai->pclk));
+-                      return PTR_ERR(sai->pclk);
+-              }
++              if (IS_ERR(sai->pclk))
++                      return dev_err_probe(&pdev->dev, PTR_ERR(sai->pclk),
++                                           "missing bus clock pclk\n");
+       }
+       sai->clk_x8k = devm_clk_get(&pdev->dev, "x8k");
+-      if (IS_ERR(sai->clk_x8k)) {
+-              if (PTR_ERR(sai->clk_x8k) != -EPROBE_DEFER)
+-                      dev_err(&pdev->dev, "missing x8k parent clock: %ld\n",
+-                              PTR_ERR(sai->clk_x8k));
+-              return PTR_ERR(sai->clk_x8k);
+-      }
++      if (IS_ERR(sai->clk_x8k))
++              return dev_err_probe(&pdev->dev, PTR_ERR(sai->clk_x8k),
++                                   "missing x8k parent clock\n");
+       sai->clk_x11k = devm_clk_get(&pdev->dev, "x11k");
+-      if (IS_ERR(sai->clk_x11k)) {
+-              if (PTR_ERR(sai->clk_x11k) != -EPROBE_DEFER)
+-                      dev_err(&pdev->dev, "missing x11k parent clock: %ld\n",
+-                              PTR_ERR(sai->clk_x11k));
+-              return PTR_ERR(sai->clk_x11k);
+-      }
++      if (IS_ERR(sai->clk_x11k))
++              return dev_err_probe(&pdev->dev, PTR_ERR(sai->clk_x11k),
++                                   "missing x11k parent clock\n");
+       /* init irqs */
+       sai->irq = platform_get_irq(pdev, 0);
+@@ -204,12 +195,10 @@ static int stm32_sai_probe(struct platfo
+       /* reset */
+       rst = devm_reset_control_get_optional_exclusive(&pdev->dev, NULL);
+-      if (IS_ERR(rst)) {
+-              if (PTR_ERR(rst) != -EPROBE_DEFER)
+-                      dev_err(&pdev->dev, "Reset controller error %ld\n",
+-                              PTR_ERR(rst));
+-              return PTR_ERR(rst);
+-      }
++      if (IS_ERR(rst))
++              return dev_err_probe(&pdev->dev, PTR_ERR(rst),
++                                   "Reset controller error\n");
++
+       reset_control_assert(rst);
+       udelay(2);
+       reset_control_deassert(rst);
+--- a/sound/soc/stm/stm32_sai_sub.c
++++ b/sound/soc/stm/stm32_sai_sub.c
+@@ -1379,12 +1379,9 @@ static int stm32_sai_sub_parse_of(struct
+        */
+       sai->regmap = devm_regmap_init_mmio(&pdev->dev, base,
+                                           sai->regmap_config);
+-      if (IS_ERR(sai->regmap)) {
+-              if (PTR_ERR(sai->regmap) != -EPROBE_DEFER)
+-                      dev_err(&pdev->dev, "Regmap init error %ld\n",
+-                              PTR_ERR(sai->regmap));
+-              return PTR_ERR(sai->regmap);
+-      }
++      if (IS_ERR(sai->regmap))
++              return dev_err_probe(&pdev->dev, PTR_ERR(sai->regmap),
++                                   "Regmap init error\n");
+       /* Get direction property */
+       if (of_property_match_string(np, "dma-names", "tx") >= 0) {
+@@ -1472,12 +1469,9 @@ static int stm32_sai_sub_parse_of(struct
+       of_node_put(args.np);
+       sai->sai_ck = devm_clk_get(&pdev->dev, "sai_ck");
+-      if (IS_ERR(sai->sai_ck)) {
+-              if (PTR_ERR(sai->sai_ck) != -EPROBE_DEFER)
+-                      dev_err(&pdev->dev, "Missing kernel clock sai_ck: %ld\n",
+-                              PTR_ERR(sai->sai_ck));
+-              return PTR_ERR(sai->sai_ck);
+-      }
++      if (IS_ERR(sai->sai_ck))
++              return dev_err_probe(&pdev->dev, PTR_ERR(sai->sai_ck),
++                                   "Missing kernel clock sai_ck\n");
+       ret = clk_prepare(sai->pdata->pclk);
+       if (ret < 0)
+@@ -1551,11 +1545,8 @@ static int stm32_sai_sub_probe(struct pl
+               conf = &stm32_sai_pcm_config_spdif;
+       ret = snd_dmaengine_pcm_register(&pdev->dev, conf, 0);
+-      if (ret) {
+-              if (ret != -EPROBE_DEFER)
+-                      dev_err(&pdev->dev, "Could not register pcm dma\n");
+-              return ret;
+-      }
++      if (ret)
++              return dev_err_probe(&pdev->dev, ret, "Could not register pcm dma\n");
+       ret = snd_soc_register_component(&pdev->dev, &stm32_component,
+                                        &sai->cpu_dai_drv, 1);
+--- a/sound/soc/stm/stm32_spdifrx.c
++++ b/sound/soc/stm/stm32_spdifrx.c
+@@ -405,12 +405,9 @@ static int stm32_spdifrx_dma_ctrl_regist
+       int ret;
+       spdifrx->ctrl_chan = dma_request_chan(dev, "rx-ctrl");
+-      if (IS_ERR(spdifrx->ctrl_chan)) {
+-              if (PTR_ERR(spdifrx->ctrl_chan) != -EPROBE_DEFER)
+-                      dev_err(dev, "dma_request_slave_channel error %ld\n",
+-                              PTR_ERR(spdifrx->ctrl_chan));
+-              return PTR_ERR(spdifrx->ctrl_chan);
+-      }
++      if (IS_ERR(spdifrx->ctrl_chan))
++              return dev_err_probe(dev, PTR_ERR(spdifrx->ctrl_chan),
++                                   "dma_request_slave_channel error\n");
+       spdifrx->dmab = devm_kzalloc(dev, sizeof(struct snd_dma_buffer),
+                                    GFP_KERNEL);
+@@ -929,12 +926,9 @@ static int stm32_spdifrx_parse_of(struct
+       spdifrx->phys_addr = res->start;
+       spdifrx->kclk = devm_clk_get(&pdev->dev, "kclk");
+-      if (IS_ERR(spdifrx->kclk)) {
+-              if (PTR_ERR(spdifrx->kclk) != -EPROBE_DEFER)
+-                      dev_err(&pdev->dev, "Could not get kclk: %ld\n",
+-                              PTR_ERR(spdifrx->kclk));
+-              return PTR_ERR(spdifrx->kclk);
+-      }
++      if (IS_ERR(spdifrx->kclk))
++              return dev_err_probe(&pdev->dev, PTR_ERR(spdifrx->kclk),
++                                   "Could not get kclk\n");
+       spdifrx->irq = platform_get_irq(pdev, 0);
+       if (spdifrx->irq < 0)
+@@ -985,12 +979,9 @@ static int stm32_spdifrx_probe(struct pl
+       spdifrx->regmap = devm_regmap_init_mmio_clk(&pdev->dev, "kclk",
+                                                   spdifrx->base,
+                                                   spdifrx->regmap_conf);
+-      if (IS_ERR(spdifrx->regmap)) {
+-              if (PTR_ERR(spdifrx->regmap) != -EPROBE_DEFER)
+-                      dev_err(&pdev->dev, "Regmap init error %ld\n",
+-                              PTR_ERR(spdifrx->regmap));
+-              return PTR_ERR(spdifrx->regmap);
+-      }
++      if (IS_ERR(spdifrx->regmap))
++              return dev_err_probe(&pdev->dev, PTR_ERR(spdifrx->regmap),
++                                   "Regmap init error\n");
+       ret = devm_request_irq(&pdev->dev, spdifrx->irq, stm32_spdifrx_isr, 0,
+                              dev_name(&pdev->dev), spdifrx);
+@@ -1000,23 +991,18 @@ static int stm32_spdifrx_probe(struct pl
+       }
+       rst = devm_reset_control_get_optional_exclusive(&pdev->dev, NULL);
+-      if (IS_ERR(rst)) {
+-              if (PTR_ERR(rst) != -EPROBE_DEFER)
+-                      dev_err(&pdev->dev, "Reset controller error %ld\n",
+-                              PTR_ERR(rst));
+-              return PTR_ERR(rst);
+-      }
++      if (IS_ERR(rst))
++              return dev_err_probe(&pdev->dev, PTR_ERR(rst),
++                                   "Reset controller error\n");
++
+       reset_control_assert(rst);
+       udelay(2);
+       reset_control_deassert(rst);
+       pcm_config = &stm32_spdifrx_pcm_config;
+       ret = snd_dmaengine_pcm_register(&pdev->dev, pcm_config, 0);
+-      if (ret) {
+-              if (ret != -EPROBE_DEFER)
+-                      dev_err(&pdev->dev, "PCM DMA register error %d\n", ret);
+-              return ret;
+-      }
++      if (ret)
++              return dev_err_probe(&pdev->dev, ret, "PCM DMA register error\n");
+       ret = snd_soc_register_component(&pdev->dev,
+                                        &stm32_spdifrx_component,
diff --git a/queue-5.15/asoc-stm32-sai-fix-clk-prepare-imbalance-on-probe-failure.patch b/queue-5.15/asoc-stm32-sai-fix-clk-prepare-imbalance-on-probe-failure.patch
new file mode 100644 (file)
index 0000000..ba87c6f
--- /dev/null
@@ -0,0 +1,93 @@
+From stable+bounces-204810-greg=kroah.com@vger.kernel.org Mon Jan  5 15:32:00 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon,  5 Jan 2026 09:27:28 -0500
+Subject: ASoC: stm32: sai: fix clk prepare imbalance on probe failure
+To: stable@vger.kernel.org
+Cc: Johan Hovold <johan@kernel.org>, Olivier Moysan <olivier.moysan@st.com>, olivier moysan <olivier.moysan@foss.st.com>, Mark Brown <broonie@kernel.org>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260105142728.2602716-3-sashal@kernel.org>
+
+From: Johan Hovold <johan@kernel.org>
+
+[ Upstream commit 312ec2f0d9d1a5656f76d770bbf1d967e9289aa7 ]
+
+Make sure to unprepare the parent clock also on probe failures (e.g.
+probe deferral).
+
+Fixes: a14bf98c045b ("ASoC: stm32: sai: fix possible circular locking")
+Cc: stable@vger.kernel.org     # 5.5
+Cc: Olivier Moysan <olivier.moysan@st.com>
+Signed-off-by: Johan Hovold <johan@kernel.org>
+Reviewed-by: olivier moysan <olivier.moysan@foss.st.com>
+Link: https://patch.msgid.link/20251124104908.15754-3-johan@kernel.org
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ sound/soc/stm/stm32_sai_sub.c |   28 +++++++++++++++++++++-------
+ 1 file changed, 21 insertions(+), 7 deletions(-)
+
+--- a/sound/soc/stm/stm32_sai_sub.c
++++ b/sound/soc/stm/stm32_sai_sub.c
+@@ -1484,14 +1484,21 @@ static int stm32_sai_sub_parse_of(struct
+       if (of_find_property(np, "#clock-cells", NULL)) {
+               ret = stm32_sai_add_mclk_provider(sai);
+               if (ret < 0)
+-                      return ret;
++                      goto err_unprepare_pclk;
+       } else {
+               sai->sai_mclk = devm_clk_get_optional(&pdev->dev, "MCLK");
+-              if (IS_ERR(sai->sai_mclk))
+-                      return PTR_ERR(sai->sai_mclk);
++              if (IS_ERR(sai->sai_mclk)) {
++                      ret = PTR_ERR(sai->sai_mclk);
++                      goto err_unprepare_pclk;
++              }
+       }
+       return 0;
++
++err_unprepare_pclk:
++      clk_unprepare(sai->pdata->pclk);
++
++      return ret;
+ }
+ static int stm32_sai_sub_probe(struct platform_device *pdev)
+@@ -1535,26 +1542,33 @@ static int stm32_sai_sub_probe(struct pl
+                              IRQF_SHARED, dev_name(&pdev->dev), sai);
+       if (ret) {
+               dev_err(&pdev->dev, "IRQ request returned %d\n", ret);
+-              return ret;
++              goto err_unprepare_pclk;
+       }
+       if (STM_SAI_PROTOCOL_IS_SPDIF(sai))
+               conf = &stm32_sai_pcm_config_spdif;
+       ret = snd_dmaengine_pcm_register(&pdev->dev, conf, 0);
+-      if (ret)
+-              return dev_err_probe(&pdev->dev, ret, "Could not register pcm dma\n");
++      if (ret) {
++              ret = dev_err_probe(&pdev->dev, ret, "Could not register pcm dma\n");
++              goto err_unprepare_pclk;
++      }
+       ret = snd_soc_register_component(&pdev->dev, &stm32_component,
+                                        &sai->cpu_dai_drv, 1);
+       if (ret) {
+               snd_dmaengine_pcm_unregister(&pdev->dev);
+-              return ret;
++              goto err_unprepare_pclk;
+       }
+       pm_runtime_enable(&pdev->dev);
+       return 0;
++
++err_unprepare_pclk:
++      clk_unprepare(sai->pdata->pclk);
++
++      return ret;
+ }
+ static int stm32_sai_sub_remove(struct platform_device *pdev)
diff --git a/queue-5.15/asoc-stm32-sai-fix-of-node-leak-on-probe.patch b/queue-5.15/asoc-stm32-sai-fix-of-node-leak-on-probe.patch
new file mode 100644 (file)
index 0000000..89cad6e
--- /dev/null
@@ -0,0 +1,149 @@
+From stable+bounces-204834-greg=kroah.com@vger.kernel.org Mon Jan  5 16:16:50 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon,  5 Jan 2026 10:10:33 -0500
+Subject: ASoC: stm32: sai: fix OF node leak on probe
+To: stable@vger.kernel.org
+Cc: Johan Hovold <johan@kernel.org>, Olivier Moysan <olivier.moysan@st.com>, olivier moysan <olivier.moysan@foss.st.com>, Mark Brown <broonie@kernel.org>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260105151034.2625317-6-sashal@kernel.org>
+
+From: Johan Hovold <johan@kernel.org>
+
+[ Upstream commit 23261f0de09427367e99f39f588e31e2856a690e ]
+
+The reference taken to the sync provider OF node when probing the
+platform device is currently only dropped if the set_sync() callback
+fails during DAI probe.
+
+Make sure to drop the reference on platform probe failures (e.g. probe
+deferral) and on driver unbind.
+
+This also avoids a potential use-after-free in case the DAI is ever
+reprobed without first rebinding the platform driver.
+
+Fixes: 5914d285f6b7 ("ASoC: stm32: sai: Add synchronization support")
+Fixes: d4180b4c02e7 ("ASoC: stm32: sai: fix set_sync service")
+Cc: Olivier Moysan <olivier.moysan@st.com>
+Cc: stable@vger.kernel.org      # 4.16: d4180b4c02e7
+Signed-off-by: Johan Hovold <johan@kernel.org>
+Reviewed-by: olivier moysan <olivier.moysan@foss.st.com>
+Link: https://patch.msgid.link/20251124104908.15754-4-johan@kernel.org
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ sound/soc/stm/stm32_sai.c     |   12 +++---------
+ sound/soc/stm/stm32_sai_sub.c |   23 ++++++++++++++++-------
+ 2 files changed, 19 insertions(+), 16 deletions(-)
+
+--- a/sound/soc/stm/stm32_sai.c
++++ b/sound/soc/stm/stm32_sai.c
+@@ -122,7 +122,6 @@ static int stm32_sai_set_sync(struct stm
+       if (!pdev) {
+               dev_err(&sai_client->pdev->dev,
+                       "Device not found for node %pOFn\n", np_provider);
+-              of_node_put(np_provider);
+               return -ENODEV;
+       }
+@@ -131,21 +130,16 @@ static int stm32_sai_set_sync(struct stm
+       if (!sai_provider) {
+               dev_err(&sai_client->pdev->dev,
+                       "SAI sync provider data not found\n");
+-              ret = -EINVAL;
+-              goto error;
++              return -EINVAL;
+       }
+       /* Configure sync client */
+       ret = stm32_sai_sync_conf_client(sai_client, synci);
+       if (ret < 0)
+-              goto error;
++              return ret;
+       /* Configure sync provider */
+-      ret = stm32_sai_sync_conf_provider(sai_provider, synco);
+-
+-error:
+-      of_node_put(np_provider);
+-      return ret;
++      return stm32_sai_sync_conf_provider(sai_provider, synco);
+ }
+ static int stm32_sai_probe(struct platform_device *pdev)
+--- a/sound/soc/stm/stm32_sai_sub.c
++++ b/sound/soc/stm/stm32_sai_sub.c
+@@ -1436,7 +1436,8 @@ static int stm32_sai_sub_parse_of(struct
+                               dev_err(&pdev->dev,
+                                       "External synchro not supported\n");
+                               of_node_put(args.np);
+-                              return -EINVAL;
++                              ret = -EINVAL;
++                              goto err_put_sync_provider;
+                       }
+                       sai->sync = SAI_SYNC_EXTERNAL;
+@@ -1445,7 +1446,8 @@ static int stm32_sai_sub_parse_of(struct
+                           (sai->synci > (SAI_GCR_SYNCIN_MAX + 1))) {
+                               dev_err(&pdev->dev, "Wrong SAI index\n");
+                               of_node_put(args.np);
+-                              return -EINVAL;
++                              ret = -EINVAL;
++                              goto err_put_sync_provider;
+                       }
+                       if (of_property_match_string(args.np, "compatible",
+@@ -1459,7 +1461,8 @@ static int stm32_sai_sub_parse_of(struct
+                       if (!sai->synco) {
+                               dev_err(&pdev->dev, "Unknown SAI sub-block\n");
+                               of_node_put(args.np);
+-                              return -EINVAL;
++                              ret = -EINVAL;
++                              goto err_put_sync_provider;
+                       }
+               }
+@@ -1469,13 +1472,15 @@ static int stm32_sai_sub_parse_of(struct
+       of_node_put(args.np);
+       sai->sai_ck = devm_clk_get(&pdev->dev, "sai_ck");
+-      if (IS_ERR(sai->sai_ck))
+-              return dev_err_probe(&pdev->dev, PTR_ERR(sai->sai_ck),
+-                                   "Missing kernel clock sai_ck\n");
++      if (IS_ERR(sai->sai_ck)) {
++              ret = dev_err_probe(&pdev->dev, PTR_ERR(sai->sai_ck),
++                                  "Missing kernel clock sai_ck\n");
++              goto err_put_sync_provider;
++      }
+       ret = clk_prepare(sai->pdata->pclk);
+       if (ret < 0)
+-              return ret;
++              goto err_put_sync_provider;
+       if (STM_SAI_IS_F4(sai->pdata))
+               return 0;
+@@ -1497,6 +1502,8 @@ static int stm32_sai_sub_parse_of(struct
+ err_unprepare_pclk:
+       clk_unprepare(sai->pdata->pclk);
++err_put_sync_provider:
++      of_node_put(sai->np_sync_provider);
+       return ret;
+ }
+@@ -1567,6 +1574,7 @@ static int stm32_sai_sub_probe(struct pl
+ err_unprepare_pclk:
+       clk_unprepare(sai->pdata->pclk);
++      of_node_put(sai->np_sync_provider);
+       return ret;
+ }
+@@ -1579,6 +1587,7 @@ static void stm32_sai_sub_remove(struct
+       snd_dmaengine_pcm_unregister(&pdev->dev);
+       snd_soc_unregister_component(&pdev->dev);
+       pm_runtime_disable(&pdev->dev);
++      of_node_put(sai->np_sync_provider);
+ }
+ #ifdef CONFIG_PM_SLEEP
diff --git a/queue-5.15/asoc-stm32-sai-use-the-devm_clk_get_optional-helper.patch b/queue-5.15/asoc-stm32-sai-use-the-devm_clk_get_optional-helper.patch
new file mode 100644 (file)
index 0000000..baf2d8e
--- /dev/null
@@ -0,0 +1,43 @@
+From stable+bounces-204811-greg=kroah.com@vger.kernel.org Mon Jan  5 15:32:05 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon,  5 Jan 2026 09:27:27 -0500
+Subject: ASoC: stm32: sai: Use the devm_clk_get_optional() helper
+To: stable@vger.kernel.org
+Cc: Christophe JAILLET <christophe.jaillet@wanadoo.fr>, Mark Brown <broonie@kernel.org>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260105142728.2602716-2-sashal@kernel.org>
+
+From: Christophe JAILLET <christophe.jaillet@wanadoo.fr>
+
+[ Upstream commit 374628fb668e50b42fe81f2a63af616182415bcd ]
+
+Use devm_clk_get_optional() instead of hand writing it.
+This saves some LoC and improves the semantic.
+
+Signed-off-by: Christophe JAILLET <christophe.jaillet@wanadoo.fr>
+Link: https://lore.kernel.org/r/f7987f18dadf77bfa09969fd4c82d5a0f4e4e3b7.1684594838.git.christophe.jaillet@wanadoo.fr
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Stable-dep-of: 312ec2f0d9d1 ("ASoC: stm32: sai: fix clk prepare imbalance on probe failure")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ sound/soc/stm/stm32_sai_sub.c |    9 +++------
+ 1 file changed, 3 insertions(+), 6 deletions(-)
+
+--- a/sound/soc/stm/stm32_sai_sub.c
++++ b/sound/soc/stm/stm32_sai_sub.c
+@@ -1486,12 +1486,9 @@ static int stm32_sai_sub_parse_of(struct
+               if (ret < 0)
+                       return ret;
+       } else {
+-              sai->sai_mclk = devm_clk_get(&pdev->dev, "MCLK");
+-              if (IS_ERR(sai->sai_mclk)) {
+-                      if (PTR_ERR(sai->sai_mclk) != -ENOENT)
+-                              return PTR_ERR(sai->sai_mclk);
+-                      sai->sai_mclk = NULL;
+-              }
++              sai->sai_mclk = devm_clk_get_optional(&pdev->dev, "MCLK");
++              if (IS_ERR(sai->sai_mclk))
++                      return PTR_ERR(sai->sai_mclk);
+       }
+       return 0;
diff --git a/queue-5.15/btrfs-don-t-rewrite-ret-from-inode_permission.patch b/queue-5.15/btrfs-don-t-rewrite-ret-from-inode_permission.patch
new file mode 100644 (file)
index 0000000..89bb916
--- /dev/null
@@ -0,0 +1,51 @@
+From stable+bounces-204142-greg=kroah.com@vger.kernel.org Mon Dec 29 23:12:48 2025
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 29 Dec 2025 17:12:38 -0500
+Subject: btrfs: don't rewrite ret from inode_permission
+To: stable@vger.kernel.org
+Cc: Josef Bacik <josef@toxicpanda.com>, Johannes Thumshirn <johannes.thumshirn@wdc.com>, Daniel Vacek <neelx@suse.com>, David Sterba <dsterba@suse.com>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20251229221238.1738481-1-sashal@kernel.org>
+
+From: Josef Bacik <josef@toxicpanda.com>
+
+[ Upstream commit 0185c2292c600993199bc6b1f342ad47a9e8c678 ]
+
+In our user safe ino resolve ioctl we'll just turn any ret into -EACCES
+from inode_permission().  This is redundant, and could potentially be
+wrong if we had an ENOMEM in the security layer or some such other
+error, so simply return the actual return value.
+
+Note: The patch was taken from v5 of fscrypt patchset
+(https://lore.kernel.org/linux-btrfs/cover.1706116485.git.josef@toxicpanda.com/)
+which was handled over time by various people: Omar Sandoval, Sweet Tea
+Dorminy, Josef Bacik.
+
+Fixes: 23d0b79dfaed ("btrfs: Add unprivileged version of ino_lookup ioctl")
+CC: stable@vger.kernel.org # 5.4+
+Reviewed-by: Johannes Thumshirn <johannes.thumshirn@wdc.com>
+Signed-off-by: Josef Bacik <josef@toxicpanda.com>
+Signed-off-by: Daniel Vacek <neelx@suse.com>
+Reviewed-by: David Sterba <dsterba@suse.com>
+[ add note ]
+Signed-off-by: David Sterba <dsterba@suse.com>
+[ Adjust context ]
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/btrfs/ioctl.c |    4 +---
+ 1 file changed, 1 insertion(+), 3 deletions(-)
+
+--- a/fs/btrfs/ioctl.c
++++ b/fs/btrfs/ioctl.c
+@@ -2553,10 +2553,8 @@ static int btrfs_search_path_in_tree_use
+                       ret = inode_permission(mnt_userns, temp_inode,
+                                              MAY_READ | MAY_EXEC);
+                       iput(temp_inode);
+-                      if (ret) {
+-                              ret = -EACCES;
++                      if (ret)
+                               goto out_put;
+-                      }
+                       if (key.offset == upper_limit.objectid)
+                               break;
diff --git a/queue-5.15/crypto-af_alg-zero-initialize-memory-allocated-via-sock_kmalloc.patch b/queue-5.15/crypto-af_alg-zero-initialize-memory-allocated-via-sock_kmalloc.patch
new file mode 100644 (file)
index 0000000..671bc81
--- /dev/null
@@ -0,0 +1,102 @@
+From stable+bounces-204381-greg=kroah.com@vger.kernel.org Wed Dec 31 19:47:33 2025
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 31 Dec 2025 13:47:27 -0500
+Subject: crypto: af_alg - zero initialize memory allocated via sock_kmalloc
+To: stable@vger.kernel.org
+Cc: Shivani Agarwal <shivani.agarwal@broadcom.com>, Herbert Xu <herbert@gondor.apana.org.au>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20251231184727.3370622-1-sashal@kernel.org>
+
+From: Shivani Agarwal <shivani.agarwal@broadcom.com>
+
+[ Upstream commit 6f6e309328d53a10c0fe1f77dec2db73373179b6 ]
+
+Several crypto user API contexts and requests allocated with
+sock_kmalloc() were left uninitialized, relying on callers to
+set fields explicitly. This resulted in the use of uninitialized
+data in certain error paths or when new fields are added in the
+future.
+
+The ACVP patches also contain two user-space interface files:
+algif_kpp.c and algif_akcipher.c. These too rely on proper
+initialization of their context structures.
+
+A particular issue has been observed with the newly added
+'inflight' variable introduced in af_alg_ctx by commit:
+
+  67b164a871af ("crypto: af_alg - Disallow multiple in-flight AIO requests")
+
+Because the context is not memset to zero after allocation,
+the inflight variable has contained garbage values. As a result,
+af_alg_alloc_areq() has incorrectly returned -EBUSY randomly when
+the garbage value was interpreted as true:
+
+  https://github.com/gregkh/linux/blame/master/crypto/af_alg.c#L1209
+
+The check directly tests ctx->inflight without explicitly
+comparing against true/false. Since inflight is only ever set to
+true or false later, an uninitialized value has triggered
+-EBUSY failures. Zero-initializing memory allocated with
+sock_kmalloc() ensures inflight and other fields start in a known
+state, removing random issues caused by uninitialized data.
+
+Fixes: fe869cdb89c9 ("crypto: algif_hash - User-space interface for hash operations")
+Fixes: 5afdfd22e6ba ("crypto: algif_rng - add random number generator support")
+Fixes: 2d97591ef43d ("crypto: af_alg - consolidation of duplicate code")
+Fixes: 67b164a871af ("crypto: af_alg - Disallow multiple in-flight AIO requests")
+Cc: stable@vger.kernel.org
+Signed-off-by: Shivani Agarwal <shivani.agarwal@broadcom.com>
+Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
+[ Adjust context ]
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ crypto/af_alg.c     |    5 ++---
+ crypto/algif_hash.c |    3 +--
+ crypto/algif_rng.c  |    3 +--
+ 3 files changed, 4 insertions(+), 7 deletions(-)
+
+--- a/crypto/af_alg.c
++++ b/crypto/af_alg.c
+@@ -1139,14 +1139,13 @@ struct af_alg_async_req *af_alg_alloc_ar
+       if (unlikely(!areq))
+               return ERR_PTR(-ENOMEM);
++      memset(areq, 0, areqlen);
++
+       ctx->inflight = true;
+       areq->areqlen = areqlen;
+       areq->sk = sk;
+-      areq->last_rsgl = NULL;
+       INIT_LIST_HEAD(&areq->rsgl_list);
+-      areq->tsgl = NULL;
+-      areq->tsgl_entries = 0;
+       return areq;
+ }
+--- a/crypto/algif_hash.c
++++ b/crypto/algif_hash.c
+@@ -423,9 +423,8 @@ static int hash_accept_parent_nokey(void
+       if (!ctx)
+               return -ENOMEM;
+-      ctx->result = NULL;
++      memset(ctx, 0, len);
+       ctx->len = len;
+-      ctx->more = false;
+       crypto_init_wait(&ctx->wait);
+       ask->private = ctx;
+--- a/crypto/algif_rng.c
++++ b/crypto/algif_rng.c
+@@ -250,9 +250,8 @@ static int rng_accept_parent(void *priva
+       if (!ctx)
+               return -ENOMEM;
++      memset(ctx, 0, len);
+       ctx->len = len;
+-      ctx->addtl = NULL;
+-      ctx->addtl_len = 0;
+       /*
+        * No seeding done at that point -- if multiple accepts are
diff --git a/queue-5.15/drm-gma500-remove-unused-helper-psb_fbdev_fb_setcolreg.patch b/queue-5.15/drm-gma500-remove-unused-helper-psb_fbdev_fb_setcolreg.patch
new file mode 100644 (file)
index 0000000..a70d026
--- /dev/null
@@ -0,0 +1,101 @@
+From stable+bounces-206177-greg=kroah.com@vger.kernel.org Wed Jan  7 17:12:48 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed,  7 Jan 2026 10:57:33 -0500
+Subject: drm/gma500: Remove unused helper psb_fbdev_fb_setcolreg()
+To: stable@vger.kernel.org
+Cc: Thomas Zimmermann <tzimmermann@suse.de>, Patrik Jakobsson <patrik.r.jakobsson@gmail.com>, Stefan Christ <contact@stefanchrist.eu>, Daniel Vetter <daniel.vetter@ffwll.ch>, dri-devel@lists.freedesktop.org, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260107155733.4065165-1-sashal@kernel.org>
+
+From: Thomas Zimmermann <tzimmermann@suse.de>
+
+[ Upstream commit be729f9de6c64240645dc80a24162ac4d3fe00a8 ]
+
+Remove psb_fbdev_fb_setcolreg(), which hasn't been called in almost
+a decade.
+
+Gma500 commit 4d8d096e9ae8 ("gma500: introduce the framebuffer support
+code") added the helper psb_fbdev_fb_setcolreg() for setting the fbdev
+palette via fbdev's fb_setcolreg callback. Later
+commit 3da6c2f3b730 ("drm/gma500: use DRM_FB_HELPER_DEFAULT_OPS for
+fb_ops") set several default helpers for fbdev emulation, including
+fb_setcmap.
+
+The fbdev subsystem always prefers fb_setcmap over fb_setcolreg. [1]
+Hence, the gma500 code is no longer in use and gma500 has been using
+drm_fb_helper_setcmap() for several years without issues.
+
+Fixes: 3da6c2f3b730 ("drm/gma500: use DRM_FB_HELPER_DEFAULT_OPS for fb_ops")
+Cc: Patrik Jakobsson <patrik.r.jakobsson@gmail.com>
+Cc: Stefan Christ <contact@stefanchrist.eu>
+Cc: Daniel Vetter <daniel.vetter@ffwll.ch>
+Cc: dri-devel@lists.freedesktop.org
+Cc: <stable@vger.kernel.org> # v4.10+
+Link: https://elixir.bootlin.com/linux/v6.16.9/source/drivers/video/fbdev/core/fbcmap.c#L246 # [1]
+Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
+Acked-by: Patrik Jakobsson <patrik.r.jakobsson@gmail.com>
+Link: https://lore.kernel.org/r/20250929082338.18845-1-tzimmermann@suse.de
+[ adapted patch from fbdev.c to framebuffer.c where the function was named psbfb_setcolreg() instead of psb_fbdev_fb_setcolreg() ]
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/gpu/drm/gma500/framebuffer.c |   42 -----------------------------------
+ 1 file changed, 42 deletions(-)
+
+--- a/drivers/gpu/drm/gma500/framebuffer.c
++++ b/drivers/gpu/drm/gma500/framebuffer.c
+@@ -35,47 +35,6 @@ static const struct drm_framebuffer_func
+       .create_handle = drm_gem_fb_create_handle,
+ };
+-#define CMAP_TOHW(_val, _width) ((((_val) << (_width)) + 0x7FFF - (_val)) >> 16)
+-
+-static int psbfb_setcolreg(unsigned regno, unsigned red, unsigned green,
+-                         unsigned blue, unsigned transp,
+-                         struct fb_info *info)
+-{
+-      struct drm_fb_helper *fb_helper = info->par;
+-      struct drm_framebuffer *fb = fb_helper->fb;
+-      uint32_t v;
+-
+-      if (!fb)
+-              return -ENOMEM;
+-
+-      if (regno > 255)
+-              return 1;
+-
+-      red = CMAP_TOHW(red, info->var.red.length);
+-      blue = CMAP_TOHW(blue, info->var.blue.length);
+-      green = CMAP_TOHW(green, info->var.green.length);
+-      transp = CMAP_TOHW(transp, info->var.transp.length);
+-
+-      v = (red << info->var.red.offset) |
+-          (green << info->var.green.offset) |
+-          (blue << info->var.blue.offset) |
+-          (transp << info->var.transp.offset);
+-
+-      if (regno < 16) {
+-              switch (fb->format->cpp[0] * 8) {
+-              case 16:
+-                      ((uint32_t *) info->pseudo_palette)[regno] = v;
+-                      break;
+-              case 24:
+-              case 32:
+-                      ((uint32_t *) info->pseudo_palette)[regno] = v;
+-                      break;
+-              }
+-      }
+-
+-      return 0;
+-}
+-
+ static vm_fault_t psbfb_vm_fault(struct vm_fault *vmf)
+ {
+       struct vm_area_struct *vma = vmf->vma;
+@@ -147,7 +106,6 @@ static int psbfb_mmap(struct fb_info *in
+ static const struct fb_ops psbfb_unaccel_ops = {
+       .owner = THIS_MODULE,
+       DRM_FB_HELPER_DEFAULT_OPS,
+-      .fb_setcolreg = psbfb_setcolreg,
+       .fb_fillrect = drm_fb_helper_cfb_fillrect,
+       .fb_copyarea = drm_fb_helper_cfb_copyarea,
+       .fb_imageblit = drm_fb_helper_cfb_imageblit,
diff --git a/queue-5.15/drm-i915-selftests-fix-subtraction-overflow-bug.patch b/queue-5.15/drm-i915-selftests-fix-subtraction-overflow-bug.patch
new file mode 100644 (file)
index 0000000..61814c5
--- /dev/null
@@ -0,0 +1,41 @@
+From stable+bounces-200858-greg=kroah.com@vger.kernel.org Fri Dec 12 06:47:00 2025
+From: Rajani Kantha <681739313@139.com>
+Date: Fri, 12 Dec 2025 13:46:33 +0800
+Subject: drm/i915/selftests: fix subtraction overflow bug
+To: andrzej.hajda@intel.com, andi.shyti@linux.intel.com, rodrigo.vivi@intel.com
+Cc: stable@vger.kernel.org
+Message-ID: <20251212054633.2127-1-681739313@139.com>
+
+From: Andrzej Hajda <andrzej.hajda@intel.com>
+
+[ Upstream commit ab3edc679c552a466e4bf0b11af3666008bd65a2 ]
+
+On some machines hole_end can be small enough to cause subtraction
+overflow. On the other side (addr + 2 * min_alignment) can overflow
+in case of mock tests. This patch should handle both cases.
+
+Fixes: e1c5f754067b59 ("drm/i915: Avoid overflow in computing pot_hole loop termination")
+Closes: https://gitlab.freedesktop.org/drm/intel/-/issues/3674
+Signed-off-by: Andrzej Hajda <andrzej.hajda@intel.com>
+Reviewed-by: Andi Shyti <andi.shyti@linux.intel.com>
+Signed-off-by: Andi Shyti <andi.shyti@linux.intel.com>
+Link: https://patchwork.freedesktop.org/patch/msgid/20220624113528.2159210-1-andrzej.hajda@intel.com
+Signed-off-by: Rodrigo Vivi <rodrigo.vivi@intel.com>
+[ Using I915_GTT_PAGE_SIZE instead of min_alignment due to 5.15 missing commit:87bd701ee268 ("drm/i915: enforce min GTT alignment for discrete cards")]
+Signed-off-by: Rajani Kantha <681739313@139.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/gpu/drm/i915/selftests/i915_gem_gtt.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/gpu/drm/i915/selftests/i915_gem_gtt.c
++++ b/drivers/gpu/drm/i915/selftests/i915_gem_gtt.c
+@@ -715,7 +715,7 @@ static int pot_hole(struct i915_address_
+               u64 addr;
+               for (addr = round_up(hole_start + I915_GTT_PAGE_SIZE, step) - I915_GTT_PAGE_SIZE;
+-                   addr <= round_down(hole_end - 2*I915_GTT_PAGE_SIZE, step) - I915_GTT_PAGE_SIZE;
++                   hole_end > addr && hole_end - addr >= 2 * I915_GTT_PAGE_SIZE;
+                    addr += step) {
+                       err = i915_vma_pin(vma, 0, 0, addr | flags);
+                       if (err) {
diff --git a/queue-5.15/drm-mediatek-fix-probe-memory-leak.patch b/queue-5.15/drm-mediatek-fix-probe-memory-leak.patch
new file mode 100644 (file)
index 0000000..d885fcf
--- /dev/null
@@ -0,0 +1,44 @@
+From stable+bounces-206143-greg=kroah.com@vger.kernel.org Wed Jan  7 13:47:50 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed,  7 Jan 2026 07:46:00 -0500
+Subject: drm/mediatek: Fix probe memory leak
+To: stable@vger.kernel.org
+Cc: Johan Hovold <johan@kernel.org>, CK Hu <ck.hu@mediatek.com>, AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>, Chun-Kuang Hu <chunkuang.hu@kernel.org>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260107124600.3997704-1-sashal@kernel.org>
+
+From: Johan Hovold <johan@kernel.org>
+
+[ Upstream commit 5e49200593f331cd0629b5376fab9192f698e8ef ]
+
+The Mediatek DRM driver allocates private data for components without a
+platform driver but as the lifetime is tied to each component device,
+the memory is never freed.
+
+Tie the allocation lifetime to the DRM platform device so that the
+memory is released on probe failure (e.g. probe deferral) and when the
+driver is unbound.
+
+Fixes: c0d36de868a6 ("drm/mediatek: Move clk info from struct mtk_ddp_comp to sub driver private data")
+Cc: stable@vger.kernel.org     # 5.12
+Cc: CK Hu <ck.hu@mediatek.com>
+Signed-off-by: Johan Hovold <johan@kernel.org>
+Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
+Link: https://patchwork.kernel.org/project/dri-devel/patch/20250923152340.18234-3-johan@kernel.org/
+Signed-off-by: Chun-Kuang Hu <chunkuang.hu@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c
++++ b/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c
+@@ -487,7 +487,7 @@ int mtk_ddp_comp_init(struct device_node
+           type == MTK_DISP_RDMA)
+               return 0;
+-      priv = devm_kzalloc(comp->dev, sizeof(*priv), GFP_KERNEL);
++      priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+       if (!priv)
+               return -ENOMEM;
diff --git a/queue-5.15/f2fs-fix-to-avoid-updating-zero-sized-extent-in-extent-cache.patch b/queue-5.15/f2fs-fix-to-avoid-updating-zero-sized-extent-in-extent-cache.patch
new file mode 100644 (file)
index 0000000..90b6b9a
--- /dev/null
@@ -0,0 +1,65 @@
+From stable+bounces-204263-greg=kroah.com@vger.kernel.org Tue Dec 30 18:26:41 2025
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 30 Dec 2025 12:26:36 -0500
+Subject: f2fs: fix to avoid updating zero-sized extent in extent cache
+To: stable@vger.kernel.org
+Cc: Chao Yu <chao@kernel.org>, stable@kernel.org, syzbot+24124df3170c3638b35f@syzkaller.appspotmail.com, Jaegeuk Kim <jaegeuk@kernel.org>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20251230172636.2349925-1-sashal@kernel.org>
+
+From: Chao Yu <chao@kernel.org>
+
+[ Upstream commit 7c37c79510329cd951a4dedf3f7bf7e2b18dccec ]
+
+As syzbot reported:
+
+F2FS-fs (loop0): __update_extent_tree_range: extent len is zero, type: 0, extent [0, 0, 0], age [0, 0]
+------------[ cut here ]------------
+kernel BUG at fs/f2fs/extent_cache.c:678!
+Oops: invalid opcode: 0000 [#1] SMP KASAN NOPTI
+CPU: 0 UID: 0 PID: 5336 Comm: syz.0.0 Not tainted syzkaller #0 PREEMPT(full)
+Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 1.16.3-debian-1.16.3-2~bpo12+1 04/01/2014
+RIP: 0010:__update_extent_tree_range+0x13bc/0x1500 fs/f2fs/extent_cache.c:678
+Call Trace:
+ <TASK>
+ f2fs_update_read_extent_cache_range+0x192/0x3e0 fs/f2fs/extent_cache.c:1085
+ f2fs_do_zero_range fs/f2fs/file.c:1657 [inline]
+ f2fs_zero_range+0x10c1/0x1580 fs/f2fs/file.c:1737
+ f2fs_fallocate+0x583/0x990 fs/f2fs/file.c:2030
+ vfs_fallocate+0x669/0x7e0 fs/open.c:342
+ ioctl_preallocate fs/ioctl.c:289 [inline]
+ file_ioctl+0x611/0x780 fs/ioctl.c:-1
+ do_vfs_ioctl+0xb33/0x1430 fs/ioctl.c:576
+ __do_sys_ioctl fs/ioctl.c:595 [inline]
+ __se_sys_ioctl+0x82/0x170 fs/ioctl.c:583
+ do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline]
+ do_syscall_64+0xfa/0x3b0 arch/x86/entry/syscall_64.c:94
+ entry_SYSCALL_64_after_hwframe+0x77/0x7f
+RIP: 0033:0x7f07bc58eec9
+
+In error path of f2fs_zero_range(), it may add a zero-sized extent
+into extent cache, it should be avoided.
+
+Fixes: 6e9619499f53 ("f2fs: support in batch fzero in dnode page")
+Cc: stable@kernel.org
+Reported-by: syzbot+24124df3170c3638b35f@syzkaller.appspotmail.com
+Closes: https://lore.kernel.org/linux-f2fs-devel/68e5d698.050a0220.256323.0032.GAE@google.com
+Signed-off-by: Chao Yu <chao@kernel.org>
+Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/f2fs/file.c |    3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+--- a/fs/f2fs/file.c
++++ b/fs/f2fs/file.c
+@@ -1470,7 +1470,8 @@ static int f2fs_do_zero_range(struct dno
+               f2fs_set_data_blkaddr(dn);
+       }
+-      f2fs_update_extent_cache_range(dn, start, 0, index - start);
++      if (index > start)
++              f2fs_update_extent_cache_range(dn, start, 0, index - start);
+       return ret;
+ }
diff --git a/queue-5.15/f2fs-fix-to-detect-recoverable-inode-during-dryrun-of-find_fsync_dnodes.patch b/queue-5.15/f2fs-fix-to-detect-recoverable-inode-during-dryrun-of-find_fsync_dnodes.patch
new file mode 100644 (file)
index 0000000..008ef7e
--- /dev/null
@@ -0,0 +1,93 @@
+From stable+bounces-204287-greg=kroah.com@vger.kernel.org Tue Dec 30 21:08:59 2025
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 30 Dec 2025 15:08:41 -0500
+Subject: f2fs: fix to detect recoverable inode during dryrun of find_fsync_dnodes()
+To: stable@vger.kernel.org
+Cc: Chao Yu <chao@kernel.org>, stable@kernel.org, Jaegeuk Kim <jaegeuk@kernel.org>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20251230200841.2453139-1-sashal@kernel.org>
+
+From: Chao Yu <chao@kernel.org>
+
+[ Upstream commit 68d05693f8c031257a0822464366e1c2a239a512 ]
+
+mkfs.f2fs -f /dev/vdd
+mount /dev/vdd /mnt/f2fs
+touch /mnt/f2fs/foo
+sync           # avoid CP_UMOUNT_FLAG in last f2fs_checkpoint.ckpt_flags
+touch /mnt/f2fs/bar
+f2fs_io fsync /mnt/f2fs/bar
+f2fs_io shutdown 2 /mnt/f2fs
+umount /mnt/f2fs
+blockdev --setro /dev/vdd
+mount /dev/vdd /mnt/f2fs
+mount: /mnt/f2fs: WARNING: source write-protected, mounted read-only.
+
+For the case if we create and fsync a new inode before sudden power-cut,
+without norecovery or disable_roll_forward mount option, the following
+mount will succeed w/o recovering last fsynced inode.
+
+The problem here is that we only check inode_list list after
+find_fsync_dnodes() in f2fs_recover_fsync_data() to find out whether
+there is recoverable data in the iamge, but there is a missed case, if
+last fsynced inode is not existing in last checkpoint, then, we will
+fail to get its inode due to nat of inode node is not existing in last
+checkpoint, so the inode won't be linked in inode_list.
+
+Let's detect such case in dyrun mode to fix this issue.
+
+After this change, mount will fail as expected below:
+mount: /mnt/f2fs: cannot mount /dev/vdd read-only.
+       dmesg(1) may have more information after failed mount system call.
+demsg:
+F2FS-fs (vdd): Need to recover fsync data, but write access unavailable, please try mount w/ disable_roll_forward or norecovery
+
+Cc: stable@kernel.org
+Fixes: 6781eabba1bd ("f2fs: give -EINVAL for norecovery and rw mount")
+Signed-off-by: Chao Yu <chao@kernel.org>
+Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
+[ folio => page ]
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/f2fs/recovery.c |    9 ++++++---
+ 1 file changed, 6 insertions(+), 3 deletions(-)
+
+--- a/fs/f2fs/recovery.c
++++ b/fs/f2fs/recovery.c
+@@ -343,7 +343,7 @@ static int recover_inode(struct inode *i
+ }
+ static int find_fsync_dnodes(struct f2fs_sb_info *sbi, struct list_head *head,
+-                              bool check_only)
++                              bool check_only, bool *new_inode)
+ {
+       struct curseg_info *curseg;
+       struct page *page = NULL;
+@@ -400,6 +400,8 @@ static int find_fsync_dnodes(struct f2fs
+                       if (IS_ERR(entry)) {
+                               err = PTR_ERR(entry);
+                               if (err == -ENOENT) {
++                                      if (check_only)
++                                              *new_inode = true;
+                                       err = 0;
+                                       goto next;
+                               }
+@@ -805,6 +807,7 @@ int f2fs_recover_fsync_data(struct f2fs_
+       unsigned long s_flags = sbi->sb->s_flags;
+       bool need_writecp = false;
+       bool fix_curseg_write_pointer = false;
++      bool new_inode = false;
+ #ifdef CONFIG_QUOTA
+       int quota_enabled;
+ #endif
+@@ -829,8 +832,8 @@ int f2fs_recover_fsync_data(struct f2fs_
+       down_write(&sbi->cp_global_sem);
+       /* step #1: find fsynced inode numbers */
+-      err = find_fsync_dnodes(sbi, &inode_list, check_only);
+-      if (err || list_empty(&inode_list))
++      err = find_fsync_dnodes(sbi, &inode_list, check_only, &new_inode);
++      if (err < 0 || (list_empty(&inode_list) && (!check_only || !new_inode)))
+               goto skip;
+       if (check_only) {
diff --git a/queue-5.15/f2fs-fix-to-propagate-error-from-f2fs_enable_checkpoint.patch b/queue-5.15/f2fs-fix-to-propagate-error-from-f2fs_enable_checkpoint.patch
new file mode 100644 (file)
index 0000000..be2e299
--- /dev/null
@@ -0,0 +1,86 @@
+From stable+bounces-204264-greg=kroah.com@vger.kernel.org Tue Dec 30 18:34:58 2025
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 30 Dec 2025 12:34:52 -0500
+Subject: f2fs: fix to propagate error from f2fs_enable_checkpoint()
+To: stable@vger.kernel.org
+Cc: Chao Yu <chao@kernel.org>, stable@kernel.org, Jaegeuk Kim <jaegeuk@kernel.org>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20251230173452.2352003-1-sashal@kernel.org>
+
+From: Chao Yu <chao@kernel.org>
+
+[ Upstream commit be112e7449a6e1b54aa9feac618825d154b3a5c7 ]
+
+In order to let userspace detect such error rather than suffering
+silent failure.
+
+Fixes: 4354994f097d ("f2fs: checkpoint disabling")
+Cc: stable@kernel.org
+Signed-off-by: Chao Yu <chao@kernel.org>
+Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
+[ Adjust context, no rollback ]
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/f2fs/super.c |   24 +++++++++++++++---------
+ 1 file changed, 15 insertions(+), 9 deletions(-)
+
+--- a/fs/f2fs/super.c
++++ b/fs/f2fs/super.c
+@@ -2177,9 +2177,10 @@ restore_flag:
+       return err;
+ }
+-static void f2fs_enable_checkpoint(struct f2fs_sb_info *sbi)
++static int f2fs_enable_checkpoint(struct f2fs_sb_info *sbi)
+ {
+       int retry = DEFAULT_RETRY_IO_COUNT;
++      int ret;
+       /* we should flush all the data to keep data consistency */
+       do {
+@@ -2197,10 +2198,14 @@ static void f2fs_enable_checkpoint(struc
+       set_sbi_flag(sbi, SBI_IS_DIRTY);
+       up_write(&sbi->gc_lock);
+-      f2fs_sync_fs(sbi->sb, 1);
++      ret = f2fs_sync_fs(sbi->sb, 1);
++      if (ret)
++              f2fs_err(sbi, "%s sync_fs failed, ret: %d", __func__, ret);
+       /* Let's ensure there's no pending checkpoint anymore */
+       f2fs_flush_ckpt_thread(sbi);
++
++      return ret;
+ }
+ static int f2fs_remount(struct super_block *sb, int *flags, char *data)
+@@ -2416,7 +2421,9 @@ static int f2fs_remount(struct super_blo
+                       if (err)
+                               goto restore_discard;
+               } else {
+-                      f2fs_enable_checkpoint(sbi);
++                      err = f2fs_enable_checkpoint(sbi);
++                      if (err)
++                              goto restore_discard;
+               }
+       }
+@@ -4397,13 +4404,12 @@ reset_checkpoint:
+       /* f2fs_recover_fsync_data() cleared this already */
+       clear_sbi_flag(sbi, SBI_POR_DOING);
+-      if (test_opt(sbi, DISABLE_CHECKPOINT)) {
++      if (test_opt(sbi, DISABLE_CHECKPOINT))
+               err = f2fs_disable_checkpoint(sbi);
+-              if (err)
+-                      goto sync_free_meta;
+-      } else if (is_set_ckpt_flags(sbi, CP_DISABLED_FLAG)) {
+-              f2fs_enable_checkpoint(sbi);
+-      }
++      else if (is_set_ckpt_flags(sbi, CP_DISABLED_FLAG))
++              err = f2fs_enable_checkpoint(sbi);
++      if (err)
++              goto sync_free_meta;
+       /*
+        * If filesystem is not mounted as read-only then
diff --git a/queue-5.15/f2fs-use-global-inline_xattr_slab-instead-of-per-sb-slab-cache.patch b/queue-5.15/f2fs-use-global-inline_xattr_slab-instead-of-per-sb-slab-cache.patch
new file mode 100644 (file)
index 0000000..37cc2c9
--- /dev/null
@@ -0,0 +1,237 @@
+From stable+bounces-204285-greg=kroah.com@vger.kernel.org Tue Dec 30 20:55:22 2025
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 30 Dec 2025 14:55:17 -0500
+Subject: f2fs: use global inline_xattr_slab instead of per-sb slab cache
+To: stable@vger.kernel.org
+Cc: Chao Yu <chao@kernel.org>, stable@kernel.org, Hong Yun <yhong@link.cuhk.edu.hk>, Jaegeuk Kim <jaegeuk@kernel.org>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20251230195517.2448220-1-sashal@kernel.org>
+
+From: Chao Yu <chao@kernel.org>
+
+[ Upstream commit 1f27ef42bb0b7c0740c5616ec577ec188b8a1d05 ]
+
+As Hong Yun reported in mailing list:
+
+loop7: detected capacity change from 0 to 131072
+------------[ cut here ]------------
+kmem_cache of name 'f2fs_xattr_entry-7:7' already exists
+WARNING: CPU: 0 PID: 24426 at mm/slab_common.c:110 kmem_cache_sanity_check mm/slab_common.c:109 [inline]
+WARNING: CPU: 0 PID: 24426 at mm/slab_common.c:110 __kmem_cache_create_args+0xa6/0x320 mm/slab_common.c:307
+CPU: 0 UID: 0 PID: 24426 Comm: syz.7.1370 Not tainted 6.17.0-rc4 #1 PREEMPT(full)
+Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.13.0-1ubuntu1.1 04/01/2014
+RIP: 0010:kmem_cache_sanity_check mm/slab_common.c:109 [inline]
+RIP: 0010:__kmem_cache_create_args+0xa6/0x320 mm/slab_common.c:307
+Call Trace:
+ __kmem_cache_create include/linux/slab.h:353 [inline]
+ f2fs_kmem_cache_create fs/f2fs/f2fs.h:2943 [inline]
+ f2fs_init_xattr_caches+0xa5/0xe0 fs/f2fs/xattr.c:843
+ f2fs_fill_super+0x1645/0x2620 fs/f2fs/super.c:4918
+ get_tree_bdev_flags+0x1fb/0x260 fs/super.c:1692
+ vfs_get_tree+0x43/0x140 fs/super.c:1815
+ do_new_mount+0x201/0x550 fs/namespace.c:3808
+ do_mount fs/namespace.c:4136 [inline]
+ __do_sys_mount fs/namespace.c:4347 [inline]
+ __se_sys_mount+0x298/0x2f0 fs/namespace.c:4324
+ do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline]
+ do_syscall_64+0x8e/0x3a0 arch/x86/entry/syscall_64.c:94
+ entry_SYSCALL_64_after_hwframe+0x76/0x7e
+
+The bug can be reproduced w/ below scripts:
+- mount /dev/vdb /mnt1
+- mount /dev/vdc /mnt2
+- umount /mnt1
+- mounnt /dev/vdb /mnt1
+
+The reason is if we created two slab caches, named f2fs_xattr_entry-7:3
+and f2fs_xattr_entry-7:7, and they have the same slab size. Actually,
+slab system will only create one slab cache core structure which has
+slab name of "f2fs_xattr_entry-7:3", and two slab caches share the same
+structure and cache address.
+
+So, if we destroy f2fs_xattr_entry-7:3 cache w/ cache address, it will
+decrease reference count of slab cache, rather than release slab cache
+entirely, since there is one more user has referenced the cache.
+
+Then, if we try to create slab cache w/ name "f2fs_xattr_entry-7:3" again,
+slab system will find that there is existed cache which has the same name
+and trigger the warning.
+
+Let's changes to use global inline_xattr_slab instead of per-sb slab cache
+for fixing.
+
+Fixes: a999150f4fe3 ("f2fs: use kmem_cache pool during inline xattr lookups")
+Cc: stable@kernel.org
+Reported-by: Hong Yun <yhong@link.cuhk.edu.hk>
+Tested-by: Hong Yun <yhong@link.cuhk.edu.hk>
+Signed-off-by: Chao Yu <chao@kernel.org>
+Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
+[ folio => page + different module init/exit ordering ]
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/f2fs/f2fs.h  |    3 ---
+ fs/f2fs/super.c |   15 +++++++--------
+ fs/f2fs/xattr.c |   32 +++++++++++---------------------
+ fs/f2fs/xattr.h |   10 ++++++----
+ 4 files changed, 24 insertions(+), 36 deletions(-)
+
+--- a/fs/f2fs/f2fs.h
++++ b/fs/f2fs/f2fs.h
+@@ -1763,9 +1763,6 @@ struct f2fs_sb_info {
+       struct workqueue_struct *post_read_wq;  /* post read workqueue */
+-      struct kmem_cache *inline_xattr_slab;   /* inline xattr entry */
+-      unsigned int inline_xattr_slab_size;    /* default inline xattr slab size */
+-
+       /* For reclaimed segs statistics per each GC mode */
+       unsigned int gc_segment_mode;           /* GC state for reclaimed segments */
+       unsigned int gc_reclaimed_segs[MAX_GC_MODE];    /* Reclaimed segs for each mode */
+--- a/fs/f2fs/super.c
++++ b/fs/f2fs/super.c
+@@ -1655,7 +1655,6 @@ static void f2fs_put_super(struct super_
+       destroy_device_list(sbi);
+       f2fs_destroy_page_array_cache(sbi);
+-      f2fs_destroy_xattr_caches(sbi);
+       mempool_destroy(sbi->write_io_dummy);
+ #ifdef CONFIG_QUOTA
+       for (i = 0; i < MAXQUOTAS; i++)
+@@ -4166,13 +4165,9 @@ try_onemore:
+               }
+       }
+-      /* init per sbi slab cache */
+-      err = f2fs_init_xattr_caches(sbi);
+-      if (err)
+-              goto free_io_dummy;
+       err = f2fs_init_page_array_cache(sbi);
+       if (err)
+-              goto free_xattr_cache;
++              goto free_io_dummy;
+       /* get an inode for meta space */
+       sbi->meta_inode = f2fs_iget(sb, F2FS_META_INO(sbi));
+@@ -4492,8 +4487,6 @@ free_meta_inode:
+       sbi->meta_inode = NULL;
+ free_page_array_cache:
+       f2fs_destroy_page_array_cache(sbi);
+-free_xattr_cache:
+-      f2fs_destroy_xattr_caches(sbi);
+ free_io_dummy:
+       mempool_destroy(sbi->write_io_dummy);
+ free_percpu:
+@@ -4660,7 +4653,12 @@ static int __init init_f2fs_fs(void)
+       err = f2fs_create_casefold_cache();
+       if (err)
+               goto free_compress_cache;
++      err = f2fs_init_xattr_cache();
++      if (err)
++              goto free_casefold_cache;
+       return 0;
++free_casefold_cache:
++      f2fs_destroy_casefold_cache();
+ free_compress_cache:
+       f2fs_destroy_compress_cache();
+ free_compress_mempool:
+@@ -4700,6 +4698,7 @@ fail:
+ static void __exit exit_f2fs_fs(void)
+ {
++      f2fs_destroy_xattr_cache();
+       f2fs_destroy_casefold_cache();
+       f2fs_destroy_compress_cache();
+       f2fs_destroy_compress_mempool();
+--- a/fs/f2fs/xattr.c
++++ b/fs/f2fs/xattr.c
+@@ -23,11 +23,12 @@
+ #include "xattr.h"
+ #include "segment.h"
++static struct kmem_cache *inline_xattr_slab;
+ static void *xattr_alloc(struct f2fs_sb_info *sbi, int size, bool *is_inline)
+ {
+-      if (likely(size == sbi->inline_xattr_slab_size)) {
++      if (likely(size == DEFAULT_XATTR_SLAB_SIZE)) {
+               *is_inline = true;
+-              return f2fs_kmem_cache_alloc(sbi->inline_xattr_slab,
++              return f2fs_kmem_cache_alloc(inline_xattr_slab,
+                                       GFP_F2FS_ZERO, false, sbi);
+       }
+       *is_inline = false;
+@@ -38,7 +39,7 @@ static void xattr_free(struct f2fs_sb_in
+                                                       bool is_inline)
+ {
+       if (is_inline)
+-              kmem_cache_free(sbi->inline_xattr_slab, xattr_addr);
++              kmem_cache_free(inline_xattr_slab, xattr_addr);
+       else
+               kfree(xattr_addr);
+ }
+@@ -818,25 +819,14 @@ int f2fs_setxattr(struct inode *inode, i
+       return err;
+ }
+-int f2fs_init_xattr_caches(struct f2fs_sb_info *sbi)
++int __init f2fs_init_xattr_cache(void)
+ {
+-      dev_t dev = sbi->sb->s_bdev->bd_dev;
+-      char slab_name[32];
+-
+-      sprintf(slab_name, "f2fs_xattr_entry-%u:%u", MAJOR(dev), MINOR(dev));
+-
+-      sbi->inline_xattr_slab_size = F2FS_OPTION(sbi).inline_xattr_size *
+-                                      sizeof(__le32) + XATTR_PADDING_SIZE;
+-
+-      sbi->inline_xattr_slab = f2fs_kmem_cache_create(slab_name,
+-                                      sbi->inline_xattr_slab_size);
+-      if (!sbi->inline_xattr_slab)
+-              return -ENOMEM;
+-
+-      return 0;
++      inline_xattr_slab = f2fs_kmem_cache_create("f2fs_xattr_entry",
++                                      DEFAULT_XATTR_SLAB_SIZE);
++      return inline_xattr_slab ? 0 : -ENOMEM;
+ }
+-void f2fs_destroy_xattr_caches(struct f2fs_sb_info *sbi)
++void f2fs_destroy_xattr_cache(void)
+ {
+-      kmem_cache_destroy(sbi->inline_xattr_slab);
+-}
++      kmem_cache_destroy(inline_xattr_slab);
++}
+\ No newline at end of file
+--- a/fs/f2fs/xattr.h
++++ b/fs/f2fs/xattr.h
+@@ -88,6 +88,8 @@ struct f2fs_xattr_entry {
+                       F2FS_TOTAL_EXTRA_ATTR_SIZE / sizeof(__le32) -   \
+                       DEF_INLINE_RESERVED_SIZE -                      \
+                       MIN_INLINE_DENTRY_SIZE / sizeof(__le32))
++#define DEFAULT_XATTR_SLAB_SIZE       (DEFAULT_INLINE_XATTR_ADDRS *           \
++                              sizeof(__le32) + XATTR_PADDING_SIZE)
+ /*
+  * On-disk structure of f2fs_xattr
+@@ -131,8 +133,8 @@ extern int f2fs_setxattr(struct inode *,
+ extern int f2fs_getxattr(struct inode *, int, const char *, void *,
+                                               size_t, struct page *);
+ extern ssize_t f2fs_listxattr(struct dentry *, char *, size_t);
+-extern int f2fs_init_xattr_caches(struct f2fs_sb_info *);
+-extern void f2fs_destroy_xattr_caches(struct f2fs_sb_info *);
++int __init f2fs_init_xattr_cache(void);
++void f2fs_destroy_xattr_cache(void);
+ #else
+ #define f2fs_xattr_handlers   NULL
+@@ -149,8 +151,8 @@ static inline int f2fs_getxattr(struct i
+ {
+       return -EOPNOTSUPP;
+ }
+-static inline int f2fs_init_xattr_caches(struct f2fs_sb_info *sbi) { return 0; }
+-static inline void f2fs_destroy_xattr_caches(struct f2fs_sb_info *sbi) { }
++static inline int __init f2fs_init_xattr_cache(void) { return 0; }
++static inline void f2fs_destroy_xattr_cache(void) { }
+ #endif
+ #ifdef CONFIG_F2FS_FS_SECURITY
diff --git a/queue-5.15/fuse-fix-readahead-reclaim-deadlock.patch b/queue-5.15/fuse-fix-readahead-reclaim-deadlock.patch
new file mode 100644 (file)
index 0000000..68ca8aa
--- /dev/null
@@ -0,0 +1,120 @@
+From stable+bounces-204418-greg=kroah.com@vger.kernel.org Thu Jan  1 16:57:37 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu,  1 Jan 2026 10:57:31 -0500
+Subject: fuse: fix readahead reclaim deadlock
+To: stable@vger.kernel.org
+Cc: Joanne Koong <joannelkoong@gmail.com>, Omar Sandoval <osandov@fb.com>, Miklos Szeredi <mszeredi@redhat.com>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260101155731.4129270-1-sashal@kernel.org>
+
+From: Joanne Koong <joannelkoong@gmail.com>
+
+[ Upstream commit bd5603eaae0aabf527bfb3ce1bb07e979ce5bd50 ]
+
+Commit e26ee4efbc79 ("fuse: allocate ff->release_args only if release is
+needed") skips allocating ff->release_args if the server does not
+implement open. However in doing so, fuse_prepare_release() now skips
+grabbing the reference on the inode, which makes it possible for an
+inode to be evicted from the dcache while there are inflight readahead
+requests. This causes a deadlock if the server triggers reclaim while
+servicing the readahead request and reclaim attempts to evict the inode
+of the file being read ahead. Since the folio is locked during
+readahead, when reclaim evicts the fuse inode and fuse_evict_inode()
+attempts to remove all folios associated with the inode from the page
+cache (truncate_inode_pages_range()), reclaim will block forever waiting
+for the lock since readahead cannot relinquish the lock because it is
+itself blocked in reclaim:
+
+>>> stack_trace(1504735)
+ folio_wait_bit_common (mm/filemap.c:1308:4)
+ folio_lock (./include/linux/pagemap.h:1052:3)
+ truncate_inode_pages_range (mm/truncate.c:336:10)
+ fuse_evict_inode (fs/fuse/inode.c:161:2)
+ evict (fs/inode.c:704:3)
+ dentry_unlink_inode (fs/dcache.c:412:3)
+ __dentry_kill (fs/dcache.c:615:3)
+ shrink_kill (fs/dcache.c:1060:12)
+ shrink_dentry_list (fs/dcache.c:1087:3)
+ prune_dcache_sb (fs/dcache.c:1168:2)
+ super_cache_scan (fs/super.c:221:10)
+ do_shrink_slab (mm/shrinker.c:435:9)
+ shrink_slab (mm/shrinker.c:626:10)
+ shrink_node (mm/vmscan.c:5951:2)
+ shrink_zones (mm/vmscan.c:6195:3)
+ do_try_to_free_pages (mm/vmscan.c:6257:3)
+ do_swap_page (mm/memory.c:4136:11)
+ handle_pte_fault (mm/memory.c:5562:10)
+ handle_mm_fault (mm/memory.c:5870:9)
+ do_user_addr_fault (arch/x86/mm/fault.c:1338:10)
+ handle_page_fault (arch/x86/mm/fault.c:1481:3)
+ exc_page_fault (arch/x86/mm/fault.c:1539:2)
+ asm_exc_page_fault+0x22/0x27
+
+Fix this deadlock by allocating ff->release_args and grabbing the
+reference on the inode when preparing the file for release even if the
+server does not implement open. The inode reference will be dropped when
+the last reference on the fuse file is dropped (see fuse_file_put() ->
+fuse_release_end()).
+
+Fixes: e26ee4efbc79 ("fuse: allocate ff->release_args only if release is needed")
+Cc: stable@vger.kernel.org
+Signed-off-by: Joanne Koong <joannelkoong@gmail.com>
+Reported-by: Omar Sandoval <osandov@fb.com>
+Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/fuse/file.c |   26 +++++++++++++++++++-------
+ 1 file changed, 19 insertions(+), 7 deletions(-)
+
+--- a/fs/fuse/file.c
++++ b/fs/fuse/file.c
+@@ -112,7 +112,9 @@ static void fuse_file_put(struct fuse_fi
+               struct fuse_args *args = (ra ? &ra->args : NULL);
+               if (!args) {
+-                      /* Do nothing when server does not implement 'open' */
++                      /* Do nothing when server does not implement 'opendir' */
++              } else if (args->opcode == FUSE_RELEASE && ff->fm->fc->no_open) {
++                      fuse_release_end(ff->fm, args, 0);
+               } else if (sync) {
+                       fuse_simple_request(ff->fm, args);
+                       fuse_release_end(ff->fm, args, 0);
+@@ -133,8 +135,17 @@ struct fuse_file *fuse_file_open(struct
+       struct fuse_file *ff;
+       int opcode = isdir ? FUSE_OPENDIR : FUSE_OPEN;
+       bool open = isdir ? !fc->no_opendir : !fc->no_open;
++      bool release = !isdir || open;
+-      ff = fuse_file_alloc(fm, open);
++      /*
++       * ff->args->release_args still needs to be allocated (so we can hold an
++       * inode reference while there are pending inflight file operations when
++       * ->release() is called, see fuse_prepare_release()) even if
++       * fc->no_open is set else it becomes possible for reclaim to deadlock
++       * if while servicing the readahead request the server triggers reclaim
++       * and reclaim evicts the inode of the file being read ahead.
++       */
++      ff = fuse_file_alloc(fm, release);
+       if (!ff)
+               return ERR_PTR(-ENOMEM);
+@@ -153,13 +164,14 @@ struct fuse_file *fuse_file_open(struct
+                       fuse_file_free(ff);
+                       return ERR_PTR(err);
+               } else {
+-                      /* No release needed */
+-                      kfree(ff->release_args);
+-                      ff->release_args = NULL;
+-                      if (isdir)
++                      if (isdir) {
++                              /* No release needed */
++                              kfree(ff->release_args);
++                              ff->release_args = NULL;
+                               fc->no_opendir = 1;
+-                      else
++                      } else {
+                               fc->no_open = 1;
++                      }
+               }
+       }
diff --git a/queue-5.15/hid-core-harden-s32ton-against-conversion-to-0-bits.patch b/queue-5.15/hid-core-harden-s32ton-against-conversion-to-0-bits.patch
new file mode 100644 (file)
index 0000000..51e4646
--- /dev/null
@@ -0,0 +1,55 @@
+From stable+bounces-200015-greg=kroah.com@vger.kernel.org Thu Dec  4 13:40:56 2025
+From: jetlan9@163.com
+Date: Thu,  4 Dec 2025 12:39:01 +0000
+Subject: HID: core: Harden s32ton() against conversion to 0 bits
+To: stable@vger.kernel.org
+Cc: Alan Stern <stern@rowland.harvard.edu>, syzbot+b63d677d63bcac06cf90@syzkaller.appspotmail.com, Benjamin Tissoires <bentiss@kernel.org>, Wenshan Lan <jetlan9@163.com>
+Message-ID: <20251204123901.4101-1-jetlan9@163.com>
+
+From: Alan Stern <stern@rowland.harvard.edu>
+
+[ Upstream commit a6b87bfc2ab5bccb7ad953693c85d9062aef3fdd ]
+
+Testing by the syzbot fuzzer showed that the HID core gets a
+shift-out-of-bounds exception when it tries to convert a 32-bit
+quantity to a 0-bit quantity.  Ideally this should never occur, but
+there are buggy devices and some might have a report field with size
+set to zero; we shouldn't reject the report or the device just because
+of that.
+
+Instead, harden the s32ton() routine so that it returns a reasonable
+result instead of crashing when it is called with the number of bits
+set to 0 -- the same as what snto32() does.
+
+Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
+Reported-by: syzbot+b63d677d63bcac06cf90@syzkaller.appspotmail.com
+Closes: https://lore.kernel.org/linux-usb/68753a08.050a0220.33d347.0008.GAE@google.com/
+Tested-by: syzbot+b63d677d63bcac06cf90@syzkaller.appspotmail.com
+Fixes: dde5845a529f ("[PATCH] Generic HID layer - code split")
+Cc: stable@vger.kernel.org
+Link: https://patch.msgid.link/613a66cd-4309-4bce-a4f7-2905f9bce0c9@rowland.harvard.edu
+Signed-off-by: Benjamin Tissoires <bentiss@kernel.org>
+[ s32ton() was moved by c653ffc28340 ("HID: stop exporting hid_snto32()").
+  Minor context change fixed. ]
+Signed-off-by: Wenshan Lan <jetlan9@163.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/hid/hid-core.c |    7 ++++++-
+ 1 file changed, 6 insertions(+), 1 deletion(-)
+
+--- a/drivers/hid/hid-core.c
++++ b/drivers/hid/hid-core.c
+@@ -1349,7 +1349,12 @@ EXPORT_SYMBOL_GPL(hid_snto32);
+ static u32 s32ton(__s32 value, unsigned n)
+ {
+-      s32 a = value >> (n - 1);
++      s32 a;
++
++      if (!value || !n)
++              return 0;
++
++      a = value >> (n - 1);
+       if (a && a != -1)
+               return value < 0 ? 1 << (n - 1) : (1 << (n - 1)) - 1;
+       return value & ((1 << n) - 1);
diff --git a/queue-5.15/iommu-qcom-fix-device-leak-on-of_xlate.patch b/queue-5.15/iommu-qcom-fix-device-leak-on-of_xlate.patch
new file mode 100644 (file)
index 0000000..e04322b
--- /dev/null
@@ -0,0 +1,66 @@
+From stable+bounces-204848-greg=kroah.com@vger.kernel.org Mon Jan  5 17:42:16 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon,  5 Jan 2026 11:09:11 -0500
+Subject: iommu/qcom: fix device leak on of_xlate()
+To: stable@vger.kernel.org
+Cc: Johan Hovold <johan@kernel.org>, Rob Clark <robin.clark@oss.qualcomm.com>, Yu Kuai <yukuai3@huawei.com>, Robin Murphy <robin.murphy@arm.com>, Joerg Roedel <joerg.roedel@amd.com>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260105160912.2661912-1-sashal@kernel.org>
+
+From: Johan Hovold <johan@kernel.org>
+
+[ Upstream commit 6a3908ce56e6879920b44ef136252b2f0c954194 ]
+
+Make sure to drop the reference taken to the iommu platform device when
+looking up its driver data during of_xlate().
+
+Note that commit e2eae09939a8 ("iommu/qcom: add missing put_device()
+call in qcom_iommu_of_xlate()") fixed the leak in a couple of error
+paths, but the reference is still leaking on success and late failures.
+
+Fixes: 0ae349a0f33f ("iommu/qcom: Add qcom_iommu")
+Cc: stable@vger.kernel.org     # 4.14: e2eae09939a8
+Cc: Rob Clark <robin.clark@oss.qualcomm.com>
+Cc: Yu Kuai <yukuai3@huawei.com>
+Acked-by: Robin Murphy <robin.murphy@arm.com>
+Signed-off-by: Johan Hovold <johan@kernel.org>
+Signed-off-by: Joerg Roedel <joerg.roedel@amd.com>
+[ adapted validation logic from max_asid to num_ctxs ]
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/iommu/arm/arm-smmu/qcom_iommu.c |   10 ++++------
+ 1 file changed, 4 insertions(+), 6 deletions(-)
+
+--- a/drivers/iommu/arm/arm-smmu/qcom_iommu.c
++++ b/drivers/iommu/arm/arm-smmu/qcom_iommu.c
+@@ -568,15 +568,15 @@ static int qcom_iommu_of_xlate(struct de
+       qcom_iommu = platform_get_drvdata(iommu_pdev);
++      put_device(&iommu_pdev->dev);
++
+       /* make sure the asid specified in dt is valid, so we don't have
+        * to sanity check this elsewhere, since 'asid - 1' is used to
+        * index into qcom_iommu->ctxs:
+        */
+       if (WARN_ON(asid < 1) ||
+-          WARN_ON(asid > qcom_iommu->num_ctxs)) {
+-              put_device(&iommu_pdev->dev);
++          WARN_ON(asid > qcom_iommu->num_ctxs))
+               return -EINVAL;
+-      }
+       if (!dev_iommu_priv_get(dev)) {
+               dev_iommu_priv_set(dev, qcom_iommu);
+@@ -585,10 +585,8 @@ static int qcom_iommu_of_xlate(struct de
+                * multiple different iommu devices.  Multiple context
+                * banks are ok, but multiple devices are not:
+                */
+-              if (WARN_ON(qcom_iommu != dev_iommu_priv_get(dev))) {
+-                      put_device(&iommu_pdev->dev);
++              if (WARN_ON(qcom_iommu != dev_iommu_priv_get(dev)))
+                       return -EINVAL;
+-              }
+       }
+       return iommu_fwspec_add_ids(dev, &asid, 1);
diff --git a/queue-5.15/jbd2-fix-the-inconsistency-between-checksum-and-data-in-memory-for-journal-sb.patch b/queue-5.15/jbd2-fix-the-inconsistency-between-checksum-and-data-in-memory-for-journal-sb.patch
new file mode 100644 (file)
index 0000000..2eeb9bd
--- /dev/null
@@ -0,0 +1,94 @@
+From stable+bounces-204162-greg=kroah.com@vger.kernel.org Tue Dec 30 02:01:08 2025
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 29 Dec 2025 20:01:02 -0500
+Subject: jbd2: fix the inconsistency between checksum and data in memory for journal sb
+To: stable@vger.kernel.org
+Cc: Ye Bin <yebin10@huawei.com>, Baokun Li <libaokun1@huawei.com>, "Darrick J. Wong" <djwong@kernel.org>, Jan Kara <jack@suse.cz>, Theodore Ts'o <tytso@mit.edu>, stable@kernel.org, Sasha Levin <sashal@kernel.org>
+Message-ID: <20251230010102.1899453-1-sashal@kernel.org>
+
+From: Ye Bin <yebin10@huawei.com>
+
+[ Upstream commit 6abfe107894af7e8ce3a2e120c619d81ee764ad5 ]
+
+Copying the file system while it is mounted as read-only results in
+a mount failure:
+[~]# mkfs.ext4 -F /dev/sdc
+[~]# mount /dev/sdc -o ro /mnt/test
+[~]# dd if=/dev/sdc of=/dev/sda bs=1M
+[~]# mount /dev/sda /mnt/test1
+[ 1094.849826] JBD2: journal checksum error
+[ 1094.850927] EXT4-fs (sda): Could not load journal inode
+mount: mount /dev/sda on /mnt/test1 failed: Bad message
+
+The process described above is just an abstracted way I came up with to
+reproduce the issue. In the actual scenario, the file system was mounted
+read-only and then copied while it was still mounted. It was found that
+the mount operation failed. The user intended to verify the data or use
+it as a backup, and this action was performed during a version upgrade.
+Above issue may happen as follows:
+ext4_fill_super
+ set_journal_csum_feature_set(sb)
+  if (ext4_has_metadata_csum(sb))
+   incompat = JBD2_FEATURE_INCOMPAT_CSUM_V3;
+  if (test_opt(sb, JOURNAL_CHECKSUM)
+   jbd2_journal_set_features(sbi->s_journal, compat, 0, incompat);
+    lock_buffer(journal->j_sb_buffer);
+    sb->s_feature_incompat  |= cpu_to_be32(incompat);
+    //The data in the journal sb was modified, but the checksum was not
+      updated, so the data remaining in memory has a mismatch between the
+      data and the checksum.
+    unlock_buffer(journal->j_sb_buffer);
+
+In this case, the journal sb copied over is in a state where the checksum
+and data are inconsistent, so mounting fails.
+To solve the above issue, update the checksum in memory after modifying
+the journal sb.
+
+Fixes: 4fd5ea43bc11 ("jbd2: checksum journal superblock")
+Signed-off-by: Ye Bin <yebin10@huawei.com>
+Reviewed-by: Baokun Li <libaokun1@huawei.com>
+Reviewed-by: Darrick J. Wong <djwong@kernel.org>
+Reviewed-by: Jan Kara <jack@suse.cz>
+Message-ID: <20251103010123.3753631-1-yebin@huaweicloud.com>
+Signed-off-by: Theodore Ts'o <tytso@mit.edu>
+Cc: stable@kernel.org
+[ Changed jbd2_superblock_csum(sb) to jbd2_superblock_csum(journal, sb) ]
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/jbd2/journal.c |   14 ++++++++++++++
+ 1 file changed, 14 insertions(+)
+
+--- a/fs/jbd2/journal.c
++++ b/fs/jbd2/journal.c
+@@ -2390,6 +2390,12 @@ int jbd2_journal_set_features(journal_t
+       sb->s_feature_compat    |= cpu_to_be32(compat);
+       sb->s_feature_ro_compat |= cpu_to_be32(ro);
+       sb->s_feature_incompat  |= cpu_to_be32(incompat);
++      /*
++       * Update the checksum now so that it is valid even for read-only
++       * filesystems where jbd2_write_superblock() doesn't get called.
++       */
++      if (jbd2_journal_has_csum_v2or3(journal))
++              sb->s_checksum = jbd2_superblock_csum(journal, sb);
+       unlock_buffer(journal->j_sb_buffer);
+       journal->j_revoke_records_per_block =
+                               journal_revoke_records_per_block(journal);
+@@ -2420,9 +2426,17 @@ void jbd2_journal_clear_features(journal
+       sb = journal->j_superblock;
++      lock_buffer(journal->j_sb_buffer);
+       sb->s_feature_compat    &= ~cpu_to_be32(compat);
+       sb->s_feature_ro_compat &= ~cpu_to_be32(ro);
+       sb->s_feature_incompat  &= ~cpu_to_be32(incompat);
++      /*
++       * Update the checksum now so that it is valid even for read-only
++       * filesystems where jbd2_write_superblock() doesn't get called.
++       */
++      if (jbd2_journal_has_csum_v2or3(journal))
++              sb->s_checksum = jbd2_superblock_csum(journal, sb);
++      unlock_buffer(journal->j_sb_buffer);
+       journal->j_revoke_records_per_block =
+                               journal_revoke_records_per_block(journal);
+ }
diff --git a/queue-5.15/kvm-nvmx-immediately-refresh-apicv-controls-as-needed-on-nested-vm-exit.patch b/queue-5.15/kvm-nvmx-immediately-refresh-apicv-controls-as-needed-on-nested-vm-exit.patch
new file mode 100644 (file)
index 0000000..52806b1
--- /dev/null
@@ -0,0 +1,93 @@
+From stable+bounces-204315-greg=kroah.com@vger.kernel.org Wed Dec 31 04:17:26 2025
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 30 Dec 2025 22:17:17 -0500
+Subject: KVM: nVMX: Immediately refresh APICv controls as needed on nested VM-Exit
+To: stable@vger.kernel.org
+Cc: Dongli Zhang <dongli.zhang@oracle.com>, Chao Gao <chao.gao@intel.com>, Sean Christopherson <seanjc@google.com>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20251231031717.2685182-1-sashal@kernel.org>
+
+From: Dongli Zhang <dongli.zhang@oracle.com>
+
+[ Upstream commit 29763138830916f46daaa50e83e7f4f907a3236b ]
+
+If an APICv status updated was pended while L2 was active, immediately
+refresh vmcs01's controls instead of pending KVM_REQ_APICV_UPDATE as
+kvm_vcpu_update_apicv() only calls into vendor code if a change is
+necessary.
+
+E.g. if APICv is inhibited, and then activated while L2 is running:
+
+  kvm_vcpu_update_apicv()
+  |
+  -> __kvm_vcpu_update_apicv()
+     |
+     -> apic->apicv_active = true
+      |
+      -> vmx_refresh_apicv_exec_ctrl()
+         |
+         -> vmx->nested.update_vmcs01_apicv_status = true
+          |
+          -> return
+
+Then L2 exits to L1:
+
+  __nested_vmx_vmexit()
+  |
+  -> kvm_make_request(KVM_REQ_APICV_UPDATE)
+
+  vcpu_enter_guest(): KVM_REQ_APICV_UPDATE
+  -> kvm_vcpu_update_apicv()
+     |
+     -> __kvm_vcpu_update_apicv()
+        |
+        -> return // because if (apic->apicv_active == activate)
+
+Reported-by: Chao Gao <chao.gao@intel.com>
+Closes: https://lore.kernel.org/all/aQ2jmnN8wUYVEawF@intel.com
+Fixes: 7c69661e225c ("KVM: nVMX: Defer APICv updates while L2 is active until L1 is active")
+Cc: stable@vger.kernel.org
+Signed-off-by: Dongli Zhang <dongli.zhang@oracle.com>
+[sean: write changelog]
+Link: https://patch.msgid.link/20251205231913.441872-3-seanjc@google.com
+Signed-off-by: Sean Christopherson <seanjc@google.com>
+[ exported vmx_refresh_apicv_exec_ctrl() and added declaration in vmx.h ]
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/x86/kvm/vmx/nested.c |    2 +-
+ arch/x86/kvm/vmx/vmx.c    |    2 +-
+ arch/x86/kvm/vmx/vmx.h    |    1 +
+ 3 files changed, 3 insertions(+), 2 deletions(-)
+
+--- a/arch/x86/kvm/vmx/nested.c
++++ b/arch/x86/kvm/vmx/nested.c
+@@ -4684,7 +4684,7 @@ void nested_vmx_vmexit(struct kvm_vcpu *
+       if (vmx->nested.update_vmcs01_apicv_status) {
+               vmx->nested.update_vmcs01_apicv_status = false;
+-              kvm_make_request(KVM_REQ_APICV_UPDATE, vcpu);
++              vmx_refresh_apicv_exec_ctrl(vcpu);
+       }
+       if ((vm_exit_reason != -1) &&
+--- a/arch/x86/kvm/vmx/vmx.c
++++ b/arch/x86/kvm/vmx/vmx.c
+@@ -4217,7 +4217,7 @@ static u32 vmx_vmexit_ctrl(void)
+               ~(VM_EXIT_LOAD_IA32_PERF_GLOBAL_CTRL | VM_EXIT_LOAD_IA32_EFER);
+ }
+-static void vmx_refresh_apicv_exec_ctrl(struct kvm_vcpu *vcpu)
++void vmx_refresh_apicv_exec_ctrl(struct kvm_vcpu *vcpu)
+ {
+       struct vcpu_vmx *vmx = to_vmx(vcpu);
+--- a/arch/x86/kvm/vmx/vmx.h
++++ b/arch/x86/kvm/vmx/vmx.h
+@@ -386,6 +386,7 @@ void __vmx_set_segment(struct kvm_vcpu *
+ u64 construct_eptp(struct kvm_vcpu *vcpu, hpa_t root_hpa, int root_level);
+ bool vmx_guest_inject_ac(struct kvm_vcpu *vcpu);
++void vmx_refresh_apicv_exec_ctrl(struct kvm_vcpu *vcpu);
+ void vmx_update_exception_bitmap(struct kvm_vcpu *vcpu);
+ bool vmx_nmi_blocked(struct kvm_vcpu *vcpu);
+ bool __vmx_interrupt_blocked(struct kvm_vcpu *vcpu);
diff --git a/queue-5.15/kvm-svm-mark-vmcb_npt-as-dirty-on-nested-vmrun.patch b/queue-5.15/kvm-svm-mark-vmcb_npt-as-dirty-on-nested-vmrun.patch
new file mode 100644 (file)
index 0000000..ab26a8a
--- /dev/null
@@ -0,0 +1,41 @@
+From stable+bounces-204358-greg=kroah.com@vger.kernel.org Wed Dec 31 15:39:22 2025
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 31 Dec 2025 09:39:17 -0500
+Subject: KVM: SVM: Mark VMCB_NPT as dirty on nested VMRUN
+To: stable@vger.kernel.org
+Cc: Jim Mattson <jmattson@google.com>, Sean Christopherson <seanjc@google.com>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20251231143917.3047237-1-sashal@kernel.org>
+
+From: Jim Mattson <jmattson@google.com>
+
+[ Upstream commit 7c8b465a1c91f674655ea9cec5083744ec5f796a ]
+
+Mark the VMCB_NPT bit as dirty in nested_vmcb02_prepare_save()
+on every nested VMRUN.
+
+If L1 changes the PAT MSR between two VMRUN instructions on the same
+L1 vCPU, the g_pat field in the associated vmcb02 will change, and the
+VMCB_NPT clean bit should be cleared.
+
+Fixes: 4bb170a5430b ("KVM: nSVM: do not mark all VMCB02 fields dirty on nested vmexit")
+Cc: stable@vger.kernel.org
+Signed-off-by: Jim Mattson <jmattson@google.com>
+Link: https://lore.kernel.org/r/20250922162935.621409-3-jmattson@google.com
+Signed-off-by: Sean Christopherson <seanjc@google.com>
+[ adapted vmcb02 local variable to svm->vmcb direct access pattern ]
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/x86/kvm/svm/nested.c |    1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/arch/x86/kvm/svm/nested.c
++++ b/arch/x86/kvm/svm/nested.c
+@@ -456,6 +456,7 @@ static void nested_vmcb02_prepare_save(s
+       bool new_vmcb12 = false;
+       nested_vmcb02_compute_g_pat(svm);
++      vmcb_mark_dirty(svm->vmcb, VMCB_NPT);
+       /* Load the nested guest state */
+       if (svm->nested.vmcb12_gpa != svm->nested.last_vmcb12_gpa) {
diff --git a/queue-5.15/kvm-x86-acquire-kvm-srcu-when-handling-kvm_set_vcpu_events.patch b/queue-5.15/kvm-x86-acquire-kvm-srcu-when-handling-kvm_set_vcpu_events.patch
new file mode 100644 (file)
index 0000000..1c94e2e
--- /dev/null
@@ -0,0 +1,86 @@
+From stable+bounces-199969-greg=kroah.com@vger.kernel.org Thu Dec  4 09:25:54 2025
+From: Rajani Kantha <681739313@139.com>
+Date: Thu,  4 Dec 2025 16:19:31 +0800
+Subject: KVM: x86: Acquire kvm->srcu when handling KVM_SET_VCPU_EVENTS
+To: seanjc@google.com
+Cc: stable@vger.kernel.org
+Message-ID: <20251204081931.14728-1-681739313@139.com>
+
+From: Sean Christopherson <seanjc@google.com>
+
+commit 4bcdd831d9d01e0fb64faea50732b59b2ee88da1 upstream.
+
+Grab kvm->srcu when processing KVM_SET_VCPU_EVENTS, as KVM will forcibly
+leave nested VMX/SVM if SMM mode is being toggled, and leaving nested VMX
+reads guest memory.
+
+Note, kvm_vcpu_ioctl_x86_set_vcpu_events() can also be called from KVM_RUN
+via sync_regs(), which already holds SRCU.  I.e. trying to precisely use
+kvm_vcpu_srcu_read_lock() around the problematic SMM code would cause
+problems.  Acquiring SRCU isn't all that expensive, so for simplicity,
+grab it unconditionally for KVM_SET_VCPU_EVENTS.
+
+ =============================
+ WARNING: suspicious RCU usage
+ 6.10.0-rc7-332d2c1d713e-next-vm #552 Not tainted
+ -----------------------------
+ include/linux/kvm_host.h:1027 suspicious rcu_dereference_check() usage!
+
+ other info that might help us debug this:
+
+ rcu_scheduler_active = 2, debug_locks = 1
+ 1 lock held by repro/1071:
+  #0: ffff88811e424430 (&vcpu->mutex){+.+.}-{3:3}, at: kvm_vcpu_ioctl+0x7d/0x970 [kvm]
+
+ stack backtrace:
+ CPU: 15 PID: 1071 Comm: repro Not tainted 6.10.0-rc7-332d2c1d713e-next-vm #552
+ Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 0.0.0 02/06/2015
+ Call Trace:
+  <TASK>
+  dump_stack_lvl+0x7f/0x90
+  lockdep_rcu_suspicious+0x13f/0x1a0
+  kvm_vcpu_gfn_to_memslot+0x168/0x190 [kvm]
+  kvm_vcpu_read_guest+0x3e/0x90 [kvm]
+  nested_vmx_load_msr+0x6b/0x1d0 [kvm_intel]
+  load_vmcs12_host_state+0x432/0xb40 [kvm_intel]
+  vmx_leave_nested+0x30/0x40 [kvm_intel]
+  kvm_vcpu_ioctl_x86_set_vcpu_events+0x15d/0x2b0 [kvm]
+  kvm_arch_vcpu_ioctl+0x1107/0x1750 [kvm]
+  ? mark_held_locks+0x49/0x70
+  ? kvm_vcpu_ioctl+0x7d/0x970 [kvm]
+  ? kvm_vcpu_ioctl+0x497/0x970 [kvm]
+  kvm_vcpu_ioctl+0x497/0x970 [kvm]
+  ? lock_acquire+0xba/0x2d0
+  ? find_held_lock+0x2b/0x80
+  ? do_user_addr_fault+0x40c/0x6f0
+  ? lock_release+0xb7/0x270
+  __x64_sys_ioctl+0x82/0xb0
+  do_syscall_64+0x6c/0x170
+  entry_SYSCALL_64_after_hwframe+0x4b/0x53
+ RIP: 0033:0x7ff11eb1b539
+  </TASK>
+
+Fixes: f7e570780efc ("KVM: x86: Forcibly leave nested virt when SMM state is toggled")
+Cc: stable@vger.kernel.org
+Link: https://lore.kernel.org/r/20240723232055.3643811-1-seanjc@google.com
+Signed-off-by: Sean Christopherson <seanjc@google.com>
+[ Based on kernel 5.15 available functions, using srcu_read_lock/srcu_read_unlock instead of
+kvm_vcpu_srcu_read_lock/kvm_vcpu_srcu_read_unlock ]
+Signed-off-by: Rajani Kantha <681739313@139.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/x86/kvm/x86.c |    2 ++
+ 1 file changed, 2 insertions(+)
+
+--- a/arch/x86/kvm/x86.c
++++ b/arch/x86/kvm/x86.c
+@@ -5294,7 +5294,9 @@ long kvm_arch_vcpu_ioctl(struct file *fi
+               if (copy_from_user(&events, argp, sizeof(struct kvm_vcpu_events)))
+                       break;
++              vcpu->srcu_idx = srcu_read_lock(&vcpu->kvm->srcu);
+               r = kvm_vcpu_ioctl_x86_set_vcpu_events(vcpu, &events);
++              srcu_read_unlock(&vcpu->kvm->srcu, vcpu->srcu_idx);
+               break;
+       }
+       case KVM_GET_DEBUGREGS: {
diff --git a/queue-5.15/lockd-fix-vfs_test_lock-calls.patch b/queue-5.15/lockd-fix-vfs_test_lock-calls.patch
new file mode 100644 (file)
index 0000000..bc00df7
--- /dev/null
@@ -0,0 +1,182 @@
+From stable+bounces-206053-greg=kroah.com@vger.kernel.org Wed Jan  7 00:28:41 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue,  6 Jan 2026 18:28:35 -0500
+Subject: lockd: fix vfs_test_lock() calls
+To: stable@vger.kernel.org
+Cc: NeilBrown <neil@brown.name>, Olga Kornievskaia <okorniev@redhat.com>, Jeff Layton <jlayton@kernel.org>, Chuck Lever <chuck.lever@oracle.com>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260106232835.3452850-1-sashal@kernel.org>
+
+From: NeilBrown <neil@brown.name>
+
+[ Upstream commit a49a2a1baa0c553c3548a1c414b6a3c005a8deba ]
+
+Usage of vfs_test_lock() is somewhat confused.  Documentation suggests
+it is given a "lock" but this is not the case.  It is given a struct
+file_lock which contains some details of the sort of lock it should be
+looking for.
+
+In particular passing a "file_lock" containing fl_lmops or fl_ops is
+meaningless and possibly confusing.
+
+This is particularly problematic in lockd.  nlmsvc_testlock() receives
+an initialised "file_lock" from xdr-decode, including manager ops and an
+owner.  It then mistakenly passes this to vfs_test_lock() which might
+replace the owner and the ops.  This can lead to confusion when freeing
+the lock.
+
+The primary role of the 'struct file_lock' passed to vfs_test_lock() is
+to report a conflicting lock that was found, so it makes more sense for
+nlmsvc_testlock() to pass "conflock", which it uses for returning the
+conflicting lock.
+
+With this change, freeing of the lock is not confused and code in
+__nlm4svc_proc_test() and __nlmsvc_proc_test() can be simplified.
+
+Documentation for vfs_test_lock() is improved to reflect its real
+purpose, and a WARN_ON_ONCE() is added to avoid a similar problem in the
+future.
+
+Reported-by: Olga Kornievskaia <okorniev@redhat.com>
+Closes: https://lore.kernel.org/all/20251021130506.45065-1-okorniev@redhat.com
+Signed-off-by: NeilBrown <neil@brown.name>
+Fixes: 20fa19027286 ("nfs: add export operations")
+Cc: stable@vger.kernel.org
+Reviewed-by: Jeff Layton <jlayton@kernel.org>
+Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
+[ adapted c.flc_* field accesses to direct fl_* fields ]
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/lockd/svc4proc.c |    4 +---
+ fs/lockd/svclock.c  |   21 ++++++++++++---------
+ fs/lockd/svcproc.c  |    5 +----
+ fs/locks.c          |   13 +++++++++++--
+ 4 files changed, 25 insertions(+), 18 deletions(-)
+
+--- a/fs/lockd/svc4proc.c
++++ b/fs/lockd/svc4proc.c
+@@ -96,7 +96,6 @@ __nlm4svc_proc_test(struct svc_rqst *rqs
+       struct nlm_args *argp = rqstp->rq_argp;
+       struct nlm_host *host;
+       struct nlm_file *file;
+-      struct nlm_lockowner *test_owner;
+       __be32 rc = rpc_success;
+       dprintk("lockd: TEST4        called\n");
+@@ -106,7 +105,6 @@ __nlm4svc_proc_test(struct svc_rqst *rqs
+       if ((resp->status = nlm4svc_retrieve_args(rqstp, argp, &host, &file)))
+               return resp->status == nlm_drop_reply ? rpc_drop_reply :rpc_success;
+-      test_owner = argp->lock.fl.fl_owner;
+       /* Now check for conflicting locks */
+       resp->status = nlmsvc_testlock(rqstp, file, host, &argp->lock, &resp->lock, &resp->cookie);
+       if (resp->status == nlm_drop_reply)
+@@ -114,7 +112,7 @@ __nlm4svc_proc_test(struct svc_rqst *rqs
+       else
+               dprintk("lockd: TEST4        status %d\n", ntohl(resp->status));
+-      nlmsvc_put_lockowner(test_owner);
++      nlmsvc_release_lockowner(&argp->lock);
+       nlmsvc_release_host(host);
+       nlm_release_file(file);
+       return rc;
+--- a/fs/lockd/svclock.c
++++ b/fs/lockd/svclock.c
+@@ -604,7 +604,13 @@ nlmsvc_testlock(struct svc_rqst *rqstp,
+       }
+       mode = lock_to_openmode(&lock->fl);
+-      error = vfs_test_lock(file->f_file[mode], &lock->fl);
++      locks_init_lock(&conflock->fl);
++      /* vfs_test_lock only uses start, end, and owner, but tests fl_file */
++      conflock->fl.fl_file = lock->fl.fl_file;
++      conflock->fl.fl_start = lock->fl.fl_start;
++      conflock->fl.fl_end = lock->fl.fl_end;
++      conflock->fl.fl_owner = lock->fl.fl_owner;
++      error = vfs_test_lock(file->f_file[mode], &conflock->fl);
+       if (error) {
+               /* We can't currently deal with deferred test requests */
+               if (error == FILE_LOCK_DEFERRED)
+@@ -614,22 +620,19 @@ nlmsvc_testlock(struct svc_rqst *rqstp,
+               goto out;
+       }
+-      if (lock->fl.fl_type == F_UNLCK) {
++      if (conflock->fl.fl_type == F_UNLCK) {
+               ret = nlm_granted;
+               goto out;
+       }
+       dprintk("lockd: conflicting lock(ty=%d, %Ld-%Ld)\n",
+-              lock->fl.fl_type, (long long)lock->fl.fl_start,
+-              (long long)lock->fl.fl_end);
++              conflock->fl.fl_type, (long long)conflock->fl.fl_start,
++              (long long)conflock->fl.fl_end);
+       conflock->caller = "somehost";  /* FIXME */
+       conflock->len = strlen(conflock->caller);
+       conflock->oh.len = 0;           /* don't return OH info */
+-      conflock->svid = lock->fl.fl_pid;
+-      conflock->fl.fl_type = lock->fl.fl_type;
+-      conflock->fl.fl_start = lock->fl.fl_start;
+-      conflock->fl.fl_end = lock->fl.fl_end;
+-      locks_release_private(&lock->fl);
++      conflock->svid = conflock->fl.fl_pid;
++      locks_release_private(&conflock->fl);
+       ret = nlm_lck_denied;
+ out:
+--- a/fs/lockd/svcproc.c
++++ b/fs/lockd/svcproc.c
+@@ -117,7 +117,6 @@ __nlmsvc_proc_test(struct svc_rqst *rqst
+       struct nlm_args *argp = rqstp->rq_argp;
+       struct nlm_host *host;
+       struct nlm_file *file;
+-      struct nlm_lockowner *test_owner;
+       __be32 rc = rpc_success;
+       dprintk("lockd: TEST          called\n");
+@@ -127,8 +126,6 @@ __nlmsvc_proc_test(struct svc_rqst *rqst
+       if ((resp->status = nlmsvc_retrieve_args(rqstp, argp, &host, &file)))
+               return resp->status == nlm_drop_reply ? rpc_drop_reply :rpc_success;
+-      test_owner = argp->lock.fl.fl_owner;
+-
+       /* Now check for conflicting locks */
+       resp->status = cast_status(nlmsvc_testlock(rqstp, file, host, &argp->lock, &resp->lock, &resp->cookie));
+       if (resp->status == nlm_drop_reply)
+@@ -137,7 +134,7 @@ __nlmsvc_proc_test(struct svc_rqst *rqst
+               dprintk("lockd: TEST          status %d vers %d\n",
+                       ntohl(resp->status), rqstp->rq_vers);
+-      nlmsvc_put_lockowner(test_owner);
++      nlmsvc_release_lockowner(&argp->lock);
+       nlmsvc_release_host(host);
+       nlm_release_file(file);
+       return rc;
+--- a/fs/locks.c
++++ b/fs/locks.c
+@@ -2229,13 +2229,22 @@ SYSCALL_DEFINE2(flock, unsigned int, fd,
+ /**
+  * vfs_test_lock - test file byte range lock
+  * @filp: The file to test lock for
+- * @fl: The lock to test; also used to hold result
++ * @fl: The byte-range in the file to test; also used to hold result
+  *
++ * On entry, @fl does not contain a lock, but identifies a range (fl_start, fl_end)
++ * in the file (c.flc_file), and an owner (c.flc_owner) for whom existing locks
++ * should be ignored.  c.flc_type and c.flc_flags are ignored.
++ * Both fl_lmops and fl_ops in @fl must be NULL.
+  * Returns -ERRNO on failure.  Indicates presence of conflicting lock by
+- * setting conf->fl_type to something other than F_UNLCK.
++ * setting fl->fl_type to something other than F_UNLCK.
++ *
++ * If vfs_test_lock() does find a lock and return it, the caller must
++ * use locks_free_lock() or locks_release_private() on the returned lock.
+  */
+ int vfs_test_lock(struct file *filp, struct file_lock *fl)
+ {
++      WARN_ON_ONCE(fl->fl_ops || fl->fl_lmops);
++      WARN_ON_ONCE(filp != fl->fl_file);
+       if (filp->f_op->lock)
+               return filp->f_op->lock(filp, F_GETLK, fl);
+       posix_test_lock(filp, fl);
diff --git a/queue-5.15/media-mediatek-vcodec-fix-a-reference-leak-in-mtk_vcodec_fw_vpu_init.patch b/queue-5.15/media-mediatek-vcodec-fix-a-reference-leak-in-mtk_vcodec_fw_vpu_init.patch
new file mode 100644 (file)
index 0000000..39ac960
--- /dev/null
@@ -0,0 +1,47 @@
+From stable+bounces-204962-greg=kroah.com@vger.kernel.org Tue Jan  6 01:31:54 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon,  5 Jan 2026 19:31:47 -0500
+Subject: media: mediatek: vcodec: Fix a reference leak in mtk_vcodec_fw_vpu_init()
+To: stable@vger.kernel.org
+Cc: Haoxiang Li <haoxiang_li2024@163.com>, AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>, Tzung-Bi Shih <tzungbi@kernel.org>, Nicolas Dufresne <nicolas.dufresne@collabora.com>, Hans Verkuil <hverkuil+cisco@kernel.org>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260106003147.2858489-1-sashal@kernel.org>
+
+From: Haoxiang Li <haoxiang_li2024@163.com>
+
+[ Upstream commit cdd0f118ef87db8a664fb5ea366fd1766d2df1cd ]
+
+vpu_get_plat_device() increases the reference count of the returned
+platform device. However, when devm_kzalloc() fails, the reference
+is not released, causing a reference leak.
+
+Fix this by calling put_device() on fw_pdev->dev before returning
+on the error path.
+
+Fixes: e25a89f743b1 ("media: mtk-vcodec: potential dereference of null pointer")
+Cc: stable@vger.kernel.org
+Signed-off-by: Haoxiang Li <haoxiang_li2024@163.com>
+Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
+Reviewed-by: Tzung-Bi Shih <tzungbi@kernel.org>
+Signed-off-by: Nicolas Dufresne <nicolas.dufresne@collabora.com>
+Signed-off-by: Hans Verkuil <hverkuil+cisco@kernel.org>
+[ adapted file path from common/ subdirectory and adjusted devm_kzalloc target from plat_dev->dev to dev->plat_dev->dev ]
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/media/platform/mtk-vcodec/mtk_vcodec_fw_vpu.c |    4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+--- a/drivers/media/platform/mtk-vcodec/mtk_vcodec_fw_vpu.c
++++ b/drivers/media/platform/mtk-vcodec/mtk_vcodec_fw_vpu.c
+@@ -94,8 +94,10 @@ struct mtk_vcodec_fw *mtk_vcodec_fw_vpu_
+       vpu_wdt_reg_handler(fw_pdev, mtk_vcodec_vpu_reset_handler, dev, rst_id);
+       fw = devm_kzalloc(&dev->plat_dev->dev, sizeof(*fw), GFP_KERNEL);
+-      if (!fw)
++      if (!fw) {
++              put_device(&fw_pdev->dev);
+               return ERR_PTR(-ENOMEM);
++      }
+       fw->type = VPU;
+       fw->ops = &mtk_vcodec_vpu_msg;
+       fw->pdev = fw_pdev;
diff --git a/queue-5.15/media-renesas-rcar_drif-fix-device-node-reference-leak-in-rcar_drif_bond_enabled.patch b/queue-5.15/media-renesas-rcar_drif-fix-device-node-reference-leak-in-rcar_drif_bond_enabled.patch
new file mode 100644 (file)
index 0000000..0c4e1c7
--- /dev/null
@@ -0,0 +1,45 @@
+From stable+bounces-204910-greg=kroah.com@vger.kernel.org Mon Jan  5 21:14:56 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon,  5 Jan 2026 15:13:35 -0500
+Subject: media: renesas: rcar_drif: fix device node reference leak in rcar_drif_bond_enabled
+To: stable@vger.kernel.org
+Cc: Miaoqian Lin <linmq006@gmail.com>, Geert Uytterhoeven <geert+renesas@glider.be>, Fabrizio Castro <fabrizio.castro.jz@renesas.com>, Hans Verkuil <hverkuil+cisco@kernel.org>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260105201335.2769246-1-sashal@kernel.org>
+
+From: Miaoqian Lin <linmq006@gmail.com>
+
+[ Upstream commit 445e1658894fd74eab7e53071fa16233887574ed ]
+
+The function calls of_parse_phandle() which returns
+a device node with an incremented reference count. When the bonded device
+is not available, the function
+returns NULL without releasing the reference, causing a reference leak.
+
+Add of_node_put(np) to release the device node reference.
+The of_node_put function handles NULL pointers.
+
+Found through static analysis by reviewing the doc of of_parse_phandle()
+and cross-checking its usage patterns across the codebase.
+
+Fixes: 7625ee981af1 ("[media] media: platform: rcar_drif: Add DRIF support")
+Cc: stable@vger.kernel.org
+Signed-off-by: Miaoqian Lin <linmq006@gmail.com>
+Reviewed-by: Geert Uytterhoeven <geert+renesas@glider.be>
+Reviewed-by: Fabrizio Castro <fabrizio.castro.jz@renesas.com>
+Signed-off-by: Hans Verkuil <hverkuil+cisco@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/media/platform/rcar_drif.c |    1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/drivers/media/platform/rcar_drif.c
++++ b/drivers/media/platform/rcar_drif.c
+@@ -1253,6 +1253,7 @@ static struct device_node *rcar_drif_bon
+       if (np && of_device_is_available(np))
+               return np;
++      of_node_put(np);
+       return NULL;
+ }
diff --git a/queue-5.15/media-samsung-exynos4-is-fix-potential-abba-deadlock-on-init.patch b/queue-5.15/media-samsung-exynos4-is-fix-potential-abba-deadlock-on-init.patch
new file mode 100644 (file)
index 0000000..f2707a7
--- /dev/null
@@ -0,0 +1,48 @@
+From stable+bounces-204917-greg=kroah.com@vger.kernel.org Mon Jan  5 21:31:42 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon,  5 Jan 2026 15:31:36 -0500
+Subject: media: samsung: exynos4-is: fix potential ABBA deadlock on init
+To: stable@vger.kernel.org
+Cc: Marek Szyprowski <m.szyprowski@samsung.com>, Sylwester Nawrocki <s.nawrocki@samsung.com>, Hans Verkuil <hverkuil+cisco@kernel.org>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260105203136.2780656-1-sashal@kernel.org>
+
+From: Marek Szyprowski <m.szyprowski@samsung.com>
+
+[ Upstream commit 17dc8ccd6dd5ffe30aa9b0d36e2af1389344ce2b ]
+
+v4l2_device_register_subdev_nodes() must called without taking
+media_dev->graph_mutex to avoid potential AB-BA deadlock on further
+subdevice driver initialization.
+
+Fixes: fa91f1056f17 ("[media] exynos4-is: Add support for asynchronous subdevices registration")
+Cc: stable@vger.kernel.org
+Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
+Acked-by: Sylwester Nawrocki <s.nawrocki@samsung.com>
+Signed-off-by: Hans Verkuil <hverkuil+cisco@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/media/platform/exynos4-is/media-dev.c |   10 ++++++----
+ 1 file changed, 6 insertions(+), 4 deletions(-)
+
+--- a/drivers/media/platform/exynos4-is/media-dev.c
++++ b/drivers/media/platform/exynos4-is/media-dev.c
+@@ -1411,12 +1411,14 @@ static int subdev_notifier_complete(stru
+       mutex_lock(&fmd->media_dev.graph_mutex);
+       ret = fimc_md_create_links(fmd);
+-      if (ret < 0)
+-              goto unlock;
++      if (ret < 0) {
++              mutex_unlock(&fmd->media_dev.graph_mutex);
++              return ret;
++      }
+-      ret = v4l2_device_register_subdev_nodes(&fmd->v4l2_dev);
+-unlock:
+       mutex_unlock(&fmd->media_dev.graph_mutex);
++
++      ret = v4l2_device_register_subdev_nodes(&fmd->v4l2_dev);
+       if (ret < 0)
+               return ret;
diff --git a/queue-5.15/media-verisilicon-protect-g2-hevc-decoder-against-invalid-dpb-index.patch b/queue-5.15/media-verisilicon-protect-g2-hevc-decoder-against-invalid-dpb-index.patch
new file mode 100644 (file)
index 0000000..607df81
--- /dev/null
@@ -0,0 +1,64 @@
+From stable+bounces-204923-greg=kroah.com@vger.kernel.org Mon Jan  5 21:54:32 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon,  5 Jan 2026 15:54:26 -0500
+Subject: media: verisilicon: Protect G2 HEVC decoder against invalid DPB index
+To: stable@vger.kernel.org
+Cc: Nicolas Dufresne <nicolas.dufresne@collabora.com>, Benjamin Gaignard <benjamin.gaignard@collabora.com>, Hans Verkuil <hverkuil+cisco@kernel.org>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260105205426.2793242-1-sashal@kernel.org>
+
+From: Nicolas Dufresne <nicolas.dufresne@collabora.com>
+
+[ Upstream commit 47825b1646a6a9eca0f90baa3d4f98947c2add96 ]
+
+Fix the Hantro G2 HEVC decoder so that we use DPB index 0 whenever a
+ninvalid index is received from user space. This protects the hardware
+from doing faulty memory access which then leads to bus errors.
+
+To be noted that when a reference is missing, userspace such as GStreamer
+passes an invalid DPB index of 255. This issue was found by seeking to a
+CRA picture using GStreamer. The framework is currently missing the code
+to skip over RASL pictures placed after the CRA. This situation can also
+occur while doing live streaming over lossy transport.
+
+Fixes: cb5dd5a0fa518 ("media: hantro: Introduce G2/HEVC decoder")
+Cc: stable@vger.kernel.org
+Reviewed-by: Benjamin Gaignard <benjamin.gaignard@collabora.com>
+Signed-off-by: Nicolas Dufresne <nicolas.dufresne@collabora.com>
+Signed-off-by: Hans Verkuil <hverkuil+cisco@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/staging/media/hantro/hantro_g2_hevc_dec.c |   15 +++++++++++++--
+ 1 file changed, 13 insertions(+), 2 deletions(-)
+
+--- a/drivers/staging/media/hantro/hantro_g2_hevc_dec.c
++++ b/drivers/staging/media/hantro/hantro_g2_hevc_dec.c
+@@ -264,6 +264,15 @@ static void set_params(struct hantro_ctx
+       hantro_reg_write(vpu, &g2_apf_threshold, 8);
+ }
++static u32 get_dpb_index(const struct v4l2_ctrl_hevc_decode_params *decode_params,
++                       const u32 index)
++{
++      if (index > decode_params->num_active_dpb_entries)
++              return 0;
++
++      return index;
++}
++
+ static void set_ref_pic_list(struct hantro_ctx *ctx)
+ {
+       const struct hantro_hevc_dec_ctrls *ctrls = &ctx->hevc_dec.ctrls;
+@@ -336,8 +345,10 @@ static void set_ref_pic_list(struct hant
+               list1[j++] = list1[i++];
+       for (i = 0; i < V4L2_HEVC_DPB_ENTRIES_NUM_MAX; i++) {
+-              hantro_reg_write(vpu, &ref_pic_regs0[i], list0[i]);
+-              hantro_reg_write(vpu, &ref_pic_regs1[i], list1[i]);
++              hantro_reg_write(vpu, &ref_pic_regs0[i],
++                               get_dpb_index(decode_params, list0[i]));
++              hantro_reg_write(vpu, &ref_pic_regs1[i],
++                               get_dpb_index(decode_params, list1[i]));
+       }
+ }
diff --git a/queue-5.15/media-vpif_capture-fix-section-mismatch.patch b/queue-5.15/media-vpif_capture-fix-section-mismatch.patch
new file mode 100644 (file)
index 0000000..d8cc1ba
--- /dev/null
@@ -0,0 +1,50 @@
+From stable+bounces-204924-greg=kroah.com@vger.kernel.org Mon Jan  5 22:05:18 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon,  5 Jan 2026 16:05:09 -0500
+Subject: media: vpif_capture: fix section mismatch
+To: stable@vger.kernel.org
+Cc: Johan Hovold <johan@kernel.org>, Hans Verkuil <hverkuil+cisco@kernel.org>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260105210509.2799904-1-sashal@kernel.org>
+
+From: Johan Hovold <johan@kernel.org>
+
+[ Upstream commit 0ef841113724166c3c484d0e9ae6db1eb5634fde ]
+
+Platform drivers can be probed after their init sections have been
+discarded (e.g. on probe deferral or manual rebind through sysfs) so the
+probe function must not live in init.
+
+Note that commit ffa1b391c61b ("V4L/DVB: vpif_cap/disp: Removed section
+mismatch warning") incorrectly suppressed the modpost warning.
+
+Fixes: ffa1b391c61b ("V4L/DVB: vpif_cap/disp: Removed section mismatch warning")
+Fixes: 6ffefff5a9e7 ("V4L/DVB (12906c): V4L : vpif capture driver for DM6467")
+Cc: stable@vger.kernel.org     # 2.6.32
+Signed-off-by: Johan Hovold <johan@kernel.org>
+Signed-off-by: Hans Verkuil <hverkuil+cisco@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/media/platform/davinci/vpif_capture.c |    4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+--- a/drivers/media/platform/davinci/vpif_capture.c
++++ b/drivers/media/platform/davinci/vpif_capture.c
+@@ -1614,7 +1614,7 @@ err_cleanup:
+  * This creates device entries by register itself to the V4L2 driver and
+  * initializes fields of each channel objects
+  */
+-static __init int vpif_probe(struct platform_device *pdev)
++static int vpif_probe(struct platform_device *pdev)
+ {
+       struct vpif_subdev_info *subdevdata;
+       struct i2c_adapter *i2c_adap;
+@@ -1817,7 +1817,7 @@ static int vpif_resume(struct device *de
+ static SIMPLE_DEV_PM_OPS(vpif_pm_ops, vpif_suspend, vpif_resume);
+-static __refdata struct platform_driver vpif_driver = {
++static struct platform_driver vpif_driver = {
+       .driver = {
+               .name   = VPIF_DRIVER_NAME,
+               .pm     = &vpif_pm_ops,
diff --git a/queue-5.15/mm-balloon_compaction-convert-balloon_page_delete-to-balloon_page_finalize.patch b/queue-5.15/mm-balloon_compaction-convert-balloon_page_delete-to-balloon_page_finalize.patch
new file mode 100644 (file)
index 0000000..a8f9e79
--- /dev/null
@@ -0,0 +1,225 @@
+From stable+bounces-204899-greg=kroah.com@vger.kernel.org Mon Jan  5 20:30:54 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon,  5 Jan 2026 14:28:25 -0500
+Subject: mm/balloon_compaction: convert balloon_page_delete() to balloon_page_finalize()
+To: stable@vger.kernel.org
+Cc: "David Hildenbrand" <david@redhat.com>, "Lorenzo Stoakes" <lorenzo.stoakes@oracle.com>, "Alistair Popple" <apopple@nvidia.com>, "Al Viro" <viro@zeniv.linux.org.uk>, "Arnd Bergmann" <arnd@arndb.de>, "Brendan Jackman" <jackmanb@google.com>, "Byungchul Park" <byungchul@sk.com>, "Chengming Zhou" <chengming.zhou@linux.dev>, "Christian Brauner" <brauner@kernel.org>, "Christophe Leroy" <christophe.leroy@csgroup.eu>, "Eugenio Pé rez" <eperezma@redhat.com>, "Greg Kroah-Hartman" <gregkh@linuxfoundation.org>, "Gregory Price" <gourry@gourry.net>, "Harry Yoo" <harry.yoo@oracle.com>, "Huang, Ying" <ying.huang@linux.alibaba.com>, "Jan Kara" <jack@suse.cz>, "Jason Gunthorpe" <jgg@ziepe.ca>, "Jason Wang" <jasowang@redhat.com>, "Jerrin Shaji George" <jerrin.shaji-george@broadcom.com>, "Johannes Weiner" <hannes@cmpxchg.org>, "John Hubbard" <jhubbard@nvidia.com>, "Jonathan Corbet" <corbet@lwn.net>, "Joshua Hahn" <joshua.hahnjy@gmail.com>, "Liam Howlett" <liam.howlett@oracle.com>, "Madhavan Srinivasan" <maddy@linux.ibm.com>, "Mathew Brost" <matthew.brost@intel.com>, "Matthew Wilcox (Oracle)" <willy@infradead.org>, "Miaohe Lin" <linmiaohe@huawei.com>, "Michael Ellerman" <mpe@ellerman.id.au>, "Michael S. Tsirkin" <mst@redhat.com>, "Michal Hocko" <mhocko@suse.com>, "Mike Rapoport" <rppt@kernel.org>, "Minchan Kim" <minchan@kernel.org>, "Naoya Horiguchi" <nao.horiguchi@gmail.com>, "Nicholas Piggin" <npiggin@gmail.com>, "Oscar Salvador" <osalvador@suse.de>, "Peter Xu" <peterx@redhat.com>, "Qi Zheng" <zhengqi.arch@bytedance.com>, "Rakie Kim" <rakie.kim@sk.com>, "Rik van Riel" <riel@surriel.com>, "Sergey Senozhatsky" <senozhatsky@chromium.org>, "Shakeel Butt" <shakeel.butt@linux.dev>, "Suren Baghdasaryan" <surenb@google.com>, "Vlastimil Babka" <vbabka@suse.cz>, "Xuan Zhuo" <xuanzhuo@linux.alibaba.com>, "xu xin" <xu.xin16@zte.com.cn>, "Zi Yan" <ziy@nvidia.com>, "Andrew Morton" <akpm@linux-foundation.org>, "Sasha Levin" <sashal@kernel.org>
+Message-ID: <20260105192826.2740369-3-sashal@kernel.org>
+
+From: David Hildenbrand <david@redhat.com>
+
+[ Upstream commit 15504b1163007bbfbd9a63460d5c14737c16e96d ]
+
+Let's move the removal of the page from the balloon list into the single
+caller, to remove the dependency on the PG_isolated flag and clarify
+locking requirements.
+
+Note that for now, balloon_page_delete() was used on two paths:
+
+(1) Removing a page from the balloon for deflation through
+    balloon_page_list_dequeue()
+(2) Removing an isolated page from the balloon for migration in the
+    per-driver migration handlers. Isolated pages were already removed from
+    the balloon list during isolation.
+
+So instead of relying on the flag, we can just distinguish both cases
+directly and handle it accordingly in the caller.
+
+We'll shuffle the operations a bit such that they logically make more
+sense (e.g., remove from the list before clearing flags).
+
+In balloon migration functions we can now move the balloon_page_finalize()
+out of the balloon lock and perform the finalization just before dropping
+the balloon reference.
+
+Document that the page lock is currently required when modifying the
+movability aspects of a page; hopefully we can soon decouple this from the
+page lock.
+
+Link: https://lkml.kernel.org/r/20250704102524.326966-3-david@redhat.com
+Signed-off-by: David Hildenbrand <david@redhat.com>
+Reviewed-by: Lorenzo Stoakes <lorenzo.stoakes@oracle.com>
+Cc: Alistair Popple <apopple@nvidia.com>
+Cc: Al Viro <viro@zeniv.linux.org.uk>
+Cc: Arnd Bergmann <arnd@arndb.de>
+Cc: Brendan Jackman <jackmanb@google.com>
+Cc: Byungchul Park <byungchul@sk.com>
+Cc: Chengming Zhou <chengming.zhou@linux.dev>
+Cc: Christian Brauner <brauner@kernel.org>
+Cc: Christophe Leroy <christophe.leroy@csgroup.eu>
+Cc: Eugenio Pé rez <eperezma@redhat.com>
+Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Cc: Gregory Price <gourry@gourry.net>
+Cc: Harry Yoo <harry.yoo@oracle.com>
+Cc: "Huang, Ying" <ying.huang@linux.alibaba.com>
+Cc: Jan Kara <jack@suse.cz>
+Cc: Jason Gunthorpe <jgg@ziepe.ca>
+Cc: Jason Wang <jasowang@redhat.com>
+Cc: Jerrin Shaji George <jerrin.shaji-george@broadcom.com>
+Cc: Johannes Weiner <hannes@cmpxchg.org>
+Cc: John Hubbard <jhubbard@nvidia.com>
+Cc: Jonathan Corbet <corbet@lwn.net>
+Cc: Joshua Hahn <joshua.hahnjy@gmail.com>
+Cc: Liam Howlett <liam.howlett@oracle.com>
+Cc: Madhavan Srinivasan <maddy@linux.ibm.com>
+Cc: Mathew Brost <matthew.brost@intel.com>
+Cc: Matthew Wilcox (Oracle) <willy@infradead.org>
+Cc: Miaohe Lin <linmiaohe@huawei.com>
+Cc: Michael Ellerman <mpe@ellerman.id.au>
+Cc: "Michael S. Tsirkin" <mst@redhat.com>
+Cc: Michal Hocko <mhocko@suse.com>
+Cc: Mike Rapoport <rppt@kernel.org>
+Cc: Minchan Kim <minchan@kernel.org>
+Cc: Naoya Horiguchi <nao.horiguchi@gmail.com>
+Cc: Nicholas Piggin <npiggin@gmail.com>
+Cc: Oscar Salvador <osalvador@suse.de>
+Cc: Peter Xu <peterx@redhat.com>
+Cc: Qi Zheng <zhengqi.arch@bytedance.com>
+Cc: Rakie Kim <rakie.kim@sk.com>
+Cc: Rik van Riel <riel@surriel.com>
+Cc: Sergey Senozhatsky <senozhatsky@chromium.org>
+Cc: Shakeel Butt <shakeel.butt@linux.dev>
+Cc: Suren Baghdasaryan <surenb@google.com>
+Cc: Vlastimil Babka <vbabka@suse.cz>
+Cc: Xuan Zhuo <xuanzhuo@linux.alibaba.com>
+Cc: xu xin <xu.xin16@zte.com.cn>
+Cc: Zi Yan <ziy@nvidia.com>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Stable-dep-of: 0da2ba35c0d5 ("powerpc/pseries/cmm: adjust BALLOON_MIGRATE when migrating pages")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/powerpc/platforms/pseries/cmm.c |    2 -
+ drivers/misc/vmw_balloon.c           |    3 --
+ drivers/virtio/virtio_balloon.c      |    4 ---
+ include/linux/balloon_compaction.h   |   43 +++++++++++++----------------------
+ mm/balloon_compaction.c              |    3 +-
+ 5 files changed, 21 insertions(+), 34 deletions(-)
+
+--- a/arch/powerpc/platforms/pseries/cmm.c
++++ b/arch/powerpc/platforms/pseries/cmm.c
+@@ -550,7 +550,6 @@ static int cmm_migratepage(struct balloo
+       spin_lock_irqsave(&b_dev_info->pages_lock, flags);
+       balloon_page_insert(b_dev_info, newpage);
+-      balloon_page_delete(page);
+       b_dev_info->isolated_pages--;
+       spin_unlock_irqrestore(&b_dev_info->pages_lock, flags);
+@@ -560,6 +559,7 @@ static int cmm_migratepage(struct balloo
+        */
+       plpar_page_set_active(page);
++      balloon_page_finalize(page);
+       /* balloon page list reference */
+       put_page(page);
+--- a/drivers/misc/vmw_balloon.c
++++ b/drivers/misc/vmw_balloon.c
+@@ -1805,8 +1805,7 @@ static int vmballoon_migratepage(struct
+        * @pages_lock . We keep holding @comm_lock since we will need it in a
+        * second.
+        */
+-      balloon_page_delete(page);
+-
++      balloon_page_finalize(page);
+       put_page(page);
+       /* Inflate */
+--- a/drivers/virtio/virtio_balloon.c
++++ b/drivers/virtio/virtio_balloon.c
+@@ -796,15 +796,13 @@ static int virtballoon_migratepage(struc
+       tell_host(vb, vb->inflate_vq);
+       /* balloon's page migration 2nd step -- deflate "page" */
+-      spin_lock_irqsave(&vb_dev_info->pages_lock, flags);
+-      balloon_page_delete(page);
+-      spin_unlock_irqrestore(&vb_dev_info->pages_lock, flags);
+       vb->num_pfns = VIRTIO_BALLOON_PAGES_PER_PAGE;
+       set_page_pfns(vb, vb->pfns, page);
+       tell_host(vb, vb->deflate_vq);
+       mutex_unlock(&vb->balloon_lock);
++      balloon_page_finalize(page);
+       put_page(page); /* balloon reference */
+       return MIGRATEPAGE_SUCCESS;
+--- a/include/linux/balloon_compaction.h
++++ b/include/linux/balloon_compaction.h
+@@ -100,27 +100,6 @@ static inline void balloon_page_insert(s
+ }
+ /*
+- * balloon_page_delete - delete a page from balloon's page list and clear
+- *                     the page->private assignement accordingly.
+- * @page    : page to be released from balloon's page list
+- *
+- * Caller must ensure the page is locked and the spin_lock protecting balloon
+- * pages list is held before deleting a page from the balloon device.
+- */
+-static inline void balloon_page_delete(struct page *page)
+-{
+-      __ClearPageOffline(page);
+-      __ClearPageMovable(page);
+-      set_page_private(page, 0);
+-      /*
+-       * No touch page.lru field once @page has been isolated
+-       * because VM is using the field.
+-       */
+-      if (!PageIsolated(page))
+-              list_del(&page->lru);
+-}
+-
+-/*
+  * balloon_page_device - get the b_dev_info descriptor for the balloon device
+  *                     that enqueues the given page.
+  */
+@@ -143,12 +122,6 @@ static inline void balloon_page_insert(s
+       list_add(&page->lru, &balloon->pages);
+ }
+-static inline void balloon_page_delete(struct page *page)
+-{
+-      __ClearPageOffline(page);
+-      list_del(&page->lru);
+-}
+-
+ static inline gfp_t balloon_mapping_gfp_mask(void)
+ {
+       return GFP_HIGHUSER;
+@@ -157,6 +130,22 @@ static inline gfp_t balloon_mapping_gfp_
+ #endif /* CONFIG_BALLOON_COMPACTION */
+ /*
++ * balloon_page_finalize - prepare a balloon page that was removed from the
++ *                       balloon list for release to the page allocator
++ * @page: page to be released to the page allocator
++ *
++ * Caller must ensure that the page is locked.
++ */
++static inline void balloon_page_finalize(struct page *page)
++{
++      if (IS_ENABLED(CONFIG_BALLOON_COMPACTION)) {
++              __ClearPageMovable(page);
++              set_page_private(page, 0);
++      }
++      __ClearPageOffline(page);
++}
++
++/*
+  * balloon_page_push - insert a page into a page list.
+  * @head : pointer to list
+  * @page : page to be added
+--- a/mm/balloon_compaction.c
++++ b/mm/balloon_compaction.c
+@@ -93,7 +93,8 @@ size_t balloon_page_list_dequeue(struct
+               if (!trylock_page(page))
+                       continue;
+-              balloon_page_delete(page);
++              list_del(&page->lru);
++              balloon_page_finalize(page);
+               __count_vm_event(BALLOON_DEFLATE);
+               list_add(&page->lru, pages);
+               unlock_page(page);
diff --git a/queue-5.15/mm-balloon_compaction-make-balloon-page-compaction-callbacks-static.patch b/queue-5.15/mm-balloon_compaction-make-balloon-page-compaction-callbacks-static.patch
new file mode 100644 (file)
index 0000000..c176927
--- /dev/null
@@ -0,0 +1,96 @@
+From stable+bounces-204897-greg=kroah.com@vger.kernel.org Mon Jan  5 20:30:43 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon,  5 Jan 2026 14:28:23 -0500
+Subject: mm/balloon_compaction: make balloon page compaction callbacks static
+To: stable@vger.kernel.org
+Cc: Miaohe Lin <linmiaohe@huawei.com>, "Michael S. Tsirkin" <mst@redhat.com>, Muchun Song <songmuchun@bytedance.com>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260105192826.2740369-1-sashal@kernel.org>
+
+From: Miaohe Lin <linmiaohe@huawei.com>
+
+[ Upstream commit 504c1cabe325df65c18ef38365ddd1a41c6b591b ]
+
+Since commit b1123ea6d3b3 ("mm: balloon: use general non-lru movable page
+feature"), these functions are called via balloon_aops callbacks. They're
+not called directly outside this file. So make them static and clean up
+the relevant code.
+
+Signed-off-by: Miaohe Lin <linmiaohe@huawei.com>
+Link: https://lore.kernel.org/r/20220125132221.2220-1-linmiaohe@huawei.com
+Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
+Reviewed-by: Muchun Song <songmuchun@bytedance.com>
+Stable-dep-of: 0da2ba35c0d5 ("powerpc/pseries/cmm: adjust BALLOON_MIGRATE when migrating pages")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ include/linux/balloon_compaction.h |   22 ----------------------
+ mm/balloon_compaction.c            |    6 +++---
+ 2 files changed, 3 insertions(+), 25 deletions(-)
+
+--- a/include/linux/balloon_compaction.h
++++ b/include/linux/balloon_compaction.h
+@@ -80,12 +80,6 @@ static inline void balloon_devinfo_init(
+ #ifdef CONFIG_BALLOON_COMPACTION
+ extern const struct address_space_operations balloon_aops;
+-extern bool balloon_page_isolate(struct page *page,
+-                              isolate_mode_t mode);
+-extern void balloon_page_putback(struct page *page);
+-extern int balloon_page_migrate(struct address_space *mapping,
+-                              struct page *newpage,
+-                              struct page *page, enum migrate_mode mode);
+ /*
+  * balloon_page_insert - insert a page into the balloon's page list and make
+@@ -155,22 +149,6 @@ static inline void balloon_page_delete(s
+       list_del(&page->lru);
+ }
+-static inline bool balloon_page_isolate(struct page *page)
+-{
+-      return false;
+-}
+-
+-static inline void balloon_page_putback(struct page *page)
+-{
+-      return;
+-}
+-
+-static inline int balloon_page_migrate(struct page *newpage,
+-                              struct page *page, enum migrate_mode mode)
+-{
+-      return 0;
+-}
+-
+ static inline gfp_t balloon_mapping_gfp_mask(void)
+ {
+       return GFP_HIGHUSER;
+--- a/mm/balloon_compaction.c
++++ b/mm/balloon_compaction.c
+@@ -203,7 +203,7 @@ EXPORT_SYMBOL_GPL(balloon_page_dequeue);
+ #ifdef CONFIG_BALLOON_COMPACTION
+-bool balloon_page_isolate(struct page *page, isolate_mode_t mode)
++static bool balloon_page_isolate(struct page *page, isolate_mode_t mode)
+ {
+       struct balloon_dev_info *b_dev_info = balloon_page_device(page);
+@@ -217,7 +217,7 @@ bool balloon_page_isolate(struct page *p
+       return true;
+ }
+-void balloon_page_putback(struct page *page)
++static void balloon_page_putback(struct page *page)
+ {
+       struct balloon_dev_info *b_dev_info = balloon_page_device(page);
+       unsigned long flags;
+@@ -230,7 +230,7 @@ void balloon_page_putback(struct page *p
+ /* move_to_new_page() counterpart for a ballooned page */
+-int balloon_page_migrate(struct address_space *mapping,
++static int balloon_page_migrate(struct address_space *mapping,
+               struct page *newpage, struct page *page,
+               enum migrate_mode mode)
+ {
diff --git a/queue-5.15/mm-balloon_compaction-we-cannot-have-isolated-pages-in-the-balloon-list.patch b/queue-5.15/mm-balloon_compaction-we-cannot-have-isolated-pages-in-the-balloon-list.patch
new file mode 100644 (file)
index 0000000..f3105a1
--- /dev/null
@@ -0,0 +1,109 @@
+From stable+bounces-204898-greg=kroah.com@vger.kernel.org Mon Jan  5 20:30:49 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon,  5 Jan 2026 14:28:24 -0500
+Subject: mm/balloon_compaction: we cannot have isolated pages in the balloon list
+To: stable@vger.kernel.org
+Cc: "David Hildenbrand" <david@redhat.com>, "Zi Yan" <ziy@nvidia.com>, "Lorenzo Stoakes" <lorenzo.stoakes@oracle.com>, "Alistair Popple" <apopple@nvidia.com>, "Al Viro" <viro@zeniv.linux.org.uk>, "Arnd Bergmann" <arnd@arndb.de>, "Brendan Jackman" <jackmanb@google.com>, "Byungchul Park" <byungchul@sk.com>, "Chengming Zhou" <chengming.zhou@linux.dev>, "Christian Brauner" <brauner@kernel.org>, "Christophe Leroy" <christophe.leroy@csgroup.eu>, "Eugenio Pé rez" <eperezma@redhat.com>, "Greg Kroah-Hartman" <gregkh@linuxfoundation.org>, "Gregory Price" <gourry@gourry.net>, "Huang, Ying" <ying.huang@linux.alibaba.com>, "Jan Kara" <jack@suse.cz>, "Jason Gunthorpe" <jgg@ziepe.ca>, "Jason Wang" <jasowang@redhat.com>, "Jerrin Shaji George" <jerrin.shaji-george@broadcom.com>, "Johannes Weiner" <hannes@cmpxchg.org>, "John Hubbard" <jhubbard@nvidia.com>, "Jonathan Corbet" <corbet@lwn.net>, "Joshua Hahn" <joshua.hahnjy@gmail.com>, "Liam Howlett" <liam.howlett@oracle.com>, "Madhavan Srinivasan" <maddy@linux.ibm.com>, "Mathew Brost" <matthew.brost@intel.com>, "Matthew Wilcox (Oracle)" <willy@infradead.org>, "Miaohe Lin" <linmiaohe@huawei.com>, "Michael Ellerman" <mpe@ellerman.id.au>, "Michael S. Tsirkin" <mst@redhat.com>, "Michal Hocko" <mhocko@suse.com>, "Mike Rapoport" <rppt@kernel.org>, "Minchan Kim" <minchan@kernel.org>, "Naoya Horiguchi" <nao.horiguchi@gmail.com>, "Nicholas Piggin" <npiggin@gmail.com>, "Oscar Salvador" <osalvador@suse.de>, "Peter Xu" <peterx@redhat.com>, "Qi Zheng" <zhengqi.arch@bytedance.com>, "Rakie Kim" <rakie.kim@sk.com>, "Rik van Riel" <riel@surriel.com>, "Sergey Senozhatsky" <senozhatsky@chromium.org>, "Shakeel Butt" <shakeel.butt@linux.dev>, "Suren Baghdasaryan" <surenb@google.com>, "Vlastimil Babka" <vbabka@suse.cz>, "Xuan Zhuo" <xuanzhuo@linux.alibaba.com>, "xu xin" <xu.xin16@zte.com.cn>, "Harry Yoo" <harry.yoo@oracle.com>, "Andrew Morton" <akpm@linux-foundation.org>, "Sasha Levin" <sashal@kernel.org>
+Message-ID: <20260105192826.2740369-2-sashal@kernel.org>
+
+From: David Hildenbrand <david@redhat.com>
+
+[ Upstream commit fb05f992b6bbb4702307d96f00703ee637b24dbf ]
+
+Patch series "mm/migration: rework movable_ops page migration (part 1)",
+v2.
+
+In the future, as we decouple "struct page" from "struct folio", pages
+that support "non-lru page migration" -- movable_ops page migration such
+as memory balloons and zsmalloc -- will no longer be folios.  They will
+not have ->mapping, ->lru, and likely no refcount and no page lock.  But
+they will have a type and flags 🙂
+
+This is the first part (other parts not written yet) of decoupling
+movable_ops page migration from folio migration.
+
+In this series, we get rid of the ->mapping usage, and start cleaning up
+the code + separating it from folio migration.
+
+Migration core will have to be further reworked to not treat movable_ops
+pages like folios.  This is the first step into that direction.
+
+This patch (of 29):
+
+The core will set PG_isolated only after mops->isolate_page() was called.
+In case of the balloon, that is where we will remove it from the balloon
+list.  So we cannot have isolated pages in the balloon list.
+
+Let's drop this unnecessary check.
+
+Link: https://lkml.kernel.org/r/20250704102524.326966-2-david@redhat.com
+Signed-off-by: David Hildenbrand <david@redhat.com>
+Acked-by: Zi Yan <ziy@nvidia.com>
+Reviewed-by: Lorenzo Stoakes <lorenzo.stoakes@oracle.com>
+Cc: Alistair Popple <apopple@nvidia.com>
+Cc: Al Viro <viro@zeniv.linux.org.uk>
+Cc: Arnd Bergmann <arnd@arndb.de>
+Cc: Brendan Jackman <jackmanb@google.com>
+Cc: Byungchul Park <byungchul@sk.com>
+Cc: Chengming Zhou <chengming.zhou@linux.dev>
+Cc: Christian Brauner <brauner@kernel.org>
+Cc: Christophe Leroy <christophe.leroy@csgroup.eu>
+Cc: Eugenio Pé rez <eperezma@redhat.com>
+Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Cc: Gregory Price <gourry@gourry.net>
+Cc: "Huang, Ying" <ying.huang@linux.alibaba.com>
+Cc: Jan Kara <jack@suse.cz>
+Cc: Jason Gunthorpe <jgg@ziepe.ca>
+Cc: Jason Wang <jasowang@redhat.com>
+Cc: Jerrin Shaji George <jerrin.shaji-george@broadcom.com>
+Cc: Johannes Weiner <hannes@cmpxchg.org>
+Cc: John Hubbard <jhubbard@nvidia.com>
+Cc: Jonathan Corbet <corbet@lwn.net>
+Cc: Joshua Hahn <joshua.hahnjy@gmail.com>
+Cc: Liam Howlett <liam.howlett@oracle.com>
+Cc: Madhavan Srinivasan <maddy@linux.ibm.com>
+Cc: Mathew Brost <matthew.brost@intel.com>
+Cc: Matthew Wilcox (Oracle) <willy@infradead.org>
+Cc: Miaohe Lin <linmiaohe@huawei.com>
+Cc: Michael Ellerman <mpe@ellerman.id.au>
+Cc: "Michael S. Tsirkin" <mst@redhat.com>
+Cc: Michal Hocko <mhocko@suse.com>
+Cc: Mike Rapoport <rppt@kernel.org>
+Cc: Minchan Kim <minchan@kernel.org>
+Cc: Naoya Horiguchi <nao.horiguchi@gmail.com>
+Cc: Nicholas Piggin <npiggin@gmail.com>
+Cc: Oscar Salvador <osalvador@suse.de>
+Cc: Peter Xu <peterx@redhat.com>
+Cc: Qi Zheng <zhengqi.arch@bytedance.com>
+Cc: Rakie Kim <rakie.kim@sk.com>
+Cc: Rik van Riel <riel@surriel.com>
+Cc: Sergey Senozhatsky <senozhatsky@chromium.org>
+Cc: Shakeel Butt <shakeel.butt@linux.dev>
+Cc: Suren Baghdasaryan <surenb@google.com>
+Cc: Vlastimil Babka <vbabka@suse.cz>
+Cc: Xuan Zhuo <xuanzhuo@linux.alibaba.com>
+Cc: xu xin <xu.xin16@zte.com.cn>
+Cc: Harry Yoo <harry.yoo@oracle.com>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Stable-dep-of: 0da2ba35c0d5 ("powerpc/pseries/cmm: adjust BALLOON_MIGRATE when migrating pages")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ mm/balloon_compaction.c |    6 ------
+ 1 file changed, 6 deletions(-)
+
+--- a/mm/balloon_compaction.c
++++ b/mm/balloon_compaction.c
+@@ -93,12 +93,6 @@ size_t balloon_page_list_dequeue(struct
+               if (!trylock_page(page))
+                       continue;
+-              if (IS_ENABLED(CONFIG_BALLOON_COMPACTION) &&
+-                  PageIsolated(page)) {
+-                      /* raced with isolation */
+-                      unlock_page(page);
+-                      continue;
+-              }
+               balloon_page_delete(page);
+               __count_vm_event(BALLOON_DEFLATE);
+               list_add(&page->lru, pages);
diff --git a/queue-5.15/mm-mprotect-delete-pmd_none_or_clear_bad_unless_trans_huge.patch b/queue-5.15/mm-mprotect-delete-pmd_none_or_clear_bad_unless_trans_huge.patch
new file mode 100644 (file)
index 0000000..7db44a8
--- /dev/null
@@ -0,0 +1,279 @@
+From stable+bounces-205078-greg=kroah.com@vger.kernel.org Tue Jan  6 12:59:03 2026
+From: Harry Yoo <harry.yoo@oracle.com>
+Date: Tue,  6 Jan 2026 20:50:36 +0900
+Subject: mm/mprotect: delete pmd_none_or_clear_bad_unless_trans_huge()
+To: stable@vger.kernel.org
+Cc: Liam.Howlett@oracle.com, akpm@linux-foundation.org, baohua@kernel.org, baolin.wang@linux.alibaba.com, david@kernel.org, dev.jain@arm.com, hughd@google.com, jane.chu@oracle.com, jannh@google.com, kas@kernel.org, lance.yang@linux.dev, linux-mm@kvack.org, lorenzo.stoakes@oracle.com, npache@redhat.com, pfalcato@suse.de, ryan.roberts@arm.com, vbabka@suse.cz, ziy@nvidia.com, "Alistair Popple" <apopple@nvidia.com>, "Anshuman Khandual" <anshuman.khandual@arm.com>, "Axel Rasmussen" <axelrasmussen@google.com>, "Christophe Leroy" <christophe.leroy@csgroup.eu>, "Christoph Hellwig" <hch@infradead.org>, "David Hildenbrand" <david@redhat.com>, "Huang, Ying" <ying.huang@intel.com>, "Ira Weiny" <ira.weiny@intel.com>, "Jason Gunthorpe" <jgg@ziepe.ca>, "Kirill A . Shutemov" <kirill.shutemov@linux.intel.com>, "Lorenzo Stoakes" <lstoakes@gmail.com>, "Matthew Wilcox" <willy@infradead.org>, "Mel Gorman" <mgorman@techsingularity.net>, "Miaohe Lin" <linmiaohe@huawei.com>, "Mike Kravetz" <mike.kravetz@oracle.com>, "Mike Rapoport" <rppt@kernel.org>, "Minchan Kim" <minchan@kernel.org>, "Naoya Horiguchi" <naoya.horiguchi@nec.com>, "Pavel Tatashin" <pasha.tatashin@soleen.com>, "Peter Xu" <peterx@redhat.com>, "Peter Zijlstra" <peterz@infradead.org>, "Qi Zheng" <zhengqi.arch@bytedance.com>, "Ralph Campbell" <rcampbell@nvidia.com>, "SeongJae Park" <sj@kernel.org>, "Song Liu" <song@kernel.org>, "Steven Price" <steven.price@arm.com>, "Suren Baghdasaryan" <surenb@google.com>, "Thomas Hellström" <thomas.hellstrom@linux.intel.com>, "Will Deacon" <will@kernel.org>, "Yang Shi" <shy828301@gmail.com>, "Yu Zhao" <yuzhao@google.com>, "Zack Rusin" <zackr@vmware.com>, "Harry Yoo" <harry.yoo@oracle.com>
+Message-ID: <20260106115036.86042-3-harry.yoo@oracle.com>
+
+From: Hugh Dickins <hughd@google.com>
+
+commit 670ddd8cdcbd1d07a4571266ae3517f821728c3a upstream.
+
+change_pmd_range() had special pmd_none_or_clear_bad_unless_trans_huge(),
+required to avoid "bad" choices when setting automatic NUMA hinting under
+mmap_read_lock(); but most of that is already covered in pte_offset_map()
+now.  change_pmd_range() just wants a pmd_none() check before wasting time
+on MMU notifiers, then checks on the read-once _pmd value to work out
+what's needed for huge cases.  If change_pte_range() returns -EAGAIN to
+retry if pte_offset_map_lock() fails, nothing more special is needed.
+
+Link: https://lkml.kernel.org/r/725a42a9-91e9-c868-925-e3a5fd40bb4f@google.com
+Signed-off-by: Hugh Dickins <hughd@google.com>
+Cc: Alistair Popple <apopple@nvidia.com>
+Cc: Anshuman Khandual <anshuman.khandual@arm.com>
+Cc: Axel Rasmussen <axelrasmussen@google.com>
+Cc: Christophe Leroy <christophe.leroy@csgroup.eu>
+Cc: Christoph Hellwig <hch@infradead.org>
+Cc: David Hildenbrand <david@redhat.com>
+Cc: "Huang, Ying" <ying.huang@intel.com>
+Cc: Ira Weiny <ira.weiny@intel.com>
+Cc: Jason Gunthorpe <jgg@ziepe.ca>
+Cc: Kirill A. Shutemov <kirill.shutemov@linux.intel.com>
+Cc: Lorenzo Stoakes <lstoakes@gmail.com>
+Cc: Matthew Wilcox <willy@infradead.org>
+Cc: Mel Gorman <mgorman@techsingularity.net>
+Cc: Miaohe Lin <linmiaohe@huawei.com>
+Cc: Mike Kravetz <mike.kravetz@oracle.com>
+Cc: Mike Rapoport (IBM) <rppt@kernel.org>
+Cc: Minchan Kim <minchan@kernel.org>
+Cc: Naoya Horiguchi <naoya.horiguchi@nec.com>
+Cc: Pavel Tatashin <pasha.tatashin@soleen.com>
+Cc: Peter Xu <peterx@redhat.com>
+Cc: Peter Zijlstra <peterz@infradead.org>
+Cc: Qi Zheng <zhengqi.arch@bytedance.com>
+Cc: Ralph Campbell <rcampbell@nvidia.com>
+Cc: Ryan Roberts <ryan.roberts@arm.com>
+Cc: SeongJae Park <sj@kernel.org>
+Cc: Song Liu <song@kernel.org>
+Cc: Steven Price <steven.price@arm.com>
+Cc: Suren Baghdasaryan <surenb@google.com>
+Cc: Thomas Hellström <thomas.hellstrom@linux.intel.com>
+Cc: Will Deacon <will@kernel.org>
+Cc: Yang Shi <shy828301@gmail.com>
+Cc: Yu Zhao <yuzhao@google.com>
+Cc: Zack Rusin <zackr@vmware.com>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+[ Background:
+
+    It was reported that a bad pmd is seen when automatic NUMA balancing
+    is marking page table entries as prot_numa:
+
+      [2437548.196018] mm/pgtable-generic.c:50: bad pmd 00000000af22fc02(dffffffe71fbfe02)
+      [2437548.235022] Call Trace:
+      [2437548.238234]  <TASK>
+      [2437548.241060]  dump_stack_lvl+0x46/0x61
+      [2437548.245689]  panic+0x106/0x2e5
+      [2437548.249497]  pmd_clear_bad+0x3c/0x3c
+      [2437548.253967]  change_pmd_range.isra.0+0x34d/0x3a7
+      [2437548.259537]  change_p4d_range+0x156/0x20e
+      [2437548.264392]  change_protection_range+0x116/0x1a9
+      [2437548.269976]  change_prot_numa+0x15/0x37
+      [2437548.274774]  task_numa_work+0x1b8/0x302
+      [2437548.279512]  task_work_run+0x62/0x95
+      [2437548.283882]  exit_to_user_mode_loop+0x1a4/0x1a9
+      [2437548.289277]  exit_to_user_mode_prepare+0xf4/0xfc
+      [2437548.294751]  ? sysvec_apic_timer_interrupt+0x34/0x81
+      [2437548.300677]  irqentry_exit_to_user_mode+0x5/0x25
+      [2437548.306153]  asm_sysvec_apic_timer_interrupt+0x16/0x1b
+
+    This is due to a race condition between change_prot_numa() and
+    THP migration because the kernel doesn't check is_swap_pmd() and
+    pmd_trans_huge() atomically:
+
+    change_prot_numa()                      THP migration
+    ======================================================================
+    - change_pmd_range()
+    -> is_swap_pmd() returns false,
+    meaning it's not a PMD migration
+    entry.
+                                      - do_huge_pmd_numa_page()
+                                      -> migrate_misplaced_page() sets
+                                         migration entries for the THP.
+    - change_pmd_range()
+    -> pmd_none_or_clear_bad_unless_trans_huge()
+    -> pmd_none() and pmd_trans_huge() returns false
+    - pmd_none_or_clear_bad_unless_trans_huge()
+    -> pmd_bad() returns true for the migration entry!
+
+  The upstream commit 670ddd8cdcbd ("mm/mprotect: delete
+  pmd_none_or_clear_bad_unless_trans_huge()") closes this race condition
+  by checking is_swap_pmd() and pmd_trans_huge() atomically.
+
+  Backporting note:
+    Unlike mainline, pte_offset_map_lock() does not check if the pmd
+    entry is a migration entry or a hugepage; acquires PTL unconditionally
+    instead of returning failure. Therefore, it is necessary to keep the
+    !is_swap_pmd() && !pmd_trans_huge() && !pmd_devmap() check before
+    acquiring the PTL.
+
+    After acquiring it, open-code the mainline semantics of
+    pte_offset_map_lock() so that change_pte_range() fails if the pmd value
+    has changed (under the PTL). This requires adding one more parameter
+    (for passing pmd value that is read before calling the function) to
+    change_pte_range(). ]
+
+Signed-off-by: Harry Yoo <harry.yoo@oracle.com>
+Acked-by: David Hildenbrand (Red Hat) <david@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ mm/mprotect.c |   99 ++++++++++++++++++++++++----------------------------------
+ 1 file changed, 42 insertions(+), 57 deletions(-)
+
+--- a/mm/mprotect.c
++++ b/mm/mprotect.c
+@@ -36,10 +36,11 @@
+ #include "internal.h"
+ static long change_pte_range(struct vm_area_struct *vma, pmd_t *pmd,
+-              unsigned long addr, unsigned long end, pgprot_t newprot,
+-              unsigned long cp_flags)
++              pmd_t pmd_old, unsigned long addr, unsigned long end,
++              pgprot_t newprot, unsigned long cp_flags)
+ {
+       pte_t *pte, oldpte;
++      pmd_t _pmd;
+       spinlock_t *ptl;
+       long pages = 0;
+       int target_node = NUMA_NO_NODE;
+@@ -48,21 +49,16 @@ static long change_pte_range(struct vm_a
+       bool uffd_wp = cp_flags & MM_CP_UFFD_WP;
+       bool uffd_wp_resolve = cp_flags & MM_CP_UFFD_WP_RESOLVE;
+-      /*
+-       * Can be called with only the mmap_lock for reading by
+-       * prot_numa so we must check the pmd isn't constantly
+-       * changing from under us from pmd_none to pmd_trans_huge
+-       * and/or the other way around.
+-       */
+-      if (pmd_trans_unstable(pmd))
+-              return 0;
+-
+-      /*
+-       * The pmd points to a regular pte so the pmd can't change
+-       * from under us even if the mmap_lock is only hold for
+-       * reading.
+-       */
++
+       pte = pte_offset_map_lock(vma->vm_mm, pmd, addr, &ptl);
++      /* Make sure pmd didn't change after acquiring ptl */
++      _pmd = pmd_read_atomic(pmd);
++      /* See pmd_none_or_trans_huge_or_clear_bad for info on barrier */
++      barrier();
++      if (!pmd_same(pmd_old, _pmd)) {
++              pte_unmap_unlock(pte, ptl);
++              return -EAGAIN;
++      }
+       /* Get target node for single threaded private VMAs */
+       if (prot_numa && !(vma->vm_flags & VM_SHARED) &&
+@@ -194,31 +190,6 @@ static long change_pte_range(struct vm_a
+       return pages;
+ }
+-/*
+- * Used when setting automatic NUMA hinting protection where it is
+- * critical that a numa hinting PMD is not confused with a bad PMD.
+- */
+-static inline int pmd_none_or_clear_bad_unless_trans_huge(pmd_t *pmd)
+-{
+-      pmd_t pmdval = pmd_read_atomic(pmd);
+-
+-      /* See pmd_none_or_trans_huge_or_clear_bad for info on barrier */
+-#ifdef CONFIG_TRANSPARENT_HUGEPAGE
+-      barrier();
+-#endif
+-
+-      if (pmd_none(pmdval))
+-              return 1;
+-      if (pmd_trans_huge(pmdval))
+-              return 0;
+-      if (unlikely(pmd_bad(pmdval))) {
+-              pmd_clear_bad(pmd);
+-              return 1;
+-      }
+-
+-      return 0;
+-}
+-
+ static inline long change_pmd_range(struct vm_area_struct *vma,
+               pud_t *pud, unsigned long addr, unsigned long end,
+               pgprot_t newprot, unsigned long cp_flags)
+@@ -233,21 +204,33 @@ static inline long change_pmd_range(stru
+       pmd = pmd_offset(pud, addr);
+       do {
+-              long this_pages;
+-
++              long ret;
++              pmd_t _pmd;
++again:
+               next = pmd_addr_end(addr, end);
++              _pmd = pmd_read_atomic(pmd);
++              /* See pmd_none_or_trans_huge_or_clear_bad for info on barrier */
++#ifdef CONFIG_TRANSPARENT_HUGEPAGE
++              barrier();
++#endif
+               /*
+                * Automatic NUMA balancing walks the tables with mmap_lock
+                * held for read. It's possible a parallel update to occur
+-               * between pmd_trans_huge() and a pmd_none_or_clear_bad()
+-               * check leading to a false positive and clearing.
+-               * Hence, it's necessary to atomically read the PMD value
+-               * for all the checks.
++               * between pmd_trans_huge(), is_swap_pmd(), and
++               * a pmd_none_or_clear_bad() check leading to a false positive
++               * and clearing. Hence, it's necessary to atomically read
++               * the PMD value for all the checks.
+                */
+-              if (!is_swap_pmd(*pmd) && !pmd_devmap(*pmd) &&
+-                   pmd_none_or_clear_bad_unless_trans_huge(pmd))
+-                      goto next;
++              if (!is_swap_pmd(_pmd) && !pmd_devmap(_pmd) && !pmd_trans_huge(_pmd)) {
++                      if (pmd_none(_pmd))
++                              goto next;
++
++                      if (pmd_bad(_pmd)) {
++                              pmd_clear_bad(pmd);
++                              goto next;
++                      }
++              }
+               /* invoke the mmu notifier if the pmd is populated */
+               if (!range.start) {
+@@ -257,15 +240,15 @@ static inline long change_pmd_range(stru
+                       mmu_notifier_invalidate_range_start(&range);
+               }
+-              if (is_swap_pmd(*pmd) || pmd_trans_huge(*pmd) || pmd_devmap(*pmd)) {
++              if (is_swap_pmd(_pmd) || pmd_trans_huge(_pmd) || pmd_devmap(_pmd)) {
+                       if (next - addr != HPAGE_PMD_SIZE) {
+                               __split_huge_pmd(vma, pmd, addr, false, NULL);
+                       } else {
+-                              int nr_ptes = change_huge_pmd(vma, pmd, addr,
++                              ret = change_huge_pmd(vma, pmd, addr,
+                                                             newprot, cp_flags);
+-                              if (nr_ptes) {
+-                                      if (nr_ptes == HPAGE_PMD_NR) {
++                              if (ret) {
++                                      if (ret == HPAGE_PMD_NR) {
+                                               pages += HPAGE_PMD_NR;
+                                               nr_huge_updates++;
+                                       }
+@@ -276,9 +259,11 @@ static inline long change_pmd_range(stru
+                       }
+                       /* fall through, the trans huge pmd just split */
+               }
+-              this_pages = change_pte_range(vma, pmd, addr, next, newprot,
+-                                            cp_flags);
+-              pages += this_pages;
++              ret = change_pte_range(vma, pmd, _pmd, addr, next,
++                                            newprot, cp_flags);
++              if (ret < 0)
++                      goto again;
++              pages += ret;
+ next:
+               cond_resched();
+       } while (pmd++, addr = next, addr != end);
diff --git a/queue-5.15/mm-mprotect-use-long-for-page-accountings-and-retval.patch b/queue-5.15/mm-mprotect-use-long-for-page-accountings-and-retval.patch
new file mode 100644 (file)
index 0000000..e843156
--- /dev/null
@@ -0,0 +1,223 @@
+From stable+bounces-205079-greg=kroah.com@vger.kernel.org Tue Jan  6 12:59:45 2026
+From: Harry Yoo <harry.yoo@oracle.com>
+Date: Tue,  6 Jan 2026 20:50:35 +0900
+Subject: mm/mprotect: use long for page accountings and retval
+To: stable@vger.kernel.org
+Cc: Liam.Howlett@oracle.com, akpm@linux-foundation.org, baohua@kernel.org, baolin.wang@linux.alibaba.com, david@kernel.org, dev.jain@arm.com, hughd@google.com, jane.chu@oracle.com, jannh@google.com, kas@kernel.org, lance.yang@linux.dev, linux-mm@kvack.org, lorenzo.stoakes@oracle.com, npache@redhat.com, pfalcato@suse.de, ryan.roberts@arm.com, vbabka@suse.cz, ziy@nvidia.com, Peter Xu <peterx@redhat.com>, Mike Kravetz <mike.kravetz@oracle.com>, James Houghton <jthoughton@google.com>, Andrea Arcangeli <aarcange@redhat.com>, Axel Rasmussen <axelrasmussen@google.com>, David Hildenbrand <david@redhat.com>, Muchun Song <songmuchun@bytedance.com>, Nadav Amit <nadav.amit@gmail.com>, Harry Yoo <harry.yoo@oracle.com>
+Message-ID: <20260106115036.86042-2-harry.yoo@oracle.com>
+
+From: Peter Xu <peterx@redhat.com>
+
+commit a79390f5d6a78647fd70856bd42b22d994de0ba2 upstream.
+
+Switch to use type "long" for page accountings and retval across the whole
+procedure of change_protection().
+
+The change should have shrinked the possible maximum page number to be
+half comparing to previous (ULONG_MAX / 2), but it shouldn't overflow on
+any system either because the maximum possible pages touched by change
+protection should be ULONG_MAX / PAGE_SIZE.
+
+Two reasons to switch from "unsigned long" to "long":
+
+  1. It suites better on count_vm_numa_events(), whose 2nd parameter takes
+     a long type.
+
+  2. It paves way for returning negative (error) values in the future.
+
+Currently the only caller that consumes this retval is change_prot_numa(),
+where the unsigned long was converted to an int.  Since at it, touching up
+the numa code to also take a long, so it'll avoid any possible overflow
+too during the int-size convertion.
+
+Link: https://lkml.kernel.org/r/20230104225207.1066932-3-peterx@redhat.com
+Signed-off-by: Peter Xu <peterx@redhat.com>
+Acked-by: Mike Kravetz <mike.kravetz@oracle.com>
+Acked-by: James Houghton <jthoughton@google.com>
+Cc: Andrea Arcangeli <aarcange@redhat.com>
+Cc: Axel Rasmussen <axelrasmussen@google.com>
+Cc: David Hildenbrand <david@redhat.com>
+Cc: Muchun Song <songmuchun@bytedance.com>
+Cc: Nadav Amit <nadav.amit@gmail.com>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+[ Adjust context ]
+Signed-off-by: Harry Yoo <harry.yoo@oracle.com>
+Acked-by: David Hildenbrand (Red Hat) <david@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ include/linux/hugetlb.h |    4 ++--
+ include/linux/mm.h      |    2 +-
+ mm/hugetlb.c            |    4 ++--
+ mm/mempolicy.c          |    2 +-
+ mm/mprotect.c           |   26 +++++++++++++-------------
+ 5 files changed, 19 insertions(+), 19 deletions(-)
+
+--- a/include/linux/hugetlb.h
++++ b/include/linux/hugetlb.h
+@@ -208,7 +208,7 @@ struct page *follow_huge_pgd(struct mm_s
+ int pmd_huge(pmd_t pmd);
+ int pud_huge(pud_t pud);
+-unsigned long hugetlb_change_protection(struct vm_area_struct *vma,
++long hugetlb_change_protection(struct vm_area_struct *vma,
+               unsigned long address, unsigned long end, pgprot_t newprot);
+ bool is_hugetlb_entry_migration(pte_t pte);
+@@ -379,7 +379,7 @@ static inline void move_hugetlb_state(st
+ {
+ }
+-static inline unsigned long hugetlb_change_protection(
++static inline long hugetlb_change_protection(
+                       struct vm_area_struct *vma, unsigned long address,
+                       unsigned long end, pgprot_t newprot)
+ {
+--- a/include/linux/mm.h
++++ b/include/linux/mm.h
+@@ -1910,7 +1910,7 @@ extern unsigned long move_page_tables(st
+ #define  MM_CP_UFFD_WP_ALL                 (MM_CP_UFFD_WP | \
+                                           MM_CP_UFFD_WP_RESOLVE)
+-extern unsigned long change_protection(struct vm_area_struct *vma, unsigned long start,
++extern long change_protection(struct vm_area_struct *vma, unsigned long start,
+                             unsigned long end, pgprot_t newprot,
+                             unsigned long cp_flags);
+ extern int mprotect_fixup(struct vm_area_struct *vma,
+--- a/mm/hugetlb.c
++++ b/mm/hugetlb.c
+@@ -5644,7 +5644,7 @@ long follow_hugetlb_page(struct mm_struc
+       return i ? i : err;
+ }
+-unsigned long hugetlb_change_protection(struct vm_area_struct *vma,
++long hugetlb_change_protection(struct vm_area_struct *vma,
+               unsigned long address, unsigned long end, pgprot_t newprot)
+ {
+       struct mm_struct *mm = vma->vm_mm;
+@@ -5652,7 +5652,7 @@ unsigned long hugetlb_change_protection(
+       pte_t *ptep;
+       pte_t pte;
+       struct hstate *h = hstate_vma(vma);
+-      unsigned long pages = 0;
++      long pages = 0;
+       bool shared_pmd = false;
+       struct mmu_notifier_range range;
+--- a/mm/mempolicy.c
++++ b/mm/mempolicy.c
+@@ -634,7 +634,7 @@ unlock:
+ unsigned long change_prot_numa(struct vm_area_struct *vma,
+                       unsigned long addr, unsigned long end)
+ {
+-      int nr_updated;
++      long nr_updated;
+       nr_updated = change_protection(vma, addr, end, PAGE_NONE, MM_CP_PROT_NUMA);
+       if (nr_updated)
+--- a/mm/mprotect.c
++++ b/mm/mprotect.c
+@@ -35,13 +35,13 @@
+ #include "internal.h"
+-static unsigned long change_pte_range(struct vm_area_struct *vma, pmd_t *pmd,
++static long change_pte_range(struct vm_area_struct *vma, pmd_t *pmd,
+               unsigned long addr, unsigned long end, pgprot_t newprot,
+               unsigned long cp_flags)
+ {
+       pte_t *pte, oldpte;
+       spinlock_t *ptl;
+-      unsigned long pages = 0;
++      long pages = 0;
+       int target_node = NUMA_NO_NODE;
+       bool dirty_accountable = cp_flags & MM_CP_DIRTY_ACCT;
+       bool prot_numa = cp_flags & MM_CP_PROT_NUMA;
+@@ -219,13 +219,13 @@ static inline int pmd_none_or_clear_bad_
+       return 0;
+ }
+-static inline unsigned long change_pmd_range(struct vm_area_struct *vma,
++static inline long change_pmd_range(struct vm_area_struct *vma,
+               pud_t *pud, unsigned long addr, unsigned long end,
+               pgprot_t newprot, unsigned long cp_flags)
+ {
+       pmd_t *pmd;
+       unsigned long next;
+-      unsigned long pages = 0;
++      long pages = 0;
+       unsigned long nr_huge_updates = 0;
+       struct mmu_notifier_range range;
+@@ -233,7 +233,7 @@ static inline unsigned long change_pmd_r
+       pmd = pmd_offset(pud, addr);
+       do {
+-              unsigned long this_pages;
++              long this_pages;
+               next = pmd_addr_end(addr, end);
+@@ -291,13 +291,13 @@ next:
+       return pages;
+ }
+-static inline unsigned long change_pud_range(struct vm_area_struct *vma,
++static inline long change_pud_range(struct vm_area_struct *vma,
+               p4d_t *p4d, unsigned long addr, unsigned long end,
+               pgprot_t newprot, unsigned long cp_flags)
+ {
+       pud_t *pud;
+       unsigned long next;
+-      unsigned long pages = 0;
++      long pages = 0;
+       pud = pud_offset(p4d, addr);
+       do {
+@@ -311,13 +311,13 @@ static inline unsigned long change_pud_r
+       return pages;
+ }
+-static inline unsigned long change_p4d_range(struct vm_area_struct *vma,
++static inline long change_p4d_range(struct vm_area_struct *vma,
+               pgd_t *pgd, unsigned long addr, unsigned long end,
+               pgprot_t newprot, unsigned long cp_flags)
+ {
+       p4d_t *p4d;
+       unsigned long next;
+-      unsigned long pages = 0;
++      long pages = 0;
+       p4d = p4d_offset(pgd, addr);
+       do {
+@@ -331,7 +331,7 @@ static inline unsigned long change_p4d_r
+       return pages;
+ }
+-static unsigned long change_protection_range(struct vm_area_struct *vma,
++static long change_protection_range(struct vm_area_struct *vma,
+               unsigned long addr, unsigned long end, pgprot_t newprot,
+               unsigned long cp_flags)
+ {
+@@ -339,7 +339,7 @@ static unsigned long change_protection_r
+       pgd_t *pgd;
+       unsigned long next;
+       unsigned long start = addr;
+-      unsigned long pages = 0;
++      long pages = 0;
+       BUG_ON(addr >= end);
+       pgd = pgd_offset(mm, addr);
+@@ -361,11 +361,11 @@ static unsigned long change_protection_r
+       return pages;
+ }
+-unsigned long change_protection(struct vm_area_struct *vma, unsigned long start,
++long change_protection(struct vm_area_struct *vma, unsigned long start,
+                      unsigned long end, pgprot_t newprot,
+                      unsigned long cp_flags)
+ {
+-      unsigned long pages;
++      long pages;
+       BUG_ON((cp_flags & MM_CP_UFFD_WP_ALL) == MM_CP_UFFD_WP_ALL);
diff --git a/queue-5.15/mmc-core-use-sysfs_emit-instead-of-sprintf.patch b/queue-5.15/mmc-core-use-sysfs_emit-instead-of-sprintf.patch
new file mode 100644 (file)
index 0000000..86cd2c0
--- /dev/null
@@ -0,0 +1,225 @@
+From stable+bounces-200879-greg=kroah.com@vger.kernel.org Fri Dec 12 09:21:24 2025
+From: Chen Yu <xnguchen@sina.cn>
+Date: Fri, 12 Dec 2025 16:19:59 +0800
+Subject: mmc: core: use sysfs_emit() instead of sprintf()
+To: s.shtylyov@omp.ru, ulf.hansson@linaro.org
+Cc: stable@vger.kernel.org
+Message-ID: <20251212081959.5633-1-xnguchen@sina.cn>
+
+From: Sergey Shtylyov <s.shtylyov@omp.ru>
+
+[ Upstream commit f5d8a5fe77ce933f53eb8f2e22bb7a1a2019ea11 ]
+
+sprintf() (still used in the MMC core for the sysfs output) is vulnerable
+to the buffer overflow.  Use the new-fangled sysfs_emit() instead.
+
+Found by Linux Verification Center (linuxtesting.org) with the SVACE static
+analysis tool.
+
+Signed-off-by: Sergey Shtylyov <s.shtylyov@omp.ru>
+Cc: stable@vger.kernel.org
+Link: https://lore.kernel.org/r/717729b2-d65b-c72e-9fac-471d28d00b5a@omp.ru
+Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
+Signed-off-by: Chen Yu <xnguchen@sina.cn>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/mmc/core/bus.c      |    9 +++++----
+ drivers/mmc/core/bus.h      |    3 ++-
+ drivers/mmc/core/mmc.c      |   16 ++++++++--------
+ drivers/mmc/core/sd.c       |   27 +++++++++++++--------------
+ drivers/mmc/core/sdio.c     |    5 +++--
+ drivers/mmc/core/sdio_bus.c |    7 ++++---
+ 6 files changed, 35 insertions(+), 32 deletions(-)
+
+--- a/drivers/mmc/core/bus.c
++++ b/drivers/mmc/core/bus.c
+@@ -15,6 +15,7 @@
+ #include <linux/stat.h>
+ #include <linux/of.h>
+ #include <linux/pm_runtime.h>
++#include <linux/sysfs.h>
+ #include <linux/mmc/card.h>
+ #include <linux/mmc/host.h>
+@@ -34,13 +35,13 @@ static ssize_t type_show(struct device *
+       switch (card->type) {
+       case MMC_TYPE_MMC:
+-              return sprintf(buf, "MMC\n");
++              return sysfs_emit(buf, "MMC\n");
+       case MMC_TYPE_SD:
+-              return sprintf(buf, "SD\n");
++              return sysfs_emit(buf, "SD\n");
+       case MMC_TYPE_SDIO:
+-              return sprintf(buf, "SDIO\n");
++              return sysfs_emit(buf, "SDIO\n");
+       case MMC_TYPE_SD_COMBO:
+-              return sprintf(buf, "SDcombo\n");
++              return sysfs_emit(buf, "SDcombo\n");
+       default:
+               return -EFAULT;
+       }
+--- a/drivers/mmc/core/bus.h
++++ b/drivers/mmc/core/bus.h
+@@ -9,6 +9,7 @@
+ #define _MMC_CORE_BUS_H
+ #include <linux/device.h>
++#include <linux/sysfs.h>
+ struct mmc_host;
+ struct mmc_card;
+@@ -17,7 +18,7 @@ struct mmc_card;
+ static ssize_t mmc_##name##_show (struct device *dev, struct device_attribute *attr, char *buf)       \
+ {                                                                             \
+       struct mmc_card *card = mmc_dev_to_card(dev);                           \
+-      return sprintf(buf, fmt, args);                                         \
++      return sysfs_emit(buf, fmt, args);                                      \
+ }                                                                             \
+ static DEVICE_ATTR(name, S_IRUGO, mmc_##name##_show, NULL)
+--- a/drivers/mmc/core/mmc.c
++++ b/drivers/mmc/core/mmc.c
+@@ -12,6 +12,7 @@
+ #include <linux/slab.h>
+ #include <linux/stat.h>
+ #include <linux/pm_runtime.h>
++#include <linux/sysfs.h>
+ #include <linux/mmc/host.h>
+ #include <linux/mmc/card.h>
+@@ -812,12 +813,11 @@ static ssize_t mmc_fwrev_show(struct dev
+ {
+       struct mmc_card *card = mmc_dev_to_card(dev);
+-      if (card->ext_csd.rev < 7) {
+-              return sprintf(buf, "0x%x\n", card->cid.fwrev);
+-      } else {
+-              return sprintf(buf, "0x%*phN\n", MMC_FIRMWARE_LEN,
+-                             card->ext_csd.fwrev);
+-      }
++      if (card->ext_csd.rev < 7)
++              return sysfs_emit(buf, "0x%x\n", card->cid.fwrev);
++      else
++              return sysfs_emit(buf, "0x%*phN\n", MMC_FIRMWARE_LEN,
++                                card->ext_csd.fwrev);
+ }
+ static DEVICE_ATTR(fwrev, S_IRUGO, mmc_fwrev_show, NULL);
+@@ -830,10 +830,10 @@ static ssize_t mmc_dsr_show(struct devic
+       struct mmc_host *host = card->host;
+       if (card->csd.dsr_imp && host->dsr_req)
+-              return sprintf(buf, "0x%x\n", host->dsr);
++              return sysfs_emit(buf, "0x%x\n", host->dsr);
+       else
+               /* return default DSR value */
+-              return sprintf(buf, "0x%x\n", 0x404);
++              return sysfs_emit(buf, "0x%x\n", 0x404);
+ }
+ static DEVICE_ATTR(dsr, S_IRUGO, mmc_dsr_show, NULL);
+--- a/drivers/mmc/core/sd.c
++++ b/drivers/mmc/core/sd.c
+@@ -12,6 +12,7 @@
+ #include <linux/slab.h>
+ #include <linux/stat.h>
+ #include <linux/pm_runtime.h>
++#include <linux/sysfs.h>
+ #include <linux/mmc/host.h>
+ #include <linux/mmc/card.h>
+@@ -707,18 +708,16 @@ MMC_DEV_ATTR(ocr, "0x%08x\n", card->ocr)
+ MMC_DEV_ATTR(rca, "0x%04x\n", card->rca);
+-static ssize_t mmc_dsr_show(struct device *dev,
+-                           struct device_attribute *attr,
+-                           char *buf)
+-{
+-       struct mmc_card *card = mmc_dev_to_card(dev);
+-       struct mmc_host *host = card->host;
+-
+-       if (card->csd.dsr_imp && host->dsr_req)
+-               return sprintf(buf, "0x%x\n", host->dsr);
+-       else
+-               /* return default DSR value */
+-               return sprintf(buf, "0x%x\n", 0x404);
++static ssize_t mmc_dsr_show(struct device *dev, struct device_attribute *attr,
++                          char *buf)
++{
++      struct mmc_card *card = mmc_dev_to_card(dev);
++      struct mmc_host *host = card->host;
++
++      if (card->csd.dsr_imp && host->dsr_req)
++              return sysfs_emit(buf, "0x%x\n", host->dsr);
++      /* return default DSR value */
++      return sysfs_emit(buf, "0x%x\n", 0x404);
+ }
+ static DEVICE_ATTR(dsr, S_IRUGO, mmc_dsr_show, NULL);
+@@ -734,9 +733,9 @@ static ssize_t info##num##_show(struct d
+                                                                                               \
+       if (num > card->num_info)                                                               \
+               return -ENODATA;                                                                \
+-      if (!card->info[num-1][0])                                                              \
++      if (!card->info[num - 1][0])                                                            \
+               return 0;                                                                       \
+-      return sprintf(buf, "%s\n", card->info[num-1]);                                         \
++      return sysfs_emit(buf, "%s\n", card->info[num - 1]);                                    \
+ }                                                                                             \
+ static DEVICE_ATTR_RO(info##num)
+--- a/drivers/mmc/core/sdio.c
++++ b/drivers/mmc/core/sdio.c
+@@ -7,6 +7,7 @@
+ #include <linux/err.h>
+ #include <linux/pm_runtime.h>
++#include <linux/sysfs.h>
+ #include <linux/mmc/host.h>
+ #include <linux/mmc/card.h>
+@@ -40,9 +41,9 @@ static ssize_t info##num##_show(struct d
+                                                                                               \
+       if (num > card->num_info)                                                               \
+               return -ENODATA;                                                                \
+-      if (!card->info[num-1][0])                                                              \
++      if (!card->info[num - 1][0])                                                            \
+               return 0;                                                                       \
+-      return sprintf(buf, "%s\n", card->info[num-1]);                                         \
++      return sysfs_emit(buf, "%s\n", card->info[num - 1]);                                    \
+ }                                                                                             \
+ static DEVICE_ATTR_RO(info##num)
+--- a/drivers/mmc/core/sdio_bus.c
++++ b/drivers/mmc/core/sdio_bus.c
+@@ -14,6 +14,7 @@
+ #include <linux/pm_runtime.h>
+ #include <linux/pm_domain.h>
+ #include <linux/acpi.h>
++#include <linux/sysfs.h>
+ #include <linux/mmc/card.h>
+ #include <linux/mmc/host.h>
+@@ -35,7 +36,7 @@ field##_show(struct device *dev, struct
+       struct sdio_func *func;                                         \
+                                                                       \
+       func = dev_to_sdio_func (dev);                                  \
+-      return sprintf(buf, format_string, args);                       \
++      return sysfs_emit(buf, format_string, args);                    \
+ }                                                                     \
+ static DEVICE_ATTR_RO(field)
+@@ -52,9 +53,9 @@ static ssize_t info##num##_show(struct d
+                                                                                               \
+       if (num > func->num_info)                                                               \
+               return -ENODATA;                                                                \
+-      if (!func->info[num-1][0])                                                              \
++      if (!func->info[num - 1][0])                                                            \
+               return 0;                                                                       \
+-      return sprintf(buf, "%s\n", func->info[num-1]);                                         \
++      return sysfs_emit(buf, "%s\n", func->info[num - 1]);                                    \
+ }                                                                                             \
+ static DEVICE_ATTR_RO(info##num)
diff --git a/queue-5.15/mptcp-pm-ignore-unknown-endpoint-flags.patch b/queue-5.15/mptcp-pm-ignore-unknown-endpoint-flags.patch
new file mode 100644 (file)
index 0000000..8ce076a
--- /dev/null
@@ -0,0 +1,68 @@
+From stable+bounces-204223-greg=kroah.com@vger.kernel.org Tue Dec 30 15:09:11 2025
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 30 Dec 2025 09:07:01 -0500
+Subject: mptcp: pm: ignore unknown endpoint flags
+To: stable@vger.kernel.org
+Cc: "Matthieu Baerts (NGI0)" <matttbe@kernel.org>, Mat Martineau <martineau@kernel.org>, Jakub Kicinski <kuba@kernel.org>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20251230140701.2226659-1-sashal@kernel.org>
+
+From: "Matthieu Baerts (NGI0)" <matttbe@kernel.org>
+
+[ Upstream commit 0ace3297a7301911e52d8195cb1006414897c859 ]
+
+Before this patch, the kernel was saving any flags set by the userspace,
+even unknown ones. This doesn't cause critical issues because the kernel
+is only looking at specific ones. But on the other hand, endpoints dumps
+could tell the userspace some recent flags seem to be supported on older
+kernel versions.
+
+Instead, ignore all unknown flags when parsing them. By doing that, the
+userspace can continue to set unsupported flags, but it has a way to
+verify what is supported by the kernel.
+
+Note that it sounds better to continue accepting unsupported flags not
+to change the behaviour, but also that eases things on the userspace
+side by adding "optional" endpoint types only supported by newer kernel
+versions without having to deal with the different kernel versions.
+
+A note for the backports: there will be conflicts in mptcp.h on older
+versions not having the mentioned flags, the new line should still be
+added last, and the '5' needs to be adapted to have the same value as
+the last entry.
+
+Fixes: 01cacb00b35c ("mptcp: add netlink-based PM")
+Cc: stable@vger.kernel.org
+Reviewed-by: Mat Martineau <martineau@kernel.org>
+Signed-off-by: Matthieu Baerts (NGI0) <matttbe@kernel.org>
+Link: https://patch.msgid.link/20251205-net-mptcp-misc-fixes-6-19-rc1-v1-1-9e4781a6c1b8@kernel.org
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+[ GENMASK(5, 0) => GENMASK(3, 0) + context ]
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ include/uapi/linux/mptcp.h |    1 +
+ net/mptcp/pm_netlink.c     |    3 ++-
+ 2 files changed, 3 insertions(+), 1 deletion(-)
+
+--- a/include/uapi/linux/mptcp.h
++++ b/include/uapi/linux/mptcp.h
+@@ -74,6 +74,7 @@ enum {
+ #define MPTCP_PM_ADDR_FLAG_SUBFLOW                    (1 << 1)
+ #define MPTCP_PM_ADDR_FLAG_BACKUP                     (1 << 2)
+ #define MPTCP_PM_ADDR_FLAG_FULLMESH                   (1 << 3)
++#define MPTCP_PM_ADDR_FLAGS_MASK                      GENMASK(3, 0)
+ enum {
+       MPTCP_PM_CMD_UNSPEC,
+--- a/net/mptcp/pm_netlink.c
++++ b/net/mptcp/pm_netlink.c
+@@ -1294,7 +1294,8 @@ skip_family:
+               entry->addr.id = nla_get_u8(tb[MPTCP_PM_ADDR_ATTR_ID]);
+       if (tb[MPTCP_PM_ADDR_ATTR_FLAGS])
+-              entry->flags = nla_get_u32(tb[MPTCP_PM_ADDR_ATTR_FLAGS]);
++              entry->flags = nla_get_u32(tb[MPTCP_PM_ADDR_ATTR_FLAGS]) &
++                             MPTCP_PM_ADDR_FLAGS_MASK;
+       if (tb[MPTCP_PM_ADDR_ATTR_PORT]) {
+               if (!(entry->flags & MPTCP_PM_ADDR_FLAG_SIGNAL)) {
diff --git a/queue-5.15/net-remove-rtnl-dance-for-siocbraddif-and-siocbrdelif.patch b/queue-5.15/net-remove-rtnl-dance-for-siocbraddif-and-siocbrdelif.patch
new file mode 100644 (file)
index 0000000..242fab0
--- /dev/null
@@ -0,0 +1,292 @@
+From stable+bounces-206191-greg=kroah.com@vger.kernel.org Wed Jan  7 19:52:39 2026
+From: Thadeu Lima de Souza Cascardo <cascardo@igalia.com>
+Date: Wed,  7 Jan 2026 14:21:29 -0300
+Subject: net: Remove RTNL dance for SIOCBRADDIF and SIOCBRDELIF.
+To: stable@vger.kernel.org
+Cc: Thadeu Lima de Souza Cascardo <cascardo@igalia.com>, syzkaller <syzkaller@googlegroups.com>, yan kang <kangyan91@outlook.com>, yue sun <samsun1006219@gmail.com>, Kuniyuki Iwashima <kuniyu@amazon.com>, Stanislav Fomichev <sdf@fomichev.me>, Ido Schimmel <idosch@nvidia.com>, Nikolay Aleksandrov <razor@blackwall.org>, Paolo Abeni <pabeni@redhat.com>
+Message-ID: <20260107172129.2488617-1-cascardo@igalia.com>
+
+From: Thadeu Lima de Souza Cascardo <cascardo@igalia.com>
+
+commit ed3ba9b6e280e14cc3148c1b226ba453f02fa76c upstream.
+
+SIOCBRDELIF is passed to dev_ioctl() first and later forwarded to
+br_ioctl_call(), which causes unnecessary RTNL dance and the splat
+below [0] under RTNL pressure.
+
+Let's say Thread A is trying to detach a device from a bridge and
+Thread B is trying to remove the bridge.
+
+In dev_ioctl(), Thread A bumps the bridge device's refcnt by
+netdev_hold() and releases RTNL because the following br_ioctl_call()
+also re-acquires RTNL.
+
+In the race window, Thread B could acquire RTNL and try to remove
+the bridge device.  Then, rtnl_unlock() by Thread B will release RTNL
+and wait for netdev_put() by Thread A.
+
+Thread A, however, must hold RTNL after the unlock in dev_ifsioc(),
+which may take long under RTNL pressure, resulting in the splat by
+Thread B.
+
+  Thread A (SIOCBRDELIF)           Thread B (SIOCBRDELBR)
+  ----------------------           ----------------------
+  sock_ioctl                       sock_ioctl
+  `- sock_do_ioctl                 `- br_ioctl_call
+     `- dev_ioctl                     `- br_ioctl_stub
+        |- rtnl_lock                     |
+        |- dev_ifsioc                    '
+        '  |- dev = __dev_get_by_name(...)
+           |- netdev_hold(dev, ...)      .
+       /   |- rtnl_unlock  ------.       |
+       |   |- br_ioctl_call       `--->  |- rtnl_lock
+  Race |   |  `- br_ioctl_stub           |- br_del_bridge
+  Window   |     |                       |  |- dev = __dev_get_by_name(...)
+       |   |     |  May take long        |  `- br_dev_delete(dev, ...)
+       |   |     |  under RTNL pressure  |     `- unregister_netdevice_queue(dev, ...)
+       |   |     |               |       `- rtnl_unlock
+       \   |     |- rtnl_lock  <-'          `- netdev_run_todo
+           |     |- ...                        `- netdev_run_todo
+           |     `- rtnl_unlock                   |- __rtnl_unlock
+           |                                      |- netdev_wait_allrefs_any
+           |- netdev_put(dev, ...)  <----------------'
+                                                Wait refcnt decrement
+                                                and log splat below
+
+To avoid blocking SIOCBRDELBR unnecessarily, let's not call
+dev_ioctl() for SIOCBRADDIF and SIOCBRDELIF.
+
+In the dev_ioctl() path, we do the following:
+
+  1. Copy struct ifreq by get_user_ifreq in sock_do_ioctl()
+  2. Check CAP_NET_ADMIN in dev_ioctl()
+  3. Call dev_load() in dev_ioctl()
+  4. Fetch the master dev from ifr.ifr_name in dev_ifsioc()
+
+3. can be done by request_module() in br_ioctl_call(), so we move
+1., 2., and 4. to br_ioctl_stub().
+
+Note that 2. is also checked later in add_del_if(), but it's better
+performed before RTNL.
+
+SIOCBRADDIF and SIOCBRDELIF have been processed in dev_ioctl() since
+the pre-git era, and there seems to be no specific reason to process
+them there.
+
+[0]:
+unregister_netdevice: waiting for wpan3 to become free. Usage count = 2
+ref_tracker: wpan3@ffff8880662d8608 has 1/1 users at
+     __netdev_tracker_alloc include/linux/netdevice.h:4282 [inline]
+     netdev_hold include/linux/netdevice.h:4311 [inline]
+     dev_ifsioc+0xc6a/0x1160 net/core/dev_ioctl.c:624
+     dev_ioctl+0x255/0x10c0 net/core/dev_ioctl.c:826
+     sock_do_ioctl+0x1ca/0x260 net/socket.c:1213
+     sock_ioctl+0x23a/0x6c0 net/socket.c:1318
+     vfs_ioctl fs/ioctl.c:51 [inline]
+     __do_sys_ioctl fs/ioctl.c:906 [inline]
+     __se_sys_ioctl fs/ioctl.c:892 [inline]
+     __x64_sys_ioctl+0x1a4/0x210 fs/ioctl.c:892
+     do_syscall_x64 arch/x86/entry/common.c:52 [inline]
+     do_syscall_64+0xcb/0x250 arch/x86/entry/common.c:83
+     entry_SYSCALL_64_after_hwframe+0x77/0x7f
+
+Fixes: 893b19587534 ("net: bridge: fix ioctl locking")
+Reported-by: syzkaller <syzkaller@googlegroups.com>
+Reported-by: yan kang <kangyan91@outlook.com>
+Reported-by: yue sun <samsun1006219@gmail.com>
+Closes: https://lore.kernel.org/netdev/SY8P300MB0421225D54EB92762AE8F0F2A1D32@SY8P300MB0421.AUSP300.PROD.OUTLOOK.COM/
+Signed-off-by: Kuniyuki Iwashima <kuniyu@amazon.com>
+Acked-by: Stanislav Fomichev <sdf@fomichev.me>
+Reviewed-by: Ido Schimmel <idosch@nvidia.com>
+Acked-by: Nikolay Aleksandrov <razor@blackwall.org>
+Link: https://patch.msgid.link/20250316192851.19781-1-kuniyu@amazon.com
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+[cascardo: fixed conflict at dev_ifsioc]
+Signed-off-by: Thadeu Lima de Souza Cascardo <cascardo@igalia.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ include/linux/if_bridge.h |    6 ++----
+ net/bridge/br_ioctl.c     |   36 +++++++++++++++++++++++++++++++++---
+ net/bridge/br_private.h   |    3 +--
+ net/core/dev_ioctl.c      |   15 ---------------
+ net/socket.c              |   19 +++++++++----------
+ 5 files changed, 45 insertions(+), 34 deletions(-)
+
+--- a/include/linux/if_bridge.h
++++ b/include/linux/if_bridge.h
+@@ -62,11 +62,9 @@ struct br_ip_list {
+ #define BR_DEFAULT_AGEING_TIME        (300 * HZ)
+ struct net_bridge;
+-void brioctl_set(int (*hook)(struct net *net, struct net_bridge *br,
+-                           unsigned int cmd, struct ifreq *ifr,
++void brioctl_set(int (*hook)(struct net *net, unsigned int cmd,
+                            void __user *uarg));
+-int br_ioctl_call(struct net *net, struct net_bridge *br, unsigned int cmd,
+-                struct ifreq *ifr, void __user *uarg);
++int br_ioctl_call(struct net *net, unsigned int cmd, void __user *uarg);
+ #if IS_ENABLED(CONFIG_BRIDGE) && IS_ENABLED(CONFIG_BRIDGE_IGMP_SNOOPING)
+ int br_multicast_list_adjacent(struct net_device *dev,
+--- a/net/bridge/br_ioctl.c
++++ b/net/bridge/br_ioctl.c
+@@ -368,10 +368,26 @@ static int old_deviceless(struct net *ne
+       return -EOPNOTSUPP;
+ }
+-int br_ioctl_stub(struct net *net, struct net_bridge *br, unsigned int cmd,
+-                struct ifreq *ifr, void __user *uarg)
++int br_ioctl_stub(struct net *net, unsigned int cmd, void __user *uarg)
+ {
+       int ret = -EOPNOTSUPP;
++      struct ifreq ifr;
++
++      if (cmd == SIOCBRADDIF || cmd == SIOCBRDELIF) {
++              void __user *data;
++              char *colon;
++
++              if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
++                      return -EPERM;
++
++              if (get_user_ifreq(&ifr, &data, uarg))
++                      return -EFAULT;
++
++              ifr.ifr_name[IFNAMSIZ - 1] = 0;
++              colon = strchr(ifr.ifr_name, ':');
++              if (colon)
++                      *colon = 0;
++      }
+       rtnl_lock();
+@@ -404,7 +420,21 @@ int br_ioctl_stub(struct net *net, struc
+               break;
+       case SIOCBRADDIF:
+       case SIOCBRDELIF:
+-              ret = add_del_if(br, ifr->ifr_ifindex, cmd == SIOCBRADDIF);
++      {
++              struct net_device *dev;
++
++              dev = __dev_get_by_name(net, ifr.ifr_name);
++              if (!dev || !netif_device_present(dev)) {
++                      ret = -ENODEV;
++                      break;
++              }
++              if (!netif_is_bridge_master(dev)) {
++                      ret = -EOPNOTSUPP;
++                      break;
++              }
++
++              ret = add_del_if(netdev_priv(dev), ifr.ifr_ifindex, cmd == SIOCBRADDIF);
++      }
+               break;
+       }
+--- a/net/bridge/br_private.h
++++ b/net/bridge/br_private.h
+@@ -875,8 +875,7 @@ br_port_get_check_rtnl(const struct net_
+ /* br_ioctl.c */
+ int br_dev_siocdevprivate(struct net_device *dev, struct ifreq *rq,
+                         void __user *data, int cmd);
+-int br_ioctl_stub(struct net *net, struct net_bridge *br, unsigned int cmd,
+-                struct ifreq *ifr, void __user *uarg);
++int br_ioctl_stub(struct net *net, unsigned int cmd, void __user *uarg);
+ /* br_multicast.c */
+ #ifdef CONFIG_BRIDGE_IGMP_SNOOPING
+--- a/net/core/dev_ioctl.c
++++ b/net/core/dev_ioctl.c
+@@ -375,19 +375,6 @@ static int dev_ifsioc(struct net *net, s
+       case SIOCWANDEV:
+               return dev_siocwandev(dev, &ifr->ifr_settings);
+-      case SIOCBRADDIF:
+-      case SIOCBRDELIF:
+-              if (!netif_device_present(dev))
+-                      return -ENODEV;
+-              if (!netif_is_bridge_master(dev))
+-                      return -EOPNOTSUPP;
+-              dev_hold(dev);
+-              rtnl_unlock();
+-              err = br_ioctl_call(net, netdev_priv(dev), cmd, ifr, NULL);
+-              dev_put(dev);
+-              rtnl_lock();
+-              return err;
+-
+       case SIOCSHWTSTAMP:
+               err = net_hwtstamp_validate(ifr);
+               if (err)
+@@ -574,8 +561,6 @@ int dev_ioctl(struct net *net, unsigned
+       case SIOCBONDRELEASE:
+       case SIOCBONDSETHWADDR:
+       case SIOCBONDCHANGEACTIVE:
+-      case SIOCBRADDIF:
+-      case SIOCBRDELIF:
+       case SIOCSHWTSTAMP:
+               if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
+                       return -EPERM;
+--- a/net/socket.c
++++ b/net/socket.c
+@@ -1097,12 +1097,10 @@ static ssize_t sock_write_iter(struct ki
+  */
+ static DEFINE_MUTEX(br_ioctl_mutex);
+-static int (*br_ioctl_hook)(struct net *net, struct net_bridge *br,
+-                          unsigned int cmd, struct ifreq *ifr,
++static int (*br_ioctl_hook)(struct net *net, unsigned int cmd,
+                           void __user *uarg);
+-void brioctl_set(int (*hook)(struct net *net, struct net_bridge *br,
+-                           unsigned int cmd, struct ifreq *ifr,
++void brioctl_set(int (*hook)(struct net *net, unsigned int cmd,
+                            void __user *uarg))
+ {
+       mutex_lock(&br_ioctl_mutex);
+@@ -1111,8 +1109,7 @@ void brioctl_set(int (*hook)(struct net
+ }
+ EXPORT_SYMBOL(brioctl_set);
+-int br_ioctl_call(struct net *net, struct net_bridge *br, unsigned int cmd,
+-                struct ifreq *ifr, void __user *uarg)
++int br_ioctl_call(struct net *net, unsigned int cmd, void __user *uarg)
+ {
+       int err = -ENOPKG;
+@@ -1121,7 +1118,7 @@ int br_ioctl_call(struct net *net, struc
+       mutex_lock(&br_ioctl_mutex);
+       if (br_ioctl_hook)
+-              err = br_ioctl_hook(net, br, cmd, ifr, uarg);
++              err = br_ioctl_hook(net, cmd, uarg);
+       mutex_unlock(&br_ioctl_mutex);
+       return err;
+@@ -1218,7 +1215,9 @@ static long sock_ioctl(struct file *file
+               case SIOCSIFBR:
+               case SIOCBRADDBR:
+               case SIOCBRDELBR:
+-                      err = br_ioctl_call(net, NULL, cmd, NULL, argp);
++              case SIOCBRADDIF:
++              case SIOCBRDELIF:
++                      err = br_ioctl_call(net, cmd, argp);
+                       break;
+               case SIOCGIFVLAN:
+               case SIOCSIFVLAN:
+@@ -3321,6 +3320,8 @@ static int compat_sock_ioctl_trans(struc
+       case SIOCGPGRP:
+       case SIOCBRADDBR:
+       case SIOCBRDELBR:
++      case SIOCBRADDIF:
++      case SIOCBRDELIF:
+       case SIOCGIFVLAN:
+       case SIOCSIFVLAN:
+       case SIOCGSKNS:
+@@ -3358,8 +3359,6 @@ static int compat_sock_ioctl_trans(struc
+       case SIOCGIFPFLAGS:
+       case SIOCGIFTXQLEN:
+       case SIOCSIFTXQLEN:
+-      case SIOCBRADDIF:
+-      case SIOCBRDELIF:
+       case SIOCGIFNAME:
+       case SIOCSIFNAME:
+       case SIOCGMIIPHY:
diff --git a/queue-5.15/nfsd-clear-seclabel-in-the-suppattr_exclcreat-bitmap.patch b/queue-5.15/nfsd-clear-seclabel-in-the-suppattr_exclcreat-bitmap.patch
new file mode 100644 (file)
index 0000000..b9fd81d
--- /dev/null
@@ -0,0 +1,57 @@
+From stable+bounces-204345-greg=kroah.com@vger.kernel.org Wed Dec 31 14:46:20 2025
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 31 Dec 2025 08:46:15 -0500
+Subject: NFSD: Clear SECLABEL in the suppattr_exclcreat bitmap
+To: stable@vger.kernel.org
+Cc: Chuck Lever <chuck.lever@oracle.com>, Jeff Layton <jlayton@kernel.org>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20251231134615.2899300-1-sashal@kernel.org>
+
+From: Chuck Lever <chuck.lever@oracle.com>
+
+[ Upstream commit 27d17641cacfedd816789b75d342430f6b912bd2 ]
+
+>>From RFC 8881:
+
+5.8.1.14. Attribute 75: suppattr_exclcreat
+
+> The bit vector that would set all REQUIRED and RECOMMENDED
+> attributes that are supported by the EXCLUSIVE4_1 method of file
+> creation via the OPEN operation. The scope of this attribute
+> applies to all objects with a matching fsid.
+
+There's nothing in RFC 8881 that states that suppattr_exclcreat is
+or is not allowed to contain bits for attributes that are clear in
+the reported supported_attrs bitmask. But it doesn't make sense for
+an NFS server to indicate that it /doesn't/ implement an attribute,
+but then also indicate that clients /are/ allowed to set that
+attribute using OPEN(create) with EXCLUSIVE4_1.
+
+Ensure that the SECURITY_LABEL and ACL bits are not set in the
+suppattr_exclcreat bitmask when they are also not set in the
+supported_attrs bitmask.
+
+Fixes: 8c18f2052e75 ("nfsd41: SUPPATTR_EXCLCREAT attribute")
+Cc: stable@vger.kernel.org
+Reviewed-by: Jeff Layton <jlayton@kernel.org>
+Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
+[ Adjust context ]
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/nfsd/nfs4xdr.c |    5 +++++
+ 1 file changed, 5 insertions(+)
+
+--- a/fs/nfsd/nfs4xdr.c
++++ b/fs/nfsd/nfs4xdr.c
+@@ -3409,6 +3409,11 @@ out_acl:
+               u32 supp[3];
+               memcpy(supp, nfsd_suppattrs[minorversion], sizeof(supp));
++              if (!IS_POSIXACL(d_inode(dentry)))
++                      supp[0] &= ~FATTR4_WORD0_ACL;
++              if (!contextsupport)
++                      supp[2] &= ~FATTR4_WORD2_SECURITY_LABEL;
++
+               supp[0] &= NFSD_SUPPATTR_EXCLCREAT_WORD0;
+               supp[1] &= NFSD_SUPPATTR_EXCLCREAT_WORD1;
+               supp[2] &= NFSD_SUPPATTR_EXCLCREAT_WORD2;
diff --git a/queue-5.15/nfsd-nfsv4-file-creation-neglects-setting-acl.patch b/queue-5.15/nfsd-nfsv4-file-creation-neglects-setting-acl.patch
new file mode 100644 (file)
index 0000000..cfb1143
--- /dev/null
@@ -0,0 +1,49 @@
+From stable+bounces-204919-greg=kroah.com@vger.kernel.org Mon Jan  5 21:35:05 2026
+From: Chuck Lever <cel@kernel.org>
+Date: Mon,  5 Jan 2026 15:34:59 -0500
+Subject: NFSD: NFSv4 file creation neglects setting ACL
+To: <stable@vger.kernel.org>
+Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>, Sasha Levin <sashal@kernel.org>, <linux-nfs@vger.kernel.org>, Chuck Lever <chuck.lever@oracle.com>, Aurelien Couderc <aurelien.couderc2002@gmail.com>
+Message-ID: <20260105203459.3562478-1-cel@kernel.org>
+
+From: Chuck Lever <chuck.lever@oracle.com>
+
+[ Upstream commit 913f7cf77bf14c13cfea70e89bcb6d0b22239562 ]
+
+An NFSv4 client that sets an ACL with a named principal during file
+creation retrieves the ACL afterwards, and finds that it is only a
+default ACL (based on the mode bits) and not the ACL that was
+requested during file creation. This violates RFC 8881 section
+6.4.1.3: "the ACL attribute is set as given".
+
+The issue occurs in nfsd_create_setattr(). On 6.1.y, the check to
+determine whether nfsd_setattr() should be called is simply
+"iap->ia_valid", which only accounts for iattr changes. When only
+an ACL is present (and no iattr fields are set), nfsd_setattr() is
+skipped and the POSIX ACL is never applied to the inode.
+
+Subsequently, when the client retrieves the ACL, the server finds
+no POSIX ACL on the inode and returns one generated from the file's
+mode bits rather than returning the originally-specified ACL.
+
+Reported-by: Aurelien Couderc <aurelien.couderc2002@gmail.com>
+Fixes: c0cbe70742f4 ("NFSD: add posix ACLs to struct nfsd_attrs")
+Cc: stable@vger.kernel.org
+[ cel: Adjust nfsd_create_setattr() instead of nfsd_attrs_valid() ]
+Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/nfsd/vfs.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/fs/nfsd/vfs.c
++++ b/fs/nfsd/vfs.c
+@@ -1319,7 +1319,7 @@ nfsd_create_setattr(struct svc_rqst *rqs
+        * Callers expect new file metadata to be committed even
+        * if the attributes have not changed.
+        */
+-      if (iap->ia_valid)
++      if (iap->ia_valid || attrs->na_pacl || attrs->na_dpacl)
+               status = nfsd_setattr(rqstp, resfhp, attrs, 0, (time64_t)0);
+       else
+               status = nfserrno(commit_metadata(resfhp));
diff --git a/queue-5.15/page_pool-fix-use-after-free-in-page_pool_recycle_in_ring.patch b/queue-5.15/page_pool-fix-use-after-free-in-page_pool_recycle_in_ring.patch
new file mode 100644 (file)
index 0000000..e7c453b
--- /dev/null
@@ -0,0 +1,129 @@
+From stable+bounces-200787-greg=kroah.com@vger.kernel.org Thu Dec 11 11:02:04 2025
+From: ruohanlan@aliyun.com
+Date: Thu, 11 Dec 2025 10:01:10 +0000
+Subject: page_pool: Fix use-after-free in page_pool_recycle_in_ring
+To: stable@vger.kernel.org
+Cc: "Dong Chenchen" <dongchenchen2@huawei.com>, "Jakub Kicinski" <kuba@kernel.org>, syzbot+204a4382fcb3311f3858@syzkaller.appspotmail.com, "Toke Høiland-Jørgensen" <toke@redhat.com>, "Mina Almasry" <almasrymina@google.com>, "Ruohan Lan" <ruohanlan@aliyun.com>
+Message-ID: <20251211100110.4139-1-ruohanlan@aliyun.com>
+
+From: Dong Chenchen <dongchenchen2@huawei.com>
+
+[ Upstream commit 271683bb2cf32e5126c592b5d5e6a756fa374fd9 ]
+
+syzbot reported a uaf in page_pool_recycle_in_ring:
+
+BUG: KASAN: slab-use-after-free in lock_release+0x151/0xa30 kernel/locking/lockdep.c:5862
+Read of size 8 at addr ffff8880286045a0 by task syz.0.284/6943
+
+CPU: 0 UID: 0 PID: 6943 Comm: syz.0.284 Not tainted 6.13.0-rc3-syzkaller-gdfa94ce54f41 #0
+Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 09/13/2024
+Call Trace:
+ <TASK>
+ __dump_stack lib/dump_stack.c:94 [inline]
+ dump_stack_lvl+0x241/0x360 lib/dump_stack.c:120
+ print_address_description mm/kasan/report.c:378 [inline]
+ print_report+0x169/0x550 mm/kasan/report.c:489
+ kasan_report+0x143/0x180 mm/kasan/report.c:602
+ lock_release+0x151/0xa30 kernel/locking/lockdep.c:5862
+ __raw_spin_unlock_bh include/linux/spinlock_api_smp.h:165 [inline]
+ _raw_spin_unlock_bh+0x1b/0x40 kernel/locking/spinlock.c:210
+ spin_unlock_bh include/linux/spinlock.h:396 [inline]
+ ptr_ring_produce_bh include/linux/ptr_ring.h:164 [inline]
+ page_pool_recycle_in_ring net/core/page_pool.c:707 [inline]
+ page_pool_put_unrefed_netmem+0x748/0xb00 net/core/page_pool.c:826
+ page_pool_put_netmem include/net/page_pool/helpers.h:323 [inline]
+ page_pool_put_full_netmem include/net/page_pool/helpers.h:353 [inline]
+ napi_pp_put_page+0x149/0x2b0 net/core/skbuff.c:1036
+ skb_pp_recycle net/core/skbuff.c:1047 [inline]
+ skb_free_head net/core/skbuff.c:1094 [inline]
+ skb_release_data+0x6c4/0x8a0 net/core/skbuff.c:1125
+ skb_release_all net/core/skbuff.c:1190 [inline]
+ __kfree_skb net/core/skbuff.c:1204 [inline]
+ sk_skb_reason_drop+0x1c9/0x380 net/core/skbuff.c:1242
+ kfree_skb_reason include/linux/skbuff.h:1263 [inline]
+ __skb_queue_purge_reason include/linux/skbuff.h:3343 [inline]
+
+root cause is:
+
+page_pool_recycle_in_ring
+  ptr_ring_produce
+    spin_lock(&r->producer_lock);
+    WRITE_ONCE(r->queue[r->producer++], ptr)
+      //recycle last page to pool
+                               page_pool_release
+                                 page_pool_scrub
+                                   page_pool_empty_ring
+                                     ptr_ring_consume
+                                     page_pool_return_page  //release all page
+                                 __page_pool_destroy
+                                    free_percpu(pool->recycle_stats);
+                                    free(pool) //free
+
+     spin_unlock(&r->producer_lock); //pool->ring uaf read
+  recycle_stat_inc(pool, ring);
+
+page_pool can be free while page pool recycle the last page in ring.
+Add producer-lock barrier to page_pool_release to prevent the page
+pool from being free before all pages have been recycled.
+
+recycle_stat_inc() is empty when CONFIG_PAGE_POOL_STATS is not
+enabled, which will trigger Wempty-body build warning. Add definition
+for pool stat macro to fix warning.
+
+Suggested-by: Jakub Kicinski <kuba@kernel.org>
+Link: https://lore.kernel.org/netdev/20250513083123.3514193-1-dongchenchen2@huawei.com
+Fixes: ff7d6b27f894 ("page_pool: refurbish version of page_pool code")
+Reported-by: syzbot+204a4382fcb3311f3858@syzkaller.appspotmail.com
+Closes: https://syzkaller.appspot.com/bug?extid=204a4382fcb3311f3858
+Signed-off-by: Dong Chenchen <dongchenchen2@huawei.com>
+Reviewed-by: Toke Høiland-Jørgensen <toke@redhat.com>
+Reviewed-by: Mina Almasry <almasrymina@google.com>
+Link: https://patch.msgid.link/20250527114152.3119109-1-dongchenchen2@huawei.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+[ Linux 5.15.y does not support page pool statistics
+  (CONFIG_PAGE_POOL_STATS), so remove the related source code
+  changes from the patch. ]
+Signed-off-by: Ruohan Lan <ruohanlan@aliyun.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/core/page_pool.c |   16 ++++++++++------
+ 1 file changed, 10 insertions(+), 6 deletions(-)
+
+--- a/net/core/page_pool.c
++++ b/net/core/page_pool.c
+@@ -414,14 +414,14 @@ static void page_pool_return_page(struct
+ static bool page_pool_recycle_in_ring(struct page_pool *pool, struct page *page)
+ {
+-      int ret;
++      bool in_softirq, ret;
++
+       /* BH protection not needed if current is softirq */
+-      if (in_softirq())
+-              ret = ptr_ring_produce(&pool->ring, page);
+-      else
+-              ret = ptr_ring_produce_bh(&pool->ring, page);
++      in_softirq = page_pool_producer_lock(pool);
++      ret = !__ptr_ring_produce(&pool->ring, page);
++      page_pool_producer_unlock(pool, in_softirq);
+-      return (ret == 0) ? true : false;
++      return ret;
+ }
+ /* Only allow direct recycling in special circumstances, into the
+@@ -684,10 +684,14 @@ static void page_pool_scrub(struct page_
+ static int page_pool_release(struct page_pool *pool)
+ {
++      bool in_softirq;
+       int inflight;
+       page_pool_scrub(pool);
+       inflight = page_pool_inflight(pool);
++      /* Acquire producer lock to make sure producers have exited. */
++      in_softirq = page_pool_producer_lock(pool);
++      page_pool_producer_unlock(pool, in_softirq);
+       if (!inflight)
+               page_pool_free(pool);
diff --git a/queue-5.15/pci-brcmstb-fix-disabling-l0s-capability.patch b/queue-5.15/pci-brcmstb-fix-disabling-l0s-capability.patch
new file mode 100644 (file)
index 0000000..f058bbc
--- /dev/null
@@ -0,0 +1,79 @@
+From stable+bounces-204905-greg=kroah.com@vger.kernel.org Mon Jan  5 20:41:50 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon,  5 Jan 2026 14:41:45 -0500
+Subject: PCI: brcmstb: Fix disabling L0s capability
+To: stable@vger.kernel.org
+Cc: Jim Quinlan <james.quinlan@broadcom.com>, Bjorn Helgaas <bhelgaas@google.com>, Manivannan Sadhasivam <mani@kernel.org>, Florian Fainelli <florian.fainelli@broadcom.com>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260105194145.2748502-1-sashal@kernel.org>
+
+From: Jim Quinlan <james.quinlan@broadcom.com>
+
+[ Upstream commit 9583f9d22991d2cfb5cc59a2552040c4ae98d998 ]
+
+caab002d5069 ("PCI: brcmstb: Disable L0s component of ASPM if requested")
+set PCI_EXP_LNKCAP_ASPM_L1 and (optionally) PCI_EXP_LNKCAP_ASPM_L0S in
+PCI_EXP_LNKCAP (aka PCIE_RC_CFG_PRIV1_LINK_CAPABILITY in brcmstb).
+
+But instead of using PCI_EXP_LNKCAP_ASPM_L1 and PCI_EXP_LNKCAP_ASPM_L0S
+directly, it used PCIE_LINK_STATE_L1 and PCIE_LINK_STATE_L0S, which are
+Linux-created values that only coincidentally matched the PCIe spec.
+b478e162f227 ("PCI/ASPM: Consolidate link state defines") later changed
+them so they no longer matched the PCIe spec, so the bits ended up in the
+wrong place in PCI_EXP_LNKCAP.
+
+Use PCI_EXP_LNKCAP_ASPM_L0S to clear L0s support when there's an
+'aspm-no-l0s' property.  Rely on brcmstb hardware to advertise L0s and/or
+L1 support otherwise.
+
+Fixes: caab002d5069 ("PCI: brcmstb: Disable L0s component of ASPM if requested")
+Reported-by: Bjorn Helgaas <bhelgaas@google.com>
+Closes: https://lore.kernel.org/linux-pci/20250925194424.GA2197200@bhelgaas
+Signed-off-by: Jim Quinlan <james.quinlan@broadcom.com>
+[mani: reworded subject and description, added closes tag and CCed stable]
+Signed-off-by: Manivannan Sadhasivam <mani@kernel.org>
+[bhelgaas: commit log]
+Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
+Reviewed-by: Florian Fainelli <florian.fainelli@broadcom.com>
+Cc: stable@vger.kernel.org
+Link: https://patch.msgid.link/20251003170436.1446030-1-james.quinlan@broadcom.com
+[ Adjust context in variable declaration ]
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/pci/controller/pcie-brcmstb.c |   10 +++-------
+ 1 file changed, 3 insertions(+), 7 deletions(-)
+
+--- a/drivers/pci/controller/pcie-brcmstb.c
++++ b/drivers/pci/controller/pcie-brcmstb.c
+@@ -44,7 +44,6 @@
+ #define  PCIE_RC_CFG_PRIV1_ID_VAL3_CLASS_CODE_MASK    0xffffff
+ #define PCIE_RC_CFG_PRIV1_LINK_CAPABILITY                     0x04dc
+-#define  PCIE_RC_CFG_PRIV1_LINK_CAPABILITY_ASPM_SUPPORT_MASK  0xc00
+ #define PCIE_RC_DL_MDIO_ADDR                          0x1100
+ #define PCIE_RC_DL_MDIO_WR_DATA                               0x1104
+@@ -873,7 +872,7 @@ static int brcm_pcie_setup(struct brcm_p
+       int num_out_wins = 0;
+       u16 nlw, cls, lnksta;
+       int i, ret, memc;
+-      u32 tmp, burst, aspm_support;
++      u32 tmp, burst;
+       /* Reset the bridge */
+       pcie->bridge_sw_init_set(pcie, 1);
+@@ -995,12 +994,9 @@ static int brcm_pcie_setup(struct brcm_p
+       }
+       /* Don't advertise L0s capability if 'aspm-no-l0s' */
+-      aspm_support = PCIE_LINK_STATE_L1;
+-      if (!of_property_read_bool(pcie->np, "aspm-no-l0s"))
+-              aspm_support |= PCIE_LINK_STATE_L0S;
+       tmp = readl(base + PCIE_RC_CFG_PRIV1_LINK_CAPABILITY);
+-      u32p_replace_bits(&tmp, aspm_support,
+-              PCIE_RC_CFG_PRIV1_LINK_CAPABILITY_ASPM_SUPPORT_MASK);
++      if (of_property_read_bool(pcie->np, "aspm-no-l0s"))
++              tmp &= ~PCI_EXP_LNKCAP_ASPM_L0S;
+       writel(tmp, base + PCIE_RC_CFG_PRIV1_LINK_CAPABILITY);
+       /*
diff --git a/queue-5.15/pmdomain-imx-fix-reference-count-leak-in-imx_gpc_probe.patch b/queue-5.15/pmdomain-imx-fix-reference-count-leak-in-imx_gpc_probe.patch
new file mode 100644 (file)
index 0000000..46d35fd
--- /dev/null
@@ -0,0 +1,48 @@
+From stable+bounces-206021-greg=kroah.com@vger.kernel.org Tue Jan  6 19:16:37 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue,  6 Jan 2026 13:10:16 -0500
+Subject: pmdomain: imx: Fix reference count leak in imx_gpc_probe()
+To: stable@vger.kernel.org
+Cc: Wentao Liang <vulab@iscas.ac.cn>, Frank Li <Frank.Li@nxp.com>, Ulf Hansson <ulf.hansson@linaro.org>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260106181021.3109327-3-sashal@kernel.org>
+
+From: Wentao Liang <vulab@iscas.ac.cn>
+
+[ Upstream commit 73cb5f6eafb0ac7aea8cdeb8ff12981aa741d8fb ]
+
+of_get_child_by_name() returns a node pointer with refcount incremented.
+Use the __free() attribute to manage the pgc_node reference, ensuring
+automatic of_node_put() cleanup when pgc_node goes out of scope.
+
+This eliminates the need for explicit error handling paths and avoids
+reference count leaks.
+
+Fixes: 721cabf6c660 ("soc: imx: move PGC handling to a new GPC driver")
+Cc: stable@vger.kernel.org
+Signed-off-by: Wentao Liang <vulab@iscas.ac.cn>
+Reviewed-by: Frank Li <Frank.Li@nxp.com>
+Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/soc/imx/gpc.c |    5 ++---
+ 1 file changed, 2 insertions(+), 3 deletions(-)
+
+--- a/drivers/soc/imx/gpc.c
++++ b/drivers/soc/imx/gpc.c
+@@ -405,13 +405,12 @@ clk_err:
+ static int imx_gpc_probe(struct platform_device *pdev)
+ {
+       const struct imx_gpc_dt_data *of_id_data = device_get_match_data(&pdev->dev);
+-      struct device_node *pgc_node;
++      struct device_node *pgc_node __free(device_node)
++              = of_get_child_by_name(pdev->dev.of_node, "pgc");
+       struct regmap *regmap;
+       void __iomem *base;
+       int ret;
+-      pgc_node = of_get_child_by_name(pdev->dev.of_node, "pgc");
+-
+       /* bail out if DT too old and doesn't provide the necessary info */
+       if (!of_property_read_bool(pdev->dev.of_node, "#power-domain-cells") &&
+           !pgc_node)
diff --git a/queue-5.15/pmdomain-use-device_get_match_data.patch b/queue-5.15/pmdomain-use-device_get_match_data.patch
new file mode 100644 (file)
index 0000000..8c097ab
--- /dev/null
@@ -0,0 +1,134 @@
+From stable+bounces-206020-greg=kroah.com@vger.kernel.org Tue Jan  6 20:05:19 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue,  6 Jan 2026 13:10:15 -0500
+Subject: pmdomain: Use device_get_match_data()
+To: stable@vger.kernel.org
+Cc: Rob Herring <robh@kernel.org>, Ulf Hansson <ulf.hansson@linaro.org>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260106181021.3109327-2-sashal@kernel.org>
+
+From: Rob Herring <robh@kernel.org>
+
+[ Upstream commit 3ba9fdfaa550936837b50b73d6c27ac401fde875 ]
+
+Use preferred device_get_match_data() instead of of_match_device() to
+get the driver match data. With this, adjust the includes to explicitly
+include the correct headers.
+
+Signed-off-by: Rob Herring <robh@kernel.org>
+Link: https://lore.kernel.org/r/20231006224614.444488-1-robh@kernel.org
+Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
+Stable-dep-of: 73cb5f6eafb0 ("pmdomain: imx: Fix reference count leak in imx_gpc_probe()")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/soc/actions/owl-sps.c     |   16 +++++-----------
+ drivers/soc/imx/gpc.c             |    7 +++----
+ drivers/soc/rockchip/pm_domains.c |   13 ++++---------
+ 3 files changed, 12 insertions(+), 24 deletions(-)
+
+--- a/drivers/soc/actions/owl-sps.c
++++ b/drivers/soc/actions/owl-sps.c
+@@ -8,8 +8,10 @@
+  * Copyright (c) 2017 Andreas Färber
+  */
++#include <linux/mod_devicetable.h>
+ #include <linux/of_address.h>
+-#include <linux/of_platform.h>
++#include <linux/platform_device.h>
++#include <linux/property.h>
+ #include <linux/pm_domain.h>
+ #include <linux/soc/actions/owl-sps.h>
+ #include <dt-bindings/power/owl-s500-powergate.h>
+@@ -96,24 +98,16 @@ static int owl_sps_init_domain(struct ow
+ static int owl_sps_probe(struct platform_device *pdev)
+ {
+-      const struct of_device_id *match;
+       const struct owl_sps_info *sps_info;
+       struct owl_sps *sps;
+       int i, ret;
+-      if (!pdev->dev.of_node) {
+-              dev_err(&pdev->dev, "no device node\n");
+-              return -ENODEV;
+-      }
+-
+-      match = of_match_device(pdev->dev.driver->of_match_table, &pdev->dev);
+-      if (!match || !match->data) {
++      sps_info = device_get_match_data(&pdev->dev);
++      if (!sps_info) {
+               dev_err(&pdev->dev, "unknown compatible or missing data\n");
+               return -EINVAL;
+       }
+-      sps_info = match->data;
+-
+       sps = devm_kzalloc(&pdev->dev,
+                          struct_size(sps, domains, sps_info->num_domains),
+                          GFP_KERNEL);
+--- a/drivers/soc/imx/gpc.c
++++ b/drivers/soc/imx/gpc.c
+@@ -7,9 +7,10 @@
+ #include <linux/clk.h>
+ #include <linux/delay.h>
+ #include <linux/io.h>
+-#include <linux/of_device.h>
++#include <linux/of.h>
+ #include <linux/platform_device.h>
+ #include <linux/pm_domain.h>
++#include <linux/property.h>
+ #include <linux/regmap.h>
+ #include <linux/regulator/consumer.h>
+@@ -403,9 +404,7 @@ clk_err:
+ static int imx_gpc_probe(struct platform_device *pdev)
+ {
+-      const struct of_device_id *of_id =
+-                      of_match_device(imx_gpc_dt_ids, &pdev->dev);
+-      const struct imx_gpc_dt_data *of_id_data = of_id->data;
++      const struct imx_gpc_dt_data *of_id_data = device_get_match_data(&pdev->dev);
+       struct device_node *pgc_node;
+       struct regmap *regmap;
+       void __iomem *base;
+--- a/drivers/soc/rockchip/pm_domains.c
++++ b/drivers/soc/rockchip/pm_domains.c
+@@ -9,11 +9,13 @@
+ #include <linux/iopoll.h>
+ #include <linux/err.h>
+ #include <linux/mutex.h>
++#include <linux/platform_device.h>
+ #include <linux/pm_clock.h>
+ #include <linux/pm_domain.h>
++#include <linux/property.h>
++#include <linux/of.h>
+ #include <linux/of_address.h>
+ #include <linux/of_clk.h>
+-#include <linux/of_platform.h>
+ #include <linux/clk.h>
+ #include <linux/regmap.h>
+ #include <linux/mfd/syscon.h>
+@@ -739,7 +741,6 @@ static int rockchip_pm_domain_probe(stru
+       struct device_node *node;
+       struct device *parent;
+       struct rockchip_pmu *pmu;
+-      const struct of_device_id *match;
+       const struct rockchip_pmu_info *pmu_info;
+       int error;
+@@ -748,13 +749,7 @@ static int rockchip_pm_domain_probe(stru
+               return -ENODEV;
+       }
+-      match = of_match_device(dev->driver->of_match_table, dev);
+-      if (!match || !match->data) {
+-              dev_err(dev, "missing pmu data\n");
+-              return -EINVAL;
+-      }
+-
+-      pmu_info = match->data;
++      pmu_info = device_get_match_data(dev);
+       pmu = devm_kzalloc(dev,
+                          struct_size(pmu, domains, pmu_info->num_domains),
diff --git a/queue-5.15/powerpc-64s-slb-fix-slb-multihit-issue-during-slb-preload.patch b/queue-5.15/powerpc-64s-slb-fix-slb-multihit-issue-during-slb-preload.patch
new file mode 100644 (file)
index 0000000..09b6726
--- /dev/null
@@ -0,0 +1,324 @@
+From stable+bounces-204863-greg=kroah.com@vger.kernel.org Mon Jan  5 18:21:04 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon,  5 Jan 2026 12:12:35 -0500
+Subject: powerpc/64s/slb: Fix SLB multihit issue during SLB preload
+To: stable@vger.kernel.org
+Cc: Donet Tom <donettom@linux.ibm.com>, Nicholas Piggin <npiggin@gmail.com>, "Ritesh Harjani (IBM)" <ritesh.list@gmail.com>, Madhavan Srinivasan <maddy@linux.ibm.com>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260105171235.2685455-1-sashal@kernel.org>
+
+From: Donet Tom <donettom@linux.ibm.com>
+
+[ Upstream commit 00312419f0863964625d6dcda8183f96849412c6 ]
+
+On systems using the hash MMU, there is a software SLB preload cache that
+mirrors the entries loaded into the hardware SLB buffer. This preload
+cache is subject to periodic eviction — typically after every 256 context
+switches — to remove old entry.
+
+To optimize performance, the kernel skips switch_mmu_context() in
+switch_mm_irqs_off() when the prev and next mm_struct are the same.
+However, on hash MMU systems, this can lead to inconsistencies between
+the hardware SLB and the software preload cache.
+
+If an SLB entry for a process is evicted from the software cache on one
+CPU, and the same process later runs on another CPU without executing
+switch_mmu_context(), the hardware SLB may retain stale entries. If the
+kernel then attempts to reload that entry, it can trigger an SLB
+multi-hit error.
+
+The following timeline shows how stale SLB entries are created and can
+cause a multi-hit error when a process moves between CPUs without a
+MMU context switch.
+
+CPU 0                                   CPU 1
+-----                                    -----
+Process P
+exec                                    swapper/1
+ load_elf_binary
+  begin_new_exc
+    activate_mm
+     switch_mm_irqs_off
+      switch_mmu_context
+       switch_slb
+       /*
+        * This invalidates all
+        * the entries in the HW
+        * and setup the new HW
+        * SLB entries as per the
+        * preload cache.
+        */
+context_switch
+sched_migrate_task migrates process P to cpu-1
+
+Process swapper/0                       context switch (to process P)
+(uses mm_struct of Process P)           switch_mm_irqs_off()
+                                         switch_slb
+                                           load_slb++
+                                            /*
+                                            * load_slb becomes 0 here
+                                            * and we evict an entry from
+                                            * the preload cache with
+                                            * preload_age(). We still
+                                            * keep HW SLB and preload
+                                            * cache in sync, that is
+                                            * because all HW SLB entries
+                                            * anyways gets evicted in
+                                            * switch_slb during SLBIA.
+                                            * We then only add those
+                                            * entries back in HW SLB,
+                                            * which are currently
+                                            * present in preload_cache
+                                            * (after eviction).
+                                            */
+                                        load_elf_binary continues...
+                                         setup_new_exec()
+                                          slb_setup_new_exec()
+
+                                        sched_switch event
+                                        sched_migrate_task migrates
+                                        process P to cpu-0
+
+context_switch from swapper/0 to Process P
+ switch_mm_irqs_off()
+  /*
+   * Since both prev and next mm struct are same we don't call
+   * switch_mmu_context(). This will cause the HW SLB and SW preload
+   * cache to go out of sync in preload_new_slb_context. Because there
+   * was an SLB entry which was evicted from both HW and preload cache
+   * on cpu-1. Now later in preload_new_slb_context(), when we will try
+   * to add the same preload entry again, we will add this to the SW
+   * preload cache and then will add it to the HW SLB. Since on cpu-0
+   * this entry was never invalidated, hence adding this entry to the HW
+   * SLB will cause a SLB multi-hit error.
+   */
+load_elf_binary continues...
+ START_THREAD
+  start_thread
+   preload_new_slb_context
+   /*
+    * This tries to add a new EA to preload cache which was earlier
+    * evicted from both cpu-1 HW SLB and preload cache. This caused the
+    * HW SLB of cpu-0 to go out of sync with the SW preload cache. The
+    * reason for this was, that when we context switched back on CPU-0,
+    * we should have ideally called switch_mmu_context() which will
+    * bring the HW SLB entries on CPU-0 in sync with SW preload cache
+    * entries by setting up the mmu context properly. But we didn't do
+    * that since the prev mm_struct running on cpu-0 was same as the
+    * next mm_struct (which is true for swapper / kernel threads). So
+    * now when we try to add this new entry into the HW SLB of cpu-0,
+    * we hit a SLB multi-hit error.
+    */
+
+WARNING: CPU: 0 PID: 1810970 at arch/powerpc/mm/book3s64/slb.c:62
+assert_slb_presence+0x2c/0x50(48 results) 02:47:29 [20157/42149]
+Modules linked in:
+CPU: 0 UID: 0 PID: 1810970 Comm: dd Not tainted 6.16.0-rc3-dirty #12
+VOLUNTARY
+Hardware name: IBM pSeries (emulated by qemu) POWER8 (architected)
+0x4d0200 0xf000004 of:SLOF,HEAD hv:linux,kvm pSeries
+NIP:  c00000000015426c LR: c0000000001543b4 CTR: 0000000000000000
+REGS: c0000000497c77e0 TRAP: 0700   Not tainted  (6.16.0-rc3-dirty)
+MSR:  8000000002823033 <SF,VEC,VSX,FP,ME,IR,DR,RI,LE>  CR: 28888482  XER: 00000000
+CFAR: c0000000001543b0 IRQMASK: 3
+<...>
+NIP [c00000000015426c] assert_slb_presence+0x2c/0x50
+LR [c0000000001543b4] slb_insert_entry+0x124/0x390
+Call Trace:
+  0x7fffceb5ffff (unreliable)
+  preload_new_slb_context+0x100/0x1a0
+  start_thread+0x26c/0x420
+  load_elf_binary+0x1b04/0x1c40
+  bprm_execve+0x358/0x680
+  do_execveat_common+0x1f8/0x240
+  sys_execve+0x58/0x70
+  system_call_exception+0x114/0x300
+  system_call_common+0x160/0x2c4
+
+>>From the above analysis, during early exec the hardware SLB is cleared,
+and entries from the software preload cache are reloaded into hardware
+by switch_slb. However, preload_new_slb_context and slb_setup_new_exec
+also attempt to load some of the same entries, which can trigger a
+multi-hit. In most cases, these additional preloads simply hit existing
+entries and add nothing new. Removing these functions avoids redundant
+preloads and eliminates the multi-hit issue. This patch removes these
+two functions.
+
+We tested process switching performance using the context_switch
+benchmark on POWER9/hash, and observed no regression.
+
+Without this patch: 129041 ops/sec
+With this patch:    129341 ops/sec
+
+We also measured SLB faults during boot, and the counts are essentially
+the same with and without this patch.
+
+SLB faults without this patch: 19727
+SLB faults with this patch:    19786
+
+Fixes: 5434ae74629a ("powerpc/64s/hash: Add a SLB preload cache")
+cc: stable@vger.kernel.org
+Suggested-by: Nicholas Piggin <npiggin@gmail.com>
+Signed-off-by: Donet Tom <donettom@linux.ibm.com>
+Signed-off-by: Ritesh Harjani (IBM) <ritesh.list@gmail.com>
+Signed-off-by: Madhavan Srinivasan <maddy@linux.ibm.com>
+Link: https://patch.msgid.link/0ac694ae683494fe8cadbd911a1a5018d5d3c541.1761834163.git.ritesh.list@gmail.com
+[ Adjust context ]
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/powerpc/include/asm/book3s/64/mmu-hash.h |    1 
+ arch/powerpc/kernel/process.c                 |    5 -
+ arch/powerpc/mm/book3s64/internal.h           |    1 
+ arch/powerpc/mm/book3s64/mmu_context.c        |    2 
+ arch/powerpc/mm/book3s64/slb.c                |   88 --------------------------
+ 5 files changed, 97 deletions(-)
+
+--- a/arch/powerpc/include/asm/book3s/64/mmu-hash.h
++++ b/arch/powerpc/include/asm/book3s/64/mmu-hash.h
+@@ -524,7 +524,6 @@ void slb_dump_contents(struct slb_entry
+ extern void slb_vmalloc_update(void);
+ extern void slb_set_size(u16 size);
+-void preload_new_slb_context(unsigned long start, unsigned long sp);
+ #endif /* __ASSEMBLY__ */
+ /*
+--- a/arch/powerpc/kernel/process.c
++++ b/arch/powerpc/kernel/process.c
+@@ -1794,8 +1794,6 @@ int copy_thread(unsigned long clone_flag
+       return 0;
+ }
+-void preload_new_slb_context(unsigned long start, unsigned long sp);
+-
+ /*
+  * Set up a thread for executing a new program
+  */
+@@ -1803,9 +1801,6 @@ void start_thread(struct pt_regs *regs,
+ {
+ #ifdef CONFIG_PPC64
+       unsigned long load_addr = regs->gpr[2]; /* saved by ELF_PLAT_INIT */
+-
+-      if (IS_ENABLED(CONFIG_PPC_BOOK3S_64) && !radix_enabled())
+-              preload_new_slb_context(start, sp);
+ #endif
+ #ifdef CONFIG_PPC_TRANSACTIONAL_MEM
+--- a/arch/powerpc/mm/book3s64/internal.h
++++ b/arch/powerpc/mm/book3s64/internal.h
+@@ -13,7 +13,6 @@ static inline bool stress_slb(void)
+       return static_branch_unlikely(&stress_slb_key);
+ }
+-void slb_setup_new_exec(void);
+ void exit_lazy_flush_tlb(struct mm_struct *mm, bool always_flush);
+--- a/arch/powerpc/mm/book3s64/mmu_context.c
++++ b/arch/powerpc/mm/book3s64/mmu_context.c
+@@ -147,8 +147,6 @@ static int hash__init_new_context(struct
+ void hash__setup_new_exec(void)
+ {
+       slice_setup_new_exec();
+-
+-      slb_setup_new_exec();
+ }
+ static int radix__init_new_context(struct mm_struct *mm)
+--- a/arch/powerpc/mm/book3s64/slb.c
++++ b/arch/powerpc/mm/book3s64/slb.c
+@@ -329,94 +329,6 @@ static void preload_age(struct thread_in
+       ti->slb_preload_tail = (ti->slb_preload_tail + 1) % SLB_PRELOAD_NR;
+ }
+-void slb_setup_new_exec(void)
+-{
+-      struct thread_info *ti = current_thread_info();
+-      struct mm_struct *mm = current->mm;
+-      unsigned long exec = 0x10000000;
+-
+-      WARN_ON(irqs_disabled());
+-
+-      /*
+-       * preload cache can only be used to determine whether a SLB
+-       * entry exists if it does not start to overflow.
+-       */
+-      if (ti->slb_preload_nr + 2 > SLB_PRELOAD_NR)
+-              return;
+-
+-      hard_irq_disable();
+-
+-      /*
+-       * We have no good place to clear the slb preload cache on exec,
+-       * flush_thread is about the earliest arch hook but that happens
+-       * after we switch to the mm and have aleady preloaded the SLBEs.
+-       *
+-       * For the most part that's probably okay to use entries from the
+-       * previous exec, they will age out if unused. It may turn out to
+-       * be an advantage to clear the cache before switching to it,
+-       * however.
+-       */
+-
+-      /*
+-       * preload some userspace segments into the SLB.
+-       * Almost all 32 and 64bit PowerPC executables are linked at
+-       * 0x10000000 so it makes sense to preload this segment.
+-       */
+-      if (!is_kernel_addr(exec)) {
+-              if (preload_add(ti, exec))
+-                      slb_allocate_user(mm, exec);
+-      }
+-
+-      /* Libraries and mmaps. */
+-      if (!is_kernel_addr(mm->mmap_base)) {
+-              if (preload_add(ti, mm->mmap_base))
+-                      slb_allocate_user(mm, mm->mmap_base);
+-      }
+-
+-      /* see switch_slb */
+-      asm volatile("isync" : : : "memory");
+-
+-      local_irq_enable();
+-}
+-
+-void preload_new_slb_context(unsigned long start, unsigned long sp)
+-{
+-      struct thread_info *ti = current_thread_info();
+-      struct mm_struct *mm = current->mm;
+-      unsigned long heap = mm->start_brk;
+-
+-      WARN_ON(irqs_disabled());
+-
+-      /* see above */
+-      if (ti->slb_preload_nr + 3 > SLB_PRELOAD_NR)
+-              return;
+-
+-      hard_irq_disable();
+-
+-      /* Userspace entry address. */
+-      if (!is_kernel_addr(start)) {
+-              if (preload_add(ti, start))
+-                      slb_allocate_user(mm, start);
+-      }
+-
+-      /* Top of stack, grows down. */
+-      if (!is_kernel_addr(sp)) {
+-              if (preload_add(ti, sp))
+-                      slb_allocate_user(mm, sp);
+-      }
+-
+-      /* Bottom of heap, grows up. */
+-      if (heap && !is_kernel_addr(heap)) {
+-              if (preload_add(ti, heap))
+-                      slb_allocate_user(mm, heap);
+-      }
+-
+-      /* see switch_slb */
+-      asm volatile("isync" : : : "memory");
+-
+-      local_irq_enable();
+-}
+-
+ static void slb_cache_slbie_kernel(unsigned int index)
+ {
+       unsigned long slbie_data = get_paca()->slb_cache[index];
diff --git a/queue-5.15/powerpc-pseries-cmm-adjust-balloon_migrate-when-migrating-pages.patch b/queue-5.15/powerpc-pseries-cmm-adjust-balloon_migrate-when-migrating-pages.patch
new file mode 100644 (file)
index 0000000..dc5d290
--- /dev/null
@@ -0,0 +1,45 @@
+From stable+bounces-204900-greg=kroah.com@vger.kernel.org Mon Jan  5 20:30:56 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon,  5 Jan 2026 14:28:26 -0500
+Subject: powerpc/pseries/cmm: adjust BALLOON_MIGRATE when migrating pages
+To: stable@vger.kernel.org
+Cc: David Hildenbrand <david@redhat.com>, "Ritesh Harjani (IBM)" <ritesh.list@gmail.com>, Christophe Leroy <christophe.leroy@csgroup.eu>, Madhavan Srinivasan <maddy@linux.ibm.com>, Michael Ellerman <mpe@ellerman.id.au>, Nicholas Piggin <npiggin@gmail.com>, Andrew Morton <akpm@linux-foundation.org>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260105192826.2740369-4-sashal@kernel.org>
+
+From: David Hildenbrand <david@redhat.com>
+
+[ Upstream commit 0da2ba35c0d532ca0fe7af698b17d74c4d084b9a ]
+
+Let's properly adjust BALLOON_MIGRATE like the other drivers.
+
+Note that the INFLATE/DEFLATE events are triggered from the core when
+enqueueing/dequeueing pages.
+
+This was found by code inspection.
+
+Link: https://lkml.kernel.org/r/20251021100606.148294-3-david@redhat.com
+Fixes: fe030c9b85e6 ("powerpc/pseries/cmm: Implement balloon compaction")
+Signed-off-by: David Hildenbrand <david@redhat.com>
+Reviewed-by: Ritesh Harjani (IBM) <ritesh.list@gmail.com>
+Cc: Christophe Leroy <christophe.leroy@csgroup.eu>
+Cc: Madhavan Srinivasan <maddy@linux.ibm.com>
+Cc: Michael Ellerman <mpe@ellerman.id.au>
+Cc: Nicholas Piggin <npiggin@gmail.com>
+Cc: <stable@vger.kernel.org>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/powerpc/platforms/pseries/cmm.c |    1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/arch/powerpc/platforms/pseries/cmm.c
++++ b/arch/powerpc/platforms/pseries/cmm.c
+@@ -550,6 +550,7 @@ static int cmm_migratepage(struct balloo
+       spin_lock_irqsave(&b_dev_info->pages_lock, flags);
+       balloon_page_insert(b_dev_info, newpage);
++      __count_vm_event(BALLOON_MIGRATE);
+       b_dev_info->isolated_pages--;
+       spin_unlock_irqrestore(&b_dev_info->pages_lock, flags);
diff --git a/queue-5.15/powerpc-pseries-cmm-call-balloon_devinfo_init-also-without-config_balloon_compaction.patch b/queue-5.15/powerpc-pseries-cmm-call-balloon_devinfo_init-also-without-config_balloon_compaction.patch
new file mode 100644 (file)
index 0000000..bb33c82
--- /dev/null
@@ -0,0 +1,63 @@
+From stable+bounces-204908-greg=kroah.com@vger.kernel.org Mon Jan  5 21:01:46 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon,  5 Jan 2026 15:01:20 -0500
+Subject: powerpc/pseries/cmm: call balloon_devinfo_init() also without CONFIG_BALLOON_COMPACTION
+To: stable@vger.kernel.org
+Cc: David Hildenbrand <david@redhat.com>, "Ritesh Harjani (IBM)" <ritesh.list@gmail.com>, Christophe Leroy <christophe.leroy@csgroup.eu>, Madhavan Srinivasan <maddy@linux.ibm.com>, Michael Ellerman <mpe@ellerman.id.au>, Nicholas Piggin <npiggin@gmail.com>, Andrew Morton <akpm@linux-foundation.org>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260105200120.2763600-1-sashal@kernel.org>
+
+From: David Hildenbrand <david@redhat.com>
+
+[ Upstream commit fc6bcf9ac4de76f5e7bcd020b3c0a86faff3f2d5 ]
+
+Patch series "powerpc/pseries/cmm: two smaller fixes".
+
+Two smaller fixes identified while doing a bigger rework.
+
+This patch (of 2):
+
+We always have to initialize the balloon_dev_info, even when compaction is
+not configured in: otherwise the containing list and the lock are left
+uninitialized.
+
+Likely not many such configs exist in practice, but let's CC stable to
+be sure.
+
+This was found by code inspection.
+
+Link: https://lkml.kernel.org/r/20251021100606.148294-1-david@redhat.com
+Link: https://lkml.kernel.org/r/20251021100606.148294-2-david@redhat.com
+Fixes: fe030c9b85e6 ("powerpc/pseries/cmm: Implement balloon compaction")
+Signed-off-by: David Hildenbrand <david@redhat.com>
+Reviewed-by: Ritesh Harjani (IBM) <ritesh.list@gmail.com>
+Cc: Christophe Leroy <christophe.leroy@csgroup.eu>
+Cc: Madhavan Srinivasan <maddy@linux.ibm.com>
+Cc: Michael Ellerman <mpe@ellerman.id.au>
+Cc: Nicholas Piggin <npiggin@gmail.com>
+Cc: <stable@vger.kernel.org>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+[ moved balloon_devinfo_init() call from inside cmm_balloon_compaction_init() to cmm_init() ]
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/powerpc/platforms/pseries/cmm.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/arch/powerpc/platforms/pseries/cmm.c
++++ b/arch/powerpc/platforms/pseries/cmm.c
+@@ -570,7 +570,6 @@ static int cmm_balloon_compaction_init(v
+ {
+       int rc;
+-      balloon_devinfo_init(&b_dev_info);
+       b_dev_info.migratepage = cmm_migratepage;
+       balloon_mnt = kern_mount(&balloon_fs);
+@@ -624,6 +623,7 @@ static int cmm_init(void)
+       if (!firmware_has_feature(FW_FEATURE_CMO) && !simulate)
+               return -EOPNOTSUPP;
++      balloon_devinfo_init(&b_dev_info);
+       rc = cmm_balloon_compaction_init();
+       if (rc)
+               return rc;
diff --git a/queue-5.15/r8169-fix-rtl8117-wake-on-lan-in-dash-mode.patch b/queue-5.15/r8169-fix-rtl8117-wake-on-lan-in-dash-mode.patch
new file mode 100644 (file)
index 0000000..8a0c5ec
--- /dev/null
@@ -0,0 +1,53 @@
+From stable+bounces-204346-greg=kroah.com@vger.kernel.org Wed Dec 31 14:46:48 2025
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 31 Dec 2025 08:46:42 -0500
+Subject: r8169: fix RTL8117 Wake-on-Lan in DASH mode
+To: stable@vger.kernel.org
+Cc: "René Rebe" <rene@exactco.de>, "Heiner Kallweit" <hkallweit1@gmail.com>, "Jakub Kicinski" <kuba@kernel.org>, "Sasha Levin" <sashal@kernel.org>
+Message-ID: <20251231134642.2899730-1-sashal@kernel.org>
+
+From: René Rebe <rene@exactco.de>
+
+[ Upstream commit dd75c723ef566f7f009c047f47e0eee95fe348ab ]
+
+Wake-on-Lan does currently not work for r8169 in DASH mode, e.g. the
+ASUS Pro WS X570-ACE with RTL8168fp/RTL8117.
+
+Fix by not returning early in rtl_prepare_power_down when dash_enabled.
+While this fixes WoL, it still kills the OOB RTL8117 remote management
+BMC connection. Fix by not calling rtl8168_driver_stop if WoL is enabled.
+
+Fixes: 065c27c184d6 ("r8169: phy power ops")
+Signed-off-by: René Rebe <rene@exactco.de>
+Cc: stable@vger.kernel.org
+Reviewed-by: Heiner Kallweit <hkallweit1@gmail.com>
+Link: https://patch.msgid.link/20251202.194137.1647877804487085954.rene@exactco.de
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+[ adapted tp->dash_enabled check to tp->dash_type != RTL_DASH_NONE comparison ]
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/net/ethernet/realtek/r8169_main.c |    5 +----
+ 1 file changed, 1 insertion(+), 4 deletions(-)
+
+--- a/drivers/net/ethernet/realtek/r8169_main.c
++++ b/drivers/net/ethernet/realtek/r8169_main.c
+@@ -2513,9 +2513,6 @@ static void rtl_wol_enable_rx(struct rtl
+ static void rtl_prepare_power_down(struct rtl8169_private *tp)
+ {
+-      if (tp->dash_type != RTL_DASH_NONE)
+-              return;
+-
+       if (tp->mac_version == RTL_GIGA_MAC_VER_32 ||
+           tp->mac_version == RTL_GIGA_MAC_VER_33)
+               rtl_ephy_write(tp, 0x19, 0xff64);
+@@ -4763,7 +4760,7 @@ static void rtl8169_down(struct rtl8169_
+       rtl_prepare_power_down(tp);
+-      if (tp->dash_type != RTL_DASH_NONE)
++      if (tp->dash_type != RTL_DASH_NONE && !tp->saved_wolopts)
+               rtl8168_driver_stop(tp);
+ }
index cde6a798fb5618aadb429158342b6b89784ca4b2..a965d192bc842f5bf3875a7aa3694128dc3f8a46 100644 (file)
@@ -425,3 +425,66 @@ virtio_console-fix-order-of-fields-cols-and-rows.patch
 drm-vmwgfx-fix-a-null-ptr-access-in-the-cursor-snooper.patch
 usb-xhci-move-link-chain-bit-quirk-checks-into-one-helper-function.patch
 usb-xhci-apply-the-link-chain-quirk-on-nec-isoc-endpoints.patch
+usb-gadget-udc-fix-use-after-free-in-usb_gadget_state_work.patch
+xhci-dbgtty-use-idr-to-support-several-dbc-instances.patch
+xhci-dbgtty-fix-device-unregister.patch
+jbd2-fix-the-inconsistency-between-checksum-and-data-in-memory-for-journal-sb.patch
+tpm-cap-the-number-of-pcr-banks.patch
+btrfs-don-t-rewrite-ret-from-inode_permission.patch
+wifi-mt76-fix-dts-power-limits-on-little-endian-systems.patch
+alsa-wavefront-clear-substream-pointers-on-close.patch
+alsa-wavefront-use-standard-print-api.patch
+alsa-wavefront-fix-integer-overflow-in-sample-size-validation.patch
+nfsd-clear-seclabel-in-the-suppattr_exclcreat-bitmap.patch
+kvm-nvmx-immediately-refresh-apicv-controls-as-needed-on-nested-vm-exit.patch
+xfs-fix-a-memory-leak-in-xfs_buf_item_init.patch
+f2fs-fix-to-detect-recoverable-inode-during-dryrun-of-find_fsync_dnodes.patch
+f2fs-use-global-inline_xattr_slab-instead-of-per-sb-slab-cache.patch
+f2fs-fix-to-propagate-error-from-f2fs_enable_checkpoint.patch
+f2fs-fix-to-avoid-updating-zero-sized-extent-in-extent-cache.patch
+usb-dwc3-keep-susphy-enabled-during-exit-to-avoid-controller-faults.patch
+mptcp-pm-ignore-unknown-endpoint-flags.patch
+usb-ohci-nxp-use-helper-function-devm_clk_get_enabled.patch
+usb-ohci-nxp-fix-device-leak-on-probe-failure.patch
+fuse-fix-readahead-reclaim-deadlock.patch
+arm-dts-microchip-sama7g5-fix-uart-fifo-size-to-32.patch
+svcrdma-bound-check-rq_pages-index-in-inline-path.patch
+arm-dts-microchip-sama5d2-fix-spi-flexcom-fifo-size-to-32.patch
+crypto-af_alg-zero-initialize-memory-allocated-via-sock_kmalloc.patch
+kvm-svm-mark-vmcb_npt-as-dirty-on-nested-vmrun.patch
+sunrpc-svcauth_gss-avoid-null-deref-on-zero-length-gss_token-in-gss_read_proxy_verf.patch
+media-mediatek-vcodec-fix-a-reference-leak-in-mtk_vcodec_fw_vpu_init.patch
+media-vpif_capture-fix-section-mismatch.patch
+media-verisilicon-protect-g2-hevc-decoder-against-invalid-dpb-index.patch
+nfsd-nfsv4-file-creation-neglects-setting-acl.patch
+media-samsung-exynos4-is-fix-potential-abba-deadlock-on-init.patch
+media-renesas-rcar_drif-fix-device-node-reference-leak-in-rcar_drif_bond_enabled.patch
+powerpc-pseries-cmm-call-balloon_devinfo_init-also-without-config_balloon_compaction.patch
+pci-brcmstb-fix-disabling-l0s-capability.patch
+powerpc-64s-slb-fix-slb-multihit-issue-during-slb-preload.patch
+iommu-qcom-fix-device-leak-on-of_xlate.patch
+r8169-fix-rtl8117-wake-on-lan-in-dash-mode.patch
+asoc-stm-use-dev_err_probe-helper.patch
+asoc-stm32-sai-use-the-devm_clk_get_optional-helper.patch
+asoc-stm32-sai-fix-clk-prepare-imbalance-on-probe-failure.patch
+mm-balloon_compaction-make-balloon-page-compaction-callbacks-static.patch
+mm-balloon_compaction-we-cannot-have-isolated-pages-in-the-balloon-list.patch
+mm-balloon_compaction-convert-balloon_page_delete-to-balloon_page_finalize.patch
+powerpc-pseries-cmm-adjust-balloon_migrate-when-migrating-pages.patch
+soc-rockchip-power-domain-manage-resource-conflicts-with-firmware.patch
+pmdomain-use-device_get_match_data.patch
+pmdomain-imx-fix-reference-count-leak-in-imx_gpc_probe.patch
+lockd-fix-vfs_test_lock-calls.patch
+asoc-stm-stm32_sai_sub-convert-to-platform-remove-callback-returning-void.patch
+asoc-stm32-sai-fix-of-node-leak-on-probe.patch
+wifi-mac80211-discard-beacon-frames-to-non-broadcast-address.patch
+drm-mediatek-fix-probe-memory-leak.patch
+drm-gma500-remove-unused-helper-psb_fbdev_fb_setcolreg.patch
+net-remove-rtnl-dance-for-siocbraddif-and-siocbrdelif.patch
+mmc-core-use-sysfs_emit-instead-of-sprintf.patch
+drm-i915-selftests-fix-subtraction-overflow-bug.patch
+page_pool-fix-use-after-free-in-page_pool_recycle_in_ring.patch
+kvm-x86-acquire-kvm-srcu-when-handling-kvm_set_vcpu_events.patch
+hid-core-harden-s32ton-against-conversion-to-0-bits.patch
+mm-mprotect-use-long-for-page-accountings-and-retval.patch
+mm-mprotect-delete-pmd_none_or_clear_bad_unless_trans_huge.patch
diff --git a/queue-5.15/soc-rockchip-power-domain-manage-resource-conflicts-with-firmware.patch b/queue-5.15/soc-rockchip-power-domain-manage-resource-conflicts-with-firmware.patch
new file mode 100644 (file)
index 0000000..bfdfdce
--- /dev/null
@@ -0,0 +1,291 @@
+From stable+bounces-206019-greg=kroah.com@vger.kernel.org Tue Jan  6 19:57:04 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue,  6 Jan 2026 13:10:14 -0500
+Subject: soc: rockchip: power-domain: Manage resource conflicts with firmware
+To: stable@vger.kernel.org
+Cc: Brian Norris <briannorris@chromium.org>, Peter Geis <pgwipeout@gmail.com>, Heiko Stuebner <heiko@sntech.de>, Chanwoo Choi <cw00.choi@samsung.com>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260106181021.3109327-1-sashal@kernel.org>
+
+From: Brian Norris <briannorris@chromium.org>
+
+[ Upstream commit defec178df76e0caadd4e8ef68f3d655a2088198 ]
+
+On RK3399 platforms, power domains are managed mostly by the kernel
+(drivers/soc/rockchip/pm_domains.c), but there are a few exceptions
+where ARM Trusted Firmware has to be involved:
+
+(1) system suspend/resume
+(2) DRAM DVFS (a.k.a., "ddrfreq")
+
+Exception (1) does not cause much conflict, since the kernel has
+quiesced itself by the time we make the relevant PSCI call.
+
+Exception (2) can cause conflict, because of two actions:
+
+(a) ARM Trusted Firmware needs to read/modify/write the PMU_BUS_IDLE_REQ
+    register to idle the memory controller domain; the kernel driver
+    also has to touch this register for other domains.
+(b) ARM Trusted Firmware needs to manage the clocks associated with
+    these domains.
+
+To elaborate on (b): idling a power domain has always required ungating
+an array of clocks; see this old explanation from Rockchip:
+https://lore.kernel.org/linux-arm-kernel/54503C19.9060607@rock-chips.com/
+
+Historically, ARM Trusted Firmware has avoided this issue by using a
+special PMU_CRU_GATEDIS_CON0 register -- this register ungates all the
+necessary clocks -- when idling the memory controller. Unfortunately,
+we've found that this register is not 100% sufficient; it does not turn
+the relevant PLLs on [0].
+
+So it's possible to trigger issues with something like the following:
+
+1. enable a power domain (e.g., RK3399_PD_VDU) -- kernel will
+   temporarily enable relevant clocks/PLLs, then turn them back off
+   2. a PLL (e.g., PLL_NPLL) is part of the clock tree for
+      RK3399_PD_VDU's clocks but otherwise unused; NPLL is disabled
+3. perform a ddrfreq transition (rk3399_dmcfreq_target() -> ...
+   drivers/clk/rockchip/clk-ddr.c / ROCKCHIP_SIP_DRAM_FREQ)
+   4. ARM Trusted Firmware unagates VDU clocks (via PMU_CRU_GATEDIS_CON0)
+   5. ARM Trusted firmware idles the memory controller domain
+   6. Step 5 waits on the VDU domain/clocks, but NPLL is still off
+
+i.e., we hang the system.
+
+So for (b), we need to at a minimum manage the relevant PLLs on behalf
+of firmware. It's easier to simply manage the whole clock tree, in a
+similar way we do in rockchip_pd_power().
+
+For (a), we need to provide mutual exclusion betwen rockchip_pd_power()
+and firmware. To resolve that, we simply grab the PMU mutex and release
+it when ddrfreq is done.
+
+The Chromium OS kernel has been carrying versions of part of this hack
+for a while, based on some new custom notifiers [1]. I've rewritten as a
+simple function call between the drivers, which is OK because:
+
+ * the PMU driver isn't enabled, and we don't have this problem at all
+   (the firmware should have left us in an OK state, and there are no
+   runtime conflicts); or
+ * the PMU driver is present, and is a single instance.
+
+And the power-domain driver cannot be removed, so there's no lifetime
+management to worry about.
+
+For completeness, there's a 'dmc_pmu_mutex' to guard (likely
+theoretical?) probe()-time races. It's OK for the memory controller
+driver to start running before the PMU, because the PMU will avoid any
+critical actions during the block() sequence.
+
+[0] The RK3399 TRM for PMU_CRU_GATEDIS_CON0 only talks about ungating
+    clocks. Based on experimentation, we've found that it does not power
+    up the necessary PLLs.
+
+[1] CHROMIUM: soc: rockchip: power-domain: Add notifier to dmc driver
+    https://chromium-review.googlesource.com/q/I242dbd706d352f74ff706f5cbf42ebb92f9bcc60
+    Notably, the Chromium solution only handled conflict (a), not (b).
+    In practice, item (b) wasn't a problem in many cases because we
+    never managed to fully power off PLLs. Now that the (upstream) video
+    decoder driver performs runtime clock management, we often power off
+    NPLL.
+
+Signed-off-by: Brian Norris <briannorris@chromium.org>
+Tested-by: Peter Geis <pgwipeout@gmail.com>
+Reviewed-by: Heiko Stuebner <heiko@sntech.de>
+Signed-off-by: Chanwoo Choi <cw00.choi@samsung.com>
+Stable-dep-of: 73cb5f6eafb0 ("pmdomain: imx: Fix reference count leak in imx_gpc_probe()")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/soc/rockchip/pm_domains.c |  118 ++++++++++++++++++++++++++++++++++++++
+ include/soc/rockchip/pm_domains.h |   25 ++++++++
+ 2 files changed, 143 insertions(+)
+ create mode 100644 include/soc/rockchip/pm_domains.h
+
+--- a/drivers/soc/rockchip/pm_domains.c
++++ b/drivers/soc/rockchip/pm_domains.c
+@@ -8,6 +8,7 @@
+ #include <linux/io.h>
+ #include <linux/iopoll.h>
+ #include <linux/err.h>
++#include <linux/mutex.h>
+ #include <linux/pm_clock.h>
+ #include <linux/pm_domain.h>
+ #include <linux/of_address.h>
+@@ -16,6 +17,7 @@
+ #include <linux/clk.h>
+ #include <linux/regmap.h>
+ #include <linux/mfd/syscon.h>
++#include <soc/rockchip/pm_domains.h>
+ #include <dt-bindings/power/px30-power.h>
+ #include <dt-bindings/power/rk3036-power.h>
+ #include <dt-bindings/power/rk3066-power.h>
+@@ -139,6 +141,109 @@ struct rockchip_pmu {
+ #define DOMAIN_RK3568(name, pwr, req, wakeup)         \
+       DOMAIN_M(name, pwr, pwr, req, req, req, wakeup)
++/*
++ * Dynamic Memory Controller may need to coordinate with us -- see
++ * rockchip_pmu_block().
++ *
++ * dmc_pmu_mutex protects registration-time races, so DMC driver doesn't try to
++ * block() while we're initializing the PMU.
++ */
++static DEFINE_MUTEX(dmc_pmu_mutex);
++static struct rockchip_pmu *dmc_pmu;
++
++/*
++ * Block PMU transitions and make sure they don't interfere with ARM Trusted
++ * Firmware operations. There are two conflicts, noted in the comments below.
++ *
++ * Caller must unblock PMU transitions via rockchip_pmu_unblock().
++ */
++int rockchip_pmu_block(void)
++{
++      struct rockchip_pmu *pmu;
++      struct generic_pm_domain *genpd;
++      struct rockchip_pm_domain *pd;
++      int i, ret;
++
++      mutex_lock(&dmc_pmu_mutex);
++
++      /* No PMU (yet)? Then we just block rockchip_pmu_probe(). */
++      if (!dmc_pmu)
++              return 0;
++      pmu = dmc_pmu;
++
++      /*
++       * mutex blocks all idle transitions: we can't touch the
++       * PMU_BUS_IDLE_REQ (our ".idle_offset") register while ARM Trusted
++       * Firmware might be using it.
++       */
++      mutex_lock(&pmu->mutex);
++
++      /*
++       * Power domain clocks: Per Rockchip, we *must* keep certain clocks
++       * enabled for the duration of power-domain transitions. Most
++       * transitions are handled by this driver, but some cases (in
++       * particular, DRAM DVFS / memory-controller idle) must be handled by
++       * firmware. Firmware can handle most clock management via a special
++       * "ungate" register (PMU_CRU_GATEDIS_CON0), but unfortunately, this
++       * doesn't handle PLLs. We can assist this transition by doing the
++       * clock management on behalf of firmware.
++       */
++      for (i = 0; i < pmu->genpd_data.num_domains; i++) {
++              genpd = pmu->genpd_data.domains[i];
++              if (genpd) {
++                      pd = to_rockchip_pd(genpd);
++                      ret = clk_bulk_enable(pd->num_clks, pd->clks);
++                      if (ret < 0) {
++                              dev_err(pmu->dev,
++                                      "failed to enable clks for domain '%s': %d\n",
++                                      genpd->name, ret);
++                              goto err;
++                      }
++              }
++      }
++
++      return 0;
++
++err:
++      for (i = i - 1; i >= 0; i--) {
++              genpd = pmu->genpd_data.domains[i];
++              if (genpd) {
++                      pd = to_rockchip_pd(genpd);
++                      clk_bulk_disable(pd->num_clks, pd->clks);
++              }
++      }
++      mutex_unlock(&pmu->mutex);
++      mutex_unlock(&dmc_pmu_mutex);
++
++      return ret;
++}
++EXPORT_SYMBOL_GPL(rockchip_pmu_block);
++
++/* Unblock PMU transitions. */
++void rockchip_pmu_unblock(void)
++{
++      struct rockchip_pmu *pmu;
++      struct generic_pm_domain *genpd;
++      struct rockchip_pm_domain *pd;
++      int i;
++
++      if (dmc_pmu) {
++              pmu = dmc_pmu;
++              for (i = 0; i < pmu->genpd_data.num_domains; i++) {
++                      genpd = pmu->genpd_data.domains[i];
++                      if (genpd) {
++                              pd = to_rockchip_pd(genpd);
++                              clk_bulk_disable(pd->num_clks, pd->clks);
++                      }
++              }
++
++              mutex_unlock(&pmu->mutex);
++      }
++
++      mutex_unlock(&dmc_pmu_mutex);
++}
++EXPORT_SYMBOL_GPL(rockchip_pmu_unblock);
++
+ static bool rockchip_pmu_domain_is_idle(struct rockchip_pm_domain *pd)
+ {
+       struct rockchip_pmu *pmu = pd->pmu;
+@@ -690,6 +795,12 @@ static int rockchip_pm_domain_probe(stru
+       error = -ENODEV;
++      /*
++       * Prevent any rockchip_pmu_block() from racing with the remainder of
++       * setup (clocks, register initialization).
++       */
++      mutex_lock(&dmc_pmu_mutex);
++
+       for_each_available_child_of_node(np, node) {
+               error = rockchip_pm_add_one_domain(pmu, node);
+               if (error) {
+@@ -719,10 +830,17 @@ static int rockchip_pm_domain_probe(stru
+               goto err_out;
+       }
++      /* We only expect one PMU. */
++      if (!WARN_ON_ONCE(dmc_pmu))
++              dmc_pmu = pmu;
++
++      mutex_unlock(&dmc_pmu_mutex);
++
+       return 0;
+ err_out:
+       rockchip_pm_domain_cleanup(pmu);
++      mutex_unlock(&dmc_pmu_mutex);
+       return error;
+ }
+--- /dev/null
++++ b/include/soc/rockchip/pm_domains.h
+@@ -0,0 +1,25 @@
++/* SPDX-License-Identifier: GPL-2.0 */
++/*
++ * Copyright 2022, The Chromium OS Authors. All rights reserved.
++ */
++
++#ifndef __SOC_ROCKCHIP_PM_DOMAINS_H__
++#define __SOC_ROCKCHIP_PM_DOMAINS_H__
++
++#ifdef CONFIG_ROCKCHIP_PM_DOMAINS
++
++int rockchip_pmu_block(void);
++void rockchip_pmu_unblock(void);
++
++#else /* CONFIG_ROCKCHIP_PM_DOMAINS */
++
++static inline int rockchip_pmu_block(void)
++{
++      return 0;
++}
++
++static inline void rockchip_pmu_unblock(void) { }
++
++#endif /* CONFIG_ROCKCHIP_PM_DOMAINS */
++
++#endif /* __SOC_ROCKCHIP_PM_DOMAINS_H__ */
diff --git a/queue-5.15/sunrpc-svcauth_gss-avoid-null-deref-on-zero-length-gss_token-in-gss_read_proxy_verf.patch b/queue-5.15/sunrpc-svcauth_gss-avoid-null-deref-on-zero-length-gss_token-in-gss_read_proxy_verf.patch
new file mode 100644 (file)
index 0000000..8bec461
--- /dev/null
@@ -0,0 +1,41 @@
+From stable+bounces-204357-greg=kroah.com@vger.kernel.org Wed Dec 31 15:39:01 2025
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 31 Dec 2025 09:38:53 -0500
+Subject: SUNRPC: svcauth_gss: avoid NULL deref on zero length gss_token in gss_read_proxy_verf
+To: stable@vger.kernel.org
+Cc: Joshua Rogers <linux@joshua.hu>, Chuck Lever <chuck.lever@oracle.com>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20251231143853.3046790-1-sashal@kernel.org>
+
+From: Joshua Rogers <linux@joshua.hu>
+
+[ Upstream commit d4b69a6186b215d2dc1ebcab965ed88e8d41768d ]
+
+A zero length gss_token results in pages == 0 and in_token->pages[0]
+is NULL. The code unconditionally evaluates
+page_address(in_token->pages[0]) for the initial memcpy, which can
+dereference NULL even when the copy length is 0. Guard the first
+memcpy so it only runs when length > 0.
+
+Fixes: 5866efa8cbfb ("SUNRPC: Fix svcauth_gss_proxy_init()")
+Cc: stable@vger.kernel.org
+Signed-off-by: Joshua Rogers <linux@joshua.hu>
+Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
+[ adapted xdr buffer pointer API to older argv iov_base/iov_len API ]
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/sunrpc/auth_gss/svcauth_gss.c |    3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+--- a/net/sunrpc/auth_gss/svcauth_gss.c
++++ b/net/sunrpc/auth_gss/svcauth_gss.c
+@@ -1179,7 +1179,8 @@ static int gss_read_proxy_verf(struct sv
+       }
+       length = min_t(unsigned int, inlen, argv->iov_len);
+-      memcpy(page_address(in_token->pages[0]), argv->iov_base, length);
++      if (length)
++              memcpy(page_address(in_token->pages[0]), argv->iov_base, length);
+       inlen -= length;
+       to_offs = length;
diff --git a/queue-5.15/svcrdma-bound-check-rq_pages-index-in-inline-path.patch b/queue-5.15/svcrdma-bound-check-rq_pages-index-in-inline-path.patch
new file mode 100644 (file)
index 0000000..335d3c1
--- /dev/null
@@ -0,0 +1,39 @@
+From stable+bounces-204397-greg=kroah.com@vger.kernel.org Wed Dec 31 23:44:29 2025
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 31 Dec 2025 17:44:24 -0500
+Subject: svcrdma: bound check rq_pages index in inline path
+To: stable@vger.kernel.org
+Cc: Joshua Rogers <linux@joshua.hu>, Chuck Lever <chuck.lever@oracle.com>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20251231224424.3631279-1-sashal@kernel.org>
+
+From: Joshua Rogers <linux@joshua.hu>
+
+[ Upstream commit d1bea0ce35b6095544ee82bb54156fc62c067e58 ]
+
+svc_rdma_copy_inline_range indexed rqstp->rq_pages[rc_curpage] without
+verifying rc_curpage stays within the allocated page array. Add guards
+before the first use and after advancing to a new page.
+
+Fixes: d7cc73972661 ("svcrdma: support multiple Read chunks per RPC")
+Cc: stable@vger.kernel.org
+Signed-off-by: Joshua Rogers <linux@joshua.hu>
+Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
+[ adapted rc_curpage and rq_maxpages fields to ri_pageno and RPCSVC_MAXPAGES constant ]
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/sunrpc/xprtrdma/svc_rdma_rw.c |    3 +++
+ 1 file changed, 3 insertions(+)
+
+--- a/net/sunrpc/xprtrdma/svc_rdma_rw.c
++++ b/net/sunrpc/xprtrdma/svc_rdma_rw.c
+@@ -789,6 +789,9 @@ static int svc_rdma_copy_inline_range(st
+       for (page_no = 0; page_no < numpages; page_no++) {
+               unsigned int page_len;
++              if (info->ri_pageno >= RPCSVC_MAXPAGES)
++                      return -EINVAL;
++
+               page_len = min_t(unsigned int, remaining,
+                                PAGE_SIZE - info->ri_pageoff);
diff --git a/queue-5.15/tpm-cap-the-number-of-pcr-banks.patch b/queue-5.15/tpm-cap-the-number-of-pcr-banks.patch
new file mode 100644 (file)
index 0000000..a2206ee
--- /dev/null
@@ -0,0 +1,105 @@
+From stable+bounces-204157-greg=kroah.com@vger.kernel.org Tue Dec 30 01:13:03 2025
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 29 Dec 2025 19:12:57 -0500
+Subject: tpm: Cap the number of PCR banks
+To: stable@vger.kernel.org
+Cc: Jarkko Sakkinen <jarkko.sakkinen@opinsys.com>, Lai Yi <yi1.lai@linux.intel.com>, Jonathan McDowell <noodles@meta.com>, Roberto Sassu <roberto.sassu@huawei.com>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20251230001257.1873924-1-sashal@kernel.org>
+
+From: Jarkko Sakkinen <jarkko.sakkinen@opinsys.com>
+
+[ Upstream commit faf07e611dfa464b201223a7253e9dc5ee0f3c9e ]
+
+tpm2_get_pcr_allocation() does not cap any upper limit for the number of
+banks. Cap the limit to eight banks so that out of bounds values coming
+from external I/O cause on only limited harm.
+
+Cc: stable@vger.kernel.org # v5.10+
+Fixes: bcfff8384f6c ("tpm: dynamically allocate the allocated_banks array")
+Tested-by: Lai Yi <yi1.lai@linux.intel.com>
+Reviewed-by: Jonathan McDowell <noodles@meta.com>
+Reviewed-by: Roberto Sassu <roberto.sassu@huawei.com>
+Signed-off-by: Jarkko Sakkinen <jarkko.sakkinen@opinsys.com>
+[ added backward-compatible define for TPM_MAX_DIGEST_SIZE to support older ima_init.c code still using that macro name ]
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/char/tpm/tpm-chip.c |    1 -
+ drivers/char/tpm/tpm1-cmd.c |    5 -----
+ drivers/char/tpm/tpm2-cmd.c |    8 +++-----
+ include/linux/tpm.h         |    9 ++++++---
+ 4 files changed, 9 insertions(+), 14 deletions(-)
+
+--- a/drivers/char/tpm/tpm-chip.c
++++ b/drivers/char/tpm/tpm-chip.c
+@@ -269,7 +269,6 @@ static void tpm_dev_release(struct devic
+       kfree(chip->work_space.context_buf);
+       kfree(chip->work_space.session_buf);
+-      kfree(chip->allocated_banks);
+       kfree(chip);
+ }
+--- a/drivers/char/tpm/tpm1-cmd.c
++++ b/drivers/char/tpm/tpm1-cmd.c
+@@ -794,11 +794,6 @@ int tpm1_pm_suspend(struct tpm_chip *chi
+  */
+ int tpm1_get_pcr_allocation(struct tpm_chip *chip)
+ {
+-      chip->allocated_banks = kcalloc(1, sizeof(*chip->allocated_banks),
+-                                      GFP_KERNEL);
+-      if (!chip->allocated_banks)
+-              return -ENOMEM;
+-
+       chip->allocated_banks[0].alg_id = TPM_ALG_SHA1;
+       chip->allocated_banks[0].digest_size = hash_digest_size[HASH_ALGO_SHA1];
+       chip->allocated_banks[0].crypto_id = HASH_ALGO_SHA1;
+--- a/drivers/char/tpm/tpm2-cmd.c
++++ b/drivers/char/tpm/tpm2-cmd.c
+@@ -574,11 +574,9 @@ ssize_t tpm2_get_pcr_allocation(struct t
+       nr_possible_banks = be32_to_cpup(
+               (__be32 *)&buf.data[TPM_HEADER_SIZE + 5]);
+-
+-      chip->allocated_banks = kcalloc(nr_possible_banks,
+-                                      sizeof(*chip->allocated_banks),
+-                                      GFP_KERNEL);
+-      if (!chip->allocated_banks) {
++      if (nr_possible_banks > TPM2_MAX_PCR_BANKS) {
++              pr_err("tpm: out of bank capacity: %u > %u\n",
++                     nr_possible_banks, TPM2_MAX_PCR_BANKS);
+               rc = -ENOMEM;
+               goto out;
+       }
+--- a/include/linux/tpm.h
++++ b/include/linux/tpm.h
+@@ -25,7 +25,10 @@
+ #include <crypto/hash_info.h>
+ #define TPM_DIGEST_SIZE 20    /* Max TPM v1.2 PCR size */
+-#define TPM_MAX_DIGEST_SIZE SHA512_DIGEST_SIZE
++
++#define TPM2_MAX_DIGEST_SIZE  SHA512_DIGEST_SIZE
++#define TPM2_MAX_PCR_BANKS    8
++#define TPM_MAX_DIGEST_SIZE   TPM2_MAX_DIGEST_SIZE
+ struct tpm_chip;
+ struct trusted_key_payload;
+@@ -51,7 +54,7 @@ enum tpm_algorithms {
+ struct tpm_digest {
+       u16 alg_id;
+-      u8 digest[TPM_MAX_DIGEST_SIZE];
++      u8 digest[TPM2_MAX_DIGEST_SIZE];
+ } __packed;
+ struct tpm_bank_info {
+@@ -157,7 +160,7 @@ struct tpm_chip {
+       unsigned int groups_cnt;
+       u32 nr_allocated_banks;
+-      struct tpm_bank_info *allocated_banks;
++      struct tpm_bank_info allocated_banks[TPM2_MAX_PCR_BANKS];
+ #ifdef CONFIG_ACPI
+       acpi_handle acpi_dev_handle;
+       char ppi_version[TPM_PPI_VERSION_LEN + 1];
diff --git a/queue-5.15/usb-dwc3-keep-susphy-enabled-during-exit-to-avoid-controller-faults.patch b/queue-5.15/usb-dwc3-keep-susphy-enabled-during-exit-to-avoid-controller-faults.patch
new file mode 100644 (file)
index 0000000..21ec8b4
--- /dev/null
@@ -0,0 +1,58 @@
+From stable+bounces-204234-greg=kroah.com@vger.kernel.org Tue Dec 30 16:55:45 2025
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 30 Dec 2025 10:55:37 -0500
+Subject: usb: dwc3: keep susphy enabled during exit to avoid controller faults
+To: stable@vger.kernel.org
+Cc: Udipto Goswami <udipto.goswami@oss.qualcomm.com>, stable <stable@kernel.org>, Thinh Nguyen <Thinh.Nguyen@synopsys.com>, Greg Kroah-Hartman <gregkh@linuxfoundation.org>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20251230155538.2289361-1-sashal@kernel.org>
+
+From: Udipto Goswami <udipto.goswami@oss.qualcomm.com>
+
+[ Upstream commit e1003aa7ec9eccdde4c926bd64ef42816ad55f25 ]
+
+On some platforms, switching USB roles from host to device can trigger
+controller faults due to premature PHY power-down. This occurs when the
+PHY is disabled too early during teardown, causing synchronization
+issues between the PHY and controller.
+
+Keep susphy enabled during dwc3_host_exit() and dwc3_gadget_exit()
+ensures the PHY remains in a low-power state capable of handling
+required commands during role switch.
+
+Cc: stable <stable@kernel.org>
+Fixes: 6d735722063a ("usb: dwc3: core: Prevent phy suspend during init")
+Suggested-by: Thinh Nguyen <Thinh.Nguyen@synopsys.com>
+Signed-off-by: Udipto Goswami <udipto.goswami@oss.qualcomm.com>
+Acked-by: Thinh Nguyen <Thinh.Nguyen@synopsys.com>
+Link: https://patch.msgid.link/20251126054221.120638-1-udipto.goswami@oss.qualcomm.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+[ Adjust context ]
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/usb/dwc3/gadget.c |    2 +-
+ drivers/usb/dwc3/host.c   |    2 +-
+ 2 files changed, 2 insertions(+), 2 deletions(-)
+
+--- a/drivers/usb/dwc3/gadget.c
++++ b/drivers/usb/dwc3/gadget.c
+@@ -4585,7 +4585,7 @@ void dwc3_gadget_exit(struct dwc3 *dwc)
+       if (!dwc->gadget)
+               return;
+-      dwc3_enable_susphy(dwc, false);
++      dwc3_enable_susphy(dwc, true);
+       usb_del_gadget(dwc->gadget);
+       dwc3_gadget_free_endpoints(dwc);
+       usb_put_gadget(dwc->gadget);
+--- a/drivers/usb/dwc3/host.c
++++ b/drivers/usb/dwc3/host.c
+@@ -157,7 +157,7 @@ err:
+ void dwc3_host_exit(struct dwc3 *dwc)
+ {
+-      dwc3_enable_susphy(dwc, false);
++      dwc3_enable_susphy(dwc, true);
+       platform_device_unregister(dwc->xhci);
+       dwc->xhci = NULL;
+ }
diff --git a/queue-5.15/usb-gadget-udc-fix-use-after-free-in-usb_gadget_state_work.patch b/queue-5.15/usb-gadget-udc-fix-use-after-free-in-usb_gadget_state_work.patch
new file mode 100644 (file)
index 0000000..27b69b5
--- /dev/null
@@ -0,0 +1,117 @@
+From stable+bounces-200372-greg=kroah.com@vger.kernel.org Mon Dec  8 22:02:29 2025
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon,  8 Dec 2025 16:02:21 -0500
+Subject: usb: gadget: udc: fix use-after-free in usb_gadget_state_work
+To: stable@vger.kernel.org
+Cc: Jimmy Hu <hhhuuu@google.com>, stable <stable@kernel.org>, Greg Kroah-Hartman <gregkh@linuxfoundation.org>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20251208210221.397543-1-sashal@kernel.org>
+
+From: Jimmy Hu <hhhuuu@google.com>
+
+[ Upstream commit baeb66fbd4201d1c4325074e78b1f557dff89b5b ]
+
+A race condition during gadget teardown can lead to a use-after-free
+in usb_gadget_state_work(), as reported by KASAN:
+
+  BUG: KASAN: invalid-access in sysfs_notify+0x2c/0xd0
+  Workqueue: events usb_gadget_state_work
+
+The fundamental race occurs because a concurrent event (e.g., an
+interrupt) can call usb_gadget_set_state() and schedule gadget->work
+at any time during the cleanup process in usb_del_gadget().
+
+Commit 399a45e5237c ("usb: gadget: core: flush gadget workqueue after
+device removal") attempted to fix this by moving flush_work() to after
+device_del(). However, this does not fully solve the race, as a new
+work item can still be scheduled *after* flush_work() completes but
+before the gadget's memory is freed, leading to the same use-after-free.
+
+This patch fixes the race condition robustly by introducing a 'teardown'
+flag and a 'state_lock' spinlock to the usb_gadget struct. The flag is
+set during cleanup in usb_del_gadget() *before* calling flush_work() to
+prevent any new work from being scheduled once cleanup has commenced.
+The scheduling site, usb_gadget_set_state(), now checks this flag under
+the lock before queueing the work, thus safely closing the race window.
+
+Fixes: 5702f75375aa9 ("usb: gadget: udc-core: move sysfs_notify() to a workqueue")
+Cc: stable <stable@kernel.org>
+Signed-off-by: Jimmy Hu <hhhuuu@google.com>
+Link: https://patch.msgid.link/20251023054945.233861-1-hhhuuu@google.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+[ Adjust context ]
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/usb/gadget/udc/core.c |   17 ++++++++++++++++-
+ include/linux/usb/gadget.h    |    5 +++++
+ 2 files changed, 21 insertions(+), 1 deletion(-)
+
+--- a/drivers/usb/gadget/udc/core.c
++++ b/drivers/usb/gadget/udc/core.c
+@@ -1066,8 +1066,13 @@ static void usb_gadget_state_work(struct
+ void usb_gadget_set_state(struct usb_gadget *gadget,
+               enum usb_device_state state)
+ {
++      unsigned long flags;
++
++      spin_lock_irqsave(&gadget->state_lock, flags);
+       gadget->state = state;
+-      schedule_work(&gadget->work);
++      if (!gadget->teardown)
++              schedule_work(&gadget->work);
++      spin_unlock_irqrestore(&gadget->state_lock, flags);
+ }
+ EXPORT_SYMBOL_GPL(usb_gadget_set_state);
+@@ -1298,6 +1303,8 @@ void usb_initialize_gadget(struct device
+               void (*release)(struct device *dev))
+ {
+       dev_set_name(&gadget->dev, "gadget");
++      spin_lock_init(&gadget->state_lock);
++      gadget->teardown = false;
+       INIT_WORK(&gadget->work, usb_gadget_state_work);
+       gadget->dev.parent = parent;
+@@ -1478,6 +1485,7 @@ static void usb_gadget_remove_driver(str
+ void usb_del_gadget(struct usb_gadget *gadget)
+ {
+       struct usb_udc *udc = gadget->udc;
++      unsigned long flags;
+       if (!udc)
+               return;
+@@ -1496,6 +1504,13 @@ void usb_del_gadget(struct usb_gadget *g
+       mutex_unlock(&udc_lock);
+       kobject_uevent(&udc->dev.kobj, KOBJ_REMOVE);
++      /*
++       * Set the teardown flag before flushing the work to prevent new work
++       * from being scheduled while we are cleaning up.
++       */
++      spin_lock_irqsave(&gadget->state_lock, flags);
++      gadget->teardown = true;
++      spin_unlock_irqrestore(&gadget->state_lock, flags);
+       flush_work(&gadget->work);
+       device_unregister(&udc->dev);
+       device_del(&gadget->dev);
+--- a/include/linux/usb/gadget.h
++++ b/include/linux/usb/gadget.h
+@@ -375,6 +375,9 @@ struct usb_gadget_ops {
+  *    can handle. The UDC must support this and all slower speeds and lower
+  *    number of lanes.
+  * @state: the state we are now (attached, suspended, configured, etc)
++ * @state_lock: Spinlock protecting the `state` and `teardown` members.
++ * @teardown: True if the device is undergoing teardown, used to prevent
++ *    new work from being scheduled during cleanup.
+  * @name: Identifies the controller hardware type.  Used in diagnostics
+  *    and sometimes configuration.
+  * @dev: Driver model state for this abstract device.
+@@ -449,6 +452,8 @@ struct usb_gadget {
+       enum usb_ssp_rate               max_ssp_rate;
+       enum usb_device_state           state;
++      spinlock_t                      state_lock;
++      bool                            teardown;
+       const char                      *name;
+       struct device                   dev;
+       unsigned                        isoch_delay;
diff --git a/queue-5.15/usb-ohci-nxp-fix-device-leak-on-probe-failure.patch b/queue-5.15/usb-ohci-nxp-fix-device-leak-on-probe-failure.patch
new file mode 100644 (file)
index 0000000..e4ece91
--- /dev/null
@@ -0,0 +1,49 @@
+From stable+bounces-204215-greg=kroah.com@vger.kernel.org Tue Dec 30 14:35:06 2025
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 30 Dec 2025 08:34:58 -0500
+Subject: usb: ohci-nxp: fix device leak on probe failure
+To: stable@vger.kernel.org
+Cc: Johan Hovold <johan@kernel.org>, Ma Ke <make24@iscas.ac.cn>, Alan Stern <stern@rowland.harvard.edu>, Vladimir Zapolskiy <vz@mleia.com>, Greg Kroah-Hartman <gregkh@linuxfoundation.org>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20251230133458.2203341-2-sashal@kernel.org>
+
+From: Johan Hovold <johan@kernel.org>
+
+[ Upstream commit b4c61e542faf8c9131d69ecfc3ad6de96d1b2ab8 ]
+
+Make sure to drop the reference taken when looking up the PHY I2C device
+during probe on probe failure (e.g. probe deferral) and on driver
+unbind.
+
+Fixes: 73108aa90cbf ("USB: ohci-nxp: Use isp1301 driver")
+Cc: stable@vger.kernel.org     # 3.5
+Reported-by: Ma Ke <make24@iscas.ac.cn>
+Link: https://lore.kernel.org/lkml/20251117013428.21840-1-make24@iscas.ac.cn/
+Signed-off-by: Johan Hovold <johan@kernel.org>
+Acked-by: Alan Stern <stern@rowland.harvard.edu>
+Reviewed-by: Vladimir Zapolskiy <vz@mleia.com>
+Link: https://patch.msgid.link/20251218153519.19453-4-johan@kernel.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/usb/host/ohci-nxp.c |    2 ++
+ 1 file changed, 2 insertions(+)
+
+--- a/drivers/usb/host/ohci-nxp.c
++++ b/drivers/usb/host/ohci-nxp.c
+@@ -224,6 +224,7 @@ static int ohci_hcd_nxp_probe(struct pla
+ fail_resource:
+       usb_put_hcd(hcd);
+ fail_disable:
++      put_device(&isp1301_i2c_client->dev);
+       isp1301_i2c_client = NULL;
+       return ret;
+ }
+@@ -235,6 +236,7 @@ static int ohci_hcd_nxp_remove(struct pl
+       usb_remove_hcd(hcd);
+       ohci_nxp_stop_hc();
+       usb_put_hcd(hcd);
++      put_device(&isp1301_i2c_client->dev);
+       isp1301_i2c_client = NULL;
+       return 0;
diff --git a/queue-5.15/usb-ohci-nxp-use-helper-function-devm_clk_get_enabled.patch b/queue-5.15/usb-ohci-nxp-use-helper-function-devm_clk_get_enabled.patch
new file mode 100644 (file)
index 0000000..997882c
--- /dev/null
@@ -0,0 +1,93 @@
+From stable+bounces-204214-greg=kroah.com@vger.kernel.org Tue Dec 30 14:35:04 2025
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 30 Dec 2025 08:34:57 -0500
+Subject: usb: ohci-nxp: Use helper function devm_clk_get_enabled()
+To: stable@vger.kernel.org
+Cc: Zhang Zekun <zhangzekun11@huawei.com>, Alan Stern <stern@rowland.harvard.edu>, Greg Kroah-Hartman <gregkh@linuxfoundation.org>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20251230133458.2203341-1-sashal@kernel.org>
+
+From: Zhang Zekun <zhangzekun11@huawei.com>
+
+[ Upstream commit c146ede472717f352b7283a525bd9a1a2b15e2cf ]
+
+devm_clk_get() and clk_prepare_enable() can be replaced by helper
+function devm_clk_get_enabled(). Let's use devm_clk_get_enabled() to
+simplify code and avoid calling clk_disable_unprepare().
+
+Signed-off-by: Zhang Zekun <zhangzekun11@huawei.com>
+Acked-by: Alan Stern <stern@rowland.harvard.edu>
+Link: https://lore.kernel.org/r/20240902123020.29267-3-zhangzekun11@huawei.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Stable-dep-of: b4c61e542faf ("usb: ohci-nxp: fix device leak on probe failure")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/usb/host/ohci-nxp.c |   18 ++++--------------
+ 1 file changed, 4 insertions(+), 14 deletions(-)
+
+--- a/drivers/usb/host/ohci-nxp.c
++++ b/drivers/usb/host/ohci-nxp.c
+@@ -51,8 +51,6 @@ static struct hc_driver __read_mostly oh
+ static struct i2c_client *isp1301_i2c_client;
+-static struct clk *usb_host_clk;
+-
+ static void isp1301_configure_lpc32xx(void)
+ {
+       /* LPC32XX only supports DAT_SE0 USB mode */
+@@ -155,6 +153,7 @@ static int ohci_hcd_nxp_probe(struct pla
+       struct resource *res;
+       int ret = 0, irq;
+       struct device_node *isp1301_node;
++      struct clk *usb_host_clk;
+       if (pdev->dev.of_node) {
+               isp1301_node = of_parse_phandle(pdev->dev.of_node,
+@@ -180,26 +179,20 @@ static int ohci_hcd_nxp_probe(struct pla
+       }
+       /* Enable USB host clock */
+-      usb_host_clk = devm_clk_get(&pdev->dev, NULL);
++      usb_host_clk = devm_clk_get_enabled(&pdev->dev, NULL);
+       if (IS_ERR(usb_host_clk)) {
+-              dev_err(&pdev->dev, "failed to acquire USB OHCI clock\n");
++              dev_err(&pdev->dev, "failed to acquire and start USB OHCI clock\n");
+               ret = PTR_ERR(usb_host_clk);
+               goto fail_disable;
+       }
+-      ret = clk_prepare_enable(usb_host_clk);
+-      if (ret < 0) {
+-              dev_err(&pdev->dev, "failed to start USB OHCI clock\n");
+-              goto fail_disable;
+-      }
+-
+       isp1301_configure();
+       hcd = usb_create_hcd(driver, &pdev->dev, dev_name(&pdev->dev));
+       if (!hcd) {
+               dev_err(&pdev->dev, "Failed to allocate HC buffer\n");
+               ret = -ENOMEM;
+-              goto fail_hcd;
++              goto fail_disable;
+       }
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+@@ -230,8 +223,6 @@ static int ohci_hcd_nxp_probe(struct pla
+       ohci_nxp_stop_hc();
+ fail_resource:
+       usb_put_hcd(hcd);
+-fail_hcd:
+-      clk_disable_unprepare(usb_host_clk);
+ fail_disable:
+       isp1301_i2c_client = NULL;
+       return ret;
+@@ -244,7 +235,6 @@ static int ohci_hcd_nxp_remove(struct pl
+       usb_remove_hcd(hcd);
+       ohci_nxp_stop_hc();
+       usb_put_hcd(hcd);
+-      clk_disable_unprepare(usb_host_clk);
+       isp1301_i2c_client = NULL;
+       return 0;
diff --git a/queue-5.15/wifi-mac80211-discard-beacon-frames-to-non-broadcast-address.patch b/queue-5.15/wifi-mac80211-discard-beacon-frames-to-non-broadcast-address.patch
new file mode 100644 (file)
index 0000000..dd11fe8
--- /dev/null
@@ -0,0 +1,62 @@
+From stable+bounces-206118-greg=kroah.com@vger.kernel.org Wed Jan  7 12:00:14 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed,  7 Jan 2026 05:52:14 -0500
+Subject: wifi: mac80211: Discard Beacon frames to non-broadcast address
+To: stable@vger.kernel.org
+Cc: Jouni Malinen <jouni.malinen@oss.qualcomm.com>, Johannes Berg <johannes.berg@intel.com>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260107105214.3609231-1-sashal@kernel.org>
+
+From: Jouni Malinen <jouni.malinen@oss.qualcomm.com>
+
+[ Upstream commit 193d18f60588e95d62e0f82b6a53893e5f2f19f8 ]
+
+Beacon frames are required to be sent to the broadcast address, see IEEE
+Std 802.11-2020, 11.1.3.1 ("The Address 1 field of the Beacon .. frame
+shall be set to the broadcast address"). A unicast Beacon frame might be
+used as a targeted attack to get one of the associated STAs to do
+something (e.g., using CSA to move it to another channel). As such, it
+is better have strict filtering for this on the received side and
+discard all Beacon frames that are sent to an unexpected address.
+
+This is even more important for cases where beacon protection is used.
+The current implementation in mac80211 is correctly discarding unicast
+Beacon frames if the Protected Frame bit in the Frame Control field is
+set to 0. However, if that bit is set to 1, the logic used for checking
+for configured BIGTK(s) does not actually work. If the driver does not
+have logic for dropping unicast Beacon frames with Protected Frame bit
+1, these frames would be accepted in mac80211 processing as valid Beacon
+frames even though they are not protected. This would allow beacon
+protection to be bypassed. While the logic for checking beacon
+protection could be extended to cover this corner case, a more generic
+check for discard all Beacon frames based on A1=unicast address covers
+this without needing additional changes.
+
+Address all these issues by dropping received Beacon frames if they are
+sent to a non-broadcast address.
+
+Cc: stable@vger.kernel.org
+Fixes: af2d14b01c32 ("mac80211: Beacon protection using the new BIGTK (STA)")
+Signed-off-by: Jouni Malinen <jouni.malinen@oss.qualcomm.com>
+Link: https://patch.msgid.link/20251215151134.104501-1-jouni.malinen@oss.qualcomm.com
+Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+[ adapted RX_DROP return value to RX_DROP_MONITOR ]
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/mac80211/rx.c |    5 +++++
+ 1 file changed, 5 insertions(+)
+
+--- a/net/mac80211/rx.c
++++ b/net/mac80211/rx.c
+@@ -3193,6 +3193,11 @@ ieee80211_rx_h_mgmt_check(struct ieee802
+       if (!ieee80211_is_mgmt(mgmt->frame_control))
+               return RX_DROP_MONITOR;
++      /* Drop non-broadcast Beacon frames */
++      if (ieee80211_is_beacon(mgmt->frame_control) &&
++          !is_broadcast_ether_addr(mgmt->da))
++              return RX_DROP_MONITOR;
++
+       if (rx->sdata->vif.type == NL80211_IFTYPE_AP &&
+           ieee80211_is_beacon(mgmt->frame_control) &&
+           !(rx->flags & IEEE80211_RX_BEACON_REPORTED)) {
diff --git a/queue-5.15/wifi-mt76-fix-dts-power-limits-on-little-endian-systems.patch b/queue-5.15/wifi-mt76-fix-dts-power-limits-on-little-endian-systems.patch
new file mode 100644 (file)
index 0000000..59950d8
--- /dev/null
@@ -0,0 +1,139 @@
+From stable+bounces-204140-greg=kroah.com@vger.kernel.org Mon Dec 29 22:58:09 2025
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 29 Dec 2025 16:58:01 -0500
+Subject: wifi: mt76: Fix DTS power-limits on little endian systems
+To: stable@vger.kernel.org
+Cc: "Sven Eckelmann (Plasma Cloud)" <se@simonwunderlich.de>, Felix Fietkau <nbd@nbd.name>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20251229215801.1732809-1-sashal@kernel.org>
+
+From: "Sven Eckelmann (Plasma Cloud)" <se@simonwunderlich.de>
+
+[ Upstream commit 38b845e1f9e810869b0a0b69f202b877b7b7fb12 ]
+
+The power-limits for ru and mcs and stored in the devicetree as bytewise
+array (often with sizes which are not a multiple of 4). These arrays have a
+prefix which defines for how many modes a line is applied. This prefix is
+also only a byte - but the code still tried to fix the endianness of this
+byte with a be32 operation. As result, loading was mostly failing or was
+sending completely unexpected values to the firmware.
+
+Since the other rates are also stored in the devicetree as bytewise arrays,
+just drop the u32 access + be32_to_cpu conversion and directly access them
+as bytes arrays.
+
+Cc: stable@vger.kernel.org
+Fixes: 22b980badc0f ("mt76: add functions for parsing rate power limits from DT")
+Fixes: a9627d992b5e ("mt76: extend DT rate power limits to support 11ax devices")
+Signed-off-by: Sven Eckelmann (Plasma Cloud) <se@simonwunderlich.de>
+Signed-off-by: Felix Fietkau <nbd@nbd.name>
+[ Adjust context ]
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/net/wireless/mediatek/mt76/eeprom.c |   37 ++++++++++++++++++----------
+ 1 file changed, 24 insertions(+), 13 deletions(-)
+
+--- a/drivers/net/wireless/mediatek/mt76/eeprom.c
++++ b/drivers/net/wireless/mediatek/mt76/eeprom.c
+@@ -173,6 +173,19 @@ mt76_get_of_array(struct device_node *np
+       return prop->value;
+ }
++static const s8 *
++mt76_get_of_array_s8(struct device_node *np, char *name, size_t *len, int min)
++{
++      struct property *prop = of_find_property(np, name, NULL);
++
++      if (!prop || !prop->value || prop->length < min)
++              return NULL;
++
++      *len = prop->length;
++
++      return prop->value;
++}
++
+ static struct device_node *
+ mt76_find_channel_node(struct device_node *np, struct ieee80211_channel *chan)
+ {
+@@ -212,7 +225,7 @@ mt76_get_txs_delta(struct device_node *n
+ }
+ static void
+-mt76_apply_array_limit(s8 *pwr, size_t pwr_len, const __be32 *data,
++mt76_apply_array_limit(s8 *pwr, size_t pwr_len, const s8 *data,
+                      s8 target_power, s8 nss_delta, s8 *max_power)
+ {
+       int i;
+@@ -221,15 +234,14 @@ mt76_apply_array_limit(s8 *pwr, size_t p
+               return;
+       for (i = 0; i < pwr_len; i++) {
+-              pwr[i] = min_t(s8, target_power,
+-                             be32_to_cpu(data[i]) + nss_delta);
++              pwr[i] = min_t(s8, target_power, data[i] + nss_delta);
+               *max_power = max(*max_power, pwr[i]);
+       }
+ }
+ static void
+ mt76_apply_multi_array_limit(s8 *pwr, size_t pwr_len, s8 pwr_num,
+-                           const __be32 *data, size_t len, s8 target_power,
++                           const s8 *data, size_t len, s8 target_power,
+                            s8 nss_delta, s8 *max_power)
+ {
+       int i, cur;
+@@ -237,8 +249,7 @@ mt76_apply_multi_array_limit(s8 *pwr, si
+       if (!data)
+               return;
+-      len /= 4;
+-      cur = be32_to_cpu(data[0]);
++      cur = data[0];
+       for (i = 0; i < pwr_num; i++) {
+               if (len < pwr_len + 1)
+                       break;
+@@ -253,7 +264,7 @@ mt76_apply_multi_array_limit(s8 *pwr, si
+               if (!len)
+                       break;
+-              cur = be32_to_cpu(data[0]);
++              cur = data[0];
+       }
+ }
+@@ -264,7 +275,7 @@ s8 mt76_get_rate_power_limits(struct mt7
+ {
+       struct mt76_dev *dev = phy->dev;
+       struct device_node *np;
+-      const __be32 *val;
++      const s8 *val;
+       char name[16];
+       u32 mcs_rates = dev->drv->mcs_rates;
+       u32 ru_rates = ARRAY_SIZE(dest->ru[0]);
+@@ -307,21 +318,21 @@ s8 mt76_get_rate_power_limits(struct mt7
+       txs_delta = mt76_get_txs_delta(np, hweight8(phy->antenna_mask));
+-      val = mt76_get_of_array(np, "rates-cck", &len, ARRAY_SIZE(dest->cck));
++      val = mt76_get_of_array_s8(np, "rates-cck", &len, ARRAY_SIZE(dest->cck));
+       mt76_apply_array_limit(dest->cck, ARRAY_SIZE(dest->cck), val,
+                              target_power, txs_delta, &max_power);
+-      val = mt76_get_of_array(np, "rates-ofdm",
+-                              &len, ARRAY_SIZE(dest->ofdm));
++      val = mt76_get_of_array_s8(np, "rates-ofdm",
++                                 &len, ARRAY_SIZE(dest->ofdm));
+       mt76_apply_array_limit(dest->ofdm, ARRAY_SIZE(dest->ofdm), val,
+                              target_power, txs_delta, &max_power);
+-      val = mt76_get_of_array(np, "rates-mcs", &len, mcs_rates + 1);
++      val = mt76_get_of_array_s8(np, "rates-mcs", &len, mcs_rates + 1);
+       mt76_apply_multi_array_limit(dest->mcs[0], ARRAY_SIZE(dest->mcs[0]),
+                                    ARRAY_SIZE(dest->mcs), val, len,
+                                    target_power, txs_delta, &max_power);
+-      val = mt76_get_of_array(np, "rates-ru", &len, ru_rates + 1);
++      val = mt76_get_of_array_s8(np, "rates-ru", &len, ru_rates + 1);
+       mt76_apply_multi_array_limit(dest->ru[0], ARRAY_SIZE(dest->ru[0]),
+                                    ARRAY_SIZE(dest->ru), val, len,
+                                    target_power, txs_delta, &max_power);
diff --git a/queue-5.15/xfs-fix-a-memory-leak-in-xfs_buf_item_init.patch b/queue-5.15/xfs-fix-a-memory-leak-in-xfs_buf_item_init.patch
new file mode 100644 (file)
index 0000000..168c52e
--- /dev/null
@@ -0,0 +1,38 @@
+From stable+bounces-204313-greg=kroah.com@vger.kernel.org Wed Dec 31 04:15:52 2025
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 30 Dec 2025 22:15:44 -0500
+Subject: xfs: fix a memory leak in xfs_buf_item_init()
+To: stable@vger.kernel.org
+Cc: Haoxiang Li <lihaoxiang@isrc.iscas.ac.cn>, Christoph Hellwig <hch@lst.de>, Carlos Maiolino <cmaiolino@redhat.com>, Carlos Maiolino <cem@kernel.org>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20251231031544.2684088-1-sashal@kernel.org>
+
+From: Haoxiang Li <lihaoxiang@isrc.iscas.ac.cn>
+
+[ Upstream commit fc40459de82543b565ebc839dca8f7987f16f62e ]
+
+xfs_buf_item_get_format() may allocate memory for bip->bli_formats,
+free the memory in the error path.
+
+Fixes: c3d5f0c2fb85 ("xfs: complain if anyone tries to create a too-large buffer log item")
+Cc: stable@vger.kernel.org
+Signed-off-by: Haoxiang Li <lihaoxiang@isrc.iscas.ac.cn>
+Reviewed-by: Christoph Hellwig <hch@lst.de>
+Reviewed-by: Carlos Maiolino <cmaiolino@redhat.com>
+Signed-off-by: Carlos Maiolino <cem@kernel.org>
+[ Adjust context ]
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/xfs/xfs_buf_item.c |    1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/fs/xfs/xfs_buf_item.c
++++ b/fs/xfs/xfs_buf_item.c
+@@ -825,6 +825,7 @@ xfs_buf_item_init(
+               map_size = DIV_ROUND_UP(chunks, NBWORD);
+               if (map_size > XFS_BLF_DATAMAP_SIZE) {
++                      xfs_buf_item_free_format(bip);
+                       kmem_cache_free(xfs_buf_item_zone, bip);
+                       xfs_err(mp,
+       "buffer item dirty bitmap (%u uints) too small to reflect %u bytes!",
diff --git a/queue-5.15/xhci-dbgtty-fix-device-unregister.patch b/queue-5.15/xhci-dbgtty-fix-device-unregister.patch
new file mode 100644 (file)
index 0000000..a501101
--- /dev/null
@@ -0,0 +1,47 @@
+From stable+bounces-200326-greg=kroah.com@vger.kernel.org Mon Dec  8 07:55:25 2025
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon,  8 Dec 2025 01:54:23 -0500
+Subject: xhci: dbgtty: fix device unregister
+To: stable@vger.kernel.org
+Cc: "Łukasz Bartosik" <ukaszb@chromium.org>, stable <stable@kernel.org>, "Greg Kroah-Hartman" <gregkh@linuxfoundation.org>, "Sasha Levin" <sashal@kernel.org>
+Message-ID: <20251208065423.260017-2-sashal@kernel.org>
+
+From: Łukasz Bartosik <ukaszb@chromium.org>
+
+[ Upstream commit 1f73b8b56cf35de29a433aee7bfff26cea98be3f ]
+
+When DbC is disconnected then xhci_dbc_tty_unregister_device()
+is called. However if there is any user space process blocked
+on write to DbC terminal device then it will never be signalled
+and thus stay blocked indifinitely.
+
+This fix adds a tty_vhangup() call in xhci_dbc_tty_unregister_device().
+The tty_vhangup() wakes up any blocked writers and causes subsequent
+write attempts to DbC terminal device to fail.
+
+Cc: stable <stable@kernel.org>
+Fixes: dfba2174dc42 ("usb: xhci: Add DbC support in xHCI driver")
+Signed-off-by: Łukasz Bartosik <ukaszb@chromium.org>
+Link: https://patch.msgid.link/20251119212910.1245694-1-ukaszb@google.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/usb/host/xhci-dbgtty.c |    6 ++++++
+ 1 file changed, 6 insertions(+)
+
+--- a/drivers/usb/host/xhci-dbgtty.c
++++ b/drivers/usb/host/xhci-dbgtty.c
+@@ -489,6 +489,12 @@ static void xhci_dbc_tty_unregister_devi
+       if (!port->registered)
+               return;
++      /*
++       * Hang up the TTY. This wakes up any blocked
++       * writers and causes subsequent writes to fail.
++       */
++      tty_vhangup(port->port.tty);
++
+       tty_unregister_device(dbc_tty_driver, port->minor);
+       xhci_dbc_tty_exit_port(port);
+       port->registered = false;
diff --git a/queue-5.15/xhci-dbgtty-use-idr-to-support-several-dbc-instances.patch b/queue-5.15/xhci-dbgtty-use-idr-to-support-several-dbc-instances.patch
new file mode 100644 (file)
index 0000000..ce253e9
--- /dev/null
@@ -0,0 +1,170 @@
+From stable+bounces-200325-greg=kroah.com@vger.kernel.org Mon Dec  8 07:54:32 2025
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon,  8 Dec 2025 01:54:22 -0500
+Subject: xhci: dbgtty: use IDR to support several dbc instances.
+To: stable@vger.kernel.org
+Cc: Mathias Nyman <mathias.nyman@linux.intel.com>, Greg Kroah-Hartman <gregkh@linuxfoundation.org>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20251208065423.260017-1-sashal@kernel.org>
+
+From: Mathias Nyman <mathias.nyman@linux.intel.com>
+
+[ Upstream commit e1ec140f273e1e30cea7e6d5f50934d877232121 ]
+
+To support systems with several xhci controllers with active
+dbc on each xhci we need to use IDR to identify and give
+an index to each port.
+
+Avoid using global struct tty_driver.driver_state for storing
+dbc port pointer as it won't work with several dbc ports
+
+Signed-off-by: Mathias Nyman <mathias.nyman@linux.intel.com>
+Link: https://lore.kernel.org/r/20220216095153.1303105-6-mathias.nyman@linux.intel.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Stable-dep-of: 1f73b8b56cf3 ("xhci: dbgtty: fix device unregister")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/usb/host/xhci-dbgcap.h |    1 
+ drivers/usb/host/xhci-dbgtty.c |   46 ++++++++++++++++++++++++++++++++++-------
+ 2 files changed, 40 insertions(+), 7 deletions(-)
+
+--- a/drivers/usb/host/xhci-dbgcap.h
++++ b/drivers/usb/host/xhci-dbgcap.h
+@@ -102,6 +102,7 @@ struct dbc_ep {
+ struct dbc_port {
+       struct tty_port                 port;
+       spinlock_t                      port_lock;      /* port access */
++      int                             minor;
+       struct list_head                read_pool;
+       struct list_head                read_queue;
+--- a/drivers/usb/host/xhci-dbgtty.c
++++ b/drivers/usb/host/xhci-dbgtty.c
+@@ -10,6 +10,7 @@
+ #include <linux/slab.h>
+ #include <linux/tty.h>
+ #include <linux/tty_flip.h>
++#include <linux/idr.h>
+ #include "xhci.h"
+ #include "xhci-dbgcap.h"
+@@ -18,6 +19,8 @@ static int dbc_tty_init(void);
+ static void dbc_tty_exit(void);
+ static struct tty_driver *dbc_tty_driver;
++static struct idr dbc_tty_minors;
++static DEFINE_MUTEX(dbc_tty_minors_lock);
+ static inline struct dbc_port *dbc_to_port(struct xhci_dbc *dbc)
+ {
+@@ -195,7 +198,14 @@ xhci_dbc_free_requests(struct list_head
+ static int dbc_tty_install(struct tty_driver *driver, struct tty_struct *tty)
+ {
+-      struct dbc_port         *port = driver->driver_state;
++      struct dbc_port         *port;
++
++      mutex_lock(&dbc_tty_minors_lock);
++      port = idr_find(&dbc_tty_minors, tty->index);
++      mutex_unlock(&dbc_tty_minors_lock);
++
++      if (!port)
++              return -ENXIO;
+       tty->driver_data = port;
+@@ -424,6 +434,15 @@ static int xhci_dbc_tty_register_device(
+       xhci_dbc_tty_init_port(dbc, port);
++      mutex_lock(&dbc_tty_minors_lock);
++      port->minor = idr_alloc(&dbc_tty_minors, port, 0, 64, GFP_KERNEL);
++      mutex_unlock(&dbc_tty_minors_lock);
++
++      if (port->minor < 0) {
++              ret = port->minor;
++              goto err_idr;
++      }
++
+       ret = kfifo_alloc(&port->write_fifo, DBC_WRITE_BUF_SIZE, GFP_KERNEL);
+       if (ret)
+               goto err_exit_port;
+@@ -439,7 +458,7 @@ static int xhci_dbc_tty_register_device(
+               goto err_free_requests;
+       tty_dev = tty_port_register_device(&port->port,
+-                                         dbc_tty_driver, 0, NULL);
++                                         dbc_tty_driver, port->minor, NULL);
+       if (IS_ERR(tty_dev)) {
+               ret = PTR_ERR(tty_dev);
+               goto err_free_requests;
+@@ -455,6 +474,8 @@ err_free_requests:
+ err_free_fifo:
+       kfifo_free(&port->write_fifo);
+ err_exit_port:
++      idr_remove(&dbc_tty_minors, port->minor);
++err_idr:
+       xhci_dbc_tty_exit_port(port);
+       dev_err(dbc->dev, "can't register tty port, err %d\n", ret);
+@@ -468,10 +489,14 @@ static void xhci_dbc_tty_unregister_devi
+       if (!port->registered)
+               return;
+-      tty_unregister_device(dbc_tty_driver, 0);
++      tty_unregister_device(dbc_tty_driver, port->minor);
+       xhci_dbc_tty_exit_port(port);
+       port->registered = false;
++      mutex_lock(&dbc_tty_minors_lock);
++      idr_remove(&dbc_tty_minors, port->minor);
++      mutex_unlock(&dbc_tty_minors_lock);
++
+       kfifo_free(&port->write_fifo);
+       xhci_dbc_free_requests(&port->read_pool);
+       xhci_dbc_free_requests(&port->read_queue);
+@@ -500,9 +525,8 @@ int xhci_dbc_tty_probe(struct device *de
+               goto out;
+       }
+-      dbc_tty_driver->driver_state = port;
+-
+       dbc = xhci_alloc_dbc(dev, base, &dbc_driver);
++
+       if (!dbc) {
+               status = -ENOMEM;
+               goto out2;
+@@ -541,10 +565,14 @@ static int dbc_tty_init(void)
+ {
+       int             ret;
+-      dbc_tty_driver = tty_alloc_driver(1, TTY_DRIVER_REAL_RAW |
++      idr_init(&dbc_tty_minors);
++
++      dbc_tty_driver = tty_alloc_driver(64, TTY_DRIVER_REAL_RAW |
+                                         TTY_DRIVER_DYNAMIC_DEV);
+-      if (IS_ERR(dbc_tty_driver))
++      if (IS_ERR(dbc_tty_driver)) {
++              idr_destroy(&dbc_tty_minors);
+               return PTR_ERR(dbc_tty_driver);
++      }
+       dbc_tty_driver->driver_name = "dbc_serial";
+       dbc_tty_driver->name = "ttyDBC";
+@@ -564,7 +592,9 @@ static int dbc_tty_init(void)
+       if (ret) {
+               pr_err("Can't register dbc tty driver\n");
+               tty_driver_kref_put(dbc_tty_driver);
++              idr_destroy(&dbc_tty_minors);
+       }
++
+       return ret;
+ }
+@@ -575,4 +605,6 @@ static void dbc_tty_exit(void)
+               tty_driver_kref_put(dbc_tty_driver);
+               dbc_tty_driver = NULL;
+       }
++
++      idr_destroy(&dbc_tty_minors);
+ }