From: Greg Kroah-Hartman Date: Thu, 8 Jan 2026 10:40:45 +0000 (+0100) Subject: 6.6-stable patches X-Git-Tag: v6.1.160~56 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=a2d25f4e3ce42b1c273c84d1ddd2bd2208ea909c;p=thirdparty%2Fkernel%2Fstable-queue.git 6.6-stable patches added patches: alsa-hda-cs35l41-fix-null-pointer-dereference-in-cs35l41_hda_read_acpi.patch alsa-wavefront-clear-substream-pointers-on-close.patch alsa-wavefront-fix-integer-overflow-in-sample-size-validation.patch alsa-wavefront-use-guard-for-spin-locks.patch alsa-wavefront-use-standard-print-api.patch arm-dts-microchip-sama7g5-fix-uart-fifo-size-to-32.patch btrfs-don-t-rewrite-ret-from-inode_permission.patch drm-amd-display-fix-null-pointer-deref-in-dcn20_resource.c.patch drm-amdgpu-forward-vmid-reservation-errors.patch drm-mediatek-fix-probe-memory-leak.patch drm-mediatek-fix-probe-resource-leaks.patch drm-tilcdc-fix-removal-actions-in-case-of-failed-probe.patch drm-tilcdc-request-and-mapp-iomem-with-devres.patch ext4-fix-string-copying-in-parse_apply_sb_mount_options.patch f2fs-fix-to-avoid-potential-deadlock.patch f2fs-use-f2fs_err_ratelimited-to-avoid-redundant-logs.patch fuse-fix-readahead-reclaim-deadlock.patch gfs2-fix-freeze-error-handling.patch gpiolib-acpi-add-quirk-for-dell-precision-7780.patch jbd2-fix-the-inconsistency-between-checksum-and-data-in-memory-for-journal-sb.patch lockd-fix-vfs_test_lock-calls.patch loongarch-refactor-register-restoration-in-ftrace_common_return.patch mm-consider-non-anon-swap-cache-folios-in-folio_expected_ref_count.patch mm-ksm-fix-exec-fork-inheritance-support-for-prctl.patch mm-simplify-folio_expected_ref_count.patch mptcp-ensure-context-reset-on-disconnect.patch mptcp-fallback-earlier-on-simult-connection.patch mptcp-initialise-rcv_mss-before-calling-tcp_send_active_reset-in-mptcp_do_fastclose.patch mptcp-pm-ignore-unknown-endpoint-flags.patch net-phy-mediatek-fix-nvmem-cell-reference-leak-in-mt798x_phy_calibration.patch net-remove-rtnl-dance-for-siocbraddif-and-siocbrdelif.patch nfsd-clear-seclabel-in-the-suppattr_exclcreat-bitmap.patch pci-brcmstb-fix-disabling-l0s-capability.patch pmdomain-imx-fix-reference-count-leak-in-imx_gpc_probe.patch pmdomain-use-device_get_match_data.patch scsi-ufs-core-add-ufshcd_update_evt_hist-for-ufs-suspend-error.patch svcrdma-bound-check-rq_pages-index-in-inline-path.patch tty-introduce-and-use-tty_port_tty_vhangup-helper.patch usb-ohci-nxp-fix-device-leak-on-probe-failure.patch usb-ohci-nxp-use-helper-function-devm_clk_get_enabled.patch usb-xhci-apply-the-link-chain-quirk-on-nec-isoc-endpoints.patch usb-xhci-move-link-chain-bit-quirk-checks-into-one-helper-function.patch wifi-mac80211-discard-beacon-frames-to-non-broadcast-address.patch wifi-mt76-fix-dts-power-limits-on-little-endian-systems.patch xhci-dbgtty-fix-device-unregister-fixup.patch --- diff --git a/queue-6.6/alsa-hda-cs35l41-fix-null-pointer-dereference-in-cs35l41_hda_read_acpi.patch b/queue-6.6/alsa-hda-cs35l41-fix-null-pointer-dereference-in-cs35l41_hda_read_acpi.patch new file mode 100644 index 0000000000..cf40556d85 --- /dev/null +++ b/queue-6.6/alsa-hda-cs35l41-fix-null-pointer-dereference-in-cs35l41_hda_read_acpi.patch @@ -0,0 +1,42 @@ +From stable+bounces-201658-greg=kroah.com@vger.kernel.org Tue Dec 16 12:42:46 2025 +From: Sasha Levin +Date: Tue, 16 Dec 2025 06:42:26 -0500 +Subject: ALSA: hda: cs35l41: Fix NULL pointer dereference in cs35l41_hda_read_acpi() +To: stable@vger.kernel.org +Cc: Denis Arefev , Richard Fitzgerald , Takashi Iwai , Sasha Levin +Message-ID: <20251216114226.2766048-1-sashal@kernel.org> + +From: Denis Arefev + +[ Upstream commit c34b04cc6178f33c08331568c7fd25c5b9a39f66 ] + +The acpi_get_first_physical_node() function can return NULL, in which +case the get_device() function also returns NULL, but this value is +then dereferenced without checking,so add a check to prevent a crash. + +Found by Linux Verification Center (linuxtesting.org) with SVACE. + +Fixes: 7b2f3eb492da ("ALSA: hda: cs35l41: Add support for CS35L41 in HDA systems") +Cc: stable@vger.kernel.org +Signed-off-by: Denis Arefev +Reviewed-by: Richard Fitzgerald +Signed-off-by: Takashi Iwai +Link: https://patch.msgid.link/20251202101338.11437-1-arefev@swemel.ru +[ NULL check right after acpi_dev_put(adev) cleanup call ] +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + sound/pci/hda/cs35l41_hda.c | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/sound/pci/hda/cs35l41_hda.c ++++ b/sound/pci/hda/cs35l41_hda.c +@@ -1432,6 +1432,8 @@ static int cs35l41_hda_read_acpi(struct + + physdev = get_device(acpi_get_first_physical_node(adev)); + acpi_dev_put(adev); ++ if (!physdev) ++ return -ENODEV; + + sub = acpi_get_subsystem_id(ACPI_HANDLE(physdev)); + if (IS_ERR(sub)) diff --git a/queue-6.6/alsa-wavefront-clear-substream-pointers-on-close.patch b/queue-6.6/alsa-wavefront-clear-substream-pointers-on-close.patch new file mode 100644 index 0000000000..0c7adfe8b5 --- /dev/null +++ b/queue-6.6/alsa-wavefront-clear-substream-pointers-on-close.patch @@ -0,0 +1,47 @@ +From stable+bounces-201184-greg=kroah.com@vger.kernel.org Tue Dec 16 12:13:26 2025 +From: Sasha Levin +Date: Tue, 16 Dec 2025 06:06:30 -0500 +Subject: ALSA: wavefront: Clear substream pointers on close +To: stable@vger.kernel.org +Cc: Junrui Luo , Yuhao Jiang , Takashi Iwai , Sasha Levin +Message-ID: <20251216110630.2754006-2-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 +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 +@@ -278,6 +278,7 @@ static int snd_wavefront_midi_input_clos + return -EIO; + + guard(spinlock_irqsave)(&midi->open); ++ midi->substream_input[mpu] = NULL; + midi->mode[mpu] &= ~MPU401_MODE_INPUT; + + return 0; +@@ -300,6 +301,7 @@ static int snd_wavefront_midi_output_clo + return -EIO; + + guard(spinlock_irqsave)(&midi->open); ++ midi->substream_output[mpu] = NULL; + midi->mode[mpu] &= ~MPU401_MODE_OUTPUT; + return 0; + } diff --git a/queue-6.6/alsa-wavefront-fix-integer-overflow-in-sample-size-validation.patch b/queue-6.6/alsa-wavefront-fix-integer-overflow-in-sample-size-validation.patch new file mode 100644 index 0000000000..17bc8c3d39 --- /dev/null +++ b/queue-6.6/alsa-wavefront-fix-integer-overflow-in-sample-size-validation.patch @@ -0,0 +1,43 @@ +From stable+bounces-201177-greg=kroah.com@vger.kernel.org Tue Dec 16 11:54:53 2025 +From: Sasha Levin +Date: Tue, 16 Dec 2025 05:54:28 -0500 +Subject: ALSA: wavefront: Fix integer overflow in sample size validation +To: stable@vger.kernel.org +Cc: Junrui Luo , Takashi Iwai , Sasha Levin +Message-ID: <20251216105428.2749611-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 +@@ -950,9 +950,9 @@ wavefront_send_sample (snd_wavefront_t * + if (header->size) { + dev->freemem = wavefront_freemem (dev); + +- if (dev->freemem < (int)header->size) { ++ if (dev->freemem < 0 || dev->freemem < header->size) { + dev_err(dev->card->dev, +- "insufficient memory to load %d byte sample.\n", ++ "insufficient memory to load %u byte sample.\n", + header->size); + return -ENOMEM; + } diff --git a/queue-6.6/alsa-wavefront-use-guard-for-spin-locks.patch b/queue-6.6/alsa-wavefront-use-guard-for-spin-locks.patch new file mode 100644 index 0000000000..ce38bf0b52 --- /dev/null +++ b/queue-6.6/alsa-wavefront-use-guard-for-spin-locks.patch @@ -0,0 +1,367 @@ +From stable+bounces-201183-greg=kroah.com@vger.kernel.org Tue Dec 16 12:14:04 2025 +From: Sasha Levin +Date: Tue, 16 Dec 2025 06:06:29 -0500 +Subject: ALSA: wavefront: Use guard() for spin locks +To: stable@vger.kernel.org +Cc: Takashi Iwai , Sasha Levin +Message-ID: <20251216110630.2754006-1-sashal@kernel.org> + +From: Takashi Iwai + +[ Upstream commit 4b97f8e614ba46a50bd181d40b5a1424411a211a ] + +Clean up the code using guard() for spin locks. + +Merely code refactoring, and no behavior change. + +Signed-off-by: Takashi Iwai +Link: https://patch.msgid.link/20250829145300.5460-19-tiwai@suse.de +Stable-dep-of: e11c5c13ce0a ("ALSA: wavefront: Clear substream pointers on close") +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + sound/isa/wavefront/wavefront_midi.c | 127 +++++++++++++--------------------- + sound/isa/wavefront/wavefront_synth.c | 18 ++-- + 2 files changed, 59 insertions(+), 86 deletions(-) + +--- a/sound/isa/wavefront/wavefront_midi.c ++++ b/sound/isa/wavefront/wavefront_midi.c +@@ -113,7 +113,6 @@ static void snd_wavefront_midi_output_wr + { + snd_wavefront_midi_t *midi = &card->wavefront.midi; + snd_wavefront_mpu_id mpu; +- unsigned long flags; + unsigned char midi_byte; + int max = 256, mask = 1; + int timeout; +@@ -142,11 +141,9 @@ static void snd_wavefront_midi_output_wr + break; + } + +- spin_lock_irqsave (&midi->virtual, flags); +- if ((midi->mode[midi->output_mpu] & MPU401_MODE_OUTPUT) == 0) { +- spin_unlock_irqrestore (&midi->virtual, flags); ++ guard(spinlock_irqsave)(&midi->virtual); ++ if ((midi->mode[midi->output_mpu] & MPU401_MODE_OUTPUT) == 0) + goto __second; +- } + if (output_ready (midi)) { + if (snd_rawmidi_transmit(midi->substream_output[midi->output_mpu], &midi_byte, 1) == 1) { + if (!midi->isvirtual || +@@ -160,14 +157,11 @@ static void snd_wavefront_midi_output_wr + del_timer(&midi->timer); + } + midi->mode[midi->output_mpu] &= ~MPU401_MODE_OUTPUT_TRIGGER; +- spin_unlock_irqrestore (&midi->virtual, flags); + goto __second; + } + } else { +- spin_unlock_irqrestore (&midi->virtual, flags); + return; + } +- spin_unlock_irqrestore (&midi->virtual, flags); + } + + __second: +@@ -185,15 +179,13 @@ static void snd_wavefront_midi_output_wr + break; + } + +- spin_lock_irqsave (&midi->virtual, flags); ++ guard(spinlock_irqsave)(&midi->virtual); + if (!midi->isvirtual) + mask = 0; + mpu = midi->output_mpu ^ mask; + mask = 0; /* don't invert the value from now */ +- if ((midi->mode[mpu] & MPU401_MODE_OUTPUT) == 0) { +- spin_unlock_irqrestore (&midi->virtual, flags); ++ if ((midi->mode[mpu] & MPU401_MODE_OUTPUT) == 0) + return; +- } + if (snd_rawmidi_transmit_empty(midi->substream_output[mpu])) + goto __timer; + if (output_ready (midi)) { +@@ -215,20 +207,16 @@ static void snd_wavefront_midi_output_wr + del_timer(&midi->timer); + } + midi->mode[mpu] &= ~MPU401_MODE_OUTPUT_TRIGGER; +- spin_unlock_irqrestore (&midi->virtual, flags); + return; + } + } else { +- spin_unlock_irqrestore (&midi->virtual, flags); + return; + } +- spin_unlock_irqrestore (&midi->virtual, flags); + } + } + + static int snd_wavefront_midi_input_open(struct snd_rawmidi_substream *substream) + { +- unsigned long flags; + snd_wavefront_midi_t *midi; + snd_wavefront_mpu_id mpu; + +@@ -243,17 +231,15 @@ static int snd_wavefront_midi_input_open + if (!midi) + return -EIO; + +- spin_lock_irqsave (&midi->open, flags); ++ guard(spinlock_irqsave)(&midi->open); + midi->mode[mpu] |= MPU401_MODE_INPUT; + midi->substream_input[mpu] = substream; +- spin_unlock_irqrestore (&midi->open, flags); + + return 0; + } + + static int snd_wavefront_midi_output_open(struct snd_rawmidi_substream *substream) + { +- unsigned long flags; + snd_wavefront_midi_t *midi; + snd_wavefront_mpu_id mpu; + +@@ -268,17 +254,15 @@ static int snd_wavefront_midi_output_ope + if (!midi) + return -EIO; + +- spin_lock_irqsave (&midi->open, flags); ++ guard(spinlock_irqsave)(&midi->open); + midi->mode[mpu] |= MPU401_MODE_OUTPUT; + midi->substream_output[mpu] = substream; +- spin_unlock_irqrestore (&midi->open, flags); + + return 0; + } + + static int snd_wavefront_midi_input_close(struct snd_rawmidi_substream *substream) + { +- unsigned long flags; + snd_wavefront_midi_t *midi; + snd_wavefront_mpu_id mpu; + +@@ -293,16 +277,14 @@ static int snd_wavefront_midi_input_clos + if (!midi) + return -EIO; + +- spin_lock_irqsave (&midi->open, flags); ++ guard(spinlock_irqsave)(&midi->open); + midi->mode[mpu] &= ~MPU401_MODE_INPUT; +- spin_unlock_irqrestore (&midi->open, flags); + + return 0; + } + + static int snd_wavefront_midi_output_close(struct snd_rawmidi_substream *substream) + { +- unsigned long flags; + snd_wavefront_midi_t *midi; + snd_wavefront_mpu_id mpu; + +@@ -317,15 +299,13 @@ static int snd_wavefront_midi_output_clo + if (!midi) + return -EIO; + +- spin_lock_irqsave (&midi->open, flags); ++ guard(spinlock_irqsave)(&midi->open); + midi->mode[mpu] &= ~MPU401_MODE_OUTPUT; +- spin_unlock_irqrestore (&midi->open, flags); + return 0; + } + + static void snd_wavefront_midi_input_trigger(struct snd_rawmidi_substream *substream, int up) + { +- unsigned long flags; + snd_wavefront_midi_t *midi; + snd_wavefront_mpu_id mpu; + +@@ -341,30 +321,27 @@ static void snd_wavefront_midi_input_tri + if (!midi) + return; + +- spin_lock_irqsave (&midi->virtual, flags); ++ guard(spinlock_irqsave)(&midi->virtual); + if (up) { + midi->mode[mpu] |= MPU401_MODE_INPUT_TRIGGER; + } else { + midi->mode[mpu] &= ~MPU401_MODE_INPUT_TRIGGER; + } +- spin_unlock_irqrestore (&midi->virtual, flags); + } + + static void snd_wavefront_midi_output_timer(struct timer_list *t) + { + snd_wavefront_midi_t *midi = from_timer(midi, t, timer); + snd_wavefront_card_t *card = midi->timer_card; +- unsigned long flags; + +- spin_lock_irqsave (&midi->virtual, flags); +- mod_timer(&midi->timer, 1 + jiffies); +- spin_unlock_irqrestore (&midi->virtual, flags); ++ scoped_guard(spinlock_irqsave, &midi->virtual) { ++ mod_timer(&midi->timer, 1 + jiffies); ++ } + snd_wavefront_midi_output_write(card); + } + + static void snd_wavefront_midi_output_trigger(struct snd_rawmidi_substream *substream, int up) + { +- unsigned long flags; + snd_wavefront_midi_t *midi; + snd_wavefront_mpu_id mpu; + +@@ -380,22 +357,22 @@ static void snd_wavefront_midi_output_tr + if (!midi) + return; + +- spin_lock_irqsave (&midi->virtual, flags); +- if (up) { +- if ((midi->mode[mpu] & MPU401_MODE_OUTPUT_TRIGGER) == 0) { +- if (!midi->istimer) { +- timer_setup(&midi->timer, +- snd_wavefront_midi_output_timer, +- 0); +- mod_timer(&midi->timer, 1 + jiffies); ++ scoped_guard(spinlock_irqsave, &midi->virtual) { ++ if (up) { ++ if ((midi->mode[mpu] & MPU401_MODE_OUTPUT_TRIGGER) == 0) { ++ if (!midi->istimer) { ++ timer_setup(&midi->timer, ++ snd_wavefront_midi_output_timer, ++ 0); ++ mod_timer(&midi->timer, 1 + jiffies); ++ } ++ midi->istimer++; ++ midi->mode[mpu] |= MPU401_MODE_OUTPUT_TRIGGER; + } +- midi->istimer++; +- midi->mode[mpu] |= MPU401_MODE_OUTPUT_TRIGGER; ++ } else { ++ midi->mode[mpu] &= ~MPU401_MODE_OUTPUT_TRIGGER; + } +- } else { +- midi->mode[mpu] &= ~MPU401_MODE_OUTPUT_TRIGGER; + } +- spin_unlock_irqrestore (&midi->virtual, flags); + + if (up) + snd_wavefront_midi_output_write((snd_wavefront_card_t *)substream->rmidi->card->private_data); +@@ -405,7 +382,6 @@ void + snd_wavefront_midi_interrupt (snd_wavefront_card_t *card) + + { +- unsigned long flags; + snd_wavefront_midi_t *midi; + static struct snd_rawmidi_substream *substream = NULL; + static int mpu = external_mpu; +@@ -419,37 +395,37 @@ snd_wavefront_midi_interrupt (snd_wavefr + return; + } + +- spin_lock_irqsave (&midi->virtual, flags); +- while (--max) { ++ scoped_guard(spinlock_irqsave, &midi->virtual) { ++ while (--max) { + +- if (input_avail (midi)) { +- byte = read_data (midi); ++ if (input_avail(midi)) { ++ byte = read_data(midi); + +- if (midi->isvirtual) { +- if (byte == WF_EXTERNAL_SWITCH) { +- substream = midi->substream_input[external_mpu]; +- mpu = external_mpu; +- } else if (byte == WF_INTERNAL_SWITCH) { +- substream = midi->substream_output[internal_mpu]; ++ if (midi->isvirtual) { ++ if (byte == WF_EXTERNAL_SWITCH) { ++ substream = midi->substream_input[external_mpu]; ++ mpu = external_mpu; ++ } else if (byte == WF_INTERNAL_SWITCH) { ++ substream = midi->substream_output[internal_mpu]; ++ mpu = internal_mpu; ++ } /* else just leave it as it is */ ++ } else { ++ substream = midi->substream_input[internal_mpu]; + mpu = internal_mpu; +- } /* else just leave it as it is */ +- } else { +- substream = midi->substream_input[internal_mpu]; +- mpu = internal_mpu; +- } ++ } + +- if (substream == NULL) { +- continue; +- } ++ if (substream == NULL) { ++ continue; ++ } + +- if (midi->mode[mpu] & MPU401_MODE_INPUT_TRIGGER) { +- snd_rawmidi_receive(substream, &byte, 1); ++ if (midi->mode[mpu] & MPU401_MODE_INPUT_TRIGGER) { ++ snd_rawmidi_receive(substream, &byte, 1); ++ } ++ } else { ++ break; + } +- } else { +- break; + } +- } +- spin_unlock_irqrestore (&midi->virtual, flags); ++ } + + snd_wavefront_midi_output_write(card); + } +@@ -471,13 +447,10 @@ void + snd_wavefront_midi_disable_virtual (snd_wavefront_card_t *card) + + { +- unsigned long flags; +- +- spin_lock_irqsave (&card->wavefront.midi.virtual, flags); ++ guard(spinlock_irqsave)(&card->wavefront.midi.virtual); + // snd_wavefront_midi_input_close (card->ics2115_external_rmidi); + // snd_wavefront_midi_output_close (card->ics2115_external_rmidi); + card->wavefront.midi.isvirtual = 0; +- spin_unlock_irqrestore (&card->wavefront.midi.virtual, flags); + } + + int +--- a/sound/isa/wavefront/wavefront_synth.c ++++ b/sound/isa/wavefront/wavefront_synth.c +@@ -1741,10 +1741,10 @@ snd_wavefront_internal_interrupt (snd_wa + return; + } + +- spin_lock(&dev->irq_lock); +- dev->irq_ok = 1; +- dev->irq_cnt++; +- spin_unlock(&dev->irq_lock); ++ scoped_guard(spinlock, &dev->irq_lock) { ++ dev->irq_ok = 1; ++ dev->irq_cnt++; ++ } + wake_up(&dev->interrupt_sleeper); + } + +@@ -1796,11 +1796,11 @@ wavefront_should_cause_interrupt (snd_wa + wait_queue_entry_t wait; + + init_waitqueue_entry(&wait, current); +- spin_lock_irq(&dev->irq_lock); +- add_wait_queue(&dev->interrupt_sleeper, &wait); +- dev->irq_ok = 0; +- outb (val,port); +- spin_unlock_irq(&dev->irq_lock); ++ scoped_guard(spinlock_irq, &dev->irq_lock) { ++ add_wait_queue(&dev->interrupt_sleeper, &wait); ++ dev->irq_ok = 0; ++ outb(val, port); ++ } + while (!dev->irq_ok && time_before(jiffies, timeout)) { + schedule_timeout_uninterruptible(1); + barrier(); diff --git a/queue-6.6/alsa-wavefront-use-standard-print-api.patch b/queue-6.6/alsa-wavefront-use-standard-print-api.patch new file mode 100644 index 0000000000..fc50d512b2 --- /dev/null +++ b/queue-6.6/alsa-wavefront-use-standard-print-api.patch @@ -0,0 +1,1000 @@ +From stable+bounces-201176-greg=kroah.com@vger.kernel.org Tue Dec 16 11:55:12 2025 +From: Sasha Levin +Date: Tue, 16 Dec 2025 05:54:27 -0500 +Subject: ALSA: wavefront: Use standard print API +To: stable@vger.kernel.org +Cc: Takashi Iwai , Jaroslav Kysela , Sasha Levin +Message-ID: <20251216105428.2749611-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 +@@ -501,7 +501,8 @@ snd_wavefront_midi_start (snd_wavefront_ + for (i = 0; i < 30000 && !output_ready (midi); i++); + + if (!output_ready (midi)) { +- snd_printk ("MIDI interface not ready for command\n"); ++ dev_err(card->wavefront.card->dev, ++ "MIDI interface not ready for command\n"); + return -1; + } + +@@ -523,7 +524,8 @@ snd_wavefront_midi_start (snd_wavefront_ + } + + if (!ok) { +- snd_printk ("cannot set UART mode for MIDI interface"); ++ dev_err(card->wavefront.card->dev, ++ "cannot set UART mode for MIDI interface"); + dev->interrupts_are_midi = 0; + return -1; + } +@@ -531,7 +533,8 @@ snd_wavefront_midi_start (snd_wavefront_ + /* Route external MIDI to WaveFront synth (by default) */ + + if (snd_wavefront_cmd (dev, WFC_MISYNTH_ON, rbuf, wbuf)) { +- snd_printk ("can't enable MIDI-IN-2-synth routing.\n"); ++ dev_warn(card->wavefront.card->dev, ++ "can't enable MIDI-IN-2-synth routing.\n"); + /* XXX error ? */ + } + +@@ -547,14 +550,16 @@ snd_wavefront_midi_start (snd_wavefront_ + */ + + if (snd_wavefront_cmd (dev, WFC_VMIDI_OFF, rbuf, wbuf)) { +- snd_printk ("virtual MIDI mode not disabled\n"); ++ dev_warn(card->wavefront.card->dev, ++ "virtual MIDI mode not disabled\n"); + return 0; /* We're OK, but missing the external MIDI dev */ + } + + snd_wavefront_midi_enable_virtual (card); + + if (snd_wavefront_cmd (dev, WFC_VMIDI_ON, rbuf, wbuf)) { +- snd_printk ("cannot enable virtual MIDI mode.\n"); ++ dev_warn(card->wavefront.card->dev, ++ "cannot enable virtual MIDI mode.\n"); + snd_wavefront_midi_disable_virtual (card); + } + return 0; +--- a/sound/isa/wavefront/wavefront_synth.c ++++ b/sound/isa/wavefront/wavefront_synth.c +@@ -116,7 +116,7 @@ MODULE_PARM_DESC(osrun_time, "how many s + + #define DPRINT(cond, ...) \ + if ((dev->debug & (cond)) == (cond)) { \ +- snd_printk (__VA_ARGS__); \ ++ pr_debug(__VA_ARGS__); \ + } + #else + #define DPRINT(cond, args...) +@@ -341,7 +341,7 @@ snd_wavefront_cmd (snd_wavefront_t *dev, + + wfcmd = wavefront_get_command(cmd); + if (!wfcmd) { +- snd_printk ("command 0x%x not supported.\n", ++ dev_err(dev->card->dev, "command 0x%x not supported.\n", + cmd); + return 1; + } +@@ -623,7 +623,7 @@ wavefront_get_sample_status (snd_wavefro + /* check sample status */ + + if (snd_wavefront_cmd (dev, WFC_GET_NSAMPLES, rbuf, wbuf)) { +- snd_printk ("cannot request sample count.\n"); ++ dev_err(dev->card->dev, "cannot request sample count.\n"); + return -1; + } + +@@ -635,8 +635,8 @@ wavefront_get_sample_status (snd_wavefro + wbuf[1] = i >> 7; + + if (snd_wavefront_cmd (dev, WFC_IDENTIFY_SAMPLE_TYPE, rbuf, wbuf)) { +- snd_printk(KERN_WARNING "cannot identify sample " +- "type of slot %d\n", i); ++ dev_warn(dev->card->dev, ++ "cannot identify sample type of slot %d\n", i); + dev->sample_status[i] = WF_ST_EMPTY; + continue; + } +@@ -661,9 +661,9 @@ wavefront_get_sample_status (snd_wavefro + break; + + default: +- snd_printk ("unknown sample type for " +- "slot %d (0x%x)\n", +- i, rbuf[0]); ++ dev_err(dev->card->dev, ++ "unknown sample type for slot %d (0x%x)\n", ++ i, rbuf[0]); + } + + if (rbuf[0] != WF_ST_EMPTY) { +@@ -671,9 +671,10 @@ wavefront_get_sample_status (snd_wavefro + } + } + +- snd_printk ("%d samples used (%d real, %d aliases, %d multi), " +- "%d empty\n", dev->samples_used, sc_real, sc_alias, sc_multi, +- WF_MAX_SAMPLE - dev->samples_used); ++ dev_info(dev->card->dev, ++ "%d samples used (%d real, %d aliases, %d multi), %d empty\n", ++ dev->samples_used, sc_real, sc_alias, sc_multi, ++ WF_MAX_SAMPLE - dev->samples_used); + + + return (0); +@@ -706,8 +707,8 @@ wavefront_get_patch_status (snd_wavefron + } else if (x == 3) { /* Bad patch number */ + dev->patch_status[i] = 0; + } else { +- snd_printk ("upload patch " +- "error 0x%x\n", x); ++ dev_err(dev->card->dev, ++ "upload patch error 0x%x\n", x); + dev->patch_status[i] = 0; + return 1; + } +@@ -724,7 +725,8 @@ wavefront_get_patch_status (snd_wavefron + } + + } +- snd_printk ("%d patch slots filled, %d in use\n", cnt, cnt2); ++ dev_info(dev->card->dev, "%d patch slots filled, %d in use\n", ++ cnt, cnt2); + + return (0); + } +@@ -760,8 +762,8 @@ wavefront_get_program_status (snd_wavefr + } else if (x == 1) { /* Bad program number */ + dev->prog_status[i] = 0; + } else { +- snd_printk ("upload program " +- "error 0x%x\n", x); ++ dev_err(dev->card->dev, ++ "upload program error 0x%x\n", x); + dev->prog_status[i] = 0; + } + } +@@ -772,7 +774,7 @@ wavefront_get_program_status (snd_wavefr + } + } + +- snd_printk ("%d programs slots in use\n", cnt); ++ dev_info(dev->card->dev, "%d programs slots in use\n", cnt); + + return (0); + } +@@ -796,7 +798,7 @@ wavefront_send_patch (snd_wavefront_t *d + munge_buf ((unsigned char *)&header->hdr.p, bptr, WF_PATCH_BYTES); + + if (snd_wavefront_cmd (dev, WFC_DOWNLOAD_PATCH, NULL, buf)) { +- snd_printk ("download patch failed\n"); ++ dev_err(dev->card->dev, "download patch failed\n"); + return -EIO; + } + +@@ -837,7 +839,7 @@ wavefront_send_program (snd_wavefront_t + munge_buf ((unsigned char *)&header->hdr.pr, &buf[1], WF_PROGRAM_BYTES); + + if (snd_wavefront_cmd (dev, WFC_DOWNLOAD_PROGRAM, NULL, buf)) { +- snd_printk ("download patch failed\n"); ++ dev_err(dev->card->dev, "download patch failed\n"); + return -EIO; + } + +@@ -851,7 +853,7 @@ wavefront_freemem (snd_wavefront_t *dev) + char rbuf[8]; + + if (snd_wavefront_cmd (dev, WFC_REPORT_FREE_MEMORY, rbuf, NULL)) { +- snd_printk ("can't get memory stats.\n"); ++ dev_err(dev->card->dev, "can't get memory stats.\n"); + return -1; + } else { + return demunge_int32 (rbuf, 4); +@@ -901,7 +903,7 @@ wavefront_send_sample (snd_wavefront_t * + x = wavefront_find_free_sample(dev); + if (x < 0) + return -ENOMEM; +- snd_printk ("unspecified sample => %d\n", x); ++ dev_info(dev->card->dev, "unspecified sample => %d\n", x); + header->number = x; + } + +@@ -935,9 +937,9 @@ wavefront_send_sample (snd_wavefront_t * + + if (dev->rom_samples_rdonly) { + if (dev->sample_status[header->number] & WF_SLOT_ROM) { +- snd_printk ("sample slot %d " +- "write protected\n", +- header->number); ++ dev_err(dev->card->dev, ++ "sample slot %d write protected\n", ++ header->number); + return -EACCES; + } + } +@@ -949,9 +951,9 @@ wavefront_send_sample (snd_wavefront_t * + dev->freemem = wavefront_freemem (dev); + + if (dev->freemem < (int)header->size) { +- snd_printk ("insufficient memory to " +- "load %d byte sample.\n", +- header->size); ++ dev_err(dev->card->dev, ++ "insufficient memory to load %d byte sample.\n", ++ header->size); + return -ENOMEM; + } + +@@ -960,8 +962,8 @@ wavefront_send_sample (snd_wavefront_t * + skip = WF_GET_CHANNEL(&header->hdr.s); + + if (skip > 0 && header->hdr.s.SampleResolution != LINEAR_16BIT) { +- snd_printk ("channel selection only " +- "possible on 16-bit samples"); ++ dev_err(dev->card->dev, ++ "channel selection only possible on 16-bit samples"); + return -EINVAL; + } + +@@ -1057,8 +1059,8 @@ wavefront_send_sample (snd_wavefront_t * + header->size ? + WFC_DOWNLOAD_SAMPLE : WFC_DOWNLOAD_SAMPLE_HEADER, + NULL, sample_hdr)) { +- snd_printk ("sample %sdownload refused.\n", +- header->size ? "" : "header "); ++ dev_err(dev->card->dev, "sample %sdownload refused.\n", ++ header->size ? "" : "header "); + return -EIO; + } + +@@ -1083,8 +1085,8 @@ wavefront_send_sample (snd_wavefront_t * + } + + if (snd_wavefront_cmd (dev, WFC_DOWNLOAD_BLOCK, NULL, NULL)) { +- snd_printk ("download block " +- "request refused.\n"); ++ dev_err(dev->card->dev, ++ "download block request refused.\n"); + return -EIO; + } + +@@ -1145,13 +1147,13 @@ wavefront_send_sample (snd_wavefront_t * + dma_ack = wavefront_read(dev); + if (dma_ack != WF_DMA_ACK) { + if (dma_ack == -1) { +- snd_printk ("upload sample " +- "DMA ack timeout\n"); ++ dev_err(dev->card->dev, ++ "upload sample DMA ack timeout\n"); + return -EIO; + } else { +- snd_printk ("upload sample " +- "DMA ack error 0x%x\n", +- dma_ack); ++ dev_err(dev->card->dev, ++ "upload sample DMA ack error 0x%x\n", ++ dma_ack); + return -EIO; + } + } +@@ -1195,7 +1197,7 @@ wavefront_send_alias (snd_wavefront_t *d + munge_int32 (*(&header->hdr.a.FrequencyBias+1), &alias_hdr[23], 2); + + if (snd_wavefront_cmd (dev, WFC_DOWNLOAD_SAMPLE_ALIAS, NULL, alias_hdr)) { +- snd_printk ("download alias failed.\n"); ++ dev_err(dev->card->dev, "download alias failed.\n"); + return -EIO; + } + +@@ -1248,7 +1250,7 @@ wavefront_send_multisample (snd_wavefron + if (snd_wavefront_cmd (dev, WFC_DOWNLOAD_MULTISAMPLE, + (unsigned char *) (long) ((num_samples*2)+3), + msample_hdr)) { +- snd_printk ("download of multisample failed.\n"); ++ dev_err(dev->card->dev, "download of multisample failed.\n"); + kfree(msample_hdr); + return -EIO; + } +@@ -1271,7 +1273,7 @@ wavefront_fetch_multisample (snd_wavefro + munge_int32 (header->number, number, 2); + + if (snd_wavefront_cmd (dev, WFC_UPLOAD_MULTISAMPLE, log_ns, number)) { +- snd_printk ("upload multisample failed.\n"); ++ dev_err(dev->card->dev, "upload multisample failed.\n"); + return -EIO; + } + +@@ -1290,16 +1292,16 @@ wavefront_fetch_multisample (snd_wavefro + + val = wavefront_read(dev); + if (val == -1) { +- snd_printk ("upload multisample failed " +- "during sample loop.\n"); ++ dev_err(dev->card->dev, ++ "upload multisample failed during sample loop.\n"); + return -EIO; + } + d[0] = val; + + val = wavefront_read(dev); + if (val == -1) { +- snd_printk ("upload multisample failed " +- "during sample loop.\n"); ++ dev_err(dev->card->dev, ++ "upload multisample failed during sample loop.\n"); + return -EIO; + } + d[1] = val; +@@ -1334,7 +1336,7 @@ wavefront_send_drum (snd_wavefront_t *de + } + + if (snd_wavefront_cmd (dev, WFC_DOWNLOAD_EDRUM_PROGRAM, NULL, drumbuf)) { +- snd_printk ("download drum failed.\n"); ++ dev_err(dev->card->dev, "download drum failed.\n"); + return -EIO; + } + +@@ -1352,7 +1354,7 @@ wavefront_find_free_sample (snd_wavefron + return i; + } + } +- snd_printk ("no free sample slots!\n"); ++ dev_err(dev->card->dev, "no free sample slots!\n"); + return -1; + } + +@@ -1368,7 +1370,7 @@ wavefront_find_free_patch (snd_wavefront + return i; + } + } +- snd_printk ("no free patch slots!\n"); ++ dev_err(dev->card->dev, "no free patch slots!\n"); + return -1; + } + #endif +@@ -1385,7 +1387,7 @@ wavefront_load_patch (snd_wavefront_t *d + + if (copy_from_user (header, addr, sizeof(wavefront_patch_info) - + sizeof(wavefront_any))) { +- snd_printk ("bad address for load patch.\n"); ++ dev_err(dev->card->dev, "bad address for load patch.\n"); + err = -EFAULT; + goto __error; + } +@@ -1463,8 +1465,8 @@ wavefront_load_patch (snd_wavefront_t *d + break; + + default: +- snd_printk ("unknown patch type %d.\n", +- header->subkey); ++ dev_err(dev->card->dev, "unknown patch type %d.\n", ++ header->subkey); + err = -EINVAL; + break; + } +@@ -1527,13 +1529,13 @@ wavefront_synth_control (snd_wavefront_c + switch (wc->cmd) { + + case WFC_DISABLE_INTERRUPTS: +- snd_printk ("interrupts disabled.\n"); ++ dev_dbg(dev->card->dev, "interrupts disabled.\n"); + outb (0x80|0x20, dev->control_port); + dev->interrupts_are_midi = 1; + return 0; + + case WFC_ENABLE_INTERRUPTS: +- snd_printk ("interrupts enabled.\n"); ++ dev_dbg(dev->card->dev, "interrupts enabled.\n"); + outb (0x80|0x40|0x20, dev->control_port); + dev->interrupts_are_midi = 1; + return 0; +@@ -1550,7 +1552,7 @@ wavefront_synth_control (snd_wavefront_c + case WFC_IDENTIFY_SLOT_TYPE: + i = wc->wbuf[0] | (wc->wbuf[1] << 7); + if (i <0 || i >= WF_MAX_SAMPLE) { +- snd_printk ("invalid slot ID %d\n", ++ dev_err(dev->card->dev, "invalid slot ID %d\n", + i); + wc->status = EINVAL; + return -EINVAL; +@@ -1561,7 +1563,7 @@ wavefront_synth_control (snd_wavefront_c + + case WFC_DEBUG_DRIVER: + dev->debug = wc->wbuf[0]; +- snd_printk ("debug = 0x%x\n", dev->debug); ++ dev_dbg(dev->card->dev, "debug = 0x%x\n", dev->debug); + return 0; + + case WFC_UPLOAD_PATCH: +@@ -1578,8 +1580,8 @@ wavefront_synth_control (snd_wavefront_c + return 0; + + case WFC_UPLOAD_SAMPLE_ALIAS: +- snd_printk ("support for sample alias upload " +- "being considered.\n"); ++ dev_err(dev->card->dev, ++ "support for sample alias upload being considered.\n"); + wc->status = EINVAL; + return -EINVAL; + } +@@ -1620,9 +1622,8 @@ wavefront_synth_control (snd_wavefront_c + break; + + case WFC_UPLOAD_SAMPLE_ALIAS: +- snd_printk ("support for " +- "sample aliases still " +- "being considered.\n"); ++ dev_err(dev->card->dev, ++ "support for sample aliases still being considered.\n"); + break; + + case WFC_VMIDI_OFF: +@@ -1760,7 +1761,7 @@ snd_wavefront_internal_interrupt (snd_wa + */ + + static int +-snd_wavefront_interrupt_bits (int irq) ++snd_wavefront_interrupt_bits(snd_wavefront_t *dev, int irq) + + { + int bits; +@@ -1780,7 +1781,7 @@ snd_wavefront_interrupt_bits (int irq) + break; + + default: +- snd_printk ("invalid IRQ %d\n", irq); ++ dev_err(dev->card->dev, "invalid IRQ %d\n", irq); + bits = -1; + } + +@@ -1815,7 +1816,7 @@ wavefront_reset_to_cleanliness (snd_wave + + /* IRQ already checked */ + +- bits = snd_wavefront_interrupt_bits (dev->irq); ++ bits = snd_wavefront_interrupt_bits(dev, dev->irq); + + /* try reset of port */ + +@@ -1885,7 +1886,7 @@ wavefront_reset_to_cleanliness (snd_wave + */ + + if (!dev->irq_ok) { +- snd_printk ("intr not received after h/w un-reset.\n"); ++ dev_err(dev->card->dev, "intr not received after h/w un-reset.\n"); + goto gone_bad; + } + +@@ -1909,18 +1910,18 @@ wavefront_reset_to_cleanliness (snd_wave + dev->data_port, ramcheck_time*HZ); + + if (!dev->irq_ok) { +- snd_printk ("post-RAM-check interrupt not received.\n"); ++ dev_err(dev->card->dev, "post-RAM-check interrupt not received.\n"); + goto gone_bad; + } + + if (!wavefront_wait (dev, STAT_CAN_READ)) { +- snd_printk ("no response to HW version cmd.\n"); ++ dev_err(dev->card->dev, "no response to HW version cmd.\n"); + goto gone_bad; + } + + hwv[0] = wavefront_read(dev); + if (hwv[0] == -1) { +- snd_printk ("board not responding correctly.\n"); ++ dev_err(dev->card->dev, "board not responding correctly.\n"); + goto gone_bad; + } + +@@ -1932,11 +1933,11 @@ wavefront_reset_to_cleanliness (snd_wave + + hwv[0] = wavefront_read(dev); + if (hwv[0] == -1) { +- snd_printk ("on-board RAM test failed " +- "(bad error code).\n"); ++ dev_err(dev->card->dev, ++ "on-board RAM test failed (bad error code).\n"); + } else { +- snd_printk ("on-board RAM test failed " +- "(error code: 0x%x).\n", ++ dev_err(dev->card->dev, ++ "on-board RAM test failed (error code: 0x%x).\n", + hwv[0]); + } + goto gone_bad; +@@ -1946,12 +1947,12 @@ wavefront_reset_to_cleanliness (snd_wave + + hwv[1] = wavefront_read(dev); + if (hwv[1] == -1) { +- snd_printk ("incorrect h/w response.\n"); ++ dev_err(dev->card->dev, "incorrect h/w response.\n"); + goto gone_bad; + } + +- snd_printk ("hardware version %d.%d\n", +- hwv[0], hwv[1]); ++ dev_info(dev->card->dev, "hardware version %d.%d\n", ++ hwv[0], hwv[1]); + + return 0; + +@@ -1971,7 +1972,7 @@ wavefront_download_firmware (snd_wavefro + + err = request_firmware(&firmware, path, dev->card->dev); + if (err < 0) { +- snd_printk(KERN_ERR "firmware (%s) download failed!!!\n", path); ++ dev_err(dev->card->dev, "firmware (%s) download failed!!!\n", path); + return 1; + } + +@@ -1982,16 +1983,16 @@ wavefront_download_firmware (snd_wavefro + if (section_length == 0) + break; + if (section_length < 0 || section_length > WF_SECTION_MAX) { +- snd_printk(KERN_ERR +- "invalid firmware section length %d\n", +- section_length); ++ dev_err(dev->card->dev, ++ "invalid firmware section length %d\n", ++ section_length); + goto failure; + } + buf++; + len++; + + if (firmware->size < len + section_length) { +- snd_printk(KERN_ERR "firmware section read error.\n"); ++ dev_err(dev->card->dev, "firmware section read error.\n"); + goto failure; + } + +@@ -2008,15 +2009,14 @@ wavefront_download_firmware (snd_wavefro + + /* get ACK */ + if (!wavefront_wait(dev, STAT_CAN_READ)) { +- snd_printk(KERN_ERR "time out for firmware ACK.\n"); ++ dev_err(dev->card->dev, "time out for firmware ACK.\n"); + goto failure; + } + err = inb(dev->data_port); + if (err != WF_ACK) { +- snd_printk(KERN_ERR +- "download of section #%d not " +- "acknowledged, ack = 0x%x\n", +- section_cnt_downloaded + 1, err); ++ dev_err(dev->card->dev, ++ "download of section #%d not acknowledged, ack = 0x%x\n", ++ section_cnt_downloaded + 1, err); + goto failure; + } + +@@ -2028,7 +2028,7 @@ wavefront_download_firmware (snd_wavefro + + failure: + release_firmware(firmware); +- snd_printk(KERN_ERR "firmware download failed!!!\n"); ++ dev_err(dev->card->dev, "firmware download failed!!!\n"); + return 1; + } + +@@ -2040,7 +2040,7 @@ wavefront_do_reset (snd_wavefront_t *dev + char voices[1]; + + if (wavefront_reset_to_cleanliness (dev)) { +- snd_printk ("hw reset failed.\n"); ++ dev_err(dev->card->dev, "hw reset failed.\n"); + goto gone_bad; + } + +@@ -2064,7 +2064,7 @@ wavefront_do_reset (snd_wavefront_t *dev + (osrun_time*HZ)); + + if (!dev->irq_ok) { +- snd_printk ("no post-OS interrupt.\n"); ++ dev_err(dev->card->dev, "no post-OS interrupt.\n"); + goto gone_bad; + } + +@@ -2074,7 +2074,7 @@ wavefront_do_reset (snd_wavefront_t *dev + dev->data_port, (10*HZ)); + + if (!dev->irq_ok) { +- snd_printk ("no post-OS interrupt(2).\n"); ++ dev_err(dev->card->dev, "no post-OS interrupt(2).\n"); + goto gone_bad; + } + +@@ -2094,20 +2094,20 @@ wavefront_do_reset (snd_wavefront_t *dev + if (dev->freemem < 0) + goto gone_bad; + +- snd_printk ("available DRAM %dk\n", dev->freemem / 1024); ++ dev_info(dev->card->dev, "available DRAM %dk\n", dev->freemem / 1024); + + if (wavefront_write (dev, 0xf0) || + wavefront_write (dev, 1) || + (wavefront_read (dev) < 0)) { + dev->debug = 0; +- snd_printk ("MPU emulation mode not set.\n"); ++ dev_err(dev->card->dev, "MPU emulation mode not set.\n"); + goto gone_bad; + } + + voices[0] = 32; + + if (snd_wavefront_cmd (dev, WFC_SET_NVOICES, NULL, voices)) { +- snd_printk ("cannot set number of voices to 32.\n"); ++ dev_err(dev->card->dev, "cannot set number of voices to 32.\n"); + goto gone_bad; + } + +@@ -2187,8 +2187,8 @@ snd_wavefront_detect (snd_wavefront_card + dev->fw_version[0] = rbuf[0]; + dev->fw_version[1] = rbuf[1]; + +- snd_printk ("firmware %d.%d already loaded.\n", +- rbuf[0], rbuf[1]); ++ dev_info(dev->card->dev, "firmware %d.%d already loaded.\n", ++ rbuf[0], rbuf[1]); + + /* check that a command actually works */ + +@@ -2197,22 +2197,24 @@ snd_wavefront_detect (snd_wavefront_card + dev->hw_version[0] = rbuf[0]; + dev->hw_version[1] = rbuf[1]; + } else { +- snd_printk ("not raw, but no " +- "hardware version!\n"); ++ dev_err(dev->card->dev, ++ "not raw, but no hardware version!\n"); + return -1; + } + + if (!wf_raw) { + return 0; + } else { +- snd_printk ("reloading firmware as you requested.\n"); ++ dev_info(dev->card->dev, ++ "reloading firmware as you requested.\n"); + dev->israw = 1; + } + + } else { + + dev->israw = 1; +- snd_printk ("no response to firmware probe, assume raw.\n"); ++ dev_info(dev->card->dev, ++ "no response to firmware probe, assume raw.\n"); + + } + diff --git a/queue-6.6/arm-dts-microchip-sama7g5-fix-uart-fifo-size-to-32.patch b/queue-6.6/arm-dts-microchip-sama7g5-fix-uart-fifo-size-to-32.patch new file mode 100644 index 0000000000..b7bb96bea1 --- /dev/null +++ b/queue-6.6/arm-dts-microchip-sama7g5-fix-uart-fifo-size-to-32.patch @@ -0,0 +1,46 @@ +From stable+bounces-204390-greg=kroah.com@vger.kernel.org Wed Dec 31 22:20:43 2025 +From: Sasha Levin +Date: Wed, 31 Dec 2025 16:20:37 -0500 +Subject: ARM: dts: microchip: sama7g5: fix uart fifo size to 32 +To: stable@vger.kernel.org +Cc: Nicolas Ferre , Claudiu Beznea , Sasha Levin +Message-ID: <20251231212037.3504979-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/microchip/sama7g5.dtsi | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/arch/arm/boot/dts/microchip/sama7g5.dtsi ++++ b/arch/arm/boot/dts/microchip/sama7g5.dtsi +@@ -811,7 +811,7 @@ + dma-names = "tx", "rx"; + atmel,use-dma-rx; + atmel,use-dma-tx; +- atmel,fifo-size = <16>; ++ atmel,fifo-size = <32>; + status = "disabled"; + }; + }; +@@ -837,7 +837,7 @@ + dma-names = "tx", "rx"; + atmel,use-dma-rx; + atmel,use-dma-tx; +- atmel,fifo-size = <16>; ++ atmel,fifo-size = <32>; + status = "disabled"; + }; + }; diff --git a/queue-6.6/btrfs-don-t-rewrite-ret-from-inode_permission.patch b/queue-6.6/btrfs-don-t-rewrite-ret-from-inode_permission.patch new file mode 100644 index 0000000000..7e60a05e36 --- /dev/null +++ b/queue-6.6/btrfs-don-t-rewrite-ret-from-inode_permission.patch @@ -0,0 +1,51 @@ +From stable+bounces-204139-greg=kroah.com@vger.kernel.org Mon Dec 29 22:51:55 2025 +From: Sasha Levin +Date: Mon, 29 Dec 2025 16:51:49 -0500 +Subject: btrfs: don't rewrite ret from inode_permission +To: stable@vger.kernel.org +Cc: Josef Bacik , Johannes Thumshirn , Daniel Vacek , David Sterba , Sasha Levin +Message-ID: <20251229215149.1729676-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 +@@ -2006,10 +2006,8 @@ static int btrfs_search_path_in_tree_use + ret = inode_permission(idmap, temp_inode, + MAY_READ | MAY_EXEC); + iput(temp_inode); +- if (ret) { +- ret = -EACCES; ++ if (ret) + goto out_put; +- } + + if (key.offset == upper_limit.objectid) + break; diff --git a/queue-6.6/drm-amd-display-fix-null-pointer-deref-in-dcn20_resource.c.patch b/queue-6.6/drm-amd-display-fix-null-pointer-deref-in-dcn20_resource.c.patch new file mode 100644 index 0000000000..9ee5be79a4 --- /dev/null +++ b/queue-6.6/drm-amd-display-fix-null-pointer-deref-in-dcn20_resource.c.patch @@ -0,0 +1,82 @@ +From david.nystrom@est.tech Wed Jan 7 11:15:51 2026 +From: "David Nyström" +Date: Wed, 07 Jan 2026 11:15:26 +0100 +Subject: drm/amd/display: Fix null pointer deref in dcn20_resource.c +To: stable@vger.kernel.org +Cc: "Aurabindo Pillai" , "Sasha Levin" , "Greg Kroah-Hartman" , "Alex Deucher" , "Rodrigo Siqueira" , "David Nyström" +Message-ID: <20260107-null_pointer-v1-1-7443ed011f10@est.tech> + +From: Aurabindo Pillai + +[ Upstream commit ecbf60782662f0a388493685b85a645a0ba1613c ] + +Fixes a hang thats triggered when MPV is run on a DCN401 dGPU: + +mpv --hwdec=vaapi --vo=gpu --hwdec-codecs=all + +and then enabling fullscreen playback (double click on the video) + +The following calltrace will be seen: + +[ 181.843989] BUG: kernel NULL pointer dereference, address: 0000000000000000 +[ 181.843997] #PF: supervisor instruction fetch in kernel mode +[ 181.844003] #PF: error_code(0x0010) - not-present page +[ 181.844009] PGD 0 P4D 0 +[ 181.844020] Oops: 0010 [#1] PREEMPT SMP NOPTI +[ 181.844028] CPU: 6 PID: 1892 Comm: gnome-shell Tainted: G W OE 6.5.0-41-generic #41~22.04.2-Ubuntu +[ 181.844038] Hardware name: System manufacturer System Product Name/CROSSHAIR VI HERO, BIOS 6302 10/23/2018 +[ 181.844044] RIP: 0010:0x0 +[ 181.844079] Code: Unable to access opcode bytes at 0xffffffffffffffd6. +[ 181.844084] RSP: 0018:ffffb593c2b8f7b0 EFLAGS: 00010246 +[ 181.844093] RAX: 0000000000000000 RBX: 0000000000000000 RCX: 0000000000000004 +[ 181.844099] RDX: ffffb593c2b8f804 RSI: ffffb593c2b8f7e0 RDI: ffff9e3c8e758400 +[ 181.844105] RBP: ffffb593c2b8f7b8 R08: ffffb593c2b8f9c8 R09: ffffb593c2b8f96c +[ 181.844110] R10: 0000000000000000 R11: 0000000000000000 R12: ffffb593c2b8f9c8 +[ 181.844115] R13: 0000000000000001 R14: ffff9e3c88000000 R15: 0000000000000005 +[ 181.844121] FS: 00007c6e323bb5c0(0000) GS:ffff9e3f85f80000(0000) knlGS:0000000000000000 +[ 181.844128] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 +[ 181.844134] CR2: ffffffffffffffd6 CR3: 0000000140fbe000 CR4: 00000000003506e0 +[ 181.844141] Call Trace: +[ 181.844146] +[ 181.844153] ? show_regs+0x6d/0x80 +[ 181.844167] ? __die+0x24/0x80 +[ 181.844179] ? page_fault_oops+0x99/0x1b0 +[ 181.844192] ? do_user_addr_fault+0x31d/0x6b0 +[ 181.844204] ? exc_page_fault+0x83/0x1b0 +[ 181.844216] ? asm_exc_page_fault+0x27/0x30 +[ 181.844237] dcn20_get_dcc_compression_cap+0x23/0x30 [amdgpu] +[ 181.845115] amdgpu_dm_plane_validate_dcc.constprop.0+0xe5/0x180 [amdgpu] +[ 181.845985] amdgpu_dm_plane_fill_plane_buffer_attributes+0x300/0x580 [amdgpu] +[ 181.846848] fill_dc_plane_info_and_addr+0x258/0x350 [amdgpu] +[ 181.847734] fill_dc_plane_attributes+0x162/0x350 [amdgpu] +[ 181.848748] dm_update_plane_state.constprop.0+0x4e3/0x6b0 [amdgpu] +[ 181.849791] ? dm_update_plane_state.constprop.0+0x4e3/0x6b0 [amdgpu] +[ 181.850840] amdgpu_dm_atomic_check+0xdfe/0x1760 [amdgpu] + +Signed-off-by: Aurabindo Pillai +Reviewed-by: Rodrigo Siqueira +Signed-off-by: Alex Deucher +Signed-off-by: David Nyström +Signed-off-by: Greg Kroah-Hartman +--- + drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c | 9 +++++---- + 1 file changed, 5 insertions(+), 4 deletions(-) + +--- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c ++++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c +@@ -2179,10 +2179,11 @@ bool dcn20_get_dcc_compression_cap(const + const struct dc_dcc_surface_param *input, + struct dc_surface_dcc_cap *output) + { +- return dc->res_pool->hubbub->funcs->get_dcc_compression_cap( +- dc->res_pool->hubbub, +- input, +- output); ++ if (dc->res_pool->hubbub->funcs->get_dcc_compression_cap) ++ return dc->res_pool->hubbub->funcs->get_dcc_compression_cap( ++ dc->res_pool->hubbub, input, output); ++ ++ return false; + } + + static void dcn20_destroy_resource_pool(struct resource_pool **pool) diff --git a/queue-6.6/drm-amdgpu-forward-vmid-reservation-errors.patch b/queue-6.6/drm-amdgpu-forward-vmid-reservation-errors.patch new file mode 100644 index 0000000000..846216923f --- /dev/null +++ b/queue-6.6/drm-amdgpu-forward-vmid-reservation-errors.patch @@ -0,0 +1,45 @@ +From stable+bounces-206132-greg=kroah.com@vger.kernel.org Wed Jan 7 13:00:07 2026 +From: Sasha Levin +Date: Wed, 7 Jan 2026 06:54:14 -0500 +Subject: drm/amdgpu: Forward VMID reservation errors +To: stable@vger.kernel.org +Cc: "Natalie Vock" , "Christian König" , "Alex Deucher" , "Sasha Levin" +Message-ID: <20260107115414.3985195-1-sashal@kernel.org> + +From: Natalie Vock + +[ Upstream commit 8defb4f081a5feccc3ea8372d0c7af3522124e1f ] + +Otherwise userspace may be fooled into believing it has a reserved VMID +when in reality it doesn't, ultimately leading to GPU hangs when SPM is +used. + +Fixes: 80e709ee6ecc ("drm/amdgpu: add option params to enforce process isolation between graphics and compute") +Cc: stable@vger.kernel.org +Reviewed-by: Christian König +Signed-off-by: Natalie Vock +Signed-off-by: Alex Deucher +[ adapted 3-argument amdgpu_vmid_alloc_reserved(adev, vm, vmhub) call to 2-argument version and added separate error check to preserve reserved_vmid tracking logic. ] +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c +@@ -2496,10 +2496,12 @@ int amdgpu_vm_ioctl(struct drm_device *d + case AMDGPU_VM_OP_RESERVE_VMID: + /* We only have requirement to reserve vmid from gfxhub */ + if (!fpriv->vm.reserved_vmid[AMDGPU_GFXHUB(0)]) { +- amdgpu_vmid_alloc_reserved(adev, AMDGPU_GFXHUB(0)); ++ int r = amdgpu_vmid_alloc_reserved(adev, AMDGPU_GFXHUB(0)); ++ ++ if (r) ++ return r; + fpriv->vm.reserved_vmid[AMDGPU_GFXHUB(0)] = true; + } +- + break; + case AMDGPU_VM_OP_UNRESERVE_VMID: + if (fpriv->vm.reserved_vmid[AMDGPU_GFXHUB(0)]) { diff --git a/queue-6.6/drm-mediatek-fix-probe-memory-leak.patch b/queue-6.6/drm-mediatek-fix-probe-memory-leak.patch new file mode 100644 index 0000000000..db26c76050 --- /dev/null +++ b/queue-6.6/drm-mediatek-fix-probe-memory-leak.patch @@ -0,0 +1,44 @@ +From stable+bounces-206138-greg=kroah.com@vger.kernel.org Wed Jan 7 13:07:19 2026 +From: Sasha Levin +Date: Wed, 7 Jan 2026 07:07:09 -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: <20260107120710.3990944-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 +@@ -588,7 +588,7 @@ int mtk_ddp_comp_init(struct device_node + type == MTK_DSI) + return 0; + +- priv = devm_kzalloc(comp->dev, sizeof(*priv), GFP_KERNEL); ++ priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + diff --git a/queue-6.6/drm-mediatek-fix-probe-resource-leaks.patch b/queue-6.6/drm-mediatek-fix-probe-resource-leaks.patch new file mode 100644 index 0000000000..1db1572771 --- /dev/null +++ b/queue-6.6/drm-mediatek-fix-probe-resource-leaks.patch @@ -0,0 +1,110 @@ +From stable+bounces-206158-greg=kroah.com@vger.kernel.org Wed Jan 7 17:10:32 2026 +From: Sasha Levin +Date: Wed, 7 Jan 2026 10:47:23 -0500 +Subject: drm/mediatek: Fix probe resource leaks +To: stable@vger.kernel.org +Cc: Johan Hovold , CK Hu , AngeloGioacchino Del Regno , Chun-Kuang Hu , Sasha Levin +Message-ID: <20260107154724.4055170-1-sashal@kernel.org> + +From: Johan Hovold + +[ Upstream commit 07c7c640a8eb9e196f357d15d88a59602a947197 ] + +Make sure to unmap and release the component iomap and clock on probe +failure (e.g. probe deferral) and on driver unbind. + +Note that unlike of_iomap(), devm_of_iomap() also checks whether the +region is already mapped. + +Fixes: 119f5173628a ("drm/mediatek: Add DRM Driver for Mediatek SoC MT8173.") +Cc: stable@vger.kernel.org # 4.7 +Cc: CK Hu +Signed-off-by: Johan Hovold +Reviewed-by: AngeloGioacchino Del Regno +Link: https://patchwork.kernel.org/project/dri-devel/patch/20250923152340.18234-2-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 | 20 ++++++++++++++++---- + drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.h | 2 +- + drivers/gpu/drm/mediatek/mtk_drm_drv.c | 4 ++-- + 3 files changed, 19 insertions(+), 7 deletions(-) + +--- a/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c ++++ b/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c +@@ -543,15 +543,20 @@ unsigned int mtk_drm_find_possible_crtc_ + return ret; + } + +-int mtk_ddp_comp_init(struct device_node *node, struct mtk_ddp_comp *comp, ++static void mtk_ddp_comp_clk_put(void *_clk) ++{ ++ struct clk *clk = _clk; ++ ++ clk_put(clk); ++} ++ ++int mtk_ddp_comp_init(struct device *dev, struct device_node *node, struct mtk_ddp_comp *comp, + unsigned int comp_id) + { + struct platform_device *comp_pdev; + enum mtk_ddp_comp_type type; + struct mtk_ddp_comp_dev *priv; +-#if IS_REACHABLE(CONFIG_MTK_CMDQ) + int ret; +-#endif + + if (comp_id >= DDP_COMPONENT_DRM_ID_MAX) + return -EINVAL; +@@ -592,11 +597,18 @@ int mtk_ddp_comp_init(struct device_node + if (!priv) + return -ENOMEM; + +- priv->regs = of_iomap(node, 0); ++ priv->regs = devm_of_iomap(dev, node, 0, NULL); ++ if (IS_ERR(priv->regs)) ++ return PTR_ERR(priv->regs); ++ + priv->clk = of_clk_get(node, 0); + if (IS_ERR(priv->clk)) + return PTR_ERR(priv->clk); + ++ ret = devm_add_action_or_reset(dev, mtk_ddp_comp_clk_put, priv->clk); ++ if (ret) ++ return ret; ++ + #if IS_REACHABLE(CONFIG_MTK_CMDQ) + ret = cmdq_dev_get_client_reg(comp->dev, &priv->cmdq_reg, 0); + if (ret) +--- a/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.h ++++ b/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.h +@@ -279,7 +279,7 @@ int mtk_ddp_comp_get_id(struct device_no + enum mtk_ddp_comp_type comp_type); + unsigned int mtk_drm_find_possible_crtc_by_comp(struct drm_device *drm, + struct device *dev); +-int mtk_ddp_comp_init(struct device_node *comp_node, struct mtk_ddp_comp *comp, ++int mtk_ddp_comp_init(struct device *dev, struct device_node *comp_node, struct mtk_ddp_comp *comp, + unsigned int comp_id); + enum mtk_ddp_comp_type mtk_ddp_comp_get_type(unsigned int comp_id); + void mtk_ddp_write(struct cmdq_pkt *cmdq_pkt, unsigned int value, +--- a/drivers/gpu/drm/mediatek/mtk_drm_drv.c ++++ b/drivers/gpu/drm/mediatek/mtk_drm_drv.c +@@ -841,7 +841,7 @@ static int mtk_drm_probe(struct platform + (void *)private->mmsys_dev, + sizeof(*private->mmsys_dev)); + private->ddp_comp[DDP_COMPONENT_DRM_OVL_ADAPTOR].dev = &ovl_adaptor->dev; +- mtk_ddp_comp_init(NULL, &private->ddp_comp[DDP_COMPONENT_DRM_OVL_ADAPTOR], ++ mtk_ddp_comp_init(dev, NULL, &private->ddp_comp[DDP_COMPONENT_DRM_OVL_ADAPTOR], + DDP_COMPONENT_DRM_OVL_ADAPTOR); + component_match_add(dev, &match, compare_dev, &ovl_adaptor->dev); + } +@@ -910,7 +910,7 @@ static int mtk_drm_probe(struct platform + node); + } + +- ret = mtk_ddp_comp_init(node, &private->ddp_comp[comp_id], comp_id); ++ ret = mtk_ddp_comp_init(dev, node, &private->ddp_comp[comp_id], comp_id); + if (ret) { + of_node_put(node); + goto err_node; diff --git a/queue-6.6/drm-tilcdc-fix-removal-actions-in-case-of-failed-probe.patch b/queue-6.6/drm-tilcdc-fix-removal-actions-in-case-of-failed-probe.patch new file mode 100644 index 0000000000..7cf4ece9e3 --- /dev/null +++ b/queue-6.6/drm-tilcdc-fix-removal-actions-in-case-of-failed-probe.patch @@ -0,0 +1,213 @@ +From stable+bounces-206180-greg=kroah.com@vger.kernel.org Wed Jan 7 18:13:19 2026 +From: Sasha Levin +Date: Wed, 7 Jan 2026 11:14:08 -0500 +Subject: drm/tilcdc: Fix removal actions in case of failed probe +To: stable@vger.kernel.org +Cc: "Kory Maincent (TI.com)" , Douglas Anderson , Luca Ceresoli , Sasha Levin +Message-ID: <20260107161408.4074126-2-sashal@kernel.org> + +From: "Kory Maincent (TI.com)" + +[ Upstream commit a585c7ef9cabda58088916baedc6573e9a5cd2a7 ] + +The drm_kms_helper_poll_fini() and drm_atomic_helper_shutdown() helpers +should only be called when the device has been successfully registered. +Currently, these functions are called unconditionally in tilcdc_fini(), +which causes warnings during probe deferral scenarios. + +[ 7.972317] WARNING: CPU: 0 PID: 23 at drivers/gpu/drm/drm_atomic_state_helper.c:175 drm_atomic_helper_crtc_duplicate_state+0x60/0x68 +... +[ 8.005820] drm_atomic_helper_crtc_duplicate_state from drm_atomic_get_crtc_state+0x68/0x108 +[ 8.005858] drm_atomic_get_crtc_state from drm_atomic_helper_disable_all+0x90/0x1c8 +[ 8.005885] drm_atomic_helper_disable_all from drm_atomic_helper_shutdown+0x90/0x144 +[ 8.005911] drm_atomic_helper_shutdown from tilcdc_fini+0x68/0xf8 [tilcdc] +[ 8.005957] tilcdc_fini [tilcdc] from tilcdc_pdev_probe+0xb0/0x6d4 [tilcdc] + +Fix this by rewriting the failed probe cleanup path using the standard +goto error handling pattern, which ensures that cleanup functions are +only called on successfully initialized resources. Additionally, remove +the now-unnecessary is_registered flag. + +Cc: stable@vger.kernel.org +Fixes: 3c4babae3c4a ("drm: Call drm_atomic_helper_shutdown() at shutdown/remove time for misc drivers") +Signed-off-by: Kory Maincent (TI.com) +Reviewed-by: Douglas Anderson +Reviewed-by: Luca Ceresoli +Signed-off-by: Douglas Anderson +Link: https://patch.msgid.link/20251125090546.137193-1-kory.maincent@bootlin.com +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + drivers/gpu/drm/tilcdc/tilcdc_crtc.c | 2 - + drivers/gpu/drm/tilcdc/tilcdc_drv.c | 53 +++++++++++++++++++++++------------ + drivers/gpu/drm/tilcdc/tilcdc_drv.h | 2 - + 3 files changed, 37 insertions(+), 20 deletions(-) + +--- a/drivers/gpu/drm/tilcdc/tilcdc_crtc.c ++++ b/drivers/gpu/drm/tilcdc/tilcdc_crtc.c +@@ -586,7 +586,7 @@ out: + drm_modeset_unlock(&crtc->mutex); + } + +-static void tilcdc_crtc_destroy(struct drm_crtc *crtc) ++void tilcdc_crtc_destroy(struct drm_crtc *crtc) + { + struct tilcdc_drm_private *priv = crtc->dev->dev_private; + +--- a/drivers/gpu/drm/tilcdc/tilcdc_drv.c ++++ b/drivers/gpu/drm/tilcdc/tilcdc_drv.c +@@ -171,8 +171,7 @@ static void tilcdc_fini(struct drm_devic + if (priv->crtc) + tilcdc_crtc_shutdown(priv->crtc); + +- if (priv->is_registered) +- drm_dev_unregister(dev); ++ drm_dev_unregister(dev); + + drm_kms_helper_poll_fini(dev); + drm_atomic_helper_shutdown(dev); +@@ -219,21 +218,21 @@ static int tilcdc_init(const struct drm_ + priv->wq = alloc_ordered_workqueue("tilcdc", 0); + if (!priv->wq) { + ret = -ENOMEM; +- goto init_failed; ++ goto put_drm; + } + + priv->mmio = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(priv->mmio)) { + dev_err(dev, "failed to request / ioremap\n"); + ret = PTR_ERR(priv->mmio); +- goto init_failed; ++ goto free_wq; + } + + priv->clk = clk_get(dev, "fck"); + if (IS_ERR(priv->clk)) { + dev_err(dev, "failed to get functional clock\n"); + ret = -ENODEV; +- goto init_failed; ++ goto free_wq; + } + + pm_runtime_enable(dev); +@@ -312,7 +311,7 @@ static int tilcdc_init(const struct drm_ + ret = tilcdc_crtc_create(ddev); + if (ret < 0) { + dev_err(dev, "failed to create crtc\n"); +- goto init_failed; ++ goto disable_pm; + } + modeset_init(ddev); + +@@ -323,46 +322,46 @@ static int tilcdc_init(const struct drm_ + if (ret) { + dev_err(dev, "failed to register cpufreq notifier\n"); + priv->freq_transition.notifier_call = NULL; +- goto init_failed; ++ goto destroy_crtc; + } + #endif + + if (priv->is_componentized) { + ret = component_bind_all(dev, ddev); + if (ret < 0) +- goto init_failed; ++ goto unregister_cpufreq_notif; + + ret = tilcdc_add_component_encoder(ddev); + if (ret < 0) +- goto init_failed; ++ goto unbind_component; + } else { + ret = tilcdc_attach_external_device(ddev); + if (ret) +- goto init_failed; ++ goto unregister_cpufreq_notif; + } + + if (!priv->external_connector && + ((priv->num_encoders == 0) || (priv->num_connectors == 0))) { + dev_err(dev, "no encoders/connectors found\n"); + ret = -EPROBE_DEFER; +- goto init_failed; ++ goto unbind_component; + } + + ret = drm_vblank_init(ddev, 1); + if (ret < 0) { + dev_err(dev, "failed to initialize vblank\n"); +- goto init_failed; ++ goto unbind_component; + } + + ret = platform_get_irq(pdev, 0); + if (ret < 0) +- goto init_failed; ++ goto unbind_component; + priv->irq = ret; + + ret = tilcdc_irq_install(ddev, priv->irq); + if (ret < 0) { + dev_err(dev, "failed to install IRQ handler\n"); +- goto init_failed; ++ goto unbind_component; + } + + drm_mode_config_reset(ddev); +@@ -371,15 +370,33 @@ static int tilcdc_init(const struct drm_ + + ret = drm_dev_register(ddev, 0); + if (ret) +- goto init_failed; +- priv->is_registered = true; ++ goto stop_poll; + + drm_fbdev_dma_setup(ddev, bpp); + return 0; + +-init_failed: +- tilcdc_fini(ddev); ++stop_poll: ++ drm_kms_helper_poll_fini(ddev); ++ tilcdc_irq_uninstall(ddev); ++unbind_component: ++ if (priv->is_componentized) ++ component_unbind_all(dev, ddev); ++unregister_cpufreq_notif: ++#ifdef CONFIG_CPU_FREQ ++ cpufreq_unregister_notifier(&priv->freq_transition, ++ CPUFREQ_TRANSITION_NOTIFIER); ++destroy_crtc: ++#endif ++ tilcdc_crtc_destroy(priv->crtc); ++disable_pm: ++ pm_runtime_disable(dev); ++ clk_put(priv->clk); ++free_wq: ++ destroy_workqueue(priv->wq); ++put_drm: + platform_set_drvdata(pdev, NULL); ++ ddev->dev_private = NULL; ++ drm_dev_put(ddev); + + return ret; + } +--- a/drivers/gpu/drm/tilcdc/tilcdc_drv.h ++++ b/drivers/gpu/drm/tilcdc/tilcdc_drv.h +@@ -82,7 +82,6 @@ struct tilcdc_drm_private { + struct drm_encoder *external_encoder; + struct drm_connector *external_connector; + +- bool is_registered; + bool is_componentized; + bool irq_enabled; + }; +@@ -164,6 +163,7 @@ void tilcdc_crtc_set_panel_info(struct d + void tilcdc_crtc_set_simulate_vesa_sync(struct drm_crtc *crtc, + bool simulate_vesa_sync); + void tilcdc_crtc_shutdown(struct drm_crtc *crtc); ++void tilcdc_crtc_destroy(struct drm_crtc *crtc); + int tilcdc_crtc_update_fb(struct drm_crtc *crtc, + struct drm_framebuffer *fb, + struct drm_pending_vblank_event *event); diff --git a/queue-6.6/drm-tilcdc-request-and-mapp-iomem-with-devres.patch b/queue-6.6/drm-tilcdc-request-and-mapp-iomem-with-devres.patch new file mode 100644 index 0000000000..322e1cb37e --- /dev/null +++ b/queue-6.6/drm-tilcdc-request-and-mapp-iomem-with-devres.patch @@ -0,0 +1,73 @@ +From stable+bounces-206181-greg=kroah.com@vger.kernel.org Wed Jan 7 18:13:19 2026 +From: Sasha Levin +Date: Wed, 7 Jan 2026 11:14:07 -0500 +Subject: drm/tilcdc: request and mapp iomem with devres +To: stable@vger.kernel.org +Cc: Philipp Stanner , Thomas Zimmermann , Jyri Sarha , Sasha Levin +Message-ID: <20260107161408.4074126-1-sashal@kernel.org> + +From: Philipp Stanner + +[ Upstream commit a196a5166e0812db267281c32fa0724fc5be6582 ] + +tilcdc currently just ioremaps its iomem, without doing the (a bit more +robust) request on the memory first. The devm_ functions provide a handy +way to both request and ioremap the memory with automatic cleanup. + +Replace the manual ioremap with the devm_ version. + +Suggested-by: Thomas Zimmermann +Signed-off-by: Philipp Stanner +Reviewed-by: Jyri Sarha +Tested-by: Jyri Sarha +Signed-off-by: Jyri Sarha +Link: https://patchwork.freedesktop.org/patch/msgid/20231222115216.19218-2-pstanner@redhat.com +Stable-dep-of: a585c7ef9cab ("drm/tilcdc: Fix removal actions in case of failed probe") +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + drivers/gpu/drm/tilcdc/tilcdc_drv.c | 19 ++++--------------- + 1 file changed, 4 insertions(+), 15 deletions(-) + +--- a/drivers/gpu/drm/tilcdc/tilcdc_drv.c ++++ b/drivers/gpu/drm/tilcdc/tilcdc_drv.c +@@ -182,9 +182,6 @@ static void tilcdc_fini(struct drm_devic + if (priv->clk) + clk_put(priv->clk); + +- if (priv->mmio) +- iounmap(priv->mmio); +- + if (priv->wq) + destroy_workqueue(priv->wq); + +@@ -201,7 +198,6 @@ static int tilcdc_init(const struct drm_ + struct platform_device *pdev = to_platform_device(dev); + struct device_node *node = dev->of_node; + struct tilcdc_drm_private *priv; +- struct resource *res; + u32 bpp = 0; + int ret; + +@@ -226,17 +222,10 @@ static int tilcdc_init(const struct drm_ + goto init_failed; + } + +- res = platform_get_resource(pdev, IORESOURCE_MEM, 0); +- if (!res) { +- dev_err(dev, "failed to get memory resource\n"); +- ret = -EINVAL; +- goto init_failed; +- } +- +- priv->mmio = ioremap(res->start, resource_size(res)); +- if (!priv->mmio) { +- dev_err(dev, "failed to ioremap\n"); +- ret = -ENOMEM; ++ priv->mmio = devm_platform_ioremap_resource(pdev, 0); ++ if (IS_ERR(priv->mmio)) { ++ dev_err(dev, "failed to request / ioremap\n"); ++ ret = PTR_ERR(priv->mmio); + goto init_failed; + } + diff --git a/queue-6.6/ext4-fix-string-copying-in-parse_apply_sb_mount_options.patch b/queue-6.6/ext4-fix-string-copying-in-parse_apply_sb_mount_options.patch new file mode 100644 index 0000000000..bd3b66bd22 --- /dev/null +++ b/queue-6.6/ext4-fix-string-copying-in-parse_apply_sb_mount_options.patch @@ -0,0 +1,86 @@ +From stable+bounces-204160-greg=kroah.com@vger.kernel.org Tue Dec 30 01:47:33 2025 +From: Sasha Levin +Date: Mon, 29 Dec 2025 19:47:24 -0500 +Subject: ext4: fix string copying in parse_apply_sb_mount_options() +To: stable@vger.kernel.org +Cc: Fedor Pchelkin , Baokun Li , Jan Kara , Theodore Ts'o , Sasha Levin +Message-ID: <20251230004724.1896388-1-sashal@kernel.org> + +From: Fedor Pchelkin + +[ Upstream commit ee5a977b4e771cc181f39d504426dbd31ed701cc ] + +strscpy_pad() can't be used to copy a non-NUL-term string into a NUL-term +string of possibly bigger size. Commit 0efc5990bca5 ("string.h: Introduce +memtostr() and memtostr_pad()") provides additional information in that +regard. So if this happens, the following warning is observed: + +strnlen: detected buffer overflow: 65 byte read of buffer size 64 +WARNING: CPU: 0 PID: 28655 at lib/string_helpers.c:1032 __fortify_report+0x96/0xc0 lib/string_helpers.c:1032 +Modules linked in: +CPU: 0 UID: 0 PID: 28655 Comm: syz-executor.3 Not tainted 6.12.54-syzkaller-00144-g5f0270f1ba00 #0 +Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.16.3-debian-1.16.3-2 04/01/2014 +RIP: 0010:__fortify_report+0x96/0xc0 lib/string_helpers.c:1032 +Call Trace: + + __fortify_panic+0x1f/0x30 lib/string_helpers.c:1039 + strnlen include/linux/fortify-string.h:235 [inline] + sized_strscpy include/linux/fortify-string.h:309 [inline] + parse_apply_sb_mount_options fs/ext4/super.c:2504 [inline] + __ext4_fill_super fs/ext4/super.c:5261 [inline] + ext4_fill_super+0x3c35/0xad00 fs/ext4/super.c:5706 + get_tree_bdev_flags+0x387/0x620 fs/super.c:1636 + vfs_get_tree+0x93/0x380 fs/super.c:1814 + do_new_mount fs/namespace.c:3553 [inline] + path_mount+0x6ae/0x1f70 fs/namespace.c:3880 + do_mount fs/namespace.c:3893 [inline] + __do_sys_mount fs/namespace.c:4103 [inline] + __se_sys_mount fs/namespace.c:4080 [inline] + __x64_sys_mount+0x280/0x300 fs/namespace.c:4080 + do_syscall_x64 arch/x86/entry/common.c:52 [inline] + do_syscall_64+0x64/0x140 arch/x86/entry/common.c:83 + entry_SYSCALL_64_after_hwframe+0x76/0x7e + +Since userspace is expected to provide s_mount_opts field to be at most 63 +characters long with the ending byte being NUL-term, use a 64-byte buffer +which matches the size of s_mount_opts, so that strscpy_pad() does its job +properly. Return with error if the user still managed to provide a +non-NUL-term string here. + +Found by Linux Verification Center (linuxtesting.org) with Syzkaller. + +Fixes: 8ecb790ea8c3 ("ext4: avoid potential buffer over-read in parse_apply_sb_mount_options()") +Cc: stable@vger.kernel.org +Signed-off-by: Fedor Pchelkin +Reviewed-by: Baokun Li +Reviewed-by: Jan Kara +Message-ID: <20251101160430.222297-1-pchelkin@ispras.ru> +Signed-off-by: Theodore Ts'o +[ adapted 2-argument strscpy_pad() call to 3-argument form with explicit sizeof() ] +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + fs/ext4/super.c | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +--- a/fs/ext4/super.c ++++ b/fs/ext4/super.c +@@ -2507,7 +2507,7 @@ static int parse_apply_sb_mount_options( + struct ext4_fs_context *m_ctx) + { + struct ext4_sb_info *sbi = EXT4_SB(sb); +- char s_mount_opts[65]; ++ char s_mount_opts[64]; + struct ext4_fs_context *s_ctx = NULL; + struct fs_context *fc = NULL; + int ret = -ENOMEM; +@@ -2515,7 +2515,8 @@ static int parse_apply_sb_mount_options( + if (!sbi->s_es->s_mount_opts[0]) + return 0; + +- strscpy_pad(s_mount_opts, sbi->s_es->s_mount_opts, sizeof(s_mount_opts)); ++ if (strscpy_pad(s_mount_opts, sbi->s_es->s_mount_opts, sizeof(s_mount_opts)) < 0) ++ return -E2BIG; + + fc = kzalloc(sizeof(struct fs_context), GFP_KERNEL); + if (!fc) diff --git a/queue-6.6/f2fs-fix-to-avoid-potential-deadlock.patch b/queue-6.6/f2fs-fix-to-avoid-potential-deadlock.patch new file mode 100644 index 0000000000..23f3c17968 --- /dev/null +++ b/queue-6.6/f2fs-fix-to-avoid-potential-deadlock.patch @@ -0,0 +1,221 @@ +From stable+bounces-204244-greg=kroah.com@vger.kernel.org Tue Dec 30 17:15:46 2025 +From: Sasha Levin +Date: Tue, 30 Dec 2025 11:15:39 -0500 +Subject: f2fs: fix to avoid potential deadlock +To: stable@vger.kernel.org +Cc: Chao Yu , stable@kernel.org, syzbot+14b90e1156b9f6fc1266@syzkaller.appspotmail.com, Jiaming Zhang , Jaegeuk Kim , Sasha Levin +Message-ID: <20251230161539.2301172-2-sashal@kernel.org> + +From: Chao Yu + +[ Upstream commit ca8b201f28547e28343a6f00a6e91fa8c09572fe ] + +As Jiaming Zhang and syzbot reported, there is potential deadlock in +f2fs as below: + +Chain exists of: + &sbi->cp_rwsem --> fs_reclaim --> sb_internal#2 + + Possible unsafe locking scenario: + + CPU0 CPU1 + ---- ---- + rlock(sb_internal#2); + lock(fs_reclaim); + lock(sb_internal#2); + rlock(&sbi->cp_rwsem); + + *** DEADLOCK *** + +3 locks held by kswapd0/73: + #0: ffffffff8e247a40 (fs_reclaim){+.+.}-{0:0}, at: balance_pgdat mm/vmscan.c:7015 [inline] + #0: ffffffff8e247a40 (fs_reclaim){+.+.}-{0:0}, at: kswapd+0x951/0x2800 mm/vmscan.c:7389 + #1: ffff8880118400e0 (&type->s_umount_key#50){.+.+}-{4:4}, at: super_trylock_shared fs/super.c:562 [inline] + #1: ffff8880118400e0 (&type->s_umount_key#50){.+.+}-{4:4}, at: super_cache_scan+0x91/0x4b0 fs/super.c:197 + #2: ffff888011840610 (sb_internal#2){.+.+}-{0:0}, at: f2fs_evict_inode+0x8d9/0x1b60 fs/f2fs/inode.c:890 + +stack backtrace: +CPU: 0 UID: 0 PID: 73 Comm: kswapd0 Not tainted syzkaller #0 PREEMPT(full) +Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 1.16.3-debian-1.16.3-2~bpo12+1 04/01/2014 +Call Trace: + + dump_stack_lvl+0x189/0x250 lib/dump_stack.c:120 + print_circular_bug+0x2ee/0x310 kernel/locking/lockdep.c:2043 + check_noncircular+0x134/0x160 kernel/locking/lockdep.c:2175 + check_prev_add kernel/locking/lockdep.c:3165 [inline] + check_prevs_add kernel/locking/lockdep.c:3284 [inline] + validate_chain+0xb9b/0x2140 kernel/locking/lockdep.c:3908 + __lock_acquire+0xab9/0xd20 kernel/locking/lockdep.c:5237 + lock_acquire+0x120/0x360 kernel/locking/lockdep.c:5868 + down_read+0x46/0x2e0 kernel/locking/rwsem.c:1537 + f2fs_down_read fs/f2fs/f2fs.h:2278 [inline] + f2fs_lock_op fs/f2fs/f2fs.h:2357 [inline] + f2fs_do_truncate_blocks+0x21c/0x10c0 fs/f2fs/file.c:791 + f2fs_truncate_blocks+0x10a/0x300 fs/f2fs/file.c:867 + f2fs_truncate+0x489/0x7c0 fs/f2fs/file.c:925 + f2fs_evict_inode+0x9f2/0x1b60 fs/f2fs/inode.c:897 + evict+0x504/0x9c0 fs/inode.c:810 + f2fs_evict_inode+0x1dc/0x1b60 fs/f2fs/inode.c:853 + evict+0x504/0x9c0 fs/inode.c:810 + dispose_list fs/inode.c:852 [inline] + prune_icache_sb+0x21b/0x2c0 fs/inode.c:1000 + super_cache_scan+0x39b/0x4b0 fs/super.c:224 + do_shrink_slab+0x6ef/0x1110 mm/shrinker.c:437 + shrink_slab_memcg mm/shrinker.c:550 [inline] + shrink_slab+0x7ef/0x10d0 mm/shrinker.c:628 + shrink_one+0x28a/0x7c0 mm/vmscan.c:4955 + shrink_many mm/vmscan.c:5016 [inline] + lru_gen_shrink_node mm/vmscan.c:5094 [inline] + shrink_node+0x315d/0x3780 mm/vmscan.c:6081 + kswapd_shrink_node mm/vmscan.c:6941 [inline] + balance_pgdat mm/vmscan.c:7124 [inline] + kswapd+0x147c/0x2800 mm/vmscan.c:7389 + kthread+0x70e/0x8a0 kernel/kthread.c:463 + ret_from_fork+0x4bc/0x870 arch/x86/kernel/process.c:158 + ret_from_fork_asm+0x1a/0x30 arch/x86/entry/entry_64.S:245 + + +The root cause is deadlock among four locks as below: + +kswapd +- fs_reclaim --- Lock A + - shrink_one + - evict + - f2fs_evict_inode + - sb_start_intwrite --- Lock B + +- iput + - evict + - f2fs_evict_inode + - sb_start_intwrite --- Lock B + - f2fs_truncate + - f2fs_truncate_blocks + - f2fs_do_truncate_blocks + - f2fs_lock_op --- Lock C + +ioctl +- f2fs_ioc_commit_atomic_write + - f2fs_lock_op --- Lock C + - __f2fs_commit_atomic_write + - __replace_atomic_write_block + - f2fs_get_dnode_of_data + - __get_node_folio + - f2fs_check_nid_range + - f2fs_handle_error + - f2fs_record_errors + - f2fs_down_write --- Lock D + +open +- do_open + - do_truncate + - security_inode_need_killpriv + - f2fs_getxattr + - lookup_all_xattrs + - f2fs_handle_error + - f2fs_record_errors + - f2fs_down_write --- Lock D + - f2fs_commit_super + - read_mapping_folio + - filemap_alloc_folio_noprof + - prepare_alloc_pages + - fs_reclaim_acquire --- Lock A + +In order to avoid such deadlock, we need to avoid grabbing sb_lock in +f2fs_handle_error(), so, let's use asynchronous method instead: +- remove f2fs_handle_error() implementation +- rename f2fs_handle_error_async() to f2fs_handle_error() +- spread f2fs_handle_error() + +Fixes: 95fa90c9e5a7 ("f2fs: support recording errors into superblock") +Cc: stable@kernel.org +Reported-by: syzbot+14b90e1156b9f6fc1266@syzkaller.appspotmail.com +Closes: https://lore.kernel.org/linux-f2fs-devel/68eae49b.050a0220.ac43.0001.GAE@google.com +Reported-by: Jiaming Zhang +Closes: https://lore.kernel.org/lkml/CANypQFa-Gy9sD-N35o3PC+FystOWkNuN8pv6S75HLT0ga-Tzgw@mail.gmail.com +Signed-off-by: Chao Yu +Signed-off-by: Jaegeuk Kim +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + fs/f2fs/compress.c | 5 +---- + fs/f2fs/f2fs.h | 1 - + fs/f2fs/super.c | 41 ----------------------------------------- + 3 files changed, 1 insertion(+), 46 deletions(-) + +--- a/fs/f2fs/compress.c ++++ b/fs/f2fs/compress.c +@@ -754,10 +754,7 @@ void f2fs_decompress_cluster(struct deco + ret = -EFSCORRUPTED; + + /* Avoid f2fs_commit_super in irq context */ +- if (!in_task) +- f2fs_handle_error_async(sbi, ERROR_FAIL_DECOMPRESSION); +- else +- f2fs_handle_error(sbi, ERROR_FAIL_DECOMPRESSION); ++ f2fs_handle_error(sbi, ERROR_FAIL_DECOMPRESSION); + goto out_release; + } + +--- a/fs/f2fs/f2fs.h ++++ b/fs/f2fs/f2fs.h +@@ -3638,7 +3638,6 @@ void f2fs_quota_off_umount(struct super_ + void f2fs_save_errors(struct f2fs_sb_info *sbi, unsigned char flag); + void f2fs_handle_critical_error(struct f2fs_sb_info *sbi, unsigned char reason); + void f2fs_handle_error(struct f2fs_sb_info *sbi, unsigned char error); +-void f2fs_handle_error_async(struct f2fs_sb_info *sbi, unsigned char error); + int f2fs_commit_super(struct f2fs_sb_info *sbi, bool recover); + int f2fs_sync_fs(struct super_block *sb, int sync); + int f2fs_sanity_check_ckpt(struct f2fs_sb_info *sbi); +--- a/fs/f2fs/super.c ++++ b/fs/f2fs/super.c +@@ -4071,50 +4071,9 @@ void f2fs_save_errors(struct f2fs_sb_inf + spin_unlock_irqrestore(&sbi->error_lock, flags); + } + +-static bool f2fs_update_errors(struct f2fs_sb_info *sbi) +-{ +- unsigned long flags; +- bool need_update = false; +- +- spin_lock_irqsave(&sbi->error_lock, flags); +- if (sbi->error_dirty) { +- memcpy(F2FS_RAW_SUPER(sbi)->s_errors, sbi->errors, +- MAX_F2FS_ERRORS); +- sbi->error_dirty = false; +- need_update = true; +- } +- spin_unlock_irqrestore(&sbi->error_lock, flags); +- +- return need_update; +-} +- +-static void f2fs_record_errors(struct f2fs_sb_info *sbi, unsigned char error) +-{ +- int err; +- +- f2fs_down_write(&sbi->sb_lock); +- +- if (!f2fs_update_errors(sbi)) +- goto out_unlock; +- +- err = f2fs_commit_super(sbi, false); +- if (err) +- f2fs_err_ratelimited(sbi, +- "f2fs_commit_super fails to record errors:%u, err:%d", +- error, err); +-out_unlock: +- f2fs_up_write(&sbi->sb_lock); +-} +- + void f2fs_handle_error(struct f2fs_sb_info *sbi, unsigned char error) + { + f2fs_save_errors(sbi, error); +- f2fs_record_errors(sbi, error); +-} +- +-void f2fs_handle_error_async(struct f2fs_sb_info *sbi, unsigned char error) +-{ +- f2fs_save_errors(sbi, error); + + if (!sbi->error_dirty) + return; diff --git a/queue-6.6/f2fs-use-f2fs_err_ratelimited-to-avoid-redundant-logs.patch b/queue-6.6/f2fs-use-f2fs_err_ratelimited-to-avoid-redundant-logs.patch new file mode 100644 index 0000000000..086a68a04b --- /dev/null +++ b/queue-6.6/f2fs-use-f2fs_err_ratelimited-to-avoid-redundant-logs.patch @@ -0,0 +1,50 @@ +From stable+bounces-204243-greg=kroah.com@vger.kernel.org Tue Dec 30 17:15:44 2025 +From: Sasha Levin +Date: Tue, 30 Dec 2025 11:15:38 -0500 +Subject: f2fs: use f2fs_err_ratelimited() to avoid redundant logs +To: stable@vger.kernel.org +Cc: Chao Yu , Jaegeuk Kim , Sasha Levin +Message-ID: <20251230161539.2301172-1-sashal@kernel.org> + +From: Chao Yu + +[ Upstream commit 0b8eb814e05885cde53c1d56ee012a029b8413e6 ] + +Use f2fs_err_ratelimited() to instead f2fs_err() in +f2fs_record_stop_reason() and f2fs_record_errors() to +avoid redundant logs. + +Signed-off-by: Chao Yu +Signed-off-by: Jaegeuk Kim +Stable-dep-of: ca8b201f2854 ("f2fs: fix to avoid potential deadlock") +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + fs/f2fs/super.c | 9 ++++++--- + 1 file changed, 6 insertions(+), 3 deletions(-) + +--- a/fs/f2fs/super.c ++++ b/fs/f2fs/super.c +@@ -4054,7 +4054,9 @@ static void f2fs_record_stop_reason(stru + + f2fs_up_write(&sbi->sb_lock); + if (err) +- f2fs_err(sbi, "f2fs_commit_super fails to record err:%d", err); ++ f2fs_err_ratelimited(sbi, ++ "f2fs_commit_super fails to record stop_reason, err:%d", ++ err); + } + + void f2fs_save_errors(struct f2fs_sb_info *sbi, unsigned char flag) +@@ -4097,8 +4099,9 @@ static void f2fs_record_errors(struct f2 + + err = f2fs_commit_super(sbi, false); + if (err) +- f2fs_err(sbi, "f2fs_commit_super fails to record errors:%u, err:%d", +- error, err); ++ f2fs_err_ratelimited(sbi, ++ "f2fs_commit_super fails to record errors:%u, err:%d", ++ error, err); + out_unlock: + f2fs_up_write(&sbi->sb_lock); + } diff --git a/queue-6.6/fuse-fix-readahead-reclaim-deadlock.patch b/queue-6.6/fuse-fix-readahead-reclaim-deadlock.patch new file mode 100644 index 0000000000..cad613a738 --- /dev/null +++ b/queue-6.6/fuse-fix-readahead-reclaim-deadlock.patch @@ -0,0 +1,120 @@ +From stable+bounces-204415-greg=kroah.com@vger.kernel.org Thu Jan 1 15:13:49 2026 +From: Sasha Levin +Date: Thu, 1 Jan 2026 09:13:41 -0500 +Subject: fuse: fix readahead reclaim deadlock +To: stable@vger.kernel.org +Cc: Joanne Koong , Omar Sandoval , Miklos Szeredi , Sasha Levin +Message-ID: <20260101141342.4003826-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 +@@ -113,7 +113,9 @@ static void fuse_file_put(struct fuse_fi + struct fuse_args *args = (ra ? &ra->args : NULL); + + if (!args) { +- /* Do nothing when server does not implement 'open' */ ++ /* Do nothing when server does not implement 'opendir' */ ++ } else if (args->opcode == FUSE_RELEASE && ff->fm->fc->no_open) { ++ fuse_release_end(ff->fm, args, 0); + } else if (sync) { + fuse_simple_request(ff->fm, args); + fuse_release_end(ff->fm, args, 0); +@@ -134,8 +136,17 @@ struct fuse_file *fuse_file_open(struct + struct fuse_file *ff; + int opcode = isdir ? FUSE_OPENDIR : FUSE_OPEN; + bool open = isdir ? !fc->no_opendir : !fc->no_open; ++ bool release = !isdir || open; + +- ff = fuse_file_alloc(fm, open); ++ /* ++ * ff->args->release_args still needs to be allocated (so we can hold an ++ * inode reference while there are pending inflight file operations when ++ * ->release() is called, see fuse_prepare_release()) even if ++ * fc->no_open is set else it becomes possible for reclaim to deadlock ++ * if while servicing the readahead request the server triggers reclaim ++ * and reclaim evicts the inode of the file being read ahead. ++ */ ++ ff = fuse_file_alloc(fm, release); + if (!ff) + return ERR_PTR(-ENOMEM); + +@@ -154,13 +165,14 @@ struct fuse_file *fuse_file_open(struct + fuse_file_free(ff); + return ERR_PTR(err); + } else { +- /* No release needed */ +- kfree(ff->release_args); +- ff->release_args = NULL; +- if (isdir) ++ if (isdir) { ++ /* No release needed */ ++ kfree(ff->release_args); ++ ff->release_args = NULL; + fc->no_opendir = 1; +- else ++ } else { + fc->no_open = 1; ++ } + } + } + diff --git a/queue-6.6/gfs2-fix-freeze-error-handling.patch b/queue-6.6/gfs2-fix-freeze-error-handling.patch new file mode 100644 index 0000000000..e5485f7ca2 --- /dev/null +++ b/queue-6.6/gfs2-fix-freeze-error-handling.patch @@ -0,0 +1,47 @@ +From stable+bounces-204149-greg=kroah.com@vger.kernel.org Tue Dec 30 00:16:02 2025 +From: Sasha Levin +Date: Mon, 29 Dec 2025 18:15:51 -0500 +Subject: gfs2: fix freeze error handling +To: stable@vger.kernel.org +Cc: Alexey Velichayshiy , Andreas Gruenbacher , Sasha Levin +Message-ID: <20251229231551.1812844-1-sashal@kernel.org> + +From: Alexey Velichayshiy + +[ Upstream commit 4cfc7d5a4a01d2133b278cdbb1371fba1b419174 ] + +After commit b77b4a4815a9 ("gfs2: Rework freeze / thaw logic"), +the freeze error handling is broken because gfs2_do_thaw() +overwrites the 'error' variable, causing incorrect processing +of the original freeze error. + +Fix this by calling gfs2_do_thaw() when gfs2_lock_fs_check_clean() +fails but ignoring its return value to preserve the original +freeze error for proper reporting. + +Found by Linux Verification Center (linuxtesting.org) with SVACE. + +Fixes: b77b4a4815a9 ("gfs2: Rework freeze / thaw logic") +Cc: stable@vger.kernel.org # v6.5+ +Signed-off-by: Alexey Velichayshiy +Signed-off-by: Andreas Gruenbacher +[ gfs2_do_thaw() only takes one param ] +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + fs/gfs2/super.c | 4 +--- + 1 file changed, 1 insertion(+), 3 deletions(-) + +--- a/fs/gfs2/super.c ++++ b/fs/gfs2/super.c +@@ -776,9 +776,7 @@ static int gfs2_freeze_super(struct supe + if (!error) + break; /* success */ + +- error = gfs2_do_thaw(sdp); +- if (error) +- goto out; ++ (void)gfs2_do_thaw(sdp); + + if (error == -EBUSY) + fs_err(sdp, "waiting for recovery before freeze\n"); diff --git a/queue-6.6/gpiolib-acpi-add-quirk-for-dell-precision-7780.patch b/queue-6.6/gpiolib-acpi-add-quirk-for-dell-precision-7780.patch new file mode 100644 index 0000000000..60af4a4962 --- /dev/null +++ b/queue-6.6/gpiolib-acpi-add-quirk-for-dell-precision-7780.patch @@ -0,0 +1,61 @@ +From stable+bounces-204361-greg=kroah.com@vger.kernel.org Wed Dec 31 16:01:06 2025 +From: Sasha Levin +Date: Wed, 31 Dec 2025 10:00:59 -0500 +Subject: gpiolib: acpi: Add quirk for Dell Precision 7780 +To: stable@vger.kernel.org +Cc: Askar Safin , Andy Shevchenko , Bartosz Golaszewski , Sasha Levin +Message-ID: <20251231150059.3101892-1-sashal@kernel.org> + +From: Askar Safin + +[ Upstream commit 2d967310c49ed93ac11cef408a55ddf15c3dd52e ] + +Dell Precision 7780 often wakes up on its own from suspend. Sometimes +wake up happens immediately (i. e. within 7 seconds), sometimes it happens +after, say, 30 minutes. + +Fixes: 1796f808e4bb ("HID: i2c-hid: acpi: Stop setting wakeup_capable") +Link: https://lore.kernel.org/linux-i2c/197ae95ffd8.dc819e60457077.7692120488609091556@zohomail.com/ +Cc: stable@vger.kernel.org +Reviewed-by: Andy Shevchenko +Signed-off-by: Askar Safin +Link: https://lore.kernel.org/r/20251206180414.3183334-2-safinaskar@gmail.com +Signed-off-by: Bartosz Golaszewski +[ adapted quirk entry location from gpiolib-acpi-quirks.c to gpiolib-acpi.c ] +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + drivers/gpio/gpiolib-acpi.c | 22 ++++++++++++++++++++++ + 1 file changed, 22 insertions(+) + +--- a/drivers/gpio/gpiolib-acpi.c ++++ b/drivers/gpio/gpiolib-acpi.c +@@ -1720,6 +1720,28 @@ static const struct dmi_system_id gpioli + .ignore_interrupt = "AMDI0030:00@11", + }, + }, ++ { ++ /* ++ * Spurious wakeups, likely from touchpad controller ++ * Dell Precision 7780 ++ * Found in BIOS 1.24.1 ++ * ++ * Found in touchpad firmware, installed by Dell Touchpad Firmware Update Utility version 1160.4196.9, A01 ++ * ( Dell-Touchpad-Firmware-Update-Utility_VYGNN_WIN64_1160.4196.9_A00.EXE ), ++ * released on 11 Jul 2024 ++ * ++ * https://lore.kernel.org/linux-i2c/197ae95ffd8.dc819e60457077.7692120488609091556@zohomail.com/ ++ */ ++ .matches = { ++ DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), ++ DMI_MATCH(DMI_PRODUCT_FAMILY, "Precision"), ++ DMI_MATCH(DMI_PRODUCT_NAME, "Precision 7780"), ++ DMI_MATCH(DMI_BOARD_NAME, "0C6JVW"), ++ }, ++ .driver_data = &(struct acpi_gpiolib_dmi_quirk) { ++ .ignore_wake = "VEN_0488:00@355", ++ }, ++ }, + {} /* Terminating entry */ + }; + diff --git a/queue-6.6/jbd2-fix-the-inconsistency-between-checksum-and-data-in-memory-for-journal-sb.patch b/queue-6.6/jbd2-fix-the-inconsistency-between-checksum-and-data-in-memory-for-journal-sb.patch new file mode 100644 index 0000000000..53761c2524 --- /dev/null +++ b/queue-6.6/jbd2-fix-the-inconsistency-between-checksum-and-data-in-memory-for-journal-sb.patch @@ -0,0 +1,94 @@ +From stable+bounces-204155-greg=kroah.com@vger.kernel.org Tue Dec 30 00:41:07 2025 +From: Sasha Levin +Date: Mon, 29 Dec 2025 18:40:57 -0500 +Subject: jbd2: fix the inconsistency between checksum and data in memory for journal sb +To: stable@vger.kernel.org +Cc: Ye Bin , Baokun Li , "Darrick J. Wong" , Jan Kara , Theodore Ts'o , stable@kernel.org, Sasha Levin +Message-ID: <20251229234057.1852171-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 +[ jbd2_superblock_csum() also takes a journal param ] +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 +@@ -2405,6 +2405,12 @@ int jbd2_journal_set_features(journal_t + sb->s_feature_compat |= cpu_to_be32(compat); + sb->s_feature_ro_compat |= cpu_to_be32(ro); + sb->s_feature_incompat |= cpu_to_be32(incompat); ++ /* ++ * Update the checksum now so that it is valid even for read-only ++ * filesystems where jbd2_write_superblock() doesn't get called. ++ */ ++ if (jbd2_journal_has_csum_v2or3(journal)) ++ sb->s_checksum = jbd2_superblock_csum(journal, sb); + unlock_buffer(journal->j_sb_buffer); + jbd2_journal_init_transaction_limits(journal); + +@@ -2434,9 +2440,17 @@ void jbd2_journal_clear_features(journal + + sb = journal->j_superblock; + ++ lock_buffer(journal->j_sb_buffer); + sb->s_feature_compat &= ~cpu_to_be32(compat); + sb->s_feature_ro_compat &= ~cpu_to_be32(ro); + sb->s_feature_incompat &= ~cpu_to_be32(incompat); ++ /* ++ * Update the checksum now so that it is valid even for read-only ++ * filesystems where jbd2_write_superblock() doesn't get called. ++ */ ++ if (jbd2_journal_has_csum_v2or3(journal)) ++ sb->s_checksum = jbd2_superblock_csum(journal, sb); ++ unlock_buffer(journal->j_sb_buffer); + jbd2_journal_init_transaction_limits(journal); + } + EXPORT_SYMBOL(jbd2_journal_clear_features); diff --git a/queue-6.6/lockd-fix-vfs_test_lock-calls.patch b/queue-6.6/lockd-fix-vfs_test_lock-calls.patch new file mode 100644 index 0000000000..644d3ddfcb --- /dev/null +++ b/queue-6.6/lockd-fix-vfs_test_lock-calls.patch @@ -0,0 +1,181 @@ +From stable+bounces-206038-greg=kroah.com@vger.kernel.org Tue Jan 6 21:47:26 2026 +From: Sasha Levin +Date: Tue, 6 Jan 2026 15:34:33 -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: <20260106203433.3165546-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 fl->c.flc_* field references to flat fl->fl_* naming convention ] +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 | 12 ++++++++++-- + 4 files changed, 24 insertions(+), 18 deletions(-) + +--- a/fs/lockd/svc4proc.c ++++ b/fs/lockd/svc4proc.c +@@ -96,7 +96,6 @@ __nlm4svc_proc_test(struct svc_rqst *rqs + struct nlm_args *argp = rqstp->rq_argp; + struct nlm_host *host; + struct nlm_file *file; +- struct nlm_lockowner *test_owner; + __be32 rc = rpc_success; + + dprintk("lockd: TEST4 called\n"); +@@ -106,7 +105,6 @@ __nlm4svc_proc_test(struct svc_rqst *rqs + if ((resp->status = nlm4svc_retrieve_args(rqstp, argp, &host, &file))) + return resp->status == nlm_drop_reply ? rpc_drop_reply :rpc_success; + +- test_owner = argp->lock.fl.fl_owner; + /* Now check for conflicting locks */ + resp->status = nlmsvc_testlock(rqstp, file, host, &argp->lock, &resp->lock, &resp->cookie); + if (resp->status == nlm_drop_reply) +@@ -114,7 +112,7 @@ __nlm4svc_proc_test(struct svc_rqst *rqs + else + dprintk("lockd: TEST4 status %d\n", ntohl(resp->status)); + +- nlmsvc_put_lockowner(test_owner); ++ nlmsvc_release_lockowner(&argp->lock); + nlmsvc_release_host(host); + nlm_release_file(file); + return rc; +--- a/fs/lockd/svclock.c ++++ b/fs/lockd/svclock.c +@@ -615,7 +615,13 @@ nlmsvc_testlock(struct svc_rqst *rqstp, + } + + mode = lock_to_openmode(&lock->fl); +- error = vfs_test_lock(file->f_file[mode], &lock->fl); ++ locks_init_lock(&conflock->fl); ++ /* vfs_test_lock only uses start, end, and owner, but tests fl_file */ ++ conflock->fl.fl_file = lock->fl.fl_file; ++ conflock->fl.fl_start = lock->fl.fl_start; ++ conflock->fl.fl_end = lock->fl.fl_end; ++ conflock->fl.fl_owner = lock->fl.fl_owner; ++ error = vfs_test_lock(file->f_file[mode], &conflock->fl); + if (error) { + /* We can't currently deal with deferred test requests */ + if (error == FILE_LOCK_DEFERRED) +@@ -625,22 +631,19 @@ nlmsvc_testlock(struct svc_rqst *rqstp, + goto out; + } + +- if (lock->fl.fl_type == F_UNLCK) { ++ if (conflock->fl.fl_type == F_UNLCK) { + ret = nlm_granted; + goto out; + } + + dprintk("lockd: conflicting lock(ty=%d, %Ld-%Ld)\n", +- lock->fl.fl_type, (long long)lock->fl.fl_start, +- (long long)lock->fl.fl_end); ++ conflock->fl.fl_type, (long long)conflock->fl.fl_start, ++ (long long)conflock->fl.fl_end); + conflock->caller = "somehost"; /* FIXME */ + conflock->len = strlen(conflock->caller); + conflock->oh.len = 0; /* don't return OH info */ +- conflock->svid = lock->fl.fl_pid; +- conflock->fl.fl_type = lock->fl.fl_type; +- conflock->fl.fl_start = lock->fl.fl_start; +- conflock->fl.fl_end = lock->fl.fl_end; +- locks_release_private(&lock->fl); ++ conflock->svid = conflock->fl.fl_pid; ++ locks_release_private(&conflock->fl); + + ret = nlm_lck_denied; + out: +--- a/fs/lockd/svcproc.c ++++ b/fs/lockd/svcproc.c +@@ -117,7 +117,6 @@ __nlmsvc_proc_test(struct svc_rqst *rqst + struct nlm_args *argp = rqstp->rq_argp; + struct nlm_host *host; + struct nlm_file *file; +- struct nlm_lockowner *test_owner; + __be32 rc = rpc_success; + + dprintk("lockd: TEST called\n"); +@@ -127,8 +126,6 @@ __nlmsvc_proc_test(struct svc_rqst *rqst + if ((resp->status = nlmsvc_retrieve_args(rqstp, argp, &host, &file))) + return resp->status == nlm_drop_reply ? rpc_drop_reply :rpc_success; + +- test_owner = argp->lock.fl.fl_owner; +- + /* Now check for conflicting locks */ + resp->status = cast_status(nlmsvc_testlock(rqstp, file, host, &argp->lock, &resp->lock, &resp->cookie)); + if (resp->status == nlm_drop_reply) +@@ -137,7 +134,7 @@ __nlmsvc_proc_test(struct svc_rqst *rqst + dprintk("lockd: TEST status %d vers %d\n", + ntohl(resp->status), rqstp->rq_vers); + +- nlmsvc_put_lockowner(test_owner); ++ nlmsvc_release_lockowner(&argp->lock); + nlmsvc_release_host(host); + nlm_release_file(file); + return rc; +--- a/fs/locks.c ++++ b/fs/locks.c +@@ -2124,13 +2124,21 @@ SYSCALL_DEFINE2(flock, unsigned int, fd, + /** + * vfs_test_lock - test file byte range lock + * @filp: The file to test lock for +- * @fl: The lock to test; also used to hold result ++ * @fl: The byte-range in the file to test; also used to hold result + * ++ * On entry, @fl does not contain a lock, but identifies a range (fl_start, fl_end) ++ * in the file (c.flc_file), and an owner (c.flc_owner) for whom existing locks ++ * should be ignored. c.flc_type and c.flc_flags are ignored. ++ * Both fl_lmops and fl_ops in @fl must be NULL. + * Returns -ERRNO on failure. Indicates presence of conflicting lock by +- * setting conf->fl_type to something other than F_UNLCK. ++ * setting fl->fl_type to something other than F_UNLCK. ++ * ++ * If vfs_test_lock() does find a lock and return it, the caller must ++ * use locks_free_lock() or locks_release_private() on the returned lock. + */ + int vfs_test_lock(struct file *filp, struct file_lock *fl) + { ++ WARN_ON_ONCE(fl->fl_ops || fl->fl_lmops); + WARN_ON_ONCE(filp != fl->fl_file); + if (filp->f_op->lock) + return filp->f_op->lock(filp, F_GETLK, fl); diff --git a/queue-6.6/loongarch-refactor-register-restoration-in-ftrace_common_return.patch b/queue-6.6/loongarch-refactor-register-restoration-in-ftrace_common_return.patch new file mode 100644 index 0000000000..66eaef8655 --- /dev/null +++ b/queue-6.6/loongarch-refactor-register-restoration-in-ftrace_common_return.patch @@ -0,0 +1,78 @@ +From stable+bounces-205031-greg=kroah.com@vger.kernel.org Tue Jan 6 04:16:59 2026 +From: Huacai Chen +Date: Tue, 6 Jan 2026 11:13:00 +0800 +Subject: LoongArch: Refactor register restoration in ftrace_common_return +To: Greg Kroah-Hartman , Sasha Levin , Huacai Chen +Cc: Xuerui Wang , stable@vger.kernel.org, linux-kernel@vger.kernel.org, loongarch@lists.linux.dev, Chenghao Duan , Huacai Chen +Message-ID: <20260106031300.961198-1-chenhuacai@loongson.cn> + +From: Chenghao Duan + +commit 45cb47c628dfbd1994c619f3eac271a780602826 upstream. + +Refactor the register restoration sequence in the ftrace_common_return +function to clearly distinguish between the logic of normal returns and +direct call returns in function tracing scenarios. The logic is as +follows: + +1. In the case of a normal return, the execution flow returns to the +traced function, and ftrace must ensure that the register data is +consistent with the state when the function was entered. + +ra = parent return address; t0 = traced function return address. + +2. In the case of a direct call return, the execution flow jumps to the +custom trampoline function, and ftrace must ensure that the register +data is consistent with the state when ftrace was entered. + +ra = traced function return address; t0 = parent return address. + +Cc: stable@vger.kernel.org +Fixes: 9cdc3b6a299c ("LoongArch: ftrace: Add direct call support") +Signed-off-by: Chenghao Duan +Signed-off-by: Huacai Chen +Signed-off-by: Greg Kroah-Hartman +--- + arch/loongarch/kernel/mcount_dyn.S | 14 ++++++++++---- + 1 file changed, 10 insertions(+), 4 deletions(-) + +--- a/arch/loongarch/kernel/mcount_dyn.S ++++ b/arch/loongarch/kernel/mcount_dyn.S +@@ -93,7 +93,6 @@ SYM_INNER_LABEL(ftrace_graph_call, SYM_L + * at the callsite, so there is no need to restore the T series regs. + */ + ftrace_common_return: +- PTR_L ra, sp, PT_R1 + PTR_L a0, sp, PT_R4 + PTR_L a1, sp, PT_R5 + PTR_L a2, sp, PT_R6 +@@ -103,12 +102,17 @@ ftrace_common_return: + PTR_L a6, sp, PT_R10 + PTR_L a7, sp, PT_R11 + PTR_L fp, sp, PT_R22 +- PTR_L t0, sp, PT_ERA + PTR_L t1, sp, PT_R13 +- PTR_ADDI sp, sp, PT_SIZE + bnez t1, .Ldirect ++ ++ PTR_L ra, sp, PT_R1 ++ PTR_L t0, sp, PT_ERA ++ PTR_ADDI sp, sp, PT_SIZE + jr t0 + .Ldirect: ++ PTR_L t0, sp, PT_R1 ++ PTR_L ra, sp, PT_ERA ++ PTR_ADDI sp, sp, PT_SIZE + jr t1 + SYM_CODE_END(ftrace_common) + +@@ -155,6 +159,8 @@ SYM_CODE_END(return_to_handler) + + #ifdef CONFIG_DYNAMIC_FTRACE_WITH_DIRECT_CALLS + SYM_CODE_START(ftrace_stub_direct_tramp) +- jr t0 ++ move t1, ra ++ move ra, t0 ++ jr t1 + SYM_CODE_END(ftrace_stub_direct_tramp) + #endif /* CONFIG_DYNAMIC_FTRACE_WITH_DIRECT_CALLS */ diff --git a/queue-6.6/mm-consider-non-anon-swap-cache-folios-in-folio_expected_ref_count.patch b/queue-6.6/mm-consider-non-anon-swap-cache-folios-in-folio_expected_ref_count.patch new file mode 100644 index 0000000000..4857777a1c --- /dev/null +++ b/queue-6.6/mm-consider-non-anon-swap-cache-folios-in-folio_expected_ref_count.patch @@ -0,0 +1,120 @@ +From stable+bounces-206060-greg=kroah.com@vger.kernel.org Wed Jan 7 00:58:27 2026 +From: Sasha Levin +Date: Tue, 6 Jan 2026 18:58:14 -0500 +Subject: mm: consider non-anon swap cache folios in folio_expected_ref_count() +To: stable@vger.kernel.org +Cc: Bijan Tabatabai , "David Hildenbrand (Red Hat)" , Zi Yan , Baolin Wang , Liam Howlett , Lorenzo Stoakes , Michal Hocko , Mike Rapoport , Shivank Garg , Suren Baghdasaryan , Vlastimil Babka , Kairui Song , Andrew Morton , Sasha Levin +Message-ID: <20260106235814.3462036-2-sashal@kernel.org> + +From: Bijan Tabatabai + +[ Upstream commit f183663901f21fe0fba8bd31ae894bc529709ee0 ] + +Currently, folio_expected_ref_count() only adds references for the swap +cache if the folio is anonymous. However, according to the comment above +the definition of PG_swapcache in enum pageflags, shmem folios can also +have PG_swapcache set. This patch makes sure references for the swap +cache are added if folio_test_swapcache(folio) is true. + +This issue was found when trying to hot-unplug memory in a QEMU/KVM +virtual machine. When initiating hot-unplug when most of the guest memory +is allocated, hot-unplug hangs partway through removal due to migration +failures. The following message would be printed several times, and would +be printed again about every five seconds: + +[ 49.641309] migrating pfn b12f25 failed ret:7 +[ 49.641310] page: refcount:2 mapcount:0 mapping:0000000033bd8fe2 index:0x7f404d925 pfn:0xb12f25 +[ 49.641311] aops:swap_aops +[ 49.641313] flags: 0x300000000030508(uptodate|active|owner_priv_1|reclaim|swapbacked|node=0|zone=3) +[ 49.641314] raw: 0300000000030508 ffffed312c4bc908 ffffed312c4bc9c8 0000000000000000 +[ 49.641315] raw: 00000007f404d925 00000000000c823b 00000002ffffffff 0000000000000000 +[ 49.641315] page dumped because: migration failure + +When debugging this, I found that these migration failures were due to +__migrate_folio() returning -EAGAIN for a small set of folios because the +expected reference count it calculates via folio_expected_ref_count() is +one less than the actual reference count of the folios. Furthermore, all +of the affected folios were not anonymous, but had the PG_swapcache flag +set, inspiring this patch. After applying this patch, the memory +hot-unplug behaves as expected. + +I tested this on a machine running Ubuntu 24.04 with kernel version +6.8.0-90-generic and 64GB of memory. The guest VM is managed by libvirt +and runs Ubuntu 24.04 with kernel version 6.18 (though the head of the +mm-unstable branch as a Dec 16, 2025 was also tested and behaves the same) +and 48GB of memory. The libvirt XML definition for the VM can be found at +[1]. CONFIG_MHP_DEFAULT_ONLINE_TYPE_ONLINE_MOVABLE is set in the guest +kernel so the hot-pluggable memory is automatically onlined. + +Below are the steps to reproduce this behavior: + +1) Define and start and virtual machine + host$ virsh -c qemu:///system define ./test_vm.xml # test_vm.xml from [1] + host$ virsh -c qemu:///system start test_vm + +2) Setup swap in the guest + guest$ sudo fallocate -l 32G /swapfile + guest$ sudo chmod 0600 /swapfile + guest$ sudo mkswap /swapfile + guest$ sudo swapon /swapfile + +3) Use alloc_data [2] to allocate most of the remaining guest memory + guest$ ./alloc_data 45 + +4) In a separate guest terminal, monitor the amount of used memory + guest$ watch -n1 free -h + +5) When alloc_data has finished allocating, initiate the memory +hot-unplug using the provided xml file [3] + host$ virsh -c qemu:///system detach-device test_vm ./remove.xml --live + +After initiating the memory hot-unplug, you should see the amount of +available memory in the guest decrease, and the amount of used swap data +increase. If everything works as expected, when all of the memory is +unplugged, there should be around 8.5-9GB of data in swap. If the +unplugging is unsuccessful, the amount of used swap data will settle below +that. If that happens, you should be able to see log messages in dmesg +similar to the one posted above. + +Link: https://lkml.kernel.org/r/20251216200727.2360228-1-bijan311@gmail.com +Link: https://github.com/BijanT/linux_patch_files/blob/main/test_vm.xml [1] +Link: https://github.com/BijanT/linux_patch_files/blob/main/alloc_data.c [2] +Link: https://github.com/BijanT/linux_patch_files/blob/main/remove.xml [3] +Fixes: 86ebd50224c0 ("mm: add folio_expected_ref_count() for reference count calculation") +Signed-off-by: Bijan Tabatabai +Acked-by: David Hildenbrand (Red Hat) +Acked-by: Zi Yan +Reviewed-by: Baolin Wang +Cc: Liam Howlett +Cc: Lorenzo Stoakes +Cc: Michal Hocko +Cc: Mike Rapoport +Cc: Shivank Garg +Cc: Suren Baghdasaryan +Cc: Vlastimil Babka +Cc: Kairui Song +Cc: +Signed-off-by: Andrew Morton +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + include/linux/mm.h | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +--- a/include/linux/mm.h ++++ b/include/linux/mm.h +@@ -2197,10 +2197,10 @@ static inline int folio_expected_ref_cou + if (WARN_ON_ONCE(page_has_type(&folio->page) && !folio_test_hugetlb(folio))) + return 0; + +- if (folio_test_anon(folio)) { +- /* One reference per page from the swapcache. */ +- ref_count += folio_test_swapcache(folio) << order; +- } else { ++ /* One reference per page from the swapcache. */ ++ ref_count += folio_test_swapcache(folio) << order; ++ ++ if (!folio_test_anon(folio)) { + /* One reference per page from the pagecache. */ + ref_count += !!folio->mapping << order; + /* One reference from PG_private. */ diff --git a/queue-6.6/mm-ksm-fix-exec-fork-inheritance-support-for-prctl.patch b/queue-6.6/mm-ksm-fix-exec-fork-inheritance-support-for-prctl.patch new file mode 100644 index 0000000000..0c6e88929f --- /dev/null +++ b/queue-6.6/mm-ksm-fix-exec-fork-inheritance-support-for-prctl.patch @@ -0,0 +1,121 @@ +From stable+bounces-204178-greg=kroah.com@vger.kernel.org Tue Dec 30 03:54:51 2025 +From: Sasha Levin +Date: Mon, 29 Dec 2025 21:54:43 -0500 +Subject: mm/ksm: fix exec/fork inheritance support for prctl +To: stable@vger.kernel.org +Cc: xu xin , Stefan Roesch , David Hildenbrand , Jinjiang Tu , Wang Yaxin , Yang Yang , Andrew Morton , Sasha Levin +Message-ID: <20251230025443.1980197-1-sashal@kernel.org> + +From: xu xin + +[ Upstream commit 590c03ca6a3fbb114396673314e2aa483839608b ] + +Patch series "ksm: fix exec/fork inheritance", v2. + +This series fixes exec/fork inheritance. See the detailed description of +the issue below. + +This patch (of 2): + +Background +========== + +commit d7597f59d1d33 ("mm: add new api to enable ksm per process") +introduced MMF_VM_MERGE_ANY for mm->flags, and allowed user to set it by +prctl() so that the process's VMAs are forcibly scanned by ksmd. + +Subsequently, the 3c6f33b7273a ("mm/ksm: support fork/exec for prctl") +supported inheriting the MMF_VM_MERGE_ANY flag when a task calls execve(). + +Finally, commit 3a9e567ca45fb ("mm/ksm: fix ksm exec support for prctl") +fixed the issue that ksmd doesn't scan the mm_struct with MMF_VM_MERGE_ANY +by adding the mm_slot to ksm_mm_head in __bprm_mm_init(). + +Problem +======= + +In some extreme scenarios, however, this inheritance of MMF_VM_MERGE_ANY +during exec/fork can fail. For example, when the scanning frequency of +ksmd is tuned extremely high, a process carrying MMF_VM_MERGE_ANY may +still fail to pass it to the newly exec'd process. This happens because +ksm_execve() is executed too early in the do_execve flow (prematurely +adding the new mm_struct to the ksm_mm_slot list). + +As a result, before do_execve completes, ksmd may have already performed a +scan and found that this new mm_struct has no VM_MERGEABLE VMAs, thus +clearing its MMF_VM_MERGE_ANY flag. Consequently, when the new program +executes, the flag MMF_VM_MERGE_ANY inheritance missed. + +Root reason +=========== + +commit d7597f59d1d33 ("mm: add new api to enable ksm per process") clear +the flag MMF_VM_MERGE_ANY when ksmd found no VM_MERGEABLE VMAs. + +Solution +======== + +Firstly, Don't clear MMF_VM_MERGE_ANY when ksmd found no VM_MERGEABLE +VMAs, because perhaps their mm_struct has just been added to ksm_mm_slot +list, and its process has not yet officially started running or has not +yet performed mmap/brk to allocate anonymous VMAS. + +Secondly, recheck MMF_VM_MERGEABLE again if a process takes +MMF_VM_MERGE_ANY, and create a mm_slot and join it into ksm_scan_list +again. + +Link: https://lkml.kernel.org/r/20251007182504440BJgK8VXRHh8TD7IGSUIY4@zte.com.cn +Link: https://lkml.kernel.org/r/20251007182821572h_SoFqYZXEP1mvWI4n9VL@zte.com.cn +Fixes: 3c6f33b7273a ("mm/ksm: support fork/exec for prctl") +Fixes: d7597f59d1d3 ("mm: add new api to enable ksm per process") +Signed-off-by: xu xin +Cc: Stefan Roesch +Cc: David Hildenbrand +Cc: Jinjiang Tu +Cc: Wang Yaxin +Cc: Yang Yang +Cc: +Signed-off-by: Andrew Morton +[ changed mm_flags_test() and mm_flags_clear() calls to test_bit() and clear_bit() ] +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + mm/ksm.c | 18 ++++++++++++++++-- + 1 file changed, 16 insertions(+), 2 deletions(-) + +--- a/mm/ksm.c ++++ b/mm/ksm.c +@@ -2451,8 +2451,14 @@ no_vmas: + spin_unlock(&ksm_mmlist_lock); + + mm_slot_free(mm_slot_cache, mm_slot); ++ /* ++ * Only clear MMF_VM_MERGEABLE. We must not clear ++ * MMF_VM_MERGE_ANY, because for those MMF_VM_MERGE_ANY process, ++ * perhaps their mm_struct has just been added to ksm_mm_slot ++ * list, and its process has not yet officially started running ++ * or has not yet performed mmap/brk to allocate anonymous VMAS. ++ */ + clear_bit(MMF_VM_MERGEABLE, &mm->flags); +- clear_bit(MMF_VM_MERGE_ANY, &mm->flags); + mmap_read_unlock(mm); + mmdrop(mm); + } else { +@@ -2567,8 +2573,16 @@ void ksm_add_vma(struct vm_area_struct * + { + struct mm_struct *mm = vma->vm_mm; + +- if (test_bit(MMF_VM_MERGE_ANY, &mm->flags)) ++ if (test_bit(MMF_VM_MERGE_ANY, &mm->flags)) { + __ksm_add_vma(vma); ++ /* ++ * Generally, the flags here always include MMF_VM_MERGEABLE. ++ * However, in rare cases, this flag may be cleared by ksmd who ++ * scans a cycle without finding any mergeable vma. ++ */ ++ if (unlikely(!test_bit(MMF_VM_MERGEABLE, &mm->flags))) ++ __ksm_enter(mm); ++ } + } + + static void ksm_add_vmas(struct mm_struct *mm) diff --git a/queue-6.6/mm-simplify-folio_expected_ref_count.patch b/queue-6.6/mm-simplify-folio_expected_ref_count.patch new file mode 100644 index 0000000000..4184c5695e --- /dev/null +++ b/queue-6.6/mm-simplify-folio_expected_ref_count.patch @@ -0,0 +1,100 @@ +From stable+bounces-206059-greg=kroah.com@vger.kernel.org Wed Jan 7 00:58:30 2026 +From: Sasha Levin +Date: Tue, 6 Jan 2026 18:58:13 -0500 +Subject: mm: simplify folio_expected_ref_count() +To: stable@vger.kernel.org +Cc: "David Hildenbrand" , "Zi Yan" , "Lorenzo Stoakes" , "Harry Yoo" , "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" , "Andrew Morton" , "Sasha Levin" +Message-ID: <20260106235814.3462036-1-sashal@kernel.org> + +From: David Hildenbrand + +[ Upstream commit 78cb1a13c42a6d843e21389f74d1edb90ed07288 ] + +Now that PAGE_MAPPING_MOVABLE is gone, we can simplify and rely on the +folio_test_anon() test only. + +... but staring at the users, this function should never even have been +called on movable_ops pages. E.g., +* __buffer_migrate_folio() does not make sense for them +* folio_migrate_mapping() does not make sense for them +* migrate_huge_page_move_mapping() does not make sense for them +* __migrate_folio() does not make sense for them +* ... and khugepaged should never stumble over them + +Let's simply refuse typed pages (which includes slab) except hugetlb, and +WARN. + +Link: https://lkml.kernel.org/r/20250704102524.326966-26-david@redhat.com +Signed-off-by: David Hildenbrand +Reviewed-by: Zi Yan +Reviewed-by: Lorenzo Stoakes +Reviewed-by: Harry Yoo +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 +Signed-off-by: Andrew Morton +Stable-dep-of: f183663901f2 ("mm: consider non-anon swap cache folios in folio_expected_ref_count()") +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + include/linux/mm.h | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/include/linux/mm.h ++++ b/include/linux/mm.h +@@ -2194,13 +2194,13 @@ static inline int folio_expected_ref_cou + const int order = folio_order(folio); + int ref_count = 0; + +- if (WARN_ON_ONCE(folio_test_slab(folio))) ++ if (WARN_ON_ONCE(page_has_type(&folio->page) && !folio_test_hugetlb(folio))) + return 0; + + if (folio_test_anon(folio)) { + /* One reference per page from the swapcache. */ + ref_count += folio_test_swapcache(folio) << order; +- } else if (!((unsigned long)folio->mapping & PAGE_MAPPING_FLAGS)) { ++ } else { + /* One reference per page from the pagecache. */ + ref_count += !!folio->mapping << order; + /* One reference from PG_private. */ diff --git a/queue-6.6/mptcp-ensure-context-reset-on-disconnect.patch b/queue-6.6/mptcp-ensure-context-reset-on-disconnect.patch new file mode 100644 index 0000000000..9c62a5a165 --- /dev/null +++ b/queue-6.6/mptcp-ensure-context-reset-on-disconnect.patch @@ -0,0 +1,122 @@ +From stable+bounces-206079-greg=kroah.com@vger.kernel.org Wed Jan 7 03:37:40 2026 +From: Sasha Levin +Date: Tue, 6 Jan 2026 21:34:03 -0500 +Subject: mptcp: ensure context reset on disconnect() +To: stable@vger.kernel.org +Cc: Paolo Abeni , "Matthieu Baerts (NGI0)" , Sasha Levin +Message-ID: <20260107023403.3509706-1-sashal@kernel.org> + +From: Paolo Abeni + +[ Upstream commit 86730ac255b0497a272704de9a1df559f5d6602e ] + +After the blamed commit below, if the MPC subflow is already in TCP_CLOSE +status or has fallback to TCP at mptcp_disconnect() time, +mptcp_do_fastclose() skips setting the `send_fastclose flag` and the later +__mptcp_close_ssk() does not reset anymore the related subflow context. + +Any later connection will be created with both the `request_mptcp` flag +and the msk-level fallback status off (it is unconditionally cleared at +MPTCP disconnect time), leading to a warning in subflow_data_ready(): + + WARNING: CPU: 26 PID: 8996 at net/mptcp/subflow.c:1519 subflow_data_ready (net/mptcp/subflow.c:1519 (discriminator 13)) + Modules linked in: + CPU: 26 UID: 0 PID: 8996 Comm: syz.22.39 Not tainted 6.18.0-rc7-05427-g11fc074f6c36 #1 PREEMPT(voluntary) + Hardware name: Bochs Bochs, BIOS Bochs 01/01/2011 + RIP: 0010:subflow_data_ready (net/mptcp/subflow.c:1519 (discriminator 13)) + Code: 90 0f 0b 90 90 e9 04 fe ff ff e8 b7 1e f5 fe 89 ee bf 07 00 00 00 e8 db 19 f5 fe 83 fd 07 0f 84 35 ff ff ff e8 9d 1e f5 fe 90 <0f> 0b 90 e9 27 ff ff ff e8 8f 1e f5 fe 4c 89 e7 48 89 de e8 14 09 + RSP: 0018:ffffc9002646fb30 EFLAGS: 00010293 + RAX: 0000000000000000 RBX: ffff88813b218000 RCX: ffffffff825c8435 + RDX: ffff8881300b3580 RSI: ffffffff825c8443 RDI: 0000000000000005 + RBP: 000000000000000b R08: ffffffff825c8435 R09: 000000000000000b + R10: 0000000000000005 R11: 0000000000000007 R12: ffff888131ac0000 + R13: 0000000000000000 R14: 0000000000000000 R15: 0000000000000000 + FS: 00007f88330af6c0(0000) GS:ffff888a93dd2000(0000) knlGS:0000000000000000 + CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 + CR2: 00007f88330aefe8 CR3: 000000010ff59000 CR4: 0000000000350ef0 + Call Trace: + + tcp_data_ready (net/ipv4/tcp_input.c:5356) + tcp_data_queue (net/ipv4/tcp_input.c:5445) + tcp_rcv_state_process (net/ipv4/tcp_input.c:7165) + tcp_v4_do_rcv (net/ipv4/tcp_ipv4.c:1955) + __release_sock (include/net/sock.h:1158 (discriminator 6) net/core/sock.c:3180 (discriminator 6)) + release_sock (net/core/sock.c:3737) + mptcp_sendmsg (net/mptcp/protocol.c:1763 net/mptcp/protocol.c:1857) + inet_sendmsg (net/ipv4/af_inet.c:853 (discriminator 7)) + __sys_sendto (net/socket.c:727 (discriminator 15) net/socket.c:742 (discriminator 15) net/socket.c:2244 (discriminator 15)) + __x64_sys_sendto (net/socket.c:2247) + do_syscall_64 (arch/x86/entry/syscall_64.c:63 (discriminator 1) arch/x86/entry/syscall_64.c:94 (discriminator 1)) + entry_SYSCALL_64_after_hwframe (arch/x86/entry/entry_64.S:130) + RIP: 0033:0x7f883326702d + +Address the issue setting an explicit `fastclosing` flag at fastclose +time, and checking such flag after mptcp_do_fastclose(). + +Fixes: ae155060247b ("mptcp: fix duplicate reset on fastclose") +Cc: stable@vger.kernel.org +Signed-off-by: Paolo Abeni +Reviewed-by: Matthieu Baerts (NGI0) +Signed-off-by: Matthieu Baerts (NGI0) +Link: https://patch.msgid.link/20251212-net-mptcp-subflow_data_ready-warn-v1-2-d1f9fd1c36c8@kernel.org +Signed-off-by: Paolo Abeni +[ adapted context in mptcp_do_fastclose() to exclude missing mptcp_backlog_purge() call ] +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + net/mptcp/protocol.c | 8 +++++--- + net/mptcp/protocol.h | 3 ++- + 2 files changed, 7 insertions(+), 4 deletions(-) + +--- a/net/mptcp/protocol.c ++++ b/net/mptcp/protocol.c +@@ -2441,10 +2441,10 @@ bool __mptcp_retransmit_pending_data(str + */ + static void __mptcp_subflow_disconnect(struct sock *ssk, + struct mptcp_subflow_context *subflow, +- unsigned int flags) ++ bool fastclosing) + { + if (((1 << ssk->sk_state) & (TCPF_CLOSE | TCPF_LISTEN)) || +- subflow->send_fastclose) { ++ fastclosing) { + /* The MPTCP code never wait on the subflow sockets, TCP-level + * disconnect should never fail + */ +@@ -2496,7 +2496,7 @@ static void __mptcp_close_ssk(struct soc + + need_push = (flags & MPTCP_CF_PUSH) && __mptcp_retransmit_pending_data(sk); + if (!dispose_it) { +- __mptcp_subflow_disconnect(ssk, subflow, flags); ++ __mptcp_subflow_disconnect(ssk, subflow, msk->fastclosing); + release_sock(ssk); + + goto out; +@@ -2808,6 +2808,7 @@ static void mptcp_do_fastclose(struct so + struct mptcp_sock *msk = mptcp_sk(sk); + + mptcp_set_state(sk, TCP_CLOSE); ++ msk->fastclosing = 1; + + /* Explicitly send the fastclose reset as need */ + if (__mptcp_check_fallback(msk)) +@@ -3320,6 +3321,7 @@ static int mptcp_disconnect(struct sock + msk->bytes_sent = 0; + msk->bytes_retrans = 0; + msk->rcvspace_init = 0; ++ msk->fastclosing = 0; + + WRITE_ONCE(sk->sk_shutdown, 0); + sk_error_report(sk); +--- a/net/mptcp/protocol.h ++++ b/net/mptcp/protocol.h +@@ -305,7 +305,8 @@ struct mptcp_sock { + fastopening:1, + in_accept_queue:1, + free_first:1, +- rcvspace_init:1; ++ rcvspace_init:1, ++ fastclosing:1; + int keepalive_cnt; + int keepalive_idle; + int keepalive_intvl; diff --git a/queue-6.6/mptcp-fallback-earlier-on-simult-connection.patch b/queue-6.6/mptcp-fallback-earlier-on-simult-connection.patch new file mode 100644 index 0000000000..102471131c --- /dev/null +++ b/queue-6.6/mptcp-fallback-earlier-on-simult-connection.patch @@ -0,0 +1,154 @@ +From stable+bounces-205177-greg=kroah.com@vger.kernel.org Tue Jan 6 18:25:31 2026 +From: Sasha Levin +Date: Tue, 6 Jan 2026 12:17:09 -0500 +Subject: mptcp: fallback earlier on simult connection +To: stable@vger.kernel.org +Cc: Paolo Abeni , syzbot+0ff6b771b4f7a5bce83b@syzkaller.appspotmail.com, "Matthieu Baerts (NGI0)" , Sasha Levin +Message-ID: <20260106171709.3088177-1-sashal@kernel.org> + +From: Paolo Abeni + +[ Upstream commit 71154bbe49423128c1c8577b6576de1ed6836830 ] + +Syzkaller reports a simult-connect race leading to inconsistent fallback +status: + + WARNING: CPU: 3 PID: 33 at net/mptcp/subflow.c:1515 subflow_data_ready+0x40b/0x7c0 net/mptcp/subflow.c:1515 + Modules linked in: + CPU: 3 UID: 0 PID: 33 Comm: ksoftirqd/3 Not tainted syzkaller #0 PREEMPT(full) + Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 1.16.3-debian-1.16.3-2~bpo12+1 04/01/2014 + RIP: 0010:subflow_data_ready+0x40b/0x7c0 net/mptcp/subflow.c:1515 + Code: 89 ee e8 78 61 3c f6 40 84 ed 75 21 e8 8e 66 3c f6 44 89 fe bf 07 00 00 00 e8 c1 61 3c f6 41 83 ff 07 74 09 e8 76 66 3c f6 90 <0f> 0b 90 e8 6d 66 3c f6 48 89 df e8 e5 ad ff ff 31 ff 89 c5 89 c6 + RSP: 0018:ffffc900006cf338 EFLAGS: 00010246 + RAX: 0000000000000000 RBX: ffff888031acd100 RCX: ffffffff8b7f2abf + RDX: ffff88801e6ea440 RSI: ffffffff8b7f2aca RDI: 0000000000000005 + RBP: 0000000000000000 R08: 0000000000000005 R09: 0000000000000007 + R10: 0000000000000004 R11: 0000000000002c10 R12: ffff88802ba69900 + R13: 1ffff920000d9e67 R14: ffff888046f81800 R15: 0000000000000004 + FS: 0000000000000000(0000) GS:ffff8880d69bc000(0000) knlGS:0000000000000000 + CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 + CR2: 0000560fc0ca1670 CR3: 0000000032c3a000 CR4: 0000000000352ef0 + Call Trace: + + tcp_data_queue+0x13b0/0x4f90 net/ipv4/tcp_input.c:5197 + tcp_rcv_state_process+0xfdf/0x4ec0 net/ipv4/tcp_input.c:6922 + tcp_v6_do_rcv+0x492/0x1740 net/ipv6/tcp_ipv6.c:1672 + tcp_v6_rcv+0x2976/0x41e0 net/ipv6/tcp_ipv6.c:1918 + ip6_protocol_deliver_rcu+0x188/0x1520 net/ipv6/ip6_input.c:438 + ip6_input_finish+0x1e4/0x4b0 net/ipv6/ip6_input.c:489 + NF_HOOK include/linux/netfilter.h:318 [inline] + NF_HOOK include/linux/netfilter.h:312 [inline] + ip6_input+0x105/0x2f0 net/ipv6/ip6_input.c:500 + dst_input include/net/dst.h:471 [inline] + ip6_rcv_finish net/ipv6/ip6_input.c:79 [inline] + NF_HOOK include/linux/netfilter.h:318 [inline] + NF_HOOK include/linux/netfilter.h:312 [inline] + ipv6_rcv+0x264/0x650 net/ipv6/ip6_input.c:311 + __netif_receive_skb_one_core+0x12d/0x1e0 net/core/dev.c:5979 + __netif_receive_skb+0x1d/0x160 net/core/dev.c:6092 + process_backlog+0x442/0x15e0 net/core/dev.c:6444 + __napi_poll.constprop.0+0xba/0x550 net/core/dev.c:7494 + napi_poll net/core/dev.c:7557 [inline] + net_rx_action+0xa9f/0xfe0 net/core/dev.c:7684 + handle_softirqs+0x216/0x8e0 kernel/softirq.c:579 + run_ksoftirqd kernel/softirq.c:968 [inline] + run_ksoftirqd+0x3a/0x60 kernel/softirq.c:960 + smpboot_thread_fn+0x3f7/0xae0 kernel/smpboot.c:160 + kthread+0x3c2/0x780 kernel/kthread.c:463 + ret_from_fork+0x5d7/0x6f0 arch/x86/kernel/process.c:148 + ret_from_fork_asm+0x1a/0x30 arch/x86/entry/entry_64.S:245 + + +The TCP subflow can process the simult-connect syn-ack packet after +transitioning to TCP_FIN1 state, bypassing the MPTCP fallback check, +as the sk_state_change() callback is not invoked for * -> FIN_WAIT1 +transitions. + +That will move the msk socket to an inconsistent status and the next +incoming data will hit the reported splat. + +Close the race moving the simult-fallback check at the earliest possible +stage - that is at syn-ack generation time. + +About the fixes tags: [2] was supposed to also fix this issue introduced +by [3]. [1] is required as a dependence: it was not explicitly marked as +a fix, but it is one and it has already been backported before [3]. In +other words, this commit should be backported up to [3], including [2] +and [1] if that's not already there. + +Fixes: 23e89e8ee7be ("tcp: Don't drop SYN+ACK for simultaneous connect().") [1] +Fixes: 4fd19a307016 ("mptcp: fix inconsistent state on fastopen race") [2] +Fixes: 1e777f39b4d7 ("mptcp: add MSG_FASTOPEN sendmsg flag support") [3] +Cc: stable@vger.kernel.org +Reported-by: syzbot+0ff6b771b4f7a5bce83b@syzkaller.appspotmail.com +Closes: https://github.com/multipath-tcp/mptcp_net-next/issues/586 +Signed-off-by: Paolo Abeni +Reviewed-by: Matthieu Baerts (NGI0) +Signed-off-by: Matthieu Baerts (NGI0) +Link: https://patch.msgid.link/20251212-net-mptcp-subflow_data_ready-warn-v1-1-d1f9fd1c36c8@kernel.org +Signed-off-by: Paolo Abeni +[ adapted mptcp_try_fallback() call ] +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + net/mptcp/options.c | 10 ++++++++++ + net/mptcp/protocol.h | 6 ++---- + net/mptcp/subflow.c | 10 +--------- + 3 files changed, 13 insertions(+), 13 deletions(-) + +--- a/net/mptcp/options.c ++++ b/net/mptcp/options.c +@@ -408,6 +408,16 @@ bool mptcp_syn_options(struct sock *sk, + */ + subflow->snd_isn = TCP_SKB_CB(skb)->end_seq; + if (subflow->request_mptcp) { ++ if (unlikely(subflow_simultaneous_connect(sk))) { ++ WARN_ON_ONCE(!mptcp_try_fallback(sk)); ++ ++ /* Ensure mptcp_finish_connect() will not process the ++ * MPC handshake. ++ */ ++ subflow->request_mptcp = 0; ++ return false; ++ } ++ + opts->suboptions = OPTION_MPTCP_MPC_SYN; + opts->csum_reqd = mptcp_is_checksum_enabled(sock_net(sk)); + opts->allow_join_id0 = mptcp_allow_join_id0(sock_net(sk)); +--- a/net/mptcp/protocol.h ++++ b/net/mptcp/protocol.h +@@ -1175,10 +1175,8 @@ static inline bool subflow_simultaneous_ + { + struct mptcp_subflow_context *subflow = mptcp_subflow_ctx(sk); + +- return (1 << sk->sk_state) & +- (TCPF_ESTABLISHED | TCPF_FIN_WAIT1 | TCPF_FIN_WAIT2 | TCPF_CLOSING) && +- is_active_ssk(subflow) && +- !subflow->conn_finished; ++ /* Note that the sk state implies !subflow->conn_finished. */ ++ return sk->sk_state == TCP_SYN_RECV && is_active_ssk(subflow); + } + + #ifdef CONFIG_SYN_COOKIES +--- a/net/mptcp/subflow.c ++++ b/net/mptcp/subflow.c +@@ -1793,18 +1793,10 @@ static void subflow_state_change(struct + { + struct mptcp_subflow_context *subflow = mptcp_subflow_ctx(sk); + struct sock *parent = subflow->conn; +- struct mptcp_sock *msk; ++ struct mptcp_sock *msk = mptcp_sk(parent); + + __subflow_state_change(sk); + +- msk = mptcp_sk(parent); +- if (subflow_simultaneous_connect(sk)) { +- WARN_ON_ONCE(!mptcp_try_fallback(sk)); +- pr_fallback(msk); +- subflow->conn_finished = 1; +- mptcp_propagate_state(parent, sk, subflow, NULL); +- } +- + /* as recvmsg() does not acquire the subflow socket for ssk selection + * a fin packet carrying a DSS can be unnoticed if we don't trigger + * the data available machinery here. diff --git a/queue-6.6/mptcp-initialise-rcv_mss-before-calling-tcp_send_active_reset-in-mptcp_do_fastclose.patch b/queue-6.6/mptcp-initialise-rcv_mss-before-calling-tcp_send_active_reset-in-mptcp_do_fastclose.patch new file mode 100644 index 0000000000..4407becb73 --- /dev/null +++ b/queue-6.6/mptcp-initialise-rcv_mss-before-calling-tcp_send_active_reset-in-mptcp_do_fastclose.patch @@ -0,0 +1,95 @@ +From stable+bounces-200345-greg=kroah.com@vger.kernel.org Mon Dec 8 12:36:09 2025 +From: Sasha Levin +Date: Mon, 8 Dec 2025 06:36:00 -0500 +Subject: mptcp: Initialise rcv_mss before calling tcp_send_active_reset() in mptcp_do_fastclose(). +To: stable@vger.kernel.org +Cc: Kuniyuki Iwashima , syzbot+3a92d359bc2ec6255a33@syzkaller.appspotmail.com, "Matthieu Baerts (NGI0)" , Paolo Abeni , Sasha Levin +Message-ID: <20251208113600.277918-1-sashal@kernel.org> + +From: Kuniyuki Iwashima + +[ Upstream commit f07f4ea53e22429c84b20832fa098b5ecc0d4e35 ] + +syzbot reported divide-by-zero in __tcp_select_window() by +MPTCP socket. [0] + +We had a similar issue for the bare TCP and fixed in commit +499350a5a6e7 ("tcp: initialize rcv_mss to TCP_MIN_MSS instead +of 0"). + +Let's apply the same fix to mptcp_do_fastclose(). + +[0]: +Oops: divide error: 0000 [#1] SMP KASAN PTI +CPU: 0 UID: 0 PID: 6068 Comm: syz.0.17 Not tainted syzkaller #0 PREEMPT(full) +Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 10/25/2025 +RIP: 0010:__tcp_select_window+0x824/0x1320 net/ipv4/tcp_output.c:3336 +Code: ff ff ff 44 89 f1 d3 e0 89 c1 f7 d1 41 01 cc 41 21 c4 e9 a9 00 00 00 e8 ca 49 01 f8 e9 9c 00 00 00 e8 c0 49 01 f8 44 89 e0 99 7c 24 1c 41 29 d4 48 bb 00 00 00 00 00 fc ff df e9 80 00 00 00 +RSP: 0018:ffffc90003017640 EFLAGS: 00010293 +RAX: 0000000000000000 RBX: 0000000000000000 RCX: ffff88807b469e40 +RDX: 0000000000000000 RSI: 0000000000000000 RDI: 0000000000000000 +RBP: ffffc90003017730 R08: ffff888033268143 R09: 1ffff1100664d028 +R10: dffffc0000000000 R11: ffffed100664d029 R12: 0000000000000000 +R13: 0000000000000000 R14: 0000000000000000 R15: 0000000000000000 +FS: 000055557faa0500(0000) GS:ffff888126135000(0000) knlGS:0000000000000000 +CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 +CR2: 00007f64a1912ff8 CR3: 0000000072122000 CR4: 00000000003526f0 +Call Trace: + + tcp_select_window net/ipv4/tcp_output.c:281 [inline] + __tcp_transmit_skb+0xbc7/0x3aa0 net/ipv4/tcp_output.c:1568 + tcp_transmit_skb net/ipv4/tcp_output.c:1649 [inline] + tcp_send_active_reset+0x2d1/0x5b0 net/ipv4/tcp_output.c:3836 + mptcp_do_fastclose+0x27e/0x380 net/mptcp/protocol.c:2793 + mptcp_disconnect+0x238/0x710 net/mptcp/protocol.c:3253 + mptcp_sendmsg_fastopen+0x2f8/0x580 net/mptcp/protocol.c:1776 + mptcp_sendmsg+0x1774/0x1980 net/mptcp/protocol.c:1855 + sock_sendmsg_nosec net/socket.c:727 [inline] + __sock_sendmsg+0xe5/0x270 net/socket.c:742 + __sys_sendto+0x3bd/0x520 net/socket.c:2244 + __do_sys_sendto net/socket.c:2251 [inline] + __se_sys_sendto net/socket.c:2247 [inline] + __x64_sys_sendto+0xde/0x100 net/socket.c:2247 + do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline] + do_syscall_64+0xfa/0xfa0 arch/x86/entry/syscall_64.c:94 + entry_SYSCALL_64_after_hwframe+0x77/0x7f +RIP: 0033:0x7f66e998f749 +Code: ff ff c3 66 2e 0f 1f 84 00 00 00 00 00 0f 1f 40 00 48 89 f8 48 89 f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 c7 c1 a8 ff ff ff f7 d8 64 89 01 48 +RSP: 002b:00007ffff9acedb8 EFLAGS: 00000246 ORIG_RAX: 000000000000002c +RAX: ffffffffffffffda RBX: 00007f66e9be5fa0 RCX: 00007f66e998f749 +RDX: 0000000000000000 RSI: 0000000000000000 RDI: 0000000000000003 +RBP: 00007ffff9acee10 R08: 0000000000000000 R09: 0000000000000000 +R10: 0000000000000000 R11: 0000000000000246 R12: 0000000000000001 +R13: 00007f66e9be5fa0 R14: 00007f66e9be5fa0 R15: 0000000000000006 + + +Fixes: ae155060247b ("mptcp: fix duplicate reset on fastclose") +Reported-by: syzbot+3a92d359bc2ec6255a33@syzkaller.appspotmail.com +Closes: https://lore.kernel.org/netdev/69260882.a70a0220.d98e3.00b4.GAE@google.com/ +Signed-off-by: Kuniyuki Iwashima +Reviewed-by: Matthieu Baerts (NGI0) +Cc: stable@vger.kernel.org +Link: https://patch.msgid.link/20251125195331.309558-1-kuniyu@google.com +Signed-off-by: Paolo Abeni +[ Adjust context ] +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + net/mptcp/protocol.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +--- a/net/mptcp/protocol.c ++++ b/net/mptcp/protocol.c +@@ -2823,6 +2823,12 @@ static void mptcp_do_fastclose(struct so + goto unlock; + + subflow->send_fastclose = 1; ++ ++ /* Initialize rcv_mss to TCP_MIN_MSS to avoid division by 0 ++ * issue in __tcp_select_window(), see tcp_disconnect(). ++ */ ++ inet_csk(ssk)->icsk_ack.rcv_mss = TCP_MIN_MSS; ++ + tcp_send_active_reset(ssk, ssk->sk_allocation); + unlock: + release_sock(ssk); diff --git a/queue-6.6/mptcp-pm-ignore-unknown-endpoint-flags.patch b/queue-6.6/mptcp-pm-ignore-unknown-endpoint-flags.patch new file mode 100644 index 0000000000..46f253150f --- /dev/null +++ b/queue-6.6/mptcp-pm-ignore-unknown-endpoint-flags.patch @@ -0,0 +1,68 @@ +From stable+bounces-204219-greg=kroah.com@vger.kernel.org Tue Dec 30 14:42:15 2025 +From: Sasha Levin +Date: Tue, 30 Dec 2025 08:42:06 -0500 +Subject: mptcp: pm: ignore unknown endpoint flags +To: stable@vger.kernel.org +Cc: "Matthieu Baerts (NGI0)" , Mat Martineau , Jakub Kicinski , Sasha Levin +Message-ID: <20251230134206.2207988-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(4, 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 +@@ -88,6 +88,7 @@ enum { + #define MPTCP_PM_ADDR_FLAG_BACKUP (1 << 2) + #define MPTCP_PM_ADDR_FLAG_FULLMESH (1 << 3) + #define MPTCP_PM_ADDR_FLAG_IMPLICIT (1 << 4) ++#define MPTCP_PM_ADDR_FLAGS_MASK GENMASK(4, 0) + + enum { + MPTCP_PM_CMD_UNSPEC, +--- a/net/mptcp/pm_netlink.c ++++ b/net/mptcp/pm_netlink.c +@@ -1435,7 +1435,8 @@ int mptcp_pm_parse_entry(struct nlattr * + } + + if (tb[MPTCP_PM_ADDR_ATTR_FLAGS]) +- entry->flags = nla_get_u32(tb[MPTCP_PM_ADDR_ATTR_FLAGS]); ++ entry->flags = nla_get_u32(tb[MPTCP_PM_ADDR_ATTR_FLAGS]) & ++ MPTCP_PM_ADDR_FLAGS_MASK; + + if (tb[MPTCP_PM_ADDR_ATTR_PORT]) + entry->addr.port = htons(nla_get_u16(tb[MPTCP_PM_ADDR_ATTR_PORT])); diff --git a/queue-6.6/net-phy-mediatek-fix-nvmem-cell-reference-leak-in-mt798x_phy_calibration.patch b/queue-6.6/net-phy-mediatek-fix-nvmem-cell-reference-leak-in-mt798x_phy_calibration.patch new file mode 100644 index 0000000000..0af15e128b --- /dev/null +++ b/queue-6.6/net-phy-mediatek-fix-nvmem-cell-reference-leak-in-mt798x_phy_calibration.patch @@ -0,0 +1,46 @@ +From stable+bounces-206078-greg=kroah.com@vger.kernel.org Wed Jan 7 03:37:34 2026 +From: Sasha Levin +Date: Tue, 6 Jan 2026 21:33:35 -0500 +Subject: net: phy: mediatek: fix nvmem cell reference leak in mt798x_phy_calibration +To: stable@vger.kernel.org +Cc: Miaoqian Lin , Daniel Golle , Andrew Lunn , Paolo Abeni , Sasha Levin +Message-ID: <20260107023335.3509482-1-sashal@kernel.org> + +From: Miaoqian Lin + +[ Upstream commit 1e5a541420b8c6d87d88eb50b6b978cdeafee1c9 ] + +When nvmem_cell_read() fails in mt798x_phy_calibration(), the function +returns without calling nvmem_cell_put(), leaking the cell reference. + +Move nvmem_cell_put() right after nvmem_cell_read() to ensure the cell +reference is always released regardless of the read result. + +Found via static analysis and code review. + +Fixes: 98c485eaf509 ("net: phy: add driver for MediaTek SoC built-in GE PHYs") +Cc: stable@vger.kernel.org +Signed-off-by: Miaoqian Lin +Reviewed-by: Daniel Golle +Reviewed-by: Andrew Lunn +Link: https://patch.msgid.link/20251211081313.2368460-1-linmq006@gmail.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + drivers/net/phy/mediatek-ge-soc.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/net/phy/mediatek-ge-soc.c ++++ b/drivers/net/phy/mediatek-ge-soc.c +@@ -1082,9 +1082,9 @@ static int mt798x_phy_calibration(struct + } + + buf = (u32 *)nvmem_cell_read(cell, &len); ++ nvmem_cell_put(cell); + if (IS_ERR(buf)) + return PTR_ERR(buf); +- nvmem_cell_put(cell); + + if (!buf[0] || !buf[1] || !buf[2] || !buf[3] || len < 4 * sizeof(u32)) { + phydev_err(phydev, "invalid efuse data\n"); diff --git a/queue-6.6/net-remove-rtnl-dance-for-siocbraddif-and-siocbrdelif.patch b/queue-6.6/net-remove-rtnl-dance-for-siocbraddif-and-siocbrdelif.patch new file mode 100644 index 0000000000..36d5229917 --- /dev/null +++ b/queue-6.6/net-remove-rtnl-dance-for-siocbraddif-and-siocbrdelif.patch @@ -0,0 +1,300 @@ +From stable+bounces-206189-greg=kroah.com@vger.kernel.org Wed Jan 7 19:17:16 2026 +From: Thadeu Lima de Souza Cascardo +Date: Wed, 7 Jan 2026 14:21:02 -0300 +Subject: net: Remove RTNL dance for SIOCBRADDIF and SIOCBRDELIF. +To: stable@vger.kernel.org +Cc: Thadeu Lima de Souza Cascardo , syzkaller , yan kang , yue sun , Kuniyuki Iwashima , Stanislav Fomichev , Ido Schimmel , Nikolay Aleksandrov , Paolo Abeni +Message-ID: <20260107172102.2488465-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 | 16 ---------------- + net/socket.c | 19 +++++++++---------- + 5 files changed, 45 insertions(+), 35 deletions(-) + +--- a/include/linux/if_bridge.h ++++ b/include/linux/if_bridge.h +@@ -65,11 +65,9 @@ struct br_ip_list { + #define BR_DEFAULT_AGEING_TIME (300 * HZ) + + struct net_bridge; +-void brioctl_set(int (*hook)(struct net *net, struct net_bridge *br, +- unsigned int cmd, struct ifreq *ifr, ++void brioctl_set(int (*hook)(struct net *net, unsigned int cmd, + void __user *uarg)); +-int br_ioctl_call(struct net *net, struct net_bridge *br, unsigned int cmd, +- struct ifreq *ifr, void __user *uarg); ++int br_ioctl_call(struct net *net, unsigned int cmd, void __user *uarg); + + #if IS_ENABLED(CONFIG_BRIDGE) && IS_ENABLED(CONFIG_BRIDGE_IGMP_SNOOPING) + int br_multicast_list_adjacent(struct net_device *dev, +--- a/net/bridge/br_ioctl.c ++++ b/net/bridge/br_ioctl.c +@@ -394,10 +394,26 @@ static int old_deviceless(struct net *ne + return -EOPNOTSUPP; + } + +-int br_ioctl_stub(struct net *net, struct net_bridge *br, unsigned int cmd, +- struct ifreq *ifr, void __user *uarg) ++int br_ioctl_stub(struct net *net, unsigned int cmd, void __user *uarg) + { + int ret = -EOPNOTSUPP; ++ struct ifreq ifr; ++ ++ if (cmd == SIOCBRADDIF || cmd == SIOCBRDELIF) { ++ void __user *data; ++ char *colon; ++ ++ if (!ns_capable(net->user_ns, CAP_NET_ADMIN)) ++ return -EPERM; ++ ++ if (get_user_ifreq(&ifr, &data, uarg)) ++ return -EFAULT; ++ ++ ifr.ifr_name[IFNAMSIZ - 1] = 0; ++ colon = strchr(ifr.ifr_name, ':'); ++ if (colon) ++ *colon = 0; ++ } + + rtnl_lock(); + +@@ -430,7 +446,21 @@ int br_ioctl_stub(struct net *net, struc + break; + case SIOCBRADDIF: + case SIOCBRDELIF: +- ret = add_del_if(br, ifr->ifr_ifindex, cmd == SIOCBRADDIF); ++ { ++ struct net_device *dev; ++ ++ dev = __dev_get_by_name(net, ifr.ifr_name); ++ if (!dev || !netif_device_present(dev)) { ++ ret = -ENODEV; ++ break; ++ } ++ if (!netif_is_bridge_master(dev)) { ++ ret = -EOPNOTSUPP; ++ break; ++ } ++ ++ ret = add_del_if(netdev_priv(dev), ifr.ifr_ifindex, cmd == SIOCBRADDIF); ++ } + break; + } + +--- a/net/bridge/br_private.h ++++ b/net/bridge/br_private.h +@@ -948,8 +948,7 @@ br_port_get_check_rtnl(const struct net_ + /* br_ioctl.c */ + int br_dev_siocdevprivate(struct net_device *dev, struct ifreq *rq, + void __user *data, int cmd); +-int br_ioctl_stub(struct net *net, struct net_bridge *br, unsigned int cmd, +- struct ifreq *ifr, void __user *uarg); ++int br_ioctl_stub(struct net *net, unsigned int cmd, void __user *uarg); + + /* br_multicast.c */ + #ifdef CONFIG_BRIDGE_IGMP_SNOOPING +--- a/net/core/dev_ioctl.c ++++ b/net/core/dev_ioctl.c +@@ -517,7 +517,6 @@ static int dev_ifsioc(struct net *net, s + int err; + struct net_device *dev = __dev_get_by_name(net, ifr->ifr_name); + const struct net_device_ops *ops; +- netdevice_tracker dev_tracker; + + if (!dev) + return -ENODEV; +@@ -580,19 +579,6 @@ static int dev_ifsioc(struct net *net, s + case SIOCWANDEV: + return dev_siocwandev(dev, &ifr->ifr_settings); + +- case SIOCBRADDIF: +- case SIOCBRDELIF: +- if (!netif_device_present(dev)) +- return -ENODEV; +- if (!netif_is_bridge_master(dev)) +- return -EOPNOTSUPP; +- netdev_hold(dev, &dev_tracker, GFP_KERNEL); +- rtnl_unlock(); +- err = br_ioctl_call(net, netdev_priv(dev), cmd, ifr, NULL); +- netdev_put(dev, &dev_tracker); +- rtnl_lock(); +- return err; +- + case SIOCDEVPRIVATE ... SIOCDEVPRIVATE + 15: + return dev_siocdevprivate(dev, ifr, data, cmd); + +@@ -773,8 +759,6 @@ int dev_ioctl(struct net *net, unsigned + case SIOCBONDRELEASE: + case SIOCBONDSETHWADDR: + case SIOCBONDCHANGEACTIVE: +- case SIOCBRADDIF: +- case SIOCBRDELIF: + case SIOCSHWTSTAMP: + if (!ns_capable(net->user_ns, CAP_NET_ADMIN)) + return -EPERM; +--- a/net/socket.c ++++ b/net/socket.c +@@ -1168,12 +1168,10 @@ static ssize_t sock_write_iter(struct ki + */ + + static DEFINE_MUTEX(br_ioctl_mutex); +-static int (*br_ioctl_hook)(struct net *net, struct net_bridge *br, +- unsigned int cmd, struct ifreq *ifr, ++static int (*br_ioctl_hook)(struct net *net, unsigned int cmd, + void __user *uarg); + +-void brioctl_set(int (*hook)(struct net *net, struct net_bridge *br, +- unsigned int cmd, struct ifreq *ifr, ++void brioctl_set(int (*hook)(struct net *net, unsigned int cmd, + void __user *uarg)) + { + mutex_lock(&br_ioctl_mutex); +@@ -1182,8 +1180,7 @@ void brioctl_set(int (*hook)(struct net + } + EXPORT_SYMBOL(brioctl_set); + +-int br_ioctl_call(struct net *net, struct net_bridge *br, unsigned int cmd, +- struct ifreq *ifr, void __user *uarg) ++int br_ioctl_call(struct net *net, unsigned int cmd, void __user *uarg) + { + int err = -ENOPKG; + +@@ -1192,7 +1189,7 @@ int br_ioctl_call(struct net *net, struc + + mutex_lock(&br_ioctl_mutex); + if (br_ioctl_hook) +- err = br_ioctl_hook(net, br, cmd, ifr, uarg); ++ err = br_ioctl_hook(net, cmd, uarg); + mutex_unlock(&br_ioctl_mutex); + + return err; +@@ -1292,7 +1289,9 @@ static long sock_ioctl(struct file *file + case SIOCSIFBR: + case SIOCBRADDBR: + case SIOCBRDELBR: +- err = br_ioctl_call(net, NULL, cmd, NULL, argp); ++ case SIOCBRADDIF: ++ case SIOCBRDELIF: ++ err = br_ioctl_call(net, cmd, argp); + break; + case SIOCGIFVLAN: + case SIOCSIFVLAN: +@@ -3454,6 +3453,8 @@ static int compat_sock_ioctl_trans(struc + case SIOCGPGRP: + case SIOCBRADDBR: + case SIOCBRDELBR: ++ case SIOCBRADDIF: ++ case SIOCBRDELIF: + case SIOCGIFVLAN: + case SIOCSIFVLAN: + case SIOCGSKNS: +@@ -3493,8 +3494,6 @@ static int compat_sock_ioctl_trans(struc + case SIOCGIFPFLAGS: + case SIOCGIFTXQLEN: + case SIOCSIFTXQLEN: +- case SIOCBRADDIF: +- case SIOCBRDELIF: + case SIOCGIFNAME: + case SIOCSIFNAME: + case SIOCGMIIPHY: diff --git a/queue-6.6/nfsd-clear-seclabel-in-the-suppattr_exclcreat-bitmap.patch b/queue-6.6/nfsd-clear-seclabel-in-the-suppattr_exclcreat-bitmap.patch new file mode 100644 index 0000000000..77d0923c8d --- /dev/null +++ b/queue-6.6/nfsd-clear-seclabel-in-the-suppattr_exclcreat-bitmap.patch @@ -0,0 +1,57 @@ +From stable+bounces-204317-greg=kroah.com@vger.kernel.org Wed Dec 31 04:46:56 2025 +From: Sasha Levin +Date: Tue, 30 Dec 2025 22:46:07 -0500 +Subject: NFSD: Clear SECLABEL in the suppattr_exclcreat bitmap +To: stable@vger.kernel.org +Cc: Chuck Lever , Jeff Layton , Sasha Levin +Message-ID: <20251231034607.2717171-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 +@@ -3419,6 +3419,11 @@ out_acl: + u32 supp[3]; + + memcpy(supp, nfsd_suppattrs[minorversion], sizeof(supp)); ++ if (!IS_POSIXACL(d_inode(dentry))) ++ supp[0] &= ~FATTR4_WORD0_ACL; ++ if (!contextsupport) ++ supp[2] &= ~FATTR4_WORD2_SECURITY_LABEL; ++ + supp[0] &= NFSD_SUPPATTR_EXCLCREAT_WORD0; + supp[1] &= NFSD_SUPPATTR_EXCLCREAT_WORD1; + supp[2] &= NFSD_SUPPATTR_EXCLCREAT_WORD2; diff --git a/queue-6.6/pci-brcmstb-fix-disabling-l0s-capability.patch b/queue-6.6/pci-brcmstb-fix-disabling-l0s-capability.patch new file mode 100644 index 0000000000..173c6ebe77 --- /dev/null +++ b/queue-6.6/pci-brcmstb-fix-disabling-l0s-capability.patch @@ -0,0 +1,79 @@ +From stable+bounces-204891-greg=kroah.com@vger.kernel.org Mon Jan 5 19:56:05 2026 +From: Sasha Levin +Date: Mon, 5 Jan 2026 13:55:56 -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: <20260105185556.2726479-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 +[ adapted context due to missing link width negotiation defines and variables ] +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 +@@ -46,7 +46,6 @@ + #define PCIE_RC_CFG_PRIV1_ID_VAL3_CLASS_CODE_MASK 0xffffff + + #define PCIE_RC_CFG_PRIV1_LINK_CAPABILITY 0x04dc +-#define PCIE_RC_CFG_PRIV1_LINK_CAPABILITY_ASPM_SUPPORT_MASK 0xc00 + + #define PCIE_RC_DL_MDIO_ADDR 0x1100 + #define PCIE_RC_DL_MDIO_WR_DATA 0x1104 +@@ -867,7 +866,7 @@ static int brcm_pcie_setup(struct brcm_p + void __iomem *base = pcie->base; + struct pci_host_bridge *bridge; + struct resource_entry *entry; +- u32 tmp, burst, aspm_support; ++ u32 tmp, burst; + int num_out_wins = 0; + int ret, memc; + +@@ -971,12 +970,9 @@ static int brcm_pcie_setup(struct brcm_p + writel(tmp, base + PCIE_MISC_RC_BAR3_CONFIG_LO); + + /* Don't advertise L0s capability if 'aspm-no-l0s' */ +- aspm_support = PCIE_LINK_STATE_L1; +- if (!of_property_read_bool(pcie->np, "aspm-no-l0s")) +- aspm_support |= PCIE_LINK_STATE_L0S; + tmp = readl(base + PCIE_RC_CFG_PRIV1_LINK_CAPABILITY); +- u32p_replace_bits(&tmp, aspm_support, +- PCIE_RC_CFG_PRIV1_LINK_CAPABILITY_ASPM_SUPPORT_MASK); ++ if (of_property_read_bool(pcie->np, "aspm-no-l0s")) ++ tmp &= ~PCI_EXP_LNKCAP_ASPM_L0S; + writel(tmp, base + PCIE_RC_CFG_PRIV1_LINK_CAPABILITY); + + /* diff --git a/queue-6.6/pmdomain-imx-fix-reference-count-leak-in-imx_gpc_probe.patch b/queue-6.6/pmdomain-imx-fix-reference-count-leak-in-imx_gpc_probe.patch new file mode 100644 index 0000000000..4dd47b88d3 --- /dev/null +++ b/queue-6.6/pmdomain-imx-fix-reference-count-leak-in-imx_gpc_probe.patch @@ -0,0 +1,48 @@ +From stable+bounces-205121-greg=kroah.com@vger.kernel.org Tue Jan 6 16:56:53 2026 +From: Sasha Levin +Date: Tue, 6 Jan 2026 10:56:03 -0500 +Subject: pmdomain: imx: Fix reference count leak in imx_gpc_probe() +To: stable@vger.kernel.org +Cc: Wentao Liang , Frank Li , Ulf Hansson , Sasha Levin +Message-ID: <20260106155609.3056915-2-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/pmdomain/imx/gpc.c | 5 ++--- + 1 file changed, 2 insertions(+), 3 deletions(-) + +--- a/drivers/pmdomain/imx/gpc.c ++++ b/drivers/pmdomain/imx/gpc.c +@@ -405,13 +405,12 @@ clk_err: + static int imx_gpc_probe(struct platform_device *pdev) + { + const struct imx_gpc_dt_data *of_id_data = device_get_match_data(&pdev->dev); +- struct device_node *pgc_node; ++ struct device_node *pgc_node __free(device_node) ++ = of_get_child_by_name(pdev->dev.of_node, "pgc"); + struct regmap *regmap; + void __iomem *base; + int ret; + +- pgc_node = of_get_child_by_name(pdev->dev.of_node, "pgc"); +- + /* bail out if DT too old and doesn't provide the necessary info */ + if (!of_property_read_bool(pdev->dev.of_node, "#power-domain-cells") && + !pgc_node) diff --git a/queue-6.6/pmdomain-use-device_get_match_data.patch b/queue-6.6/pmdomain-use-device_get_match_data.patch new file mode 100644 index 0000000000..be902fb09f --- /dev/null +++ b/queue-6.6/pmdomain-use-device_get_match_data.patch @@ -0,0 +1,134 @@ +From stable+bounces-205120-greg=kroah.com@vger.kernel.org Tue Jan 6 16:56:45 2026 +From: Sasha Levin +Date: Tue, 6 Jan 2026 10:56:02 -0500 +Subject: pmdomain: Use device_get_match_data() +To: stable@vger.kernel.org +Cc: Rob Herring , Ulf Hansson , Sasha Levin +Message-ID: <20260106155609.3056915-1-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/pmdomain/actions/owl-sps.c | 16 +++++----------- + drivers/pmdomain/imx/gpc.c | 7 +++---- + drivers/pmdomain/rockchip/pm-domains.c | 13 ++++--------- + 3 files changed, 12 insertions(+), 24 deletions(-) + +--- a/drivers/pmdomain/actions/owl-sps.c ++++ b/drivers/pmdomain/actions/owl-sps.c +@@ -8,8 +8,10 @@ + * Copyright (c) 2017 Andreas Färber + */ + ++#include + #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/pmdomain/imx/gpc.c ++++ b/drivers/pmdomain/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/pmdomain/rockchip/pm-domains.c ++++ b/drivers/pmdomain/rockchip/pm-domains.c +@@ -9,11 +9,13 @@ + #include + #include + #include ++#include + #include + #include ++#include ++#include + #include + #include +-#include + #include + #include + #include +@@ -857,7 +859,6 @@ static int rockchip_pm_domain_probe(stru + struct device_node *node; + struct device *parent; + struct rockchip_pmu *pmu; +- const struct of_device_id *match; + const struct rockchip_pmu_info *pmu_info; + int error; + +@@ -866,13 +867,7 @@ static int rockchip_pm_domain_probe(stru + return -ENODEV; + } + +- match = of_match_device(dev->driver->of_match_table, dev); +- if (!match || !match->data) { +- dev_err(dev, "missing pmu data\n"); +- return -EINVAL; +- } +- +- pmu_info = match->data; ++ pmu_info = device_get_match_data(dev); + + pmu = devm_kzalloc(dev, + struct_size(pmu, domains, pmu_info->num_domains), diff --git a/queue-6.6/scsi-ufs-core-add-ufshcd_update_evt_hist-for-ufs-suspend-error.patch b/queue-6.6/scsi-ufs-core-add-ufshcd_update_evt_hist-for-ufs-suspend-error.patch new file mode 100644 index 0000000000..9778e9d59d --- /dev/null +++ b/queue-6.6/scsi-ufs-core-add-ufshcd_update_evt_hist-for-ufs-suspend-error.patch @@ -0,0 +1,50 @@ +From stable+bounces-204238-greg=kroah.com@vger.kernel.org Tue Dec 30 16:58:07 2025 +From: Sasha Levin +Date: Tue, 30 Dec 2025 10:58:01 -0500 +Subject: scsi: ufs: core: Add ufshcd_update_evt_hist() for UFS suspend error +To: stable@vger.kernel.org +Cc: Seunghwan Baek , Peter Wang , "Martin K. Petersen" , Sasha Levin +Message-ID: <20251230155801.2291044-1-sashal@kernel.org> + +From: Seunghwan Baek + +[ Upstream commit c9f36f04a8a2725172cdf2b5e32363e4addcb14c ] + +If UFS resume fails, the event history is updated in ufshcd_resume(), but +there is no code anywhere to record UFS suspend. Therefore, add code to +record UFS suspend error event history. + +Fixes: dd11376b9f1b ("scsi: ufs: Split the drivers/scsi/ufs directory") +Cc: stable@vger.kernel.org +Signed-off-by: Seunghwan Baek +Reviewed-by: Peter Wang +Link: https://patch.msgid.link/20251210063854.1483899-2-sh8267.baek@samsung.com +Signed-off-by: Martin K. Petersen +[ Adjust context ] +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + drivers/ufs/core/ufshcd.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +--- a/drivers/ufs/core/ufshcd.c ++++ b/drivers/ufs/core/ufshcd.c +@@ -10182,7 +10182,7 @@ static int ufshcd_suspend(struct ufs_hba + ret = ufshcd_setup_clocks(hba, false); + if (ret) { + ufshcd_enable_irq(hba); +- return ret; ++ goto out; + } + if (ufshcd_is_clkgating_allowed(hba)) { + hba->clk_gating.state = CLKS_OFF; +@@ -10193,6 +10193,9 @@ static int ufshcd_suspend(struct ufs_hba + ufshcd_vreg_set_lpm(hba); + /* Put the host controller in low power mode if possible */ + ufshcd_hba_vreg_set_lpm(hba); ++out: ++ if (ret) ++ ufshcd_update_evt_hist(hba, UFS_EVT_SUSPEND_ERR, (u32)ret); + return ret; + } + diff --git a/queue-6.6/series b/queue-6.6/series index f5a3a60912..156a673c64 100644 --- a/queue-6.6/series +++ b/queue-6.6/series @@ -626,3 +626,48 @@ drm-nouveau-dispnv50-don-t-call-drm_atomic_get_crtc_state-in-prepare_fb.patch usb-gadget-lpc32xx_udc-fix-clock-imbalance-in-error-path.patch blk-mq-add-helper-for-checking-if-one-cpu-is-mapped-to-specified-hctx.patch tpm-cap-the-number-of-pcr-banks.patch +mptcp-initialise-rcv_mss-before-calling-tcp_send_active_reset-in-mptcp_do_fastclose.patch +alsa-wavefront-use-standard-print-api.patch +alsa-wavefront-fix-integer-overflow-in-sample-size-validation.patch +alsa-wavefront-use-guard-for-spin-locks.patch +alsa-wavefront-clear-substream-pointers-on-close.patch +alsa-hda-cs35l41-fix-null-pointer-dereference-in-cs35l41_hda_read_acpi.patch +ext4-fix-string-copying-in-parse_apply_sb_mount_options.patch +jbd2-fix-the-inconsistency-between-checksum-and-data-in-memory-for-journal-sb.patch +gfs2-fix-freeze-error-handling.patch +btrfs-don-t-rewrite-ret-from-inode_permission.patch +wifi-mt76-fix-dts-power-limits-on-little-endian-systems.patch +mm-ksm-fix-exec-fork-inheritance-support-for-prctl.patch +usb-ohci-nxp-use-helper-function-devm_clk_get_enabled.patch +usb-ohci-nxp-fix-device-leak-on-probe-failure.patch +scsi-ufs-core-add-ufshcd_update_evt_hist-for-ufs-suspend-error.patch +mptcp-pm-ignore-unknown-endpoint-flags.patch +f2fs-use-f2fs_err_ratelimited-to-avoid-redundant-logs.patch +f2fs-fix-to-avoid-potential-deadlock.patch +nfsd-clear-seclabel-in-the-suppattr_exclcreat-bitmap.patch +gpiolib-acpi-add-quirk-for-dell-precision-7780.patch +arm-dts-microchip-sama7g5-fix-uart-fifo-size-to-32.patch +svcrdma-bound-check-rq_pages-index-in-inline-path.patch +fuse-fix-readahead-reclaim-deadlock.patch +pci-brcmstb-fix-disabling-l0s-capability.patch +mptcp-fallback-earlier-on-simult-connection.patch +lockd-fix-vfs_test_lock-calls.patch +wifi-mac80211-discard-beacon-frames-to-non-broadcast-address.patch +mm-simplify-folio_expected_ref_count.patch +mm-consider-non-anon-swap-cache-folios-in-folio_expected_ref_count.patch +pmdomain-use-device_get_match_data.patch +pmdomain-imx-fix-reference-count-leak-in-imx_gpc_probe.patch +net-phy-mediatek-fix-nvmem-cell-reference-leak-in-mt798x_phy_calibration.patch +mptcp-ensure-context-reset-on-disconnect.patch +drm-amdgpu-forward-vmid-reservation-errors.patch +drm-mediatek-fix-probe-memory-leak.patch +drm-mediatek-fix-probe-resource-leaks.patch +drm-tilcdc-request-and-mapp-iomem-with-devres.patch +drm-tilcdc-fix-removal-actions-in-case-of-failed-probe.patch +tty-introduce-and-use-tty_port_tty_vhangup-helper.patch +xhci-dbgtty-fix-device-unregister-fixup.patch +usb-xhci-move-link-chain-bit-quirk-checks-into-one-helper-function.patch +usb-xhci-apply-the-link-chain-quirk-on-nec-isoc-endpoints.patch +net-remove-rtnl-dance-for-siocbraddif-and-siocbrdelif.patch +drm-amd-display-fix-null-pointer-deref-in-dcn20_resource.c.patch +loongarch-refactor-register-restoration-in-ftrace_common_return.patch diff --git a/queue-6.6/svcrdma-bound-check-rq_pages-index-in-inline-path.patch b/queue-6.6/svcrdma-bound-check-rq_pages-index-in-inline-path.patch new file mode 100644 index 0000000000..824d8fa529 --- /dev/null +++ b/queue-6.6/svcrdma-bound-check-rq_pages-index-in-inline-path.patch @@ -0,0 +1,39 @@ +From stable+bounces-204396-greg=kroah.com@vger.kernel.org Wed Dec 31 23:32:25 2025 +From: Sasha Levin +Date: Wed, 31 Dec 2025 17:32:17 -0500 +Subject: svcrdma: bound check rq_pages index in inline path +To: stable@vger.kernel.org +Cc: Joshua Rogers , Chuck Lever , Sasha Levin +Message-ID: <20251231223217.3548253-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 +@@ -815,6 +815,9 @@ static int svc_rdma_copy_inline_range(st + for (page_no = 0; page_no < numpages; page_no++) { + unsigned int page_len; + ++ if (info->ri_pageno >= RPCSVC_MAXPAGES) ++ return -EINVAL; ++ + page_len = min_t(unsigned int, remaining, + PAGE_SIZE - info->ri_pageoff); + diff --git a/queue-6.6/tty-introduce-and-use-tty_port_tty_vhangup-helper.patch b/queue-6.6/tty-introduce-and-use-tty_port_tty_vhangup-helper.patch new file mode 100644 index 0000000000..a48d4030db --- /dev/null +++ b/queue-6.6/tty-introduce-and-use-tty_port_tty_vhangup-helper.patch @@ -0,0 +1,233 @@ +From stable+bounces-204275-greg=kroah.com@vger.kernel.org Tue Dec 30 19:44:23 2025 +From: Sasha Levin +Date: Tue, 30 Dec 2025 13:43:20 -0500 +Subject: tty: introduce and use tty_port_tty_vhangup() helper +To: stable@vger.kernel.org +Cc: "Jiri Slaby (SUSE)" , "Karsten Keil" , "David Lin" , "Johan Hovold" , "Alex Elder" , "Oliver Neukum" , "Marcel Holtmann" , "Johan Hedberg" , "Luiz Augusto von Dentz" , "Ilpo Järvinen" , "Greg Kroah-Hartman" , "Sasha Levin" +Message-ID: <20251230184321.2402789-1-sashal@kernel.org> + +From: "Jiri Slaby (SUSE)" + +[ Upstream commit 2b5eac0f8c6e79bc152c8804f9f88d16717013ab ] + +This code (tty_get -> vhangup -> tty_put) is repeated on few places. +Introduce a helper similar to tty_port_tty_hangup() (asynchronous) to +handle even vhangup (synchronous). + +And use it on those places. + +In fact, reuse the tty_port_tty_hangup()'s code and call tty_vhangup() +depending on a new bool parameter. + +Signed-off-by: "Jiri Slaby (SUSE)" +Cc: Karsten Keil +Cc: David Lin +Cc: Johan Hovold +Cc: Alex Elder +Cc: Oliver Neukum +Cc: Marcel Holtmann +Cc: Johan Hedberg +Cc: Luiz Augusto von Dentz +Reviewed-by: Ilpo Järvinen +Link: https://lore.kernel.org/r/20250611100319.186924-2-jirislaby@kernel.org +Signed-off-by: Greg Kroah-Hartman +Stable-dep-of: 74098cc06e75 ("xhci: dbgtty: fix device unregister: fixup") +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + drivers/isdn/capi/capi.c | 8 +------- + drivers/staging/greybus/uart.c | 7 +------ + drivers/tty/serial/serial_core.c | 7 +------ + drivers/tty/tty_port.c | 12 ++++++++---- + drivers/usb/class/cdc-acm.c | 7 +------ + drivers/usb/serial/usb-serial.c | 7 +------ + include/linux/tty_port.h | 12 +++++++++++- + net/bluetooth/rfcomm/tty.c | 7 +------ + 8 files changed, 25 insertions(+), 42 deletions(-) + +--- a/drivers/isdn/capi/capi.c ++++ b/drivers/isdn/capi/capi.c +@@ -304,15 +304,9 @@ static void capincci_alloc_minor(struct + static void capincci_free_minor(struct capincci *np) + { + struct capiminor *mp = np->minorp; +- struct tty_struct *tty; + + if (mp) { +- tty = tty_port_tty_get(&mp->port); +- if (tty) { +- tty_vhangup(tty); +- tty_kref_put(tty); +- } +- ++ tty_port_tty_vhangup(&mp->port); + capiminor_free(mp); + } + } +--- a/drivers/staging/greybus/uart.c ++++ b/drivers/staging/greybus/uart.c +@@ -914,7 +914,6 @@ static void gb_uart_remove(struct gbphy_ + { + struct gb_tty *gb_tty = gb_gbphy_get_data(gbphy_dev); + struct gb_connection *connection = gb_tty->connection; +- struct tty_struct *tty; + int ret; + + ret = gbphy_runtime_get_sync(gbphy_dev); +@@ -927,11 +926,7 @@ static void gb_uart_remove(struct gbphy_ + wake_up_all(&gb_tty->wioctl); + mutex_unlock(&gb_tty->mutex); + +- tty = tty_port_tty_get(&gb_tty->port); +- if (tty) { +- tty_vhangup(tty); +- tty_kref_put(tty); +- } ++ tty_port_tty_vhangup(&gb_tty->port); + + gb_connection_disable_rx(connection); + tty_unregister_device(gb_tty_driver, gb_tty->minor); +--- a/drivers/tty/serial/serial_core.c ++++ b/drivers/tty/serial/serial_core.c +@@ -3250,7 +3250,6 @@ static void serial_core_remove_one_port( + struct uart_state *state = drv->state + uport->line; + struct tty_port *port = &state->port; + struct uart_port *uart_port; +- struct tty_struct *tty; + + mutex_lock(&port->mutex); + uart_port = uart_port_check(state); +@@ -3269,11 +3268,7 @@ static void serial_core_remove_one_port( + */ + tty_port_unregister_device(port, drv->tty_driver, uport->line); + +- tty = tty_port_tty_get(port); +- if (tty) { +- tty_vhangup(port->tty); +- tty_kref_put(tty); +- } ++ tty_port_tty_vhangup(port); + + /* + * If the port is used as a console, unregister it +--- a/drivers/tty/tty_port.c ++++ b/drivers/tty/tty_port.c +@@ -414,15 +414,19 @@ EXPORT_SYMBOL(tty_port_hangup); + * @port: tty port + * @check_clocal: hang only ttys with %CLOCAL unset? + */ +-void tty_port_tty_hangup(struct tty_port *port, bool check_clocal) ++void __tty_port_tty_hangup(struct tty_port *port, bool check_clocal, bool async) + { + struct tty_struct *tty = tty_port_tty_get(port); + +- if (tty && (!check_clocal || !C_CLOCAL(tty))) +- tty_hangup(tty); ++ if (tty && (!check_clocal || !C_CLOCAL(tty))) { ++ if (async) ++ tty_hangup(tty); ++ else ++ tty_vhangup(tty); ++ } + tty_kref_put(tty); + } +-EXPORT_SYMBOL_GPL(tty_port_tty_hangup); ++EXPORT_SYMBOL_GPL(__tty_port_tty_hangup); + + /** + * tty_port_tty_wakeup - helper to wake up a tty +--- a/drivers/usb/class/cdc-acm.c ++++ b/drivers/usb/class/cdc-acm.c +@@ -1572,7 +1572,6 @@ err_put_port: + static void acm_disconnect(struct usb_interface *intf) + { + struct acm *acm = usb_get_intfdata(intf); +- struct tty_struct *tty; + int i; + + /* sibling interface is already cleaning up */ +@@ -1599,11 +1598,7 @@ static void acm_disconnect(struct usb_in + usb_set_intfdata(acm->data, NULL); + mutex_unlock(&acm->mutex); + +- tty = tty_port_tty_get(&acm->port); +- if (tty) { +- tty_vhangup(tty); +- tty_kref_put(tty); +- } ++ tty_port_tty_vhangup(&acm->port); + + cancel_delayed_work_sync(&acm->dwork); + +--- a/drivers/usb/serial/usb-serial.c ++++ b/drivers/usb/serial/usb-serial.c +@@ -1178,7 +1178,6 @@ static void usb_serial_disconnect(struct + struct usb_serial *serial = usb_get_intfdata(interface); + struct device *dev = &interface->dev; + struct usb_serial_port *port; +- struct tty_struct *tty; + + /* sibling interface is cleaning up */ + if (!serial) +@@ -1193,11 +1192,7 @@ static void usb_serial_disconnect(struct + + for (i = 0; i < serial->num_ports; ++i) { + port = serial->port[i]; +- tty = tty_port_tty_get(&port->port); +- if (tty) { +- tty_vhangup(tty); +- tty_kref_put(tty); +- } ++ tty_port_tty_vhangup(&port->port); + usb_serial_port_poison_urbs(port); + wake_up_interruptible(&port->port.delta_msr_wait); + cancel_work_sync(&port->work); +--- a/include/linux/tty_port.h ++++ b/include/linux/tty_port.h +@@ -235,7 +235,7 @@ bool tty_port_carrier_raised(struct tty_ + void tty_port_raise_dtr_rts(struct tty_port *port); + void tty_port_lower_dtr_rts(struct tty_port *port); + void tty_port_hangup(struct tty_port *port); +-void tty_port_tty_hangup(struct tty_port *port, bool check_clocal); ++void __tty_port_tty_hangup(struct tty_port *port, bool check_clocal, bool async); + void tty_port_tty_wakeup(struct tty_port *port); + int tty_port_block_til_ready(struct tty_port *port, struct tty_struct *tty, + struct file *filp); +@@ -254,4 +254,14 @@ static inline int tty_port_users(struct + return port->count + port->blocked_open; + } + ++static inline void tty_port_tty_hangup(struct tty_port *port, bool check_clocal) ++{ ++ __tty_port_tty_hangup(port, check_clocal, true); ++} ++ ++static inline void tty_port_tty_vhangup(struct tty_port *port) ++{ ++ __tty_port_tty_hangup(port, false, false); ++} ++ + #endif +--- a/net/bluetooth/rfcomm/tty.c ++++ b/net/bluetooth/rfcomm/tty.c +@@ -438,7 +438,6 @@ static int __rfcomm_release_dev(void __u + { + struct rfcomm_dev_req req; + struct rfcomm_dev *dev; +- struct tty_struct *tty; + + if (copy_from_user(&req, arg, sizeof(req))) + return -EFAULT; +@@ -464,11 +463,7 @@ static int __rfcomm_release_dev(void __u + rfcomm_dlc_close(dev->dlc, 0); + + /* Shut down TTY synchronously before freeing rfcomm_dev */ +- tty = tty_port_tty_get(&dev->port); +- if (tty) { +- tty_vhangup(tty); +- tty_kref_put(tty); +- } ++ tty_port_tty_vhangup(&dev->port); + + if (!test_bit(RFCOMM_TTY_OWNED, &dev->status)) + tty_port_put(&dev->port); diff --git a/queue-6.6/usb-ohci-nxp-fix-device-leak-on-probe-failure.patch b/queue-6.6/usb-ohci-nxp-fix-device-leak-on-probe-failure.patch new file mode 100644 index 0000000000..ec0f747bc0 --- /dev/null +++ b/queue-6.6/usb-ohci-nxp-fix-device-leak-on-probe-failure.patch @@ -0,0 +1,49 @@ +From stable+bounces-204203-greg=kroah.com@vger.kernel.org Tue Dec 30 14:19:29 2025 +From: Sasha Levin +Date: Tue, 30 Dec 2025 08:19:21 -0500 +Subject: usb: ohci-nxp: fix device leak on probe failure +To: stable@vger.kernel.org +Cc: Johan Hovold , Ma Ke , Alan Stern , Vladimir Zapolskiy , Greg Kroah-Hartman , Sasha Levin +Message-ID: <20251230131921.2177523-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 +@@ -223,6 +223,7 @@ static int ohci_hcd_nxp_probe(struct pla + fail_resource: + usb_put_hcd(hcd); + fail_disable: ++ put_device(&isp1301_i2c_client->dev); + isp1301_i2c_client = NULL; + return ret; + } +@@ -234,6 +235,7 @@ static void ohci_hcd_nxp_remove(struct p + usb_remove_hcd(hcd); + ohci_nxp_stop_hc(); + usb_put_hcd(hcd); ++ put_device(&isp1301_i2c_client->dev); + isp1301_i2c_client = NULL; + } + diff --git a/queue-6.6/usb-ohci-nxp-use-helper-function-devm_clk_get_enabled.patch b/queue-6.6/usb-ohci-nxp-use-helper-function-devm_clk_get_enabled.patch new file mode 100644 index 0000000000..71fa5b0478 --- /dev/null +++ b/queue-6.6/usb-ohci-nxp-use-helper-function-devm_clk_get_enabled.patch @@ -0,0 +1,93 @@ +From stable+bounces-204202-greg=kroah.com@vger.kernel.org Tue Dec 30 14:19:44 2025 +From: Sasha Levin +Date: Tue, 30 Dec 2025 08:19:20 -0500 +Subject: usb: ohci-nxp: Use helper function devm_clk_get_enabled() +To: stable@vger.kernel.org +Cc: Zhang Zekun , Alan Stern , Greg Kroah-Hartman , Sasha Levin +Message-ID: <20251230131921.2177523-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; + } + + hcd->regs = devm_platform_get_and_ioremap_resource(pdev, 0, &res); +@@ -229,8 +222,6 @@ static int ohci_hcd_nxp_probe(struct pla + ohci_nxp_stop_hc(); + fail_resource: + usb_put_hcd(hcd); +-fail_hcd: +- clk_disable_unprepare(usb_host_clk); + fail_disable: + isp1301_i2c_client = NULL; + return ret; +@@ -243,7 +234,6 @@ static void ohci_hcd_nxp_remove(struct p + usb_remove_hcd(hcd); + ohci_nxp_stop_hc(); + usb_put_hcd(hcd); +- clk_disable_unprepare(usb_host_clk); + isp1301_i2c_client = NULL; + } + diff --git a/queue-6.6/usb-xhci-apply-the-link-chain-quirk-on-nec-isoc-endpoints.patch b/queue-6.6/usb-xhci-apply-the-link-chain-quirk-on-nec-isoc-endpoints.patch new file mode 100644 index 0000000000..0cff289c03 --- /dev/null +++ b/queue-6.6/usb-xhci-apply-the-link-chain-quirk-on-nec-isoc-endpoints.patch @@ -0,0 +1,116 @@ +From shivani.agarwal@broadcom.com Thu Jan 8 10:11:27 2026 +From: Shivani Agarwal +Date: Thu, 8 Jan 2026 00:50:21 -0800 +Subject: usb: xhci: Apply the link chain quirk on NEC isoc endpoints +To: stable@vger.kernel.org, gregkh@linuxfoundation.org +Cc: mathias.nyman@intel.com, linux-usb@vger.kernel.org, linux-kernel@vger.kernel.org, ajay.kaher@broadcom.com, alexey.makhalov@broadcom.com, vamsi-krishna.brahmajosyula@broadcom.com, yin.ding@broadcom.com, tapas.kundu@broadcom.com, Michal Pecio , Mathias Nyman , Shivani Agarwal +Message-ID: <20260108085021.671854-3-shivani.agarwal@broadcom.com> + +From: Michal Pecio + +commit bb0ba4cb1065e87f9cc75db1fa454e56d0894d01 upstream. + +Two clearly different specimens of NEC uPD720200 (one with start/stop +bug, one without) were seen to cause IOMMU faults after some Missed +Service Errors. Faulting address is immediately after a transfer ring +segment and patched dynamic debug messages revealed that the MSE was +received when waiting for a TD near the end of that segment: + +[ 1.041954] xhci_hcd: Miss service interval error for slot 1 ep 2 expected TD DMA ffa08fe0 +[ 1.042120] xhci_hcd: AMD-Vi: Event logged [IO_PAGE_FAULT domain=0x0005 address=0xffa09000 flags=0x0000] +[ 1.042146] xhci_hcd: AMD-Vi: Event logged [IO_PAGE_FAULT domain=0x0005 address=0xffa09040 flags=0x0000] + +It gets even funnier if the next page is a ring segment accessible to +the HC. Below, it reports MSE in segment at ff1e8000, plows through a +zero-filled page at ff1e9000 and starts reporting events for TRBs in +page at ff1ea000 every microframe, instead of jumping to seg ff1e6000. + +[ 7.041671] xhci_hcd: Miss service interval error for slot 1 ep 2 expected TD DMA ff1e8fe0 +[ 7.041999] xhci_hcd: Miss service interval error for slot 1 ep 2 expected TD DMA ff1e8fe0 +[ 7.042011] xhci_hcd: WARN: buffer overrun event for slot 1 ep 2 on endpoint +[ 7.042028] xhci_hcd: All TDs skipped for slot 1 ep 2. Clear skip flag. +[ 7.042134] xhci_hcd: WARN: buffer overrun event for slot 1 ep 2 on endpoint +[ 7.042138] xhci_hcd: ERROR Transfer event TRB DMA ptr not part of current TD ep_index 2 comp_code 31 +[ 7.042144] xhci_hcd: Looking for event-dma 00000000ff1ea040 trb-start 00000000ff1e6820 trb-end 00000000ff1e6820 +[ 7.042259] xhci_hcd: WARN: buffer overrun event for slot 1 ep 2 on endpoint +[ 7.042262] xhci_hcd: ERROR Transfer event TRB DMA ptr not part of current TD ep_index 2 comp_code 31 +[ 7.042266] xhci_hcd: Looking for event-dma 00000000ff1ea050 trb-start 00000000ff1e6820 trb-end 00000000ff1e6820 + +At some point completion events change from Isoch Buffer Overrun to +Short Packet and the HC finally finds cycle bit mismatch in ff1ec000. + +[ 7.098130] xhci_hcd: ERROR Transfer event TRB DMA ptr not part of current TD ep_index 2 comp_code 13 +[ 7.098132] xhci_hcd: Looking for event-dma 00000000ff1ecc50 trb-start 00000000ff1e6820 trb-end 00000000ff1e6820 +[ 7.098254] xhci_hcd: ERROR Transfer event TRB DMA ptr not part of current TD ep_index 2 comp_code 13 +[ 7.098256] xhci_hcd: Looking for event-dma 00000000ff1ecc60 trb-start 00000000ff1e6820 trb-end 00000000ff1e6820 +[ 7.098379] xhci_hcd: Overrun event on slot 1 ep 2 + +It's possible that data from the isochronous device were written to +random buffers of pending TDs on other endpoints (either IN or OUT), +other devices or even other HCs in the same IOMMU domain. + +Lastly, an error from a different USB device on another HC. Was it +caused by the above? I don't know, but it may have been. The disk +was working without any other issues and generated PCIe traffic to +starve the NEC of upstream BW and trigger those MSEs. The two HCs +shared one x1 slot by means of a commercial "PCIe splitter" board. + +[ 7.162604] usb 10-2: reset SuperSpeed USB device number 3 using xhci_hcd +[ 7.178990] sd 9:0:0:0: [sdb] tag#0 UNKNOWN(0x2003) Result: hostbyte=0x07 driverbyte=DRIVER_OK cmd_age=0s +[ 7.179001] sd 9:0:0:0: [sdb] tag#0 CDB: opcode=0x28 28 00 04 02 ae 00 00 02 00 00 +[ 7.179004] I/O error, dev sdb, sector 67284480 op 0x0:(READ) flags 0x80700 phys_seg 5 prio class 0 + +Fortunately, it appears that this ridiculous bug is avoided by setting +the chain bit of Link TRBs on isochronous rings. Other ancient HCs are +known which also expect the bit to be set and they ignore Link TRBs if +it's not. Reportedly, 0.95 spec guaranteed that the bit is set. + +The bandwidth-starved NEC HC running a 32KB/uframe UVC endpoint reports +tens of MSEs per second and runs into the bug within seconds. Chaining +Link TRBs allows the same workload to run for many minutes, many times. + +No negative side effects seen in UVC recording and UAC playback with a +few devices at full speed, high speed and SuperSpeed. + +The problem doesn't reproduce on the newer Renesas uPD720201/uPD720202 +and on old Etron EJ168 and VIA VL805 (but the VL805 has other bug). + +[shorten line length of log snippets in commit messge -Mathias] + +Signed-off-by: Michal Pecio +Cc: stable@vger.kernel.org +Signed-off-by: Mathias Nyman +Link: https://lore.kernel.org/r/20250306144954.3507700-14-mathias.nyman@linux.intel.com +Signed-off-by: Greg Kroah-Hartman +[Shivani: Modified to apply on 6.6.y] +Signed-off-by: Shivani Agarwal +Signed-off-by: Greg Kroah-Hartman +--- + drivers/usb/host/xhci.h | 13 +++++++++++-- + 1 file changed, 11 insertions(+), 2 deletions(-) + +--- a/drivers/usb/host/xhci.h ++++ b/drivers/usb/host/xhci.h +@@ -1785,11 +1785,20 @@ static inline void xhci_write_64(struct + } + + +-/* Link TRB chain should always be set on 0.95 hosts, and AMD 0.96 ISOC rings */ ++/* ++ * Reportedly, some chapters of v0.95 spec said that Link TRB always has its chain bit set. ++ * Other chapters and later specs say that it should only be set if the link is inside a TD ++ * which continues from the end of one segment to the next segment. ++ * ++ * Some 0.95 hardware was found to misbehave if any link TRB doesn't have the chain bit set. ++ * ++ * 0.96 hardware from AMD and NEC was found to ignore unchained isochronous link TRBs when ++ * "resynchronizing the pipe" after a Missed Service Error. ++ */ + static inline bool xhci_link_chain_quirk(struct xhci_hcd *xhci, enum xhci_ring_type type) + { + return (xhci->quirks & XHCI_LINK_TRB_QUIRK) || +- (type == TYPE_ISOC && (xhci->quirks & XHCI_AMD_0x96_HOST)); ++ (type == TYPE_ISOC && (xhci->quirks & (XHCI_AMD_0x96_HOST | XHCI_NEC_HOST))); + } + + /* xHCI debugging */ diff --git a/queue-6.6/usb-xhci-move-link-chain-bit-quirk-checks-into-one-helper-function.patch b/queue-6.6/usb-xhci-move-link-chain-bit-quirk-checks-into-one-helper-function.patch new file mode 100644 index 0000000000..0f8db104c8 --- /dev/null +++ b/queue-6.6/usb-xhci-move-link-chain-bit-quirk-checks-into-one-helper-function.patch @@ -0,0 +1,103 @@ +From shivani.agarwal@broadcom.com Thu Jan 8 10:11:25 2026 +From: Shivani Agarwal +Date: Thu, 8 Jan 2026 00:50:20 -0800 +Subject: usb: xhci: move link chain bit quirk checks into one helper function. +To: stable@vger.kernel.org, gregkh@linuxfoundation.org +Cc: mathias.nyman@intel.com, linux-usb@vger.kernel.org, linux-kernel@vger.kernel.org, ajay.kaher@broadcom.com, alexey.makhalov@broadcom.com, vamsi-krishna.brahmajosyula@broadcom.com, yin.ding@broadcom.com, tapas.kundu@broadcom.com, Niklas Neronin , Mathias Nyman , Shivani Agarwal +Message-ID: <20260108085021.671854-2-shivani.agarwal@broadcom.com> + +From: Niklas Neronin + +commit 7476a2215c07703db5e95efaa3fc5b9f957b9417 upstream. + +Older 0.95 xHCI hosts and some other specific newer hosts require the +chain bit to be set for Link TRBs even if the link TRB is not in the +middle of a transfer descriptor (TD). + +move the checks for all those cases into one xhci_link_chain_quirk() +function to clean up and avoid code duplication. + +No functional changes. + +[skip renaming chain_links flag, reword commit message -Mathias] + +Signed-off-by: Niklas Neronin +Signed-off-by: Mathias Nyman +Link: https://lore.kernel.org/r/20240626124835.1023046-10-mathias.nyman@linux.intel.com +Signed-off-by: Greg Kroah-Hartman +[Shivani: Modified to apply on 6.6.y] +Signed-off-by: Shivani Agarwal +Signed-off-by: Greg Kroah-Hartman +--- + drivers/usb/host/xhci-mem.c | 10 ++-------- + drivers/usb/host/xhci-ring.c | 8 ++------ + drivers/usb/host/xhci.h | 7 +++++-- + 3 files changed, 9 insertions(+), 16 deletions(-) + +--- a/drivers/usb/host/xhci-mem.c ++++ b/drivers/usb/host/xhci-mem.c +@@ -136,10 +136,7 @@ static void xhci_link_rings(struct xhci_ + if (!ring || !first || !last) + return; + +- /* Set chain bit for 0.95 hosts, and for isoc rings on AMD 0.96 host */ +- chain_links = !!(xhci_link_trb_quirk(xhci) || +- (ring->type == TYPE_ISOC && +- (xhci->quirks & XHCI_AMD_0x96_HOST))); ++ chain_links = xhci_link_chain_quirk(xhci, ring->type); + + next = ring->enq_seg->next; + xhci_link_segments(ring->enq_seg, first, ring->type, chain_links); +@@ -330,10 +327,7 @@ static int xhci_alloc_segments_for_ring( + unsigned int num = 0; + bool chain_links; + +- /* Set chain bit for 0.95 hosts, and for isoc rings on AMD 0.96 host */ +- chain_links = !!(xhci_link_trb_quirk(xhci) || +- (type == TYPE_ISOC && +- (xhci->quirks & XHCI_AMD_0x96_HOST))); ++ chain_links = xhci_link_chain_quirk(xhci, type); + + prev = xhci_segment_alloc(xhci, cycle_state, max_packet, num, flags); + if (!prev) +--- a/drivers/usb/host/xhci-ring.c ++++ b/drivers/usb/host/xhci-ring.c +@@ -245,9 +245,7 @@ static void inc_enq(struct xhci_hcd *xhc + * AMD 0.96 host, carry over the chain bit of the previous TRB + * (which may mean the chain bit is cleared). + */ +- if (!(ring->type == TYPE_ISOC && +- (xhci->quirks & XHCI_AMD_0x96_HOST)) && +- !xhci_link_trb_quirk(xhci)) { ++ if (!xhci_link_chain_quirk(xhci, ring->type)) { + next->link.control &= cpu_to_le32(~TRB_CHAIN); + next->link.control |= cpu_to_le32(chain); + } +@@ -3381,9 +3379,7 @@ static int prepare_ring(struct xhci_hcd + /* If we're not dealing with 0.95 hardware or isoc rings + * on AMD 0.96 host, clear the chain bit. + */ +- if (!xhci_link_trb_quirk(xhci) && +- !(ep_ring->type == TYPE_ISOC && +- (xhci->quirks & XHCI_AMD_0x96_HOST))) ++ if (!xhci_link_chain_quirk(xhci, ep_ring->type)) + ep_ring->enqueue->link.control &= + cpu_to_le32(~TRB_CHAIN); + else +--- a/drivers/usb/host/xhci.h ++++ b/drivers/usb/host/xhci.h +@@ -1784,9 +1784,12 @@ static inline void xhci_write_64(struct + lo_hi_writeq(val, regs); + } + +-static inline int xhci_link_trb_quirk(struct xhci_hcd *xhci) ++ ++/* Link TRB chain should always be set on 0.95 hosts, and AMD 0.96 ISOC rings */ ++static inline bool xhci_link_chain_quirk(struct xhci_hcd *xhci, enum xhci_ring_type type) + { +- return xhci->quirks & XHCI_LINK_TRB_QUIRK; ++ return (xhci->quirks & XHCI_LINK_TRB_QUIRK) || ++ (type == TYPE_ISOC && (xhci->quirks & XHCI_AMD_0x96_HOST)); + } + + /* xHCI debugging */ diff --git a/queue-6.6/wifi-mac80211-discard-beacon-frames-to-non-broadcast-address.patch b/queue-6.6/wifi-mac80211-discard-beacon-frames-to-non-broadcast-address.patch new file mode 100644 index 0000000000..daa87296b8 --- /dev/null +++ b/queue-6.6/wifi-mac80211-discard-beacon-frames-to-non-broadcast-address.patch @@ -0,0 +1,62 @@ +From stable+bounces-206054-greg=kroah.com@vger.kernel.org Wed Jan 7 00:28:45 2026 +From: Sasha Levin +Date: Tue, 6 Jan 2026 18:28:39 -0500 +Subject: wifi: mac80211: Discard Beacon frames to non-broadcast address +To: stable@vger.kernel.org +Cc: Jouni Malinen , Johannes Berg , Sasha Levin +Message-ID: <20260106232839.3452928-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 +[ changed RX_DROP 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 +@@ -3388,6 +3388,11 @@ ieee80211_rx_h_mgmt_check(struct ieee802 + rx->skb->len < IEEE80211_MIN_ACTION_SIZE) + return RX_DROP_U_RUNT_ACTION; + ++ /* Drop non-broadcast Beacon frames */ ++ if (ieee80211_is_beacon(mgmt->frame_control) && ++ !is_broadcast_ether_addr(mgmt->da)) ++ return RX_DROP_MONITOR; ++ + if (rx->sdata->vif.type == NL80211_IFTYPE_AP && + ieee80211_is_beacon(mgmt->frame_control) && + !(rx->flags & IEEE80211_RX_BEACON_REPORTED)) { diff --git a/queue-6.6/wifi-mt76-fix-dts-power-limits-on-little-endian-systems.patch b/queue-6.6/wifi-mt76-fix-dts-power-limits-on-little-endian-systems.patch new file mode 100644 index 0000000000..8b75467032 --- /dev/null +++ b/queue-6.6/wifi-mt76-fix-dts-power-limits-on-little-endian-systems.patch @@ -0,0 +1,139 @@ +From stable+bounces-204133-greg=kroah.com@vger.kernel.org Mon Dec 29 21:36:43 2025 +From: Sasha Levin +Date: Mon, 29 Dec 2025 15:36:31 -0500 +Subject: wifi: mt76: Fix DTS power-limits on little endian systems +To: stable@vger.kernel.org +Cc: "Sven Eckelmann (Plasma Cloud)" , Felix Fietkau , Sasha Levin +Message-ID: <20251229203631.1694637-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 +@@ -245,6 +245,19 @@ mt76_get_of_array(struct device_node *np + return prop->value; + } + ++static const s8 * ++mt76_get_of_array_s8(struct device_node *np, char *name, size_t *len, int min) ++{ ++ struct property *prop = of_find_property(np, name, NULL); ++ ++ if (!prop || !prop->value || prop->length < min) ++ return NULL; ++ ++ *len = prop->length; ++ ++ return prop->value; ++} ++ + static struct device_node * + mt76_find_channel_node(struct device_node *np, struct ieee80211_channel *chan) + { +@@ -284,7 +297,7 @@ mt76_get_txs_delta(struct device_node *n + } + + static void +-mt76_apply_array_limit(s8 *pwr, size_t pwr_len, const __be32 *data, ++mt76_apply_array_limit(s8 *pwr, size_t pwr_len, const s8 *data, + s8 target_power, s8 nss_delta, s8 *max_power) + { + int i; +@@ -293,15 +306,14 @@ mt76_apply_array_limit(s8 *pwr, size_t p + return; + + for (i = 0; i < pwr_len; i++) { +- pwr[i] = min_t(s8, target_power, +- be32_to_cpu(data[i]) + nss_delta); ++ pwr[i] = min_t(s8, target_power, data[i] + nss_delta); + *max_power = max(*max_power, pwr[i]); + } + } + + static void + mt76_apply_multi_array_limit(s8 *pwr, size_t pwr_len, s8 pwr_num, +- const __be32 *data, size_t len, s8 target_power, ++ const s8 *data, size_t len, s8 target_power, + s8 nss_delta, s8 *max_power) + { + int i, cur; +@@ -309,8 +321,7 @@ mt76_apply_multi_array_limit(s8 *pwr, si + if (!data) + return; + +- len /= 4; +- cur = be32_to_cpu(data[0]); ++ cur = data[0]; + for (i = 0; i < pwr_num; i++) { + if (len < pwr_len + 1) + break; +@@ -325,7 +336,7 @@ mt76_apply_multi_array_limit(s8 *pwr, si + if (!len) + break; + +- cur = be32_to_cpu(data[0]); ++ cur = data[0]; + } + } + +@@ -336,7 +347,7 @@ s8 mt76_get_rate_power_limits(struct mt7 + { + struct mt76_dev *dev = phy->dev; + struct device_node *np; +- const __be32 *val; ++ const s8 *val; + char name[16]; + u32 mcs_rates = dev->drv->mcs_rates; + u32 ru_rates = ARRAY_SIZE(dest->ru[0]); +@@ -382,21 +393,21 @@ s8 mt76_get_rate_power_limits(struct mt7 + + txs_delta = mt76_get_txs_delta(np, hweight8(phy->antenna_mask)); + +- val = mt76_get_of_array(np, "rates-cck", &len, ARRAY_SIZE(dest->cck)); ++ val = mt76_get_of_array_s8(np, "rates-cck", &len, ARRAY_SIZE(dest->cck)); + mt76_apply_array_limit(dest->cck, ARRAY_SIZE(dest->cck), val, + target_power, txs_delta, &max_power); + +- val = mt76_get_of_array(np, "rates-ofdm", +- &len, ARRAY_SIZE(dest->ofdm)); ++ val = mt76_get_of_array_s8(np, "rates-ofdm", ++ &len, ARRAY_SIZE(dest->ofdm)); + mt76_apply_array_limit(dest->ofdm, ARRAY_SIZE(dest->ofdm), val, + target_power, txs_delta, &max_power); + +- val = mt76_get_of_array(np, "rates-mcs", &len, mcs_rates + 1); ++ val = mt76_get_of_array_s8(np, "rates-mcs", &len, mcs_rates + 1); + mt76_apply_multi_array_limit(dest->mcs[0], ARRAY_SIZE(dest->mcs[0]), + ARRAY_SIZE(dest->mcs), val, len, + target_power, txs_delta, &max_power); + +- val = mt76_get_of_array(np, "rates-ru", &len, ru_rates + 1); ++ val = mt76_get_of_array_s8(np, "rates-ru", &len, ru_rates + 1); + mt76_apply_multi_array_limit(dest->ru[0], ARRAY_SIZE(dest->ru[0]), + ARRAY_SIZE(dest->ru), val, len, + target_power, txs_delta, &max_power); diff --git a/queue-6.6/xhci-dbgtty-fix-device-unregister-fixup.patch b/queue-6.6/xhci-dbgtty-fix-device-unregister-fixup.patch new file mode 100644 index 0000000000..12e41eab75 --- /dev/null +++ b/queue-6.6/xhci-dbgtty-fix-device-unregister-fixup.patch @@ -0,0 +1,40 @@ +From stable+bounces-204276-greg=kroah.com@vger.kernel.org Tue Dec 30 19:44:39 2025 +From: Sasha Levin +Date: Tue, 30 Dec 2025 13:43:21 -0500 +Subject: xhci: dbgtty: fix device unregister: fixup +To: stable@vger.kernel.org +Cc: "Łukasz Bartosik" , stable , "Greg Kroah-Hartman" , "Sasha Levin" +Message-ID: <20251230184321.2402789-2-sashal@kernel.org> + +From: Łukasz Bartosik + +[ Upstream commit 74098cc06e753d3ffd8398b040a3a1dfb65260c0 ] + +This fixup replaces tty_vhangup() call with call to +tty_port_tty_vhangup(). Both calls hangup tty device +synchronously however tty_port_tty_vhangup() increases +reference count during the hangup operation using +scoped_guard(tty_port_tty). + +Cc: stable +Fixes: 1f73b8b56cf3 ("xhci: dbgtty: fix device unregister") +Signed-off-by: Łukasz Bartosik +Link: https://patch.msgid.link/20251127111644.3161386-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 | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/usb/host/xhci-dbgtty.c ++++ b/drivers/usb/host/xhci-dbgtty.c +@@ -522,7 +522,7 @@ static void xhci_dbc_tty_unregister_devi + * Hang up the TTY. This wakes up any blocked + * writers and causes subsequent writes to fail. + */ +- tty_vhangup(port->port.tty); ++ tty_port_tty_vhangup(&port->port); + + tty_unregister_device(dbc_tty_driver, port->minor); + xhci_dbc_tty_exit_port(port);