From: Greg Kroah-Hartman Date: Thu, 8 Jan 2026 13:56:24 +0000 (+0100) Subject: 5.15-stable patches X-Git-Tag: v6.1.160~32 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=731660d6e680db7c6e17c770efa1b6787567bec1;p=thirdparty%2Fkernel%2Fstable-queue.git 5.15-stable patches 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 --- 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 index 0000000000..92b7981785 --- /dev/null +++ b/queue-5.15/alsa-wavefront-clear-substream-pointers-on-close.patch @@ -0,0 +1,48 @@ +From stable+bounces-202048-greg=kroah.com@vger.kernel.org Tue Dec 16 13:22:57 2025 +From: Sasha Levin +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 , Yuhao Jiang , Takashi Iwai , Sasha Levin +Message-ID: <20251216120355.2790532-1-sashal@kernel.org> + +From: Junrui Luo + +[ 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 +Reported-by: Junrui Luo +Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") +Cc: stable@vger.kernel.org +Signed-off-by: Junrui Luo +Link: https://patch.msgid.link/SYBPR01MB7881DF762CAB45EE42F6D812AFC2A@SYBPR01MB7881.ausprd01.prod.outlook.com +Signed-off-by: Takashi Iwai +[ No guard() in older trees ] +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 0000000000..9479ebf600 --- /dev/null +++ b/queue-5.15/alsa-wavefront-fix-integer-overflow-in-sample-size-validation.patch @@ -0,0 +1,43 @@ +From stable+bounces-201186-greg=kroah.com@vger.kernel.org Tue Dec 16 12:13:42 2025 +From: Sasha Levin +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 , Takashi Iwai , Sasha Levin +Message-ID: <20251216110628.2753962-2-sashal@kernel.org> + +From: Junrui Luo + +[ 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 +Link: https://patch.msgid.link/SYBPR01MB7881B47789D1B060CE8BF4C3AFC2A@SYBPR01MB7881.ausprd01.prod.outlook.com +Signed-off-by: Takashi Iwai +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 0000000000..f271d62eb7 --- /dev/null +++ b/queue-5.15/alsa-wavefront-use-standard-print-api.patch @@ -0,0 +1,1000 @@ +From stable+bounces-201185-greg=kroah.com@vger.kernel.org Tue Dec 16 12:14:05 2025 +From: Sasha Levin +Date: Tue, 16 Dec 2025 06:06:26 -0500 +Subject: ALSA: wavefront: Use standard print API +To: stable@vger.kernel.org +Cc: Takashi Iwai , Jaroslav Kysela , Sasha Levin +Message-ID: <20251216110628.2753962-1-sashal@kernel.org> + +From: Takashi Iwai + +[ 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 +Signed-off-by: Takashi Iwai +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 +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 0000000000..13d4bcc08c --- /dev/null +++ b/queue-5.15/arm-dts-microchip-sama5d2-fix-spi-flexcom-fifo-size-to-32.patch @@ -0,0 +1,73 @@ +From stable+bounces-204391-greg=kroah.com@vger.kernel.org Wed Dec 31 22:21:02 2025 +From: Sasha Levin +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 , Claudiu Beznea , Sasha Levin +Message-ID: <20251231212057.3505425-1-sashal@kernel.org> + +From: Nicolas Ferre + +[ 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 +Link: https://lore.kernel.org/r/20251114140225.30372-1-nicolas.ferre@microchip.com +Signed-off-by: Claudiu Beznea +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 0000000000..bcf508bfb8 --- /dev/null +++ b/queue-5.15/arm-dts-microchip-sama7g5-fix-uart-fifo-size-to-32.patch @@ -0,0 +1,46 @@ +From stable+bounces-204398-greg=kroah.com@vger.kernel.org Wed Dec 31 23:44:37 2025 +From: Sasha Levin +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 , Claudiu Beznea , Sasha Levin +Message-ID: <20251231224427.3631376-1-sashal@kernel.org> + +From: Nicolas Ferre + +[ 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 +Link: https://lore.kernel.org/r/20251114103313.20220-2-nicolas.ferre@microchip.com +Signed-off-by: Claudiu Beznea +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 0000000000..280006972c --- /dev/null +++ b/queue-5.15/asoc-stm-stm32_sai_sub-convert-to-platform-remove-callback-returning-void.patch @@ -0,0 +1,64 @@ +From stable+bounces-204830-greg=kroah.com@vger.kernel.org Mon Jan 5 16:12:47 2026 +From: Sasha Levin +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" , "Takashi Iwai" , "Nicolas Ferre" , "Mark Brown" , "Sasha Levin" +Message-ID: <20260105151034.2625317-2-sashal@kernel.org> + +From: Uwe Kleine-König + +[ 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 +Acked-by: Takashi Iwai +Acked-by: Nicolas Ferre +Link: https://lore.kernel.org/r/20230315150745.67084-139-u.kleine-koenig@pengutronix.de +Signed-off-by: Mark Brown +Stable-dep-of: 23261f0de094 ("ASoC: stm32: sai: fix OF node leak on probe") +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 0000000000..add8842d34 --- /dev/null +++ b/queue-5.15/asoc-stm-use-dev_err_probe-helper.patch @@ -0,0 +1,307 @@ +From stable+bounces-204809-greg=kroah.com@vger.kernel.org Mon Jan 5 15:31:23 2026 +From: Sasha Levin +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 , Mark Brown , Sasha Levin +Message-ID: <20260105142728.2602716-1-sashal@kernel.org> + +From: Kuninori Morimoto + +[ Upstream commit efc162cbd480f1fb47d439c193ec9731bcc6c749 ] + +Use the dev_err_probe() helper, instead of open-coding the same +operation. + +Signed-off-by: Kuninori Morimoto +Link: https://lore.kernel.org/r/20211214020843.2225831-22-kuninori.morimoto.gx@renesas.com +Signed-off-by: Mark Brown +Stable-dep-of: 312ec2f0d9d1 ("ASoC: stm32: sai: fix clk prepare imbalance on probe failure") +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 0000000000..ba87c6faab --- /dev/null +++ b/queue-5.15/asoc-stm32-sai-fix-clk-prepare-imbalance-on-probe-failure.patch @@ -0,0 +1,93 @@ +From stable+bounces-204810-greg=kroah.com@vger.kernel.org Mon Jan 5 15:32:00 2026 +From: Sasha Levin +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 , Olivier Moysan , olivier moysan , Mark Brown , Sasha Levin +Message-ID: <20260105142728.2602716-3-sashal@kernel.org> + +From: Johan Hovold + +[ 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 +Signed-off-by: Johan Hovold +Reviewed-by: olivier moysan +Link: https://patch.msgid.link/20251124104908.15754-3-johan@kernel.org +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 0000000000..89cad6e2c0 --- /dev/null +++ b/queue-5.15/asoc-stm32-sai-fix-of-node-leak-on-probe.patch @@ -0,0 +1,149 @@ +From stable+bounces-204834-greg=kroah.com@vger.kernel.org Mon Jan 5 16:16:50 2026 +From: Sasha Levin +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 , Olivier Moysan , olivier moysan , Mark Brown , Sasha Levin +Message-ID: <20260105151034.2625317-6-sashal@kernel.org> + +From: Johan Hovold + +[ 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 +Cc: stable@vger.kernel.org # 4.16: d4180b4c02e7 +Signed-off-by: Johan Hovold +Reviewed-by: olivier moysan +Link: https://patch.msgid.link/20251124104908.15754-4-johan@kernel.org +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 0000000000..baf2d8e8ee --- /dev/null +++ b/queue-5.15/asoc-stm32-sai-use-the-devm_clk_get_optional-helper.patch @@ -0,0 +1,43 @@ +From stable+bounces-204811-greg=kroah.com@vger.kernel.org Mon Jan 5 15:32:05 2026 +From: Sasha Levin +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 , Mark Brown , Sasha Levin +Message-ID: <20260105142728.2602716-2-sashal@kernel.org> + +From: Christophe JAILLET + +[ 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 +Link: https://lore.kernel.org/r/f7987f18dadf77bfa09969fd4c82d5a0f4e4e3b7.1684594838.git.christophe.jaillet@wanadoo.fr +Signed-off-by: Mark Brown +Stable-dep-of: 312ec2f0d9d1 ("ASoC: stm32: sai: fix clk prepare imbalance on probe failure") +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 0000000000..89bb916141 --- /dev/null +++ b/queue-5.15/btrfs-don-t-rewrite-ret-from-inode_permission.patch @@ -0,0 +1,51 @@ +From stable+bounces-204142-greg=kroah.com@vger.kernel.org Mon Dec 29 23:12:48 2025 +From: Sasha Levin +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 , Johannes Thumshirn , Daniel Vacek , David Sterba , Sasha Levin +Message-ID: <20251229221238.1738481-1-sashal@kernel.org> + +From: Josef Bacik + +[ 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 +Signed-off-by: Josef Bacik +Signed-off-by: Daniel Vacek +Reviewed-by: David Sterba +[ add note ] +Signed-off-by: David Sterba +[ Adjust context ] +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 0000000000..671bc81707 --- /dev/null +++ b/queue-5.15/crypto-af_alg-zero-initialize-memory-allocated-via-sock_kmalloc.patch @@ -0,0 +1,102 @@ +From stable+bounces-204381-greg=kroah.com@vger.kernel.org Wed Dec 31 19:47:33 2025 +From: Sasha Levin +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 , Herbert Xu , Sasha Levin +Message-ID: <20251231184727.3370622-1-sashal@kernel.org> + +From: Shivani Agarwal + +[ 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 +Signed-off-by: Herbert Xu +[ Adjust context ] +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 0000000000..a70d0267e9 --- /dev/null +++ b/queue-5.15/drm-gma500-remove-unused-helper-psb_fbdev_fb_setcolreg.patch @@ -0,0 +1,101 @@ +From stable+bounces-206177-greg=kroah.com@vger.kernel.org Wed Jan 7 17:12:48 2026 +From: Sasha Levin +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 , Patrik Jakobsson , Stefan Christ , Daniel Vetter , dri-devel@lists.freedesktop.org, Sasha Levin +Message-ID: <20260107155733.4065165-1-sashal@kernel.org> + +From: Thomas Zimmermann + +[ 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 +Cc: Stefan Christ +Cc: Daniel Vetter +Cc: dri-devel@lists.freedesktop.org +Cc: # 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 +Acked-by: Patrik Jakobsson +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 +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 0000000000..61814c5479 --- /dev/null +++ b/queue-5.15/drm-i915-selftests-fix-subtraction-overflow-bug.patch @@ -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 + +[ 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 +Reviewed-by: Andi Shyti +Signed-off-by: Andi Shyti +Link: https://patchwork.freedesktop.org/patch/msgid/20220624113528.2159210-1-andrzej.hajda@intel.com +Signed-off-by: Rodrigo Vivi +[ 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 +--- + 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 index 0000000000..d885fcfe95 --- /dev/null +++ b/queue-5.15/drm-mediatek-fix-probe-memory-leak.patch @@ -0,0 +1,44 @@ +From stable+bounces-206143-greg=kroah.com@vger.kernel.org Wed Jan 7 13:47:50 2026 +From: Sasha Levin +Date: Wed, 7 Jan 2026 07:46:00 -0500 +Subject: drm/mediatek: Fix probe memory leak +To: stable@vger.kernel.org +Cc: Johan Hovold , CK Hu , AngeloGioacchino Del Regno , Chun-Kuang Hu , Sasha Levin +Message-ID: <20260107124600.3997704-1-sashal@kernel.org> + +From: Johan Hovold + +[ 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 +Signed-off-by: Johan Hovold +Reviewed-by: AngeloGioacchino Del Regno +Link: https://patchwork.kernel.org/project/dri-devel/patch/20250923152340.18234-3-johan@kernel.org/ +Signed-off-by: Chun-Kuang Hu +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 0000000000..90b6b9ab07 --- /dev/null +++ b/queue-5.15/f2fs-fix-to-avoid-updating-zero-sized-extent-in-extent-cache.patch @@ -0,0 +1,65 @@ +From stable+bounces-204263-greg=kroah.com@vger.kernel.org Tue Dec 30 18:26:41 2025 +From: Sasha Levin +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 , stable@kernel.org, syzbot+24124df3170c3638b35f@syzkaller.appspotmail.com, Jaegeuk Kim , Sasha Levin +Message-ID: <20251230172636.2349925-1-sashal@kernel.org> + +From: Chao Yu + +[ 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: + + 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 +Signed-off-by: Jaegeuk Kim +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 0000000000..008ef7eec2 --- /dev/null +++ b/queue-5.15/f2fs-fix-to-detect-recoverable-inode-during-dryrun-of-find_fsync_dnodes.patch @@ -0,0 +1,93 @@ +From stable+bounces-204287-greg=kroah.com@vger.kernel.org Tue Dec 30 21:08:59 2025 +From: Sasha Levin +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 , stable@kernel.org, Jaegeuk Kim , Sasha Levin +Message-ID: <20251230200841.2453139-1-sashal@kernel.org> + +From: Chao Yu + +[ 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 +Signed-off-by: Jaegeuk Kim +[ folio => page ] +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 0000000000..be2e2997e2 --- /dev/null +++ b/queue-5.15/f2fs-fix-to-propagate-error-from-f2fs_enable_checkpoint.patch @@ -0,0 +1,86 @@ +From stable+bounces-204264-greg=kroah.com@vger.kernel.org Tue Dec 30 18:34:58 2025 +From: Sasha Levin +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 , stable@kernel.org, Jaegeuk Kim , Sasha Levin +Message-ID: <20251230173452.2352003-1-sashal@kernel.org> + +From: Chao Yu + +[ 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 +Signed-off-by: Jaegeuk Kim +[ Adjust context, no rollback ] +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 0000000000..37cc2c9252 --- /dev/null +++ b/queue-5.15/f2fs-use-global-inline_xattr_slab-instead-of-per-sb-slab-cache.patch @@ -0,0 +1,237 @@ +From stable+bounces-204285-greg=kroah.com@vger.kernel.org Tue Dec 30 20:55:22 2025 +From: Sasha Levin +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 , stable@kernel.org, Hong Yun , Jaegeuk Kim , Sasha Levin +Message-ID: <20251230195517.2448220-1-sashal@kernel.org> + +From: Chao Yu + +[ 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 +Tested-by: Hong Yun +Signed-off-by: Chao Yu +Signed-off-by: Jaegeuk Kim +[ folio => page + different module init/exit ordering ] +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 0000000000..68ca8aa769 --- /dev/null +++ b/queue-5.15/fuse-fix-readahead-reclaim-deadlock.patch @@ -0,0 +1,120 @@ +From stable+bounces-204418-greg=kroah.com@vger.kernel.org Thu Jan 1 16:57:37 2026 +From: Sasha Levin +Date: Thu, 1 Jan 2026 10:57:31 -0500 +Subject: fuse: fix readahead reclaim deadlock +To: stable@vger.kernel.org +Cc: Joanne Koong , Omar Sandoval , Miklos Szeredi , Sasha Levin +Message-ID: <20260101155731.4129270-1-sashal@kernel.org> + +From: Joanne Koong + +[ 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 +Reported-by: Omar Sandoval +Signed-off-by: Miklos Szeredi +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 0000000000..51e4646007 --- /dev/null +++ b/queue-5.15/hid-core-harden-s32ton-against-conversion-to-0-bits.patch @@ -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 , syzbot+b63d677d63bcac06cf90@syzkaller.appspotmail.com, Benjamin Tissoires , Wenshan Lan +Message-ID: <20251204123901.4101-1-jetlan9@163.com> + +From: Alan Stern + +[ 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 +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 +[ s32ton() was moved by c653ffc28340 ("HID: stop exporting hid_snto32()"). + Minor context change fixed. ] +Signed-off-by: Wenshan Lan +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 0000000000..e04322b6ae --- /dev/null +++ b/queue-5.15/iommu-qcom-fix-device-leak-on-of_xlate.patch @@ -0,0 +1,66 @@ +From stable+bounces-204848-greg=kroah.com@vger.kernel.org Mon Jan 5 17:42:16 2026 +From: Sasha Levin +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 , Rob Clark , Yu Kuai , Robin Murphy , Joerg Roedel , Sasha Levin +Message-ID: <20260105160912.2661912-1-sashal@kernel.org> + +From: Johan Hovold + +[ 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 +Cc: Yu Kuai +Acked-by: Robin Murphy +Signed-off-by: Johan Hovold +Signed-off-by: Joerg Roedel +[ adapted validation logic from max_asid to num_ctxs ] +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 0000000000..2eeb9bdf87 --- /dev/null +++ b/queue-5.15/jbd2-fix-the-inconsistency-between-checksum-and-data-in-memory-for-journal-sb.patch @@ -0,0 +1,94 @@ +From stable+bounces-204162-greg=kroah.com@vger.kernel.org Tue Dec 30 02:01:08 2025 +From: Sasha Levin +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 , Baokun Li , "Darrick J. Wong" , Jan Kara , Theodore Ts'o , stable@kernel.org, Sasha Levin +Message-ID: <20251230010102.1899453-1-sashal@kernel.org> + +From: Ye Bin + +[ 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 +Reviewed-by: Baokun Li +Reviewed-by: Darrick J. Wong +Reviewed-by: Jan Kara +Message-ID: <20251103010123.3753631-1-yebin@huaweicloud.com> +Signed-off-by: Theodore Ts'o +Cc: stable@kernel.org +[ Changed jbd2_superblock_csum(sb) to jbd2_superblock_csum(journal, sb) ] +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 0000000000..52806b1fe3 --- /dev/null +++ b/queue-5.15/kvm-nvmx-immediately-refresh-apicv-controls-as-needed-on-nested-vm-exit.patch @@ -0,0 +1,93 @@ +From stable+bounces-204315-greg=kroah.com@vger.kernel.org Wed Dec 31 04:17:26 2025 +From: Sasha Levin +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 , Chao Gao , Sean Christopherson , Sasha Levin +Message-ID: <20251231031717.2685182-1-sashal@kernel.org> + +From: Dongli Zhang + +[ 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 +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 +[sean: write changelog] +Link: https://patch.msgid.link/20251205231913.441872-3-seanjc@google.com +Signed-off-by: Sean Christopherson +[ exported vmx_refresh_apicv_exec_ctrl() and added declaration in vmx.h ] +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 0000000000..ab26a8a54e --- /dev/null +++ b/queue-5.15/kvm-svm-mark-vmcb_npt-as-dirty-on-nested-vmrun.patch @@ -0,0 +1,41 @@ +From stable+bounces-204358-greg=kroah.com@vger.kernel.org Wed Dec 31 15:39:22 2025 +From: Sasha Levin +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 , Sean Christopherson , Sasha Levin +Message-ID: <20251231143917.3047237-1-sashal@kernel.org> + +From: Jim Mattson + +[ 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 +Link: https://lore.kernel.org/r/20250922162935.621409-3-jmattson@google.com +Signed-off-by: Sean Christopherson +[ adapted vmcb02 local variable to svm->vmcb direct access pattern ] +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 0000000000..1c94e2e348 --- /dev/null +++ b/queue-5.15/kvm-x86-acquire-kvm-srcu-when-handling-kvm_set_vcpu_events.patch @@ -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 + +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: + + 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 + + +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 +[ 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 +--- + 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 index 0000000000..bc00df7885 --- /dev/null +++ b/queue-5.15/lockd-fix-vfs_test_lock-calls.patch @@ -0,0 +1,182 @@ +From stable+bounces-206053-greg=kroah.com@vger.kernel.org Wed Jan 7 00:28:41 2026 +From: Sasha Levin +Date: Tue, 6 Jan 2026 18:28:35 -0500 +Subject: lockd: fix vfs_test_lock() calls +To: stable@vger.kernel.org +Cc: NeilBrown , Olga Kornievskaia , Jeff Layton , Chuck Lever , Sasha Levin +Message-ID: <20260106232835.3452850-1-sashal@kernel.org> + +From: NeilBrown + +[ 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 +Closes: https://lore.kernel.org/all/20251021130506.45065-1-okorniev@redhat.com +Signed-off-by: NeilBrown +Fixes: 20fa19027286 ("nfs: add export operations") +Cc: stable@vger.kernel.org +Reviewed-by: Jeff Layton +Signed-off-by: Chuck Lever +[ adapted c.flc_* field accesses to direct fl_* fields ] +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 0000000000..39ac960768 --- /dev/null +++ b/queue-5.15/media-mediatek-vcodec-fix-a-reference-leak-in-mtk_vcodec_fw_vpu_init.patch @@ -0,0 +1,47 @@ +From stable+bounces-204962-greg=kroah.com@vger.kernel.org Tue Jan 6 01:31:54 2026 +From: Sasha Levin +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 , AngeloGioacchino Del Regno , Tzung-Bi Shih , Nicolas Dufresne , Hans Verkuil , Sasha Levin +Message-ID: <20260106003147.2858489-1-sashal@kernel.org> + +From: Haoxiang Li + +[ 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 +Reviewed-by: AngeloGioacchino Del Regno +Reviewed-by: Tzung-Bi Shih +Signed-off-by: Nicolas Dufresne +Signed-off-by: Hans Verkuil +[ 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 +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 0000000000..0c4e1c7f98 --- /dev/null +++ b/queue-5.15/media-renesas-rcar_drif-fix-device-node-reference-leak-in-rcar_drif_bond_enabled.patch @@ -0,0 +1,45 @@ +From stable+bounces-204910-greg=kroah.com@vger.kernel.org Mon Jan 5 21:14:56 2026 +From: Sasha Levin +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 , Geert Uytterhoeven , Fabrizio Castro , Hans Verkuil , Sasha Levin +Message-ID: <20260105201335.2769246-1-sashal@kernel.org> + +From: Miaoqian Lin + +[ 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 +Reviewed-by: Geert Uytterhoeven +Reviewed-by: Fabrizio Castro +Signed-off-by: Hans Verkuil +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 0000000000..f2707a708c --- /dev/null +++ b/queue-5.15/media-samsung-exynos4-is-fix-potential-abba-deadlock-on-init.patch @@ -0,0 +1,48 @@ +From stable+bounces-204917-greg=kroah.com@vger.kernel.org Mon Jan 5 21:31:42 2026 +From: Sasha Levin +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 , Sylwester Nawrocki , Hans Verkuil , Sasha Levin +Message-ID: <20260105203136.2780656-1-sashal@kernel.org> + +From: Marek Szyprowski + +[ 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 +Acked-by: Sylwester Nawrocki +Signed-off-by: Hans Verkuil +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 0000000000..607df81171 --- /dev/null +++ b/queue-5.15/media-verisilicon-protect-g2-hevc-decoder-against-invalid-dpb-index.patch @@ -0,0 +1,64 @@ +From stable+bounces-204923-greg=kroah.com@vger.kernel.org Mon Jan 5 21:54:32 2026 +From: Sasha Levin +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 , Benjamin Gaignard , Hans Verkuil , Sasha Levin +Message-ID: <20260105205426.2793242-1-sashal@kernel.org> + +From: Nicolas Dufresne + +[ 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 +Signed-off-by: Nicolas Dufresne +Signed-off-by: Hans Verkuil +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 0000000000..d8cc1ba752 --- /dev/null +++ b/queue-5.15/media-vpif_capture-fix-section-mismatch.patch @@ -0,0 +1,50 @@ +From stable+bounces-204924-greg=kroah.com@vger.kernel.org Mon Jan 5 22:05:18 2026 +From: Sasha Levin +Date: Mon, 5 Jan 2026 16:05:09 -0500 +Subject: media: vpif_capture: fix section mismatch +To: stable@vger.kernel.org +Cc: Johan Hovold , Hans Verkuil , Sasha Levin +Message-ID: <20260105210509.2799904-1-sashal@kernel.org> + +From: Johan Hovold + +[ 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 +Signed-off-by: Hans Verkuil +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 0000000000..a8f9e79aa7 --- /dev/null +++ b/queue-5.15/mm-balloon_compaction-convert-balloon_page_delete-to-balloon_page_finalize.patch @@ -0,0 +1,225 @@ +From stable+bounces-204899-greg=kroah.com@vger.kernel.org Mon Jan 5 20:30:54 2026 +From: Sasha Levin +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" , "Lorenzo Stoakes" , "Alistair Popple" , "Al Viro" , "Arnd Bergmann" , "Brendan Jackman" , "Byungchul Park" , "Chengming Zhou" , "Christian Brauner" , "Christophe Leroy" , "Eugenio Pé rez" , "Greg Kroah-Hartman" , "Gregory Price" , "Harry Yoo" , "Huang, Ying" , "Jan Kara" , "Jason Gunthorpe" , "Jason Wang" , "Jerrin Shaji George" , "Johannes Weiner" , "John Hubbard" , "Jonathan Corbet" , "Joshua Hahn" , "Liam Howlett" , "Madhavan Srinivasan" , "Mathew Brost" , "Matthew Wilcox (Oracle)" , "Miaohe Lin" , "Michael Ellerman" , "Michael S. Tsirkin" , "Michal Hocko" , "Mike Rapoport" , "Minchan Kim" , "Naoya Horiguchi" , "Nicholas Piggin" , "Oscar Salvador" , "Peter Xu" , "Qi Zheng" , "Rakie Kim" , "Rik van Riel" , "Sergey Senozhatsky" , "Shakeel Butt" , "Suren Baghdasaryan" , "Vlastimil Babka" , "Xuan Zhuo" , "xu xin" , "Zi Yan" , "Andrew Morton" , "Sasha Levin" +Message-ID: <20260105192826.2740369-3-sashal@kernel.org> + +From: David Hildenbrand + +[ 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 +Reviewed-by: Lorenzo Stoakes +Cc: Alistair Popple +Cc: Al Viro +Cc: Arnd Bergmann +Cc: Brendan Jackman +Cc: Byungchul Park +Cc: Chengming Zhou +Cc: Christian Brauner +Cc: Christophe Leroy +Cc: Eugenio Pé rez +Cc: Greg Kroah-Hartman +Cc: Gregory Price +Cc: Harry Yoo +Cc: "Huang, Ying" +Cc: Jan Kara +Cc: Jason Gunthorpe +Cc: Jason Wang +Cc: Jerrin Shaji George +Cc: Johannes Weiner +Cc: John Hubbard +Cc: Jonathan Corbet +Cc: Joshua Hahn +Cc: Liam Howlett +Cc: Madhavan Srinivasan +Cc: Mathew Brost +Cc: Matthew Wilcox (Oracle) +Cc: Miaohe Lin +Cc: Michael Ellerman +Cc: "Michael S. Tsirkin" +Cc: Michal Hocko +Cc: Mike Rapoport +Cc: Minchan Kim +Cc: Naoya Horiguchi +Cc: Nicholas Piggin +Cc: Oscar Salvador +Cc: Peter Xu +Cc: Qi Zheng +Cc: Rakie Kim +Cc: Rik van Riel +Cc: Sergey Senozhatsky +Cc: Shakeel Butt +Cc: Suren Baghdasaryan +Cc: Vlastimil Babka +Cc: Xuan Zhuo +Cc: xu xin +Cc: Zi Yan +Signed-off-by: Andrew Morton +Stable-dep-of: 0da2ba35c0d5 ("powerpc/pseries/cmm: adjust BALLOON_MIGRATE when migrating pages") +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 0000000000..c176927399 --- /dev/null +++ b/queue-5.15/mm-balloon_compaction-make-balloon-page-compaction-callbacks-static.patch @@ -0,0 +1,96 @@ +From stable+bounces-204897-greg=kroah.com@vger.kernel.org Mon Jan 5 20:30:43 2026 +From: Sasha Levin +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 , "Michael S. Tsirkin" , Muchun Song , Sasha Levin +Message-ID: <20260105192826.2740369-1-sashal@kernel.org> + +From: Miaohe Lin + +[ 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 +Link: https://lore.kernel.org/r/20220125132221.2220-1-linmiaohe@huawei.com +Signed-off-by: Michael S. Tsirkin +Reviewed-by: Muchun Song +Stable-dep-of: 0da2ba35c0d5 ("powerpc/pseries/cmm: adjust BALLOON_MIGRATE when migrating pages") +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 0000000000..f3105a1b69 --- /dev/null +++ b/queue-5.15/mm-balloon_compaction-we-cannot-have-isolated-pages-in-the-balloon-list.patch @@ -0,0 +1,109 @@ +From stable+bounces-204898-greg=kroah.com@vger.kernel.org Mon Jan 5 20:30:49 2026 +From: Sasha Levin +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" , "Zi Yan" , "Lorenzo Stoakes" , "Alistair Popple" , "Al Viro" , "Arnd Bergmann" , "Brendan Jackman" , "Byungchul Park" , "Chengming Zhou" , "Christian Brauner" , "Christophe Leroy" , "Eugenio Pé rez" , "Greg Kroah-Hartman" , "Gregory Price" , "Huang, Ying" , "Jan Kara" , "Jason Gunthorpe" , "Jason Wang" , "Jerrin Shaji George" , "Johannes Weiner" , "John Hubbard" , "Jonathan Corbet" , "Joshua Hahn" , "Liam Howlett" , "Madhavan Srinivasan" , "Mathew Brost" , "Matthew Wilcox (Oracle)" , "Miaohe Lin" , "Michael Ellerman" , "Michael S. Tsirkin" , "Michal Hocko" , "Mike Rapoport" , "Minchan Kim" , "Naoya Horiguchi" , "Nicholas Piggin" , "Oscar Salvador" , "Peter Xu" , "Qi Zheng" , "Rakie Kim" , "Rik van Riel" , "Sergey Senozhatsky" , "Shakeel Butt" , "Suren Baghdasaryan" , "Vlastimil Babka" , "Xuan Zhuo" , "xu xin" , "Harry Yoo" , "Andrew Morton" , "Sasha Levin" +Message-ID: <20260105192826.2740369-2-sashal@kernel.org> + +From: David Hildenbrand + +[ 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 +Acked-by: Zi Yan +Reviewed-by: Lorenzo Stoakes +Cc: Alistair Popple +Cc: Al Viro +Cc: Arnd Bergmann +Cc: Brendan Jackman +Cc: Byungchul Park +Cc: Chengming Zhou +Cc: Christian Brauner +Cc: Christophe Leroy +Cc: Eugenio Pé rez +Cc: Greg Kroah-Hartman +Cc: Gregory Price +Cc: "Huang, Ying" +Cc: Jan Kara +Cc: Jason Gunthorpe +Cc: Jason Wang +Cc: Jerrin Shaji George +Cc: Johannes Weiner +Cc: John Hubbard +Cc: Jonathan Corbet +Cc: Joshua Hahn +Cc: Liam Howlett +Cc: Madhavan Srinivasan +Cc: Mathew Brost +Cc: Matthew Wilcox (Oracle) +Cc: Miaohe Lin +Cc: Michael Ellerman +Cc: "Michael S. Tsirkin" +Cc: Michal Hocko +Cc: Mike Rapoport +Cc: Minchan Kim +Cc: Naoya Horiguchi +Cc: Nicholas Piggin +Cc: Oscar Salvador +Cc: Peter Xu +Cc: Qi Zheng +Cc: Rakie Kim +Cc: Rik van Riel +Cc: Sergey Senozhatsky +Cc: Shakeel Butt +Cc: Suren Baghdasaryan +Cc: Vlastimil Babka +Cc: Xuan Zhuo +Cc: xu xin +Cc: Harry Yoo +Signed-off-by: Andrew Morton +Stable-dep-of: 0da2ba35c0d5 ("powerpc/pseries/cmm: adjust BALLOON_MIGRATE when migrating pages") +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 0000000000..7db44a8fcd --- /dev/null +++ b/queue-5.15/mm-mprotect-delete-pmd_none_or_clear_bad_unless_trans_huge.patch @@ -0,0 +1,279 @@ +From stable+bounces-205078-greg=kroah.com@vger.kernel.org Tue Jan 6 12:59:03 2026 +From: Harry Yoo +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" , "Anshuman Khandual" , "Axel Rasmussen" , "Christophe Leroy" , "Christoph Hellwig" , "David Hildenbrand" , "Huang, Ying" , "Ira Weiny" , "Jason Gunthorpe" , "Kirill A . Shutemov" , "Lorenzo Stoakes" , "Matthew Wilcox" , "Mel Gorman" , "Miaohe Lin" , "Mike Kravetz" , "Mike Rapoport" , "Minchan Kim" , "Naoya Horiguchi" , "Pavel Tatashin" , "Peter Xu" , "Peter Zijlstra" , "Qi Zheng" , "Ralph Campbell" , "SeongJae Park" , "Song Liu" , "Steven Price" , "Suren Baghdasaryan" , "Thomas Hellström" , "Will Deacon" , "Yang Shi" , "Yu Zhao" , "Zack Rusin" , "Harry Yoo" +Message-ID: <20260106115036.86042-3-harry.yoo@oracle.com> + +From: Hugh Dickins + +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 +Cc: Alistair Popple +Cc: Anshuman Khandual +Cc: Axel Rasmussen +Cc: Christophe Leroy +Cc: Christoph Hellwig +Cc: David Hildenbrand +Cc: "Huang, Ying" +Cc: Ira Weiny +Cc: Jason Gunthorpe +Cc: Kirill A. Shutemov +Cc: Lorenzo Stoakes +Cc: Matthew Wilcox +Cc: Mel Gorman +Cc: Miaohe Lin +Cc: Mike Kravetz +Cc: Mike Rapoport (IBM) +Cc: Minchan Kim +Cc: Naoya Horiguchi +Cc: Pavel Tatashin +Cc: Peter Xu +Cc: Peter Zijlstra +Cc: Qi Zheng +Cc: Ralph Campbell +Cc: Ryan Roberts +Cc: SeongJae Park +Cc: Song Liu +Cc: Steven Price +Cc: Suren Baghdasaryan +Cc: Thomas Hellström +Cc: Will Deacon +Cc: Yang Shi +Cc: Yu Zhao +Cc: Zack Rusin +Signed-off-by: Andrew Morton +[ 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] + [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 +Acked-by: David Hildenbrand (Red Hat) +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 0000000000..e843156860 --- /dev/null +++ b/queue-5.15/mm-mprotect-use-long-for-page-accountings-and-retval.patch @@ -0,0 +1,223 @@ +From stable+bounces-205079-greg=kroah.com@vger.kernel.org Tue Jan 6 12:59:45 2026 +From: Harry Yoo +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 , Mike Kravetz , James Houghton , Andrea Arcangeli , Axel Rasmussen , David Hildenbrand , Muchun Song , Nadav Amit , Harry Yoo +Message-ID: <20260106115036.86042-2-harry.yoo@oracle.com> + +From: Peter Xu + +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 +Acked-by: Mike Kravetz +Acked-by: James Houghton +Cc: Andrea Arcangeli +Cc: Axel Rasmussen +Cc: David Hildenbrand +Cc: Muchun Song +Cc: Nadav Amit +Signed-off-by: Andrew Morton +[ Adjust context ] +Signed-off-by: Harry Yoo +Acked-by: David Hildenbrand (Red Hat) +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 0000000000..86cd2c03aa --- /dev/null +++ b/queue-5.15/mmc-core-use-sysfs_emit-instead-of-sprintf.patch @@ -0,0 +1,225 @@ +From stable+bounces-200879-greg=kroah.com@vger.kernel.org Fri Dec 12 09:21:24 2025 +From: Chen Yu +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 + +[ 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 +Cc: stable@vger.kernel.org +Link: https://lore.kernel.org/r/717729b2-d65b-c72e-9fac-471d28d00b5a@omp.ru +Signed-off-by: Ulf Hansson +Signed-off-by: Chen Yu +Signed-off-by: Greg Kroah-Hartman +--- + 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 + #include + #include ++#include + + #include + #include +@@ -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 ++#include + + 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 + #include + #include ++#include + + #include + #include +@@ -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 + #include + #include ++#include + + #include + #include +@@ -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 + #include ++#include + + #include + #include +@@ -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 + #include + #include ++#include + + #include + #include +@@ -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 index 0000000000..8ce076a566 --- /dev/null +++ b/queue-5.15/mptcp-pm-ignore-unknown-endpoint-flags.patch @@ -0,0 +1,68 @@ +From stable+bounces-204223-greg=kroah.com@vger.kernel.org Tue Dec 30 15:09:11 2025 +From: Sasha Levin +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)" , Mat Martineau , Jakub Kicinski , Sasha Levin +Message-ID: <20251230140701.2226659-1-sashal@kernel.org> + +From: "Matthieu Baerts (NGI0)" + +[ 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 +Signed-off-by: Matthieu Baerts (NGI0) +Link: https://patch.msgid.link/20251205-net-mptcp-misc-fixes-6-19-rc1-v1-1-9e4781a6c1b8@kernel.org +Signed-off-by: Jakub Kicinski +[ GENMASK(5, 0) => GENMASK(3, 0) + context ] +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 0000000000..242fab0bbb --- /dev/null +++ b/queue-5.15/net-remove-rtnl-dance-for-siocbraddif-and-siocbrdelif.patch @@ -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 +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 , syzkaller , yan kang , yue sun , Kuniyuki Iwashima , Stanislav Fomichev , Ido Schimmel , Nikolay Aleksandrov , Paolo Abeni +Message-ID: <20260107172129.2488617-1-cascardo@igalia.com> + +From: Thadeu Lima de Souza Cascardo + +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 +Reported-by: yan kang +Reported-by: yue sun +Closes: https://lore.kernel.org/netdev/SY8P300MB0421225D54EB92762AE8F0F2A1D32@SY8P300MB0421.AUSP300.PROD.OUTLOOK.COM/ +Signed-off-by: Kuniyuki Iwashima +Acked-by: Stanislav Fomichev +Reviewed-by: Ido Schimmel +Acked-by: Nikolay Aleksandrov +Link: https://patch.msgid.link/20250316192851.19781-1-kuniyu@amazon.com +Signed-off-by: Paolo Abeni +[cascardo: fixed conflict at dev_ifsioc] +Signed-off-by: Thadeu Lima de Souza Cascardo +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 0000000000..b9fd81dbd6 --- /dev/null +++ b/queue-5.15/nfsd-clear-seclabel-in-the-suppattr_exclcreat-bitmap.patch @@ -0,0 +1,57 @@ +From stable+bounces-204345-greg=kroah.com@vger.kernel.org Wed Dec 31 14:46:20 2025 +From: Sasha Levin +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 , Jeff Layton , Sasha Levin +Message-ID: <20251231134615.2899300-1-sashal@kernel.org> + +From: Chuck Lever + +[ 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 +Signed-off-by: Chuck Lever +[ Adjust context ] +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 0000000000..cfb1143b84 --- /dev/null +++ b/queue-5.15/nfsd-nfsv4-file-creation-neglects-setting-acl.patch @@ -0,0 +1,49 @@ +From stable+bounces-204919-greg=kroah.com@vger.kernel.org Mon Jan 5 21:35:05 2026 +From: Chuck Lever +Date: Mon, 5 Jan 2026 15:34:59 -0500 +Subject: NFSD: NFSv4 file creation neglects setting ACL +To: +Cc: Greg Kroah-Hartman , Sasha Levin , , Chuck Lever , Aurelien Couderc +Message-ID: <20260105203459.3562478-1-cel@kernel.org> + +From: Chuck Lever + +[ 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 +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 +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 0000000000..e7c453bd54 --- /dev/null +++ b/queue-5.15/page_pool-fix-use-after-free-in-page_pool_recycle_in_ring.patch @@ -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" , "Jakub Kicinski" , syzbot+204a4382fcb3311f3858@syzkaller.appspotmail.com, "Toke Høiland-Jørgensen" , "Mina Almasry" , "Ruohan Lan" +Message-ID: <20251211100110.4139-1-ruohanlan@aliyun.com> + +From: Dong Chenchen + +[ 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: + + __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 +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 +Reviewed-by: Toke Høiland-Jørgensen +Reviewed-by: Mina Almasry +Link: https://patch.msgid.link/20250527114152.3119109-1-dongchenchen2@huawei.com +Signed-off-by: Jakub Kicinski +[ 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 +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 0000000000..f058bbc38a --- /dev/null +++ b/queue-5.15/pci-brcmstb-fix-disabling-l0s-capability.patch @@ -0,0 +1,79 @@ +From stable+bounces-204905-greg=kroah.com@vger.kernel.org Mon Jan 5 20:41:50 2026 +From: Sasha Levin +Date: Mon, 5 Jan 2026 14:41:45 -0500 +Subject: PCI: brcmstb: Fix disabling L0s capability +To: stable@vger.kernel.org +Cc: Jim Quinlan , Bjorn Helgaas , Manivannan Sadhasivam , Florian Fainelli , Sasha Levin +Message-ID: <20260105194145.2748502-1-sashal@kernel.org> + +From: Jim Quinlan + +[ 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 +Closes: https://lore.kernel.org/linux-pci/20250925194424.GA2197200@bhelgaas +Signed-off-by: Jim Quinlan +[mani: reworded subject and description, added closes tag and CCed stable] +Signed-off-by: Manivannan Sadhasivam +[bhelgaas: commit log] +Signed-off-by: Bjorn Helgaas +Reviewed-by: Florian Fainelli +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 +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 0000000000..46d35fdf7c --- /dev/null +++ b/queue-5.15/pmdomain-imx-fix-reference-count-leak-in-imx_gpc_probe.patch @@ -0,0 +1,48 @@ +From stable+bounces-206021-greg=kroah.com@vger.kernel.org Tue Jan 6 19:16:37 2026 +From: Sasha Levin +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 , Frank Li , Ulf Hansson , Sasha Levin +Message-ID: <20260106181021.3109327-3-sashal@kernel.org> + +From: Wentao Liang + +[ 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 +Reviewed-by: Frank Li +Signed-off-by: Ulf Hansson +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 0000000000..8c097ab8ac --- /dev/null +++ b/queue-5.15/pmdomain-use-device_get_match_data.patch @@ -0,0 +1,134 @@ +From stable+bounces-206020-greg=kroah.com@vger.kernel.org Tue Jan 6 20:05:19 2026 +From: Sasha Levin +Date: Tue, 6 Jan 2026 13:10:15 -0500 +Subject: pmdomain: Use device_get_match_data() +To: stable@vger.kernel.org +Cc: Rob Herring , Ulf Hansson , Sasha Levin +Message-ID: <20260106181021.3109327-2-sashal@kernel.org> + +From: Rob Herring + +[ 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 +Link: https://lore.kernel.org/r/20231006224614.444488-1-robh@kernel.org +Signed-off-by: Ulf Hansson +Stable-dep-of: 73cb5f6eafb0 ("pmdomain: imx: Fix reference count leak in imx_gpc_probe()") +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + 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 + #include +-#include ++#include ++#include + #include + #include + #include +@@ -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 + #include + #include +-#include ++#include + #include + #include ++#include + #include + #include + +@@ -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 + #include + #include ++#include + #include + #include ++#include ++#include + #include + #include +-#include + #include + #include + #include +@@ -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 index 0000000000..09b67261ed --- /dev/null +++ b/queue-5.15/powerpc-64s-slb-fix-slb-multihit-issue-during-slb-preload.patch @@ -0,0 +1,324 @@ +From stable+bounces-204863-greg=kroah.com@vger.kernel.org Mon Jan 5 18:21:04 2026 +From: Sasha Levin +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 , Nicholas Piggin , "Ritesh Harjani (IBM)" , Madhavan Srinivasan , Sasha Levin +Message-ID: <20260105171235.2685455-1-sashal@kernel.org> + +From: Donet Tom + +[ 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 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 +Signed-off-by: Donet Tom +Signed-off-by: Ritesh Harjani (IBM) +Signed-off-by: Madhavan Srinivasan +Link: https://patch.msgid.link/0ac694ae683494fe8cadbd911a1a5018d5d3c541.1761834163.git.ritesh.list@gmail.com +[ Adjust context ] +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 0000000000..dc5d290096 --- /dev/null +++ b/queue-5.15/powerpc-pseries-cmm-adjust-balloon_migrate-when-migrating-pages.patch @@ -0,0 +1,45 @@ +From stable+bounces-204900-greg=kroah.com@vger.kernel.org Mon Jan 5 20:30:56 2026 +From: Sasha Levin +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 , "Ritesh Harjani (IBM)" , Christophe Leroy , Madhavan Srinivasan , Michael Ellerman , Nicholas Piggin , Andrew Morton , Sasha Levin +Message-ID: <20260105192826.2740369-4-sashal@kernel.org> + +From: David Hildenbrand + +[ 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 +Reviewed-by: Ritesh Harjani (IBM) +Cc: Christophe Leroy +Cc: Madhavan Srinivasan +Cc: Michael Ellerman +Cc: Nicholas Piggin +Cc: +Signed-off-by: Andrew Morton +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 0000000000..bb33c82cdb --- /dev/null +++ b/queue-5.15/powerpc-pseries-cmm-call-balloon_devinfo_init-also-without-config_balloon_compaction.patch @@ -0,0 +1,63 @@ +From stable+bounces-204908-greg=kroah.com@vger.kernel.org Mon Jan 5 21:01:46 2026 +From: Sasha Levin +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 , "Ritesh Harjani (IBM)" , Christophe Leroy , Madhavan Srinivasan , Michael Ellerman , Nicholas Piggin , Andrew Morton , Sasha Levin +Message-ID: <20260105200120.2763600-1-sashal@kernel.org> + +From: David Hildenbrand + +[ 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 +Reviewed-by: Ritesh Harjani (IBM) +Cc: Christophe Leroy +Cc: Madhavan Srinivasan +Cc: Michael Ellerman +Cc: Nicholas Piggin +Cc: +Signed-off-by: Andrew Morton +[ moved balloon_devinfo_init() call from inside cmm_balloon_compaction_init() to cmm_init() ] +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 0000000000..8a0c5ec6c8 --- /dev/null +++ b/queue-5.15/r8169-fix-rtl8117-wake-on-lan-in-dash-mode.patch @@ -0,0 +1,53 @@ +From stable+bounces-204346-greg=kroah.com@vger.kernel.org Wed Dec 31 14:46:48 2025 +From: Sasha Levin +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" , "Heiner Kallweit" , "Jakub Kicinski" , "Sasha Levin" +Message-ID: <20251231134642.2899730-1-sashal@kernel.org> + +From: René Rebe + +[ 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 +Cc: stable@vger.kernel.org +Reviewed-by: Heiner Kallweit +Link: https://patch.msgid.link/20251202.194137.1647877804487085954.rene@exactco.de +Signed-off-by: Jakub Kicinski +[ adapted tp->dash_enabled check to tp->dash_type != RTL_DASH_NONE comparison ] +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + 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); + } + diff --git a/queue-5.15/series b/queue-5.15/series index cde6a798fb..a965d192bc 100644 --- a/queue-5.15/series +++ b/queue-5.15/series @@ -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 index 0000000000..bfdfdcebcd --- /dev/null +++ b/queue-5.15/soc-rockchip-power-domain-manage-resource-conflicts-with-firmware.patch @@ -0,0 +1,291 @@ +From stable+bounces-206019-greg=kroah.com@vger.kernel.org Tue Jan 6 19:57:04 2026 +From: Sasha Levin +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 , Peter Geis , Heiko Stuebner , Chanwoo Choi , Sasha Levin +Message-ID: <20260106181021.3109327-1-sashal@kernel.org> + +From: Brian Norris + +[ 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 +Tested-by: Peter Geis +Reviewed-by: Heiko Stuebner +Signed-off-by: Chanwoo Choi +Stable-dep-of: 73cb5f6eafb0 ("pmdomain: imx: Fix reference count leak in imx_gpc_probe()") +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + 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 + #include + #include ++#include + #include + #include + #include +@@ -16,6 +17,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -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 index 0000000000..8bec461b7b --- /dev/null +++ b/queue-5.15/sunrpc-svcauth_gss-avoid-null-deref-on-zero-length-gss_token-in-gss_read_proxy_verf.patch @@ -0,0 +1,41 @@ +From stable+bounces-204357-greg=kroah.com@vger.kernel.org Wed Dec 31 15:39:01 2025 +From: Sasha Levin +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 , Chuck Lever , Sasha Levin +Message-ID: <20251231143853.3046790-1-sashal@kernel.org> + +From: Joshua Rogers + +[ 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 +Signed-off-by: Chuck Lever +[ adapted xdr buffer pointer API to older argv iov_base/iov_len API ] +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 0000000000..335d3c153e --- /dev/null +++ b/queue-5.15/svcrdma-bound-check-rq_pages-index-in-inline-path.patch @@ -0,0 +1,39 @@ +From stable+bounces-204397-greg=kroah.com@vger.kernel.org Wed Dec 31 23:44:29 2025 +From: Sasha Levin +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 , Chuck Lever , Sasha Levin +Message-ID: <20251231224424.3631279-1-sashal@kernel.org> + +From: Joshua Rogers + +[ 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 +Signed-off-by: Chuck Lever +[ adapted rc_curpage and rq_maxpages fields to ri_pageno and RPCSVC_MAXPAGES constant ] +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 0000000000..a2206ee646 --- /dev/null +++ b/queue-5.15/tpm-cap-the-number-of-pcr-banks.patch @@ -0,0 +1,105 @@ +From stable+bounces-204157-greg=kroah.com@vger.kernel.org Tue Dec 30 01:13:03 2025 +From: Sasha Levin +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 , Lai Yi , Jonathan McDowell , Roberto Sassu , Sasha Levin +Message-ID: <20251230001257.1873924-1-sashal@kernel.org> + +From: Jarkko Sakkinen + +[ 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 +Reviewed-by: Jonathan McDowell +Reviewed-by: Roberto Sassu +Signed-off-by: Jarkko Sakkinen +[ 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 +Signed-off-by: Greg Kroah-Hartman +--- + 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 + + #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 index 0000000000..21ec8b4e4e --- /dev/null +++ b/queue-5.15/usb-dwc3-keep-susphy-enabled-during-exit-to-avoid-controller-faults.patch @@ -0,0 +1,58 @@ +From stable+bounces-204234-greg=kroah.com@vger.kernel.org Tue Dec 30 16:55:45 2025 +From: Sasha Levin +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 , stable , Thinh Nguyen , Greg Kroah-Hartman , Sasha Levin +Message-ID: <20251230155538.2289361-1-sashal@kernel.org> + +From: Udipto Goswami + +[ 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 +Fixes: 6d735722063a ("usb: dwc3: core: Prevent phy suspend during init") +Suggested-by: Thinh Nguyen +Signed-off-by: Udipto Goswami +Acked-by: Thinh Nguyen +Link: https://patch.msgid.link/20251126054221.120638-1-udipto.goswami@oss.qualcomm.com +Signed-off-by: Greg Kroah-Hartman +[ Adjust context ] +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 0000000000..27b69b5fcb --- /dev/null +++ b/queue-5.15/usb-gadget-udc-fix-use-after-free-in-usb_gadget_state_work.patch @@ -0,0 +1,117 @@ +From stable+bounces-200372-greg=kroah.com@vger.kernel.org Mon Dec 8 22:02:29 2025 +From: Sasha Levin +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 , stable , Greg Kroah-Hartman , Sasha Levin +Message-ID: <20251208210221.397543-1-sashal@kernel.org> + +From: Jimmy Hu + +[ 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 +Signed-off-by: Jimmy Hu +Link: https://patch.msgid.link/20251023054945.233861-1-hhhuuu@google.com +Signed-off-by: Greg Kroah-Hartman +[ Adjust context ] +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 0000000000..e4ece91b02 --- /dev/null +++ b/queue-5.15/usb-ohci-nxp-fix-device-leak-on-probe-failure.patch @@ -0,0 +1,49 @@ +From stable+bounces-204215-greg=kroah.com@vger.kernel.org Tue Dec 30 14:35:06 2025 +From: Sasha Levin +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 , Ma Ke , Alan Stern , Vladimir Zapolskiy , Greg Kroah-Hartman , Sasha Levin +Message-ID: <20251230133458.2203341-2-sashal@kernel.org> + +From: Johan Hovold + +[ 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 +Link: https://lore.kernel.org/lkml/20251117013428.21840-1-make24@iscas.ac.cn/ +Signed-off-by: Johan Hovold +Acked-by: Alan Stern +Reviewed-by: Vladimir Zapolskiy +Link: https://patch.msgid.link/20251218153519.19453-4-johan@kernel.org +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 0000000000..997882ccc5 --- /dev/null +++ b/queue-5.15/usb-ohci-nxp-use-helper-function-devm_clk_get_enabled.patch @@ -0,0 +1,93 @@ +From stable+bounces-204214-greg=kroah.com@vger.kernel.org Tue Dec 30 14:35:04 2025 +From: Sasha Levin +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 , Alan Stern , Greg Kroah-Hartman , Sasha Levin +Message-ID: <20251230133458.2203341-1-sashal@kernel.org> + +From: Zhang Zekun + +[ 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 +Acked-by: Alan Stern +Link: https://lore.kernel.org/r/20240902123020.29267-3-zhangzekun11@huawei.com +Signed-off-by: Greg Kroah-Hartman +Stable-dep-of: b4c61e542faf ("usb: ohci-nxp: fix device leak on probe failure") +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 0000000000..dd11fe810f --- /dev/null +++ b/queue-5.15/wifi-mac80211-discard-beacon-frames-to-non-broadcast-address.patch @@ -0,0 +1,62 @@ +From stable+bounces-206118-greg=kroah.com@vger.kernel.org Wed Jan 7 12:00:14 2026 +From: Sasha Levin +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 , Johannes Berg , Sasha Levin +Message-ID: <20260107105214.3609231-1-sashal@kernel.org> + +From: Jouni Malinen + +[ 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 +Link: https://patch.msgid.link/20251215151134.104501-1-jouni.malinen@oss.qualcomm.com +Signed-off-by: Johannes Berg +[ adapted RX_DROP return value to RX_DROP_MONITOR ] +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 0000000000..59950d8458 --- /dev/null +++ b/queue-5.15/wifi-mt76-fix-dts-power-limits-on-little-endian-systems.patch @@ -0,0 +1,139 @@ +From stable+bounces-204140-greg=kroah.com@vger.kernel.org Mon Dec 29 22:58:09 2025 +From: Sasha Levin +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)" , Felix Fietkau , Sasha Levin +Message-ID: <20251229215801.1732809-1-sashal@kernel.org> + +From: "Sven Eckelmann (Plasma Cloud)" + +[ 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) +Signed-off-by: Felix Fietkau +[ Adjust context ] +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 0000000000..168c52e9a8 --- /dev/null +++ b/queue-5.15/xfs-fix-a-memory-leak-in-xfs_buf_item_init.patch @@ -0,0 +1,38 @@ +From stable+bounces-204313-greg=kroah.com@vger.kernel.org Wed Dec 31 04:15:52 2025 +From: Sasha Levin +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 , Christoph Hellwig , Carlos Maiolino , Carlos Maiolino , Sasha Levin +Message-ID: <20251231031544.2684088-1-sashal@kernel.org> + +From: Haoxiang Li + +[ 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 +Reviewed-by: Christoph Hellwig +Reviewed-by: Carlos Maiolino +Signed-off-by: Carlos Maiolino +[ Adjust context ] +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 0000000000..a501101ab5 --- /dev/null +++ b/queue-5.15/xhci-dbgtty-fix-device-unregister.patch @@ -0,0 +1,47 @@ +From stable+bounces-200326-greg=kroah.com@vger.kernel.org Mon Dec 8 07:55:25 2025 +From: Sasha Levin +Date: Mon, 8 Dec 2025 01:54:23 -0500 +Subject: xhci: dbgtty: fix device unregister +To: stable@vger.kernel.org +Cc: "Łukasz Bartosik" , stable , "Greg Kroah-Hartman" , "Sasha Levin" +Message-ID: <20251208065423.260017-2-sashal@kernel.org> + +From: Łukasz Bartosik + +[ 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 +Fixes: dfba2174dc42 ("usb: xhci: Add DbC support in xHCI driver") +Signed-off-by: Łukasz Bartosik +Link: https://patch.msgid.link/20251119212910.1245694-1-ukaszb@google.com +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 0000000000..ce253e91ce --- /dev/null +++ b/queue-5.15/xhci-dbgtty-use-idr-to-support-several-dbc-instances.patch @@ -0,0 +1,170 @@ +From stable+bounces-200325-greg=kroah.com@vger.kernel.org Mon Dec 8 07:54:32 2025 +From: Sasha Levin +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 , Greg Kroah-Hartman , Sasha Levin +Message-ID: <20251208065423.260017-1-sashal@kernel.org> + +From: Mathias Nyman + +[ 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 +Link: https://lore.kernel.org/r/20220216095153.1303105-6-mathias.nyman@linux.intel.com +Signed-off-by: Greg Kroah-Hartman +Stable-dep-of: 1f73b8b56cf3 ("xhci: dbgtty: fix device unregister") +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + 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 + #include + #include ++#include + + #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); + }