--- /dev/null
+From stable+bounces-260602-greg=kroah.com@vger.kernel.org Fri Jun 5 07:15:41 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 4 Jun 2026 21:31:06 -0400
+Subject: ALSA: firewire-motu: Protect register DSP event queue positions
+To: stable@vger.kernel.org
+Cc: "Cássio Gabriel" <cassiogabrielcontato@gmail.com>, "Takashi Sakamoto" <o-takashi@sakamocchi.jp>, "Takashi Iwai" <tiwai@suse.de>, "Sasha Levin" <sashal@kernel.org>
+Message-ID: <20260605013107.2963134-1-sashal@kernel.org>
+
+From: Cássio Gabriel <cassiogabrielcontato@gmail.com>
+
+[ Upstream commit 98fb1c1bb11e29eb609b7200a25e136e05aa4498 ]
+
+The register DSP event queue is updated under parser->lock, but
+snd_motu_register_dsp_message_parser_count_event() reads pull_pos and
+push_pos without the lock.
+snd_motu_register_dsp_message_parser_copy_event() also reads both queue
+positions before taking the lock.
+
+Protect these accesses with parser->lock as well. This keeps the hwdep
+poll/read path consistent with the producer side and with the cached
+meter/parameter accessors.
+
+Fixes: 634ec0b2906e ("ALSA: firewire-motu: notify event for parameter change in register DSP model")
+Cc: stable@vger.kernel.org
+Signed-off-by: Cássio Gabriel <cassiogabrielcontato@gmail.com>
+Reviewed-by: Takashi Sakamoto <o-takashi@sakamocchi.jp>
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Link: https://patch.msgid.link/20260521-alsa-firewire-motu-event-locking-v1-1-708e1c2b5e56@gmail.com
+[ converted copy_event() from manual spin_lock_irqsave/spin_unlock_irqrestore to guard(spinlock_irqsave) ]
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ sound/firewire/motu/motu-register-dsp-message-parser.c | 14 +++++++-------
+ 1 file changed, 7 insertions(+), 7 deletions(-)
+
+--- a/sound/firewire/motu/motu-register-dsp-message-parser.c
++++ b/sound/firewire/motu/motu-register-dsp-message-parser.c
+@@ -393,6 +393,8 @@ unsigned int snd_motu_register_dsp_messa
+ {
+ struct msg_parser *parser = motu->message_parser;
+
++ guard(spinlock_irqsave)(&parser->lock);
++
+ if (parser->pull_pos > parser->push_pos)
+ return EVENT_QUEUE_SIZE - parser->pull_pos + parser->push_pos;
+ else
+@@ -402,14 +404,14 @@ unsigned int snd_motu_register_dsp_messa
+ bool snd_motu_register_dsp_message_parser_copy_event(struct snd_motu *motu, u32 *event)
+ {
+ struct msg_parser *parser = motu->message_parser;
+- unsigned int pos = parser->pull_pos;
+- unsigned long flags;
++ unsigned int pos;
+
+- if (pos == parser->push_pos)
+- return false;
++ guard(spinlock_irqsave)(&parser->lock);
+
+- spin_lock_irqsave(&parser->lock, flags);
++ if (parser->pull_pos == parser->push_pos)
++ return false;
+
++ pos = parser->pull_pos;
+ *event = parser->event_queue[pos];
+
+ ++pos;
+@@ -417,7 +419,5 @@ bool snd_motu_register_dsp_message_parse
+ pos = 0;
+ parser->pull_pos = pos;
+
+- spin_unlock_irqrestore(&parser->lock, flags);
+-
+ return true;
+ }
--- /dev/null
+From stable+bounces-263425-greg=kroah.com@vger.kernel.org Mon Jun 15 23:38:10 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 15 Jun 2026 14:08:00 -0400
+Subject: hv_netvsc: use kmap_local_page in netvsc_copy_to_send_buf
+To: stable@vger.kernel.org
+Cc: Anton Leontev <leontyevantony@gmail.com>, Paolo Abeni <pabeni@redhat.com>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260615180800.2317919-1-sashal@kernel.org>
+
+From: Anton Leontev <leontyevantony@gmail.com>
+
+[ Upstream commit 004e9ecfe6c5384f9e0b2f6f6389d42ec22789af ]
+
+netvsc_copy_to_send_buf() copies page buffer entries into the VMBus
+send buffer using phys_to_virt() on the entry PFN. Entries for the
+RNDIS header and the skb linear data come from kmalloc'd memory and
+are always in the kernel direct map, but entries for skb fragments
+reference page cache or user pages, which on 32-bit x86 with
+CONFIG_HIGHMEM=y can live above the LOWMEM boundary. For such a page
+phys_to_virt() returns an address outside the direct map and the
+subsequent memcpy() faults on the transmit softirq path, which is
+fatal.
+
+Map the pages with kmap_local_page() instead, handling two properties
+of the page buffer entries:
+
+ - pb[i].pfn is a Hyper-V PFN at HV_HYP_PAGE_SIZE (4K) granularity,
+ not a native PFN. Reconstruct the physical address first and derive
+ the native page from it, so the mapping stays correct where
+ PAGE_SIZE > HV_HYP_PAGE_SIZE (e.g. arm64 with 64K pages).
+
+ - Since commit 41a6328b2c55 ("hv_netvsc: Preserve contiguous PFN
+ grouping in the page buffer array"), an entry describes a full
+ physically contiguous fragment and pb[i].len can exceed PAGE_SIZE,
+ while kmap_local_page() maps a single page. Copy page by page,
+ splitting at native page boundaries.
+
+The copy path only handles packets smaller than the send section size
+(6144 bytes by default); larger packets take the cp_partial path where
+only the RNDIS header is copied. So entries here are bounded by the
+section size and a copy is split at most once on 4K-page systems. On
+!CONFIG_HIGHMEM configs kmap_local_page() folds to page_address() and
+no mapping work is added.
+
+Fixes: c25aaf814a63 ("hyperv: Enable sendbuf mechanism on the send path")
+Cc: stable@vger.kernel.org
+Signed-off-by: Anton Leontev <leontyevantony@gmail.com>
+Link: https://patch.msgid.link/20260604165938.32033-1-leontyevantony@gmail.com
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+[ adapted `phys_to_page(paddr)` to `pfn_to_page(PHYS_PFN(paddr))` ]
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/net/hyperv/netvsc.c | 19 +++++++++++++++----
+ 1 file changed, 15 insertions(+), 4 deletions(-)
+
+--- a/drivers/net/hyperv/netvsc.c
++++ b/drivers/net/hyperv/netvsc.c
+@@ -12,6 +12,7 @@
+ #include <linux/sched.h>
+ #include <linux/wait.h>
+ #include <linux/mm.h>
++#include <linux/highmem.h>
+ #include <linux/delay.h>
+ #include <linux/io.h>
+ #include <linux/slab.h>
+@@ -957,12 +958,22 @@ static void netvsc_copy_to_send_buf(stru
+ }
+
+ for (i = 0; i < page_count; i++) {
+- char *src = phys_to_virt(pb[i].pfn << HV_HYP_PAGE_SHIFT);
+- u32 offset = pb[i].offset;
++ phys_addr_t paddr = (pb[i].pfn << HV_HYP_PAGE_SHIFT) +
++ pb[i].offset;
+ u32 len = pb[i].len;
+
+- memcpy(dest, (src + offset), len);
+- dest += len;
++ while (len) {
++ struct page *page = pfn_to_page(PHYS_PFN(paddr));
++ u32 off = offset_in_page(paddr);
++ u32 chunk = min_t(u32, len, PAGE_SIZE - off);
++ char *src = kmap_local_page(page);
++
++ memcpy(dest, src + off, chunk);
++ kunmap_local(src);
++ dest += chunk;
++ paddr += chunk;
++ len -= chunk;
++ }
+ }
+
+ if (padding)
--- /dev/null
+From stable+bounces-260560-greg=kroah.com@vger.kernel.org Fri Jun 5 00:33:19 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 4 Jun 2026 14:57:11 -0400
+Subject: iio: chemical: scd30: fix division by zero in write_raw
+To: stable@vger.kernel.org
+Cc: Antoniu Miclaus <antoniu.miclaus@analog.com>, Stable@vger.kernel.org, Jonathan Cameron <jic23@kernel.org>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260604185711.605210-2-sashal@kernel.org>
+
+From: Antoniu Miclaus <antoniu.miclaus@analog.com>
+
+[ Upstream commit 5aba4f94b225617a55fed442a70329b2ee19c0a5 ]
+
+Add a zero check for val2 before using it as a divisor when setting the
+sampling frequency. A user writing a zero fractional part to the
+sampling_frequency sysfs attribute triggers a division by zero in the
+kernel.
+
+Fixes: 64b3d8b1b0f5 ("iio: chemical: scd30: add core driver")
+Signed-off-by: Antoniu Miclaus <antoniu.miclaus@analog.com>
+Cc: <Stable@vger.kernel.org>
+Signed-off-by: Jonathan Cameron <jic23@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/iio/chemical/scd30_core.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/iio/chemical/scd30_core.c
++++ b/drivers/iio/chemical/scd30_core.c
+@@ -257,7 +257,7 @@ static int scd30_write_raw(struct iio_de
+ guard(mutex)(&state->lock);
+ switch (mask) {
+ case IIO_CHAN_INFO_SAMP_FREQ:
+- if (val)
++ if (val || !val2)
+ return -EINVAL;
+
+ val = 1000000000 / val2;
--- /dev/null
+From stable+bounces-260559-greg=kroah.com@vger.kernel.org Fri Jun 5 00:32:46 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 4 Jun 2026 14:57:10 -0400
+Subject: iio: chemical: scd30: Use guard(mutex) to allow early returns
+To: stable@vger.kernel.org
+Cc: Jonathan Cameron <Jonathan.Cameron@huawei.com>, David Lechner <dlechner@baylibre.com>, Tomasz Duszynski <tomasz.duszynski@octakon.com>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260604185711.605210-1-sashal@kernel.org>
+
+From: Jonathan Cameron <Jonathan.Cameron@huawei.com>
+
+[ Upstream commit 5feb5532870fbced5d6f450b8061a33f461b88ca ]
+
+Auto cleanup based release of the lock allows for simpler code flow in a
+few functions with large multiplexing style switch statements and no
+common operations following the switch.
+
+Suggested-by: David Lechner <dlechner@baylibre.com>
+Cc: Tomasz Duszynski <tomasz.duszynski@octakon.com>
+Reviewed-by: David Lechner <dlechner@baylibre.com>
+Link: https://patch.msgid.link/20250209180624.701140-3-jic23@kernel.org
+Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
+Stable-dep-of: 5aba4f94b225 ("iio: chemical: scd30: fix division by zero in write_raw")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/iio/chemical/scd30_core.c | 63 ++++++++++++++++----------------------
+ 1 file changed, 28 insertions(+), 35 deletions(-)
+
+--- a/drivers/iio/chemical/scd30_core.c
++++ b/drivers/iio/chemical/scd30_core.c
+@@ -5,6 +5,7 @@
+ * Copyright (c) 2020 Tomasz Duszynski <tomasz.duszynski@octakon.com>
+ */
+ #include <linux/bits.h>
++#include <linux/cleanup.h>
+ #include <linux/completion.h>
+ #include <linux/delay.h>
+ #include <linux/device.h>
+@@ -198,112 +199,104 @@ static int scd30_read_raw(struct iio_dev
+ int *val, int *val2, long mask)
+ {
+ struct scd30_state *state = iio_priv(indio_dev);
+- int ret = -EINVAL;
++ int ret;
+ u16 tmp;
+
+- mutex_lock(&state->lock);
++ guard(mutex)(&state->lock);
+ switch (mask) {
+ case IIO_CHAN_INFO_RAW:
+ case IIO_CHAN_INFO_PROCESSED:
+ if (chan->output) {
+ *val = state->pressure_comp;
+- ret = IIO_VAL_INT;
+- break;
++ return IIO_VAL_INT;
+ }
+
+ ret = iio_device_claim_direct_mode(indio_dev);
+ if (ret)
+- break;
++ return ret;
+
+ ret = scd30_read(state);
+ if (ret) {
+ iio_device_release_direct_mode(indio_dev);
+- break;
++ return ret;
+ }
+
+ *val = state->meas[chan->address];
+ iio_device_release_direct_mode(indio_dev);
+- ret = IIO_VAL_INT;
+- break;
++ return IIO_VAL_INT;
+ case IIO_CHAN_INFO_SCALE:
+ *val = 0;
+ *val2 = 1;
+- ret = IIO_VAL_INT_PLUS_MICRO;
+- break;
++ return IIO_VAL_INT_PLUS_MICRO;
+ case IIO_CHAN_INFO_SAMP_FREQ:
+ ret = scd30_command_read(state, CMD_MEAS_INTERVAL, &tmp);
+ if (ret)
+- break;
++ return ret;
+
+ *val = 0;
+ *val2 = 1000000000 / tmp;
+- ret = IIO_VAL_INT_PLUS_NANO;
+- break;
++ return IIO_VAL_INT_PLUS_NANO;
+ case IIO_CHAN_INFO_CALIBBIAS:
+ ret = scd30_command_read(state, CMD_TEMP_OFFSET, &tmp);
+ if (ret)
+- break;
++ return ret;
+
+ *val = tmp;
+- ret = IIO_VAL_INT;
+- break;
++ return IIO_VAL_INT;
++ default:
++ return -EINVAL;
+ }
+- mutex_unlock(&state->lock);
+-
+- return ret;
+ }
+
+ static int scd30_write_raw(struct iio_dev *indio_dev, struct iio_chan_spec const *chan,
+ int val, int val2, long mask)
+ {
+ struct scd30_state *state = iio_priv(indio_dev);
+- int ret = -EINVAL;
++ int ret;
+
+- mutex_lock(&state->lock);
++ guard(mutex)(&state->lock);
+ switch (mask) {
+ case IIO_CHAN_INFO_SAMP_FREQ:
+ if (val)
+- break;
++ return -EINVAL;
+
+ val = 1000000000 / val2;
+ if (val < SCD30_MEAS_INTERVAL_MIN_S || val > SCD30_MEAS_INTERVAL_MAX_S)
+- break;
++ return -EINVAL;
+
+ ret = scd30_command_write(state, CMD_MEAS_INTERVAL, val);
+ if (ret)
+- break;
++ return ret;
+
+ state->meas_interval = val;
+- break;
++ return 0;
+ case IIO_CHAN_INFO_RAW:
+ switch (chan->type) {
+ case IIO_PRESSURE:
+ if (val < SCD30_PRESSURE_COMP_MIN_MBAR ||
+ val > SCD30_PRESSURE_COMP_MAX_MBAR)
+- break;
++ return -EINVAL;
+
+ ret = scd30_command_write(state, CMD_START_MEAS, val);
+ if (ret)
+- break;
++ return ret;
+
+ state->pressure_comp = val;
+- break;
++ return 0;
+ default:
+- break;
++ return -EINVAL;
+ }
+- break;
+ case IIO_CHAN_INFO_CALIBBIAS:
+ if (val < 0 || val > SCD30_TEMP_OFFSET_MAX)
+- break;
++ return -EINVAL;
+ /*
+ * Manufacturer does not explicitly specify min/max sensible
+ * values hence check is omitted for simplicity.
+ */
+- ret = scd30_command_write(state, CMD_TEMP_OFFSET / 10, val);
++ return scd30_command_write(state, CMD_TEMP_OFFSET / 10, val);
++ default:
++ return -EINVAL;
+ }
+- mutex_unlock(&state->lock);
+-
+- return ret;
+ }
+
+ static int scd30_write_raw_get_fmt(struct iio_dev *indio_dev, struct iio_chan_spec const *chan,
--- /dev/null
+From stable+bounces-260592-greg=kroah.com@vger.kernel.org Fri Jun 5 06:04:46 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 4 Jun 2026 20:34:32 -0400
+Subject: iio: dac: ad5686: fix ref bit initialization for single-channel parts
+To: stable@vger.kernel.org
+Cc: Rodrigo Alencar <rodrigo.alencar@analog.com>, Andy Shevchenko <andriy.shevchenko@intel.com>, Stable@vger.kernel.org, Jonathan Cameron <jic23@kernel.org>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260605003432.2705436-1-sashal@kernel.org>
+
+From: Rodrigo Alencar <rodrigo.alencar@analog.com>
+
+[ Upstream commit ecae2ae606d493cf11457946436335bd0e726663 ]
+
+The reference bit position was ignored when writing the register at the
+probe() function (!!val was used). When such bit is 1, internal voltage
+reference is disabled so that an external one can be used. For
+multi-channel devices, bit 0 of the Internal Reference Setup command
+behaves the same way, so AD5686_REF_BIT_MSK is created. The issue exists
+since support for single-channel devices were first introduced.
+
+Fixes: be1b24d24541 ("iio:dac:ad5686: Add AD5691R/AD5692R/AD5693/AD5693R support")
+Reviewed-by: Andy Shevchenko <andriy.shevchenko@intel.com>
+Signed-off-by: Rodrigo Alencar <rodrigo.alencar@analog.com>
+Cc: <Stable@vger.kernel.org>
+Signed-off-by: Jonathan Cameron <jic23@kernel.org>
+[ adapted `has_external_vref` to the in-tree equivalent `voltage_uv` variable in the `val =` computation ]
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/iio/dac/ad5686.c | 6 +++---
+ drivers/iio/dac/ad5686.h | 1 +
+ 2 files changed, 4 insertions(+), 3 deletions(-)
+
+--- a/drivers/iio/dac/ad5686.c
++++ b/drivers/iio/dac/ad5686.c
+@@ -528,7 +528,7 @@ int ad5686_probe(struct device *dev,
+ break;
+ case AD5686_REGMAP:
+ cmd = AD5686_CMD_INTERNAL_REFER_SETUP;
+- ref_bit_msk = 0;
++ ref_bit_msk = AD5686_REF_BIT_MSK;
+ break;
+ case AD5693_REGMAP:
+ cmd = AD5686_CMD_CONTROL_REG;
+@@ -540,9 +540,9 @@ int ad5686_probe(struct device *dev,
+ goto error_disable_reg;
+ }
+
+- val = (voltage_uv | ref_bit_msk);
++ val = voltage_uv ? ref_bit_msk : 0;
+
+- ret = st->write(st, cmd, 0, !!val);
++ ret = st->write(st, cmd, 0, val);
+ if (ret)
+ goto error_disable_reg;
+
+--- a/drivers/iio/dac/ad5686.h
++++ b/drivers/iio/dac/ad5686.h
+@@ -46,6 +46,7 @@
+
+ #define AD5310_REF_BIT_MSK BIT(8)
+ #define AD5683_REF_BIT_MSK BIT(12)
++#define AD5686_REF_BIT_MSK BIT(0)
+ #define AD5693_REF_BIT_MSK BIT(12)
+
+ /**
--- /dev/null
+From stable+bounces-260547-greg=kroah.com@vger.kernel.org Thu Jun 4 23:08:08 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 4 Jun 2026 13:37:58 -0400
+Subject: iio: gyro: adis16260: fix division by zero in write_raw
+To: stable@vger.kernel.org
+Cc: "Antoniu Miclaus" <antoniu.miclaus@analog.com>, "Nuno Sá" <nuno.sa@analog.com>, Stable@vger.kernel.org, "Jonathan Cameron" <Jonathan.Cameron@huawei.com>, "Sasha Levin" <sashal@kernel.org>
+Message-ID: <20260604173758.25903-1-sashal@kernel.org>
+
+From: Antoniu Miclaus <antoniu.miclaus@analog.com>
+
+[ Upstream commit 761e8b489e6cf166c574034b70637f8a7eadd0ee ]
+
+Add a validation check for the sampling frequency value before using it
+as a divisor. A user writing zero to the sampling_frequency sysfs
+attribute triggers a division by zero in the kernel.
+
+Fixes: 089a41985c6c ("staging: iio: adis16260 digital gyro driver")
+Signed-off-by: Antoniu Miclaus <antoniu.miclaus@analog.com>
+Reviewed-by: Nuno Sá <nuno.sa@analog.com>
+Cc: <Stable@vger.kernel.org>
+Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/iio/gyro/adis16260.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+--- a/drivers/iio/gyro/adis16260.c
++++ b/drivers/iio/gyro/adis16260.c
+@@ -288,6 +288,9 @@ static int adis16260_write_raw(struct ii
+ addr = adis16260_addresses[chan->scan_index][1];
+ return adis_write_reg_16(adis, addr, val);
+ case IIO_CHAN_INFO_SAMP_FREQ:
++ if (val <= 0)
++ return -EINVAL;
++
+ adis_dev_lock(adis);
+ if (spi_get_device_id(adis->spi)->driver_data)
+ t = 256 / val;
--- /dev/null
+From stable+bounces-260593-greg=kroah.com@vger.kernel.org Fri Jun 5 06:04:59 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 4 Jun 2026 20:34:51 -0400
+Subject: memfd: deny writeable mappings when implying SEAL_WRITE
+To: stable@vger.kernel.org
+Cc: "Pratyush Yadav (Google)" <pratyush@kernel.org>, Pasha Tatashin <pasha.tatashin@soleen.com>, Jeff Xu <jeffxu@google.com>, Baolin Wang <baolin.wang@linux.alibaba.com>, Brendan Jackman <jackmanb@google.com>, Greg Thelen <gthelen@google.com>, Hugh Dickins <hughd@google.com>, Kees Cook <kees@kernel.org>, "David Hildenbrand (Arm)" <david@kernel.org>, Andrew Morton <akpm@linux-foundation.org>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260605003451.2707256-1-sashal@kernel.org>
+
+From: "Pratyush Yadav (Google)" <pratyush@kernel.org>
+
+[ Upstream commit 3b041514cb6eae45869b020f743c14d983363222 ]
+
+When SEAL_EXEC is added, SEAL_WRITE is implied to make W^X. But the
+implied seal is set after the check that makes sure the memfd can not have
+any writable mappings. This means one can use SEAL_EXEC to apply
+SEAL_WRITE while having writeable mappings.
+
+This breaks the contract that SEAL_WRITE provides and can be used by an
+attacker to pass a memfd that appears to be write sealed but can still be
+modified arbitrarily.
+
+Fix this by adding the implied seals before the call for
+mapping_deny_writable() is done.
+
+Link: https://lore.kernel.org/20260505133922.797635-1-pratyush@kernel.org
+Fixes: c4f75bc8bd6b ("mm/memfd: add write seals when apply SEAL_EXEC to executable memfd")
+Signed-off-by: Pratyush Yadav (Google) <pratyush@kernel.org>
+Reviewed-by: Pasha Tatashin <pasha.tatashin@soleen.com>
+Acked-by: Jeff Xu <jeffxu@google.com>
+Cc: Baolin Wang <baolin.wang@linux.alibaba.com>
+Cc: Brendan Jackman <jackmanb@google.com>
+Cc: Greg Thelen <gthelen@google.com>
+Cc: Hugh Dickins <hughd@google.com>
+Cc: Kees Cook <kees@kernel.org>
+Cc: "David Hildenbrand (Arm)" <david@kernel.org>
+Cc: <stable@vger.kernel.org>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ mm/memfd.c | 12 ++++++------
+ 1 file changed, 6 insertions(+), 6 deletions(-)
+
+--- a/mm/memfd.c
++++ b/mm/memfd.c
+@@ -210,6 +210,12 @@ static int memfd_add_seals(struct file *
+ goto unlock;
+ }
+
++ /*
++ * SEAL_EXEC implies SEAL_WRITE, making W^X from the start.
++ */
++ if (seals & F_SEAL_EXEC && inode->i_mode & 0111)
++ seals |= F_SEAL_SHRINK|F_SEAL_GROW|F_SEAL_WRITE|F_SEAL_FUTURE_WRITE;
++
+ if ((seals & F_SEAL_WRITE) && !(*file_seals & F_SEAL_WRITE)) {
+ error = mapping_deny_writable(file->f_mapping);
+ if (error)
+@@ -222,12 +228,6 @@ static int memfd_add_seals(struct file *
+ }
+ }
+
+- /*
+- * SEAL_EXEC implys SEAL_WRITE, making W^X from the start.
+- */
+- if (seals & F_SEAL_EXEC && inode->i_mode & 0111)
+- seals |= F_SEAL_SHRINK|F_SEAL_GROW|F_SEAL_WRITE|F_SEAL_FUTURE_WRITE;
+-
+ *file_seals |= seals;
+ error = 0;
+
--- /dev/null
+From stable+bounces-263330-greg=kroah.com@vger.kernel.org Mon Jun 15 21:12:52 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 15 Jun 2026 11:39:01 -0400
+Subject: mm/hugetlb: rename folio_putback_active_hugetlb() to folio_putback_hugetlb()
+To: stable@vger.kernel.org
+Cc: David Hildenbrand <david@redhat.com>, Baolin Wang <baolin.wang@linux.alibaba.com>, "Matthew Wilcox (Oracle)" <willy@infradead.org>, Muchun Song <muchun.song@linux.dev>, Sidhartha Kumar <sidhartha.kumar@oracle.com>, Andrew Morton <akpm@linux-foundation.org>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260615153903.2214102-3-sashal@kernel.org>
+
+From: David Hildenbrand <david@redhat.com>
+
+[ Upstream commit b235448e8cab7eea17d164efc7bf55505985ba65 ]
+
+Now that folio_putback_hugetlb() is only called on folios that were
+previously isolated through folio_isolate_hugetlb(), let's rename it to
+match folio_putback_lru().
+
+Add some kernel doc to clarify how this function is supposed to be used.
+
+Link: https://lkml.kernel.org/r/20250113131611.2554758-5-david@redhat.com
+Signed-off-by: David Hildenbrand <david@redhat.com>
+Reviewed-by: Baolin Wang <baolin.wang@linux.alibaba.com>
+Cc: Matthew Wilcox (Oracle) <willy@infradead.org>
+Cc: Muchun Song <muchun.song@linux.dev>
+Cc: Sidhartha Kumar <sidhartha.kumar@oracle.com>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Stable-dep-of: 3c2d42b8ee34 ("mm/memory-failure: fix hugetlb_lock AA deadlock in get_huge_page_for_hwpoison")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ include/linux/hugetlb.h | 4 ++--
+ mm/hugetlb.c | 15 +++++++++++++--
+ mm/migrate.c | 6 +++---
+ 3 files changed, 18 insertions(+), 7 deletions(-)
+
+--- a/include/linux/hugetlb.h
++++ b/include/linux/hugetlb.h
+@@ -166,7 +166,7 @@ bool folio_isolate_hugetlb(struct folio
+ int get_hwpoison_hugetlb_folio(struct folio *folio, bool *hugetlb, bool unpoison);
+ int get_huge_page_for_hwpoison(unsigned long pfn, int flags,
+ bool *migratable_cleared);
+-void folio_putback_active_hugetlb(struct folio *folio);
++void folio_putback_hugetlb(struct folio *folio);
+ void move_hugetlb_state(struct folio *old_folio, struct folio *new_folio, int reason);
+ void hugetlb_fix_reserve_counts(struct inode *inode);
+ extern struct mutex *hugetlb_fault_mutex_table;
+@@ -462,7 +462,7 @@ static inline int get_huge_page_for_hwpo
+ return 0;
+ }
+
+-static inline void folio_putback_active_hugetlb(struct folio *folio)
++static inline void folio_putback_hugetlb(struct folio *folio)
+ {
+ }
+
+--- a/mm/hugetlb.c
++++ b/mm/hugetlb.c
+@@ -7259,7 +7259,7 @@ __weak unsigned long hugetlb_mask_last_p
+ * it is already isolated/non-migratable.
+ *
+ * On success, an additional folio reference is taken that must be dropped
+- * using folio_putback_active_hugetlb() to undo the isolation.
++ * using folio_putback_hugetlb() to undo the isolation.
+ *
+ * Return: True if isolation worked, otherwise False.
+ */
+@@ -7311,7 +7311,18 @@ int get_huge_page_for_hwpoison(unsigned
+ return ret;
+ }
+
+-void folio_putback_active_hugetlb(struct folio *folio)
++/**
++ * folio_putback_hugetlb - unisolate a hugetlb folio
++ * @folio: the isolated hugetlb folio
++ *
++ * Putback/un-isolate the hugetlb folio that was previous isolated using
++ * folio_isolate_hugetlb(): marking it non-isolated/migratable and putting it
++ * back onto the active list.
++ *
++ * Will drop the additional folio reference obtained through
++ * folio_isolate_hugetlb().
++ */
++void folio_putback_hugetlb(struct folio *folio)
+ {
+ spin_lock_irq(&hugetlb_lock);
+ folio_set_hugetlb_migratable(folio);
+--- a/mm/migrate.c
++++ b/mm/migrate.c
+@@ -151,7 +151,7 @@ void putback_movable_pages(struct list_h
+
+ list_for_each_entry_safe(folio, folio2, l, lru) {
+ if (unlikely(folio_test_hugetlb(folio))) {
+- folio_putback_active_hugetlb(folio);
++ folio_putback_hugetlb(folio);
+ continue;
+ }
+ list_del(&folio->lru);
+@@ -1373,7 +1373,7 @@ static int unmap_and_move_huge_page(new_
+
+ if (folio_ref_count(src) == 1) {
+ /* page was freed from under us. So we are done. */
+- folio_putback_active_hugetlb(src);
++ folio_putback_hugetlb(src);
+ return MIGRATEPAGE_SUCCESS;
+ }
+
+@@ -1456,7 +1456,7 @@ out_unlock:
+ folio_unlock(src);
+ out:
+ if (rc == MIGRATEPAGE_SUCCESS)
+- folio_putback_active_hugetlb(src);
++ folio_putback_hugetlb(src);
+ else if (rc != -EAGAIN)
+ list_move_tail(&src->lru, ret);
+
--- /dev/null
+From stable+bounces-263328-greg=kroah.com@vger.kernel.org Mon Jun 15 21:12:40 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 15 Jun 2026 11:38:59 -0400
+Subject: mm/hugetlb: rename isolate_hugetlb() to folio_isolate_hugetlb()
+To: stable@vger.kernel.org
+Cc: David Hildenbrand <david@redhat.com>, "Matthew Wilcox (Oracle)" <willy@infradead.org>, Baolin Wang <baolin.wang@linux.alibaba.com>, Muchun Song <muchun.song@linux.dev>, Sidhartha Kumar <sidhartha.kumar@oracle.com>, Andrew Morton <akpm@linux-foundation.org>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260615153903.2214102-1-sashal@kernel.org>
+
+From: David Hildenbrand <david@redhat.com>
+
+[ Upstream commit 4c640f128074e0d4459ecf072595a44df5c2ae18 ]
+
+Let's make the function name match "folio_isolate_lru()", and add some
+kernel doc.
+
+Link: https://lkml.kernel.org/r/20250113131611.2554758-3-david@redhat.com
+Signed-off-by: David Hildenbrand <david@redhat.com>
+Reviewed-by: Matthew Wilcox (Oracle) <willy@infradead.org>
+Reviewed-by: Baolin Wang <baolin.wang@linux.alibaba.com>
+Cc: Muchun Song <muchun.song@linux.dev>
+Cc: Sidhartha Kumar <sidhartha.kumar@oracle.com>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Stable-dep-of: 3c2d42b8ee34 ("mm/memory-failure: fix hugetlb_lock AA deadlock in get_huge_page_for_hwpoison")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ include/linux/hugetlb.h | 4 ++--
+ mm/gup.c | 2 +-
+ mm/hugetlb.c | 25 +++++++++++++++++++------
+ mm/memory-failure.c | 2 +-
+ mm/memory_hotplug.c | 2 +-
+ mm/mempolicy.c | 2 +-
+ mm/migrate.c | 4 ++--
+ 7 files changed, 27 insertions(+), 14 deletions(-)
+
+--- a/include/linux/hugetlb.h
++++ b/include/linux/hugetlb.h
+@@ -162,7 +162,7 @@ bool hugetlb_reserve_pages(struct inode
+ vm_flags_t vm_flags);
+ long hugetlb_unreserve_pages(struct inode *inode, long start, long end,
+ long freed);
+-bool isolate_hugetlb(struct folio *folio, struct list_head *list);
++bool folio_isolate_hugetlb(struct folio *folio, struct list_head *list);
+ int get_hwpoison_hugetlb_folio(struct folio *folio, bool *hugetlb, bool unpoison);
+ int get_huge_page_for_hwpoison(unsigned long pfn, int flags,
+ bool *migratable_cleared);
+@@ -446,7 +446,7 @@ static inline pte_t *huge_pte_offset(str
+ return NULL;
+ }
+
+-static inline bool isolate_hugetlb(struct folio *folio, struct list_head *list)
++static inline bool folio_isolate_hugetlb(struct folio *folio, struct list_head *list)
+ {
+ return false;
+ }
+--- a/mm/gup.c
++++ b/mm/gup.c
+@@ -1971,7 +1971,7 @@ static unsigned long collect_longterm_un
+ continue;
+
+ if (folio_test_hugetlb(folio)) {
+- isolate_hugetlb(folio, movable_page_list);
++ folio_isolate_hugetlb(folio, movable_page_list);
+ continue;
+ }
+
+--- a/mm/hugetlb.c
++++ b/mm/hugetlb.c
+@@ -2969,7 +2969,7 @@ retry:
+ * Fail with -EBUSY if not possible.
+ */
+ spin_unlock_irq(&hugetlb_lock);
+- isolated = isolate_hugetlb(old_folio, list);
++ isolated = folio_isolate_hugetlb(old_folio, list);
+ ret = isolated ? 0 : -EBUSY;
+ spin_lock_irq(&hugetlb_lock);
+ goto free_new;
+@@ -3045,7 +3045,7 @@ int isolate_or_dissolve_huge_page(struct
+ if (hstate_is_gigantic(h))
+ return -ENOMEM;
+
+- if (folio_ref_count(folio) && isolate_hugetlb(folio, list))
++ if (folio_ref_count(folio) && folio_isolate_hugetlb(folio, list))
+ ret = 0;
+ else if (!folio_ref_count(folio))
+ ret = alloc_and_dissolve_hugetlb_folio(h, folio, list);
+@@ -7246,11 +7246,24 @@ __weak unsigned long hugetlb_mask_last_p
+
+ #endif /* CONFIG_ARCH_WANT_GENERAL_HUGETLB */
+
+-/*
+- * These functions are overwritable if your architecture needs its own
+- * behavior.
++/**
++ * folio_isolate_hugetlb - try to isolate an allocated hugetlb folio
++ * @folio: the folio to isolate
++ * @list: the list to add the folio to on success
++ *
++ * Isolate an allocated (refcount > 0) hugetlb folio, marking it as
++ * isolated/non-migratable, and moving it from the active list to the
++ * given list.
++ *
++ * Isolation will fail if @folio is not an allocated hugetlb folio, or if
++ * it is already isolated/non-migratable.
++ *
++ * On success, an additional folio reference is taken that must be dropped
++ * using folio_putback_active_hugetlb() to undo the isolation.
++ *
++ * Return: True if isolation worked, otherwise False.
+ */
+-bool isolate_hugetlb(struct folio *folio, struct list_head *list)
++bool folio_isolate_hugetlb(struct folio *folio, struct list_head *list)
+ {
+ bool ret = true;
+
+--- a/mm/memory-failure.c
++++ b/mm/memory-failure.c
+@@ -2639,7 +2639,7 @@ static bool isolate_page(struct page *pa
+ bool isolated = false;
+
+ if (PageHuge(page)) {
+- isolated = isolate_hugetlb(page_folio(page), pagelist);
++ isolated = folio_isolate_hugetlb(page_folio(page), pagelist);
+ } else {
+ bool lru = !__PageMovable(page);
+
+--- a/mm/memory_hotplug.c
++++ b/mm/memory_hotplug.c
+@@ -1720,7 +1720,7 @@ static void do_migrate_range(unsigned lo
+
+ if (PageHuge(page)) {
+ pfn = page_to_pfn(head) + compound_nr(head) - 1;
+- isolate_hugetlb(folio, &source);
++ folio_isolate_hugetlb(folio, &source);
+ continue;
+ } else if (PageTransHuge(page))
+ pfn = page_to_pfn(head) + thp_nr_pages(page) - 1;
+--- a/mm/mempolicy.c
++++ b/mm/mempolicy.c
+@@ -608,7 +608,7 @@ static int queue_folios_hugetlb(pte_t *p
+ */
+ if ((flags & MPOL_MF_MOVE_ALL) ||
+ (folio_estimated_sharers(folio) == 1 && !hugetlb_pmd_shared(pte)))
+- if (!isolate_hugetlb(folio, qp->pagelist))
++ if (!folio_isolate_hugetlb(folio, qp->pagelist))
+ qp->nr_failed++;
+ unlock:
+ spin_unlock(ptl);
+--- a/mm/migrate.c
++++ b/mm/migrate.c
+@@ -142,7 +142,7 @@ static void putback_movable_folio(struct
+ *
+ * This function shall be used whenever the isolated pageset has been
+ * built from lru, balloon, hugetlbfs page. See isolate_migratepages_range()
+- * and isolate_hugetlb().
++ * and folio_isolate_hugetlb().
+ */
+ void putback_movable_pages(struct list_head *l)
+ {
+@@ -2113,7 +2113,7 @@ static int add_page_for_migration(struct
+
+ if (PageHuge(page)) {
+ if (PageHead(page)) {
+- isolated = isolate_hugetlb(page_folio(page), pagelist);
++ isolated = folio_isolate_hugetlb(page_folio(page), pagelist);
+ err = isolated ? 1 : -EBUSY;
+ }
+ } else {
--- /dev/null
+From stable+bounces-263332-greg=kroah.com@vger.kernel.org Mon Jun 15 21:13:02 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 15 Jun 2026 11:39:03 -0400
+Subject: mm/memory-failure: fix hugetlb_lock AA deadlock in get_huge_page_for_hwpoison
+To: stable@vger.kernel.org
+Cc: Wupeng Ma <mawupeng1@huawei.com>, "Oscar Salvador (SUSE)" <osalvador@kernel.org>, Muchun Song <muchun.song@linux.dev>, Kefeng Wang <wangkefeng.wang@huawei.com>, Miaohe Lin <linmiaohe@huawei.com>, David Hildenbrand <david@kernel.org>, Liam Howlett <liam.howlett@oracle.com>, Lorenzo Stoakes <ljs@kernel.org>, Michal Hocko <mhocko@suse.com>, Mike Rapoport <rppt@kernel.org>, Naoya Horiguchi <nao.horiguchi@gmail.com>, Suren Baghdasaryan <surenb@google.com>, Vlastimil Babka <vbabka@kernel.org>, Andrew Morton <akpm@linux-foundation.org>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260615153903.2214102-5-sashal@kernel.org>
+
+From: Wupeng Ma <mawupeng1@huawei.com>
+
+[ Upstream commit 3c2d42b8ee345b17a4ba56b0f6492d1ff4c1178e ]
+
+Two concurrent madvise(MADV_HWPOISON) calls on the same hugetlb page can
+trigger a recursive spinlock self-deadlock (AA deadlock) on hugetlb_lock
+when racing with a concurrent unmap:
+
+ thread#0 thread#1
+ -------- --------
+ madvise(folio, MADV_HWPOISON)
+ -> poisons the folio successfully
+ madvise(folio, MADV_HWPOISON) unmap(folio)
+ try_memory_failure_hugetlb
+ get_huge_page_for_hwpoison
+ spin_lock_irq(&hugetlb_lock) <- held
+ __get_huge_page_for_hwpoison
+ hugetlb_update_hwpoison()
+ -> MF_HUGETLB_FOLIO_PRE_POISONED
+ goto out:
+ folio_put()
+ refcount: 1 -> 0
+ free_huge_folio()
+ spin_lock_irqsave(&hugetlb_lock)
+ -> AA DEADLOCK!
+
+The out: path in __get_huge_page_for_hwpoison() calls folio_put() to drop
+the GUP reference while the hugetlb_lock is still held by the hugetlb.c
+wrapper get_huge_page_for_hwpoison(). If concurrent unmap has released
+the page table mapping reference, folio_put() drops the folio refcount to
+zero, triggering free_huge_folio() which attempts to re-acquire the
+non-recursive hugetlb_lock.
+
+Fix this by moving hugetlb_lock acquisition from the hugetlb.c wrapper
+into get_huge_page_for_hwpoison(). Place spin_unlock_irq() before the
+folio_put() at the out: label so the folio is always released outside the
+lock.
+
+[akpm@linux-foundation.org: fix race, rename label per Miaohe]
+ Link: https://sashiko.dev/#/patchset/20260522010305.4099834-1-mawupeng1@huawei.com
+ Link: https://lore.kernel.org/f39f405e-4b4b-8f79-70fe-a2b5b62114eb@huawei.com
+Link: https://lore.kernel.org/20260522010305.4099834-1-mawupeng1@huawei.com
+Fixes: 405ce051236c ("mm/hwpoison: fix race between hugetlb free/demotion and memory_failure_hugetlb()")
+Signed-off-by: Wupeng Ma <mawupeng1@huawei.com>
+Acked-by: Oscar Salvador (SUSE) <osalvador@kernel.org>
+Acked-by: Muchun Song <muchun.song@linux.dev>
+Reviewed-by: Kefeng Wang <wangkefeng.wang@huawei.com>
+Acked-by: Miaohe Lin <linmiaohe@huawei.com>
+Cc: David Hildenbrand <david@kernel.org>
+Cc: Liam Howlett <liam.howlett@oracle.com>
+Cc: Lorenzo Stoakes <ljs@kernel.org>
+Cc: Michal Hocko <mhocko@suse.com>
+Cc: Mike Rapoport <rppt@kernel.org>
+Cc: Naoya Horiguchi <nao.horiguchi@gmail.com>
+Cc: Suren Baghdasaryan <surenb@google.com>
+Cc: Vlastimil Babka <vbabka@kernel.org>
+Cc: <stable@vger.kernel.org>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ include/linux/hugetlb.h | 8 --------
+ include/linux/mm.h | 8 --------
+ mm/hugetlb.c | 11 -----------
+ mm/memory-failure.c | 19 ++++++++++---------
+ 4 files changed, 10 insertions(+), 36 deletions(-)
+
+--- a/include/linux/hugetlb.h
++++ b/include/linux/hugetlb.h
+@@ -164,8 +164,6 @@ long hugetlb_unreserve_pages(struct inod
+ long freed);
+ bool folio_isolate_hugetlb(struct folio *folio, struct list_head *list);
+ int get_hwpoison_hugetlb_folio(struct folio *folio, bool *hugetlb, bool unpoison);
+-int get_huge_page_for_hwpoison(unsigned long pfn, int flags,
+- bool *migratable_cleared);
+ void folio_putback_hugetlb(struct folio *folio);
+ void move_hugetlb_state(struct folio *old_folio, struct folio *new_folio, int reason);
+ void hugetlb_fix_reserve_counts(struct inode *inode);
+@@ -455,12 +453,6 @@ static inline int get_hwpoison_hugetlb_f
+ {
+ return 0;
+ }
+-
+-static inline int get_huge_page_for_hwpoison(unsigned long pfn, int flags,
+- bool *migratable_cleared)
+-{
+- return 0;
+-}
+
+ static inline void folio_putback_hugetlb(struct folio *folio)
+ {
+--- a/include/linux/mm.h
++++ b/include/linux/mm.h
+@@ -3924,8 +3924,6 @@ extern int soft_offline_page(unsigned lo
+ */
+ extern const struct attribute_group memory_failure_attr_group;
+ extern void memory_failure_queue(unsigned long pfn, int flags);
+-extern int __get_huge_page_for_hwpoison(unsigned long pfn, int flags,
+- bool *migratable_cleared);
+ void num_poisoned_pages_inc(unsigned long pfn);
+ void num_poisoned_pages_sub(unsigned long pfn, long i);
+ struct task_struct *task_early_kill(struct task_struct *tsk, int force_early);
+@@ -3934,12 +3932,6 @@ static inline void memory_failure_queue(
+ {
+ }
+
+-static inline int __get_huge_page_for_hwpoison(unsigned long pfn, int flags,
+- bool *migratable_cleared)
+-{
+- return 0;
+-}
+-
+ static inline void num_poisoned_pages_inc(unsigned long pfn)
+ {
+ }
+--- a/mm/hugetlb.c
++++ b/mm/hugetlb.c
+@@ -7300,17 +7300,6 @@ int get_hwpoison_hugetlb_folio(struct fo
+ return ret;
+ }
+
+-int get_huge_page_for_hwpoison(unsigned long pfn, int flags,
+- bool *migratable_cleared)
+-{
+- int ret;
+-
+- spin_lock_irq(&hugetlb_lock);
+- ret = __get_huge_page_for_hwpoison(pfn, flags, migratable_cleared);
+- spin_unlock_irq(&hugetlb_lock);
+- return ret;
+-}
+-
+ /**
+ * folio_putback_hugetlb - unisolate a hugetlb folio
+ * @folio: the isolated hugetlb folio
+--- a/mm/memory-failure.c
++++ b/mm/memory-failure.c
+@@ -1994,20 +1994,19 @@ void folio_clear_hugetlb_hwpoison(struct
+ folio_free_raw_hwp(folio, true);
+ }
+
+-/*
+- * Called from hugetlb code with hugetlb_lock held.
+- */
+-int __get_huge_page_for_hwpoison(unsigned long pfn, int flags,
++static int get_huge_page_for_hwpoison(unsigned long pfn, int flags,
+ bool *migratable_cleared)
+ {
+ struct page *page = pfn_to_page(pfn);
+- struct folio *folio = page_folio(page);
++ struct folio *folio;
+ bool count_increased = false;
+ int ret, rc;
+
++ spin_lock_irq(&hugetlb_lock);
++ folio = page_folio(page);
+ if (!folio_test_hugetlb(folio)) {
+ ret = MF_HUGETLB_NON_HUGEPAGE;
+- goto out;
++ goto out_unlock;
+ } else if (flags & MF_COUNT_INCREASED) {
+ ret = MF_HUGETLB_IN_USED;
+ count_increased = true;
+@@ -2023,13 +2022,13 @@ int __get_huge_page_for_hwpoison(unsigne
+ } else {
+ ret = MF_HUGETLB_RETRY;
+ if (!(flags & MF_NO_RETRY))
+- goto out;
++ goto out_unlock;
+ }
+
+ rc = hugetlb_update_hwpoison(folio, page);
+ if (rc >= MF_HUGETLB_FOLIO_PRE_POISONED) {
+ ret = rc;
+- goto out;
++ goto out_unlock;
+ }
+
+ /*
+@@ -2041,8 +2040,10 @@ int __get_huge_page_for_hwpoison(unsigne
+ *migratable_cleared = true;
+ }
+
++ spin_unlock_irq(&hugetlb_lock);
+ return ret;
+-out:
++out_unlock:
++ spin_unlock_irq(&hugetlb_lock);
+ if (count_increased)
+ folio_put(folio);
+ return ret;
--- /dev/null
+From stable+bounces-263331-greg=kroah.com@vger.kernel.org Mon Jun 15 21:12:57 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 15 Jun 2026 11:39:02 -0400
+Subject: mm/memory-failure: fix missing ->mf_stats count in hugetlb poison
+To: stable@vger.kernel.org
+Cc: Jane Chu <jane.chu@oracle.com>, Miaohe Lin <linmiaohe@huawei.com>, Chris Mason <clm@meta.com>, David Hildenbrand <david@kernel.org>, David Rientjes <rientjes@google.com>, Jiaqi Yan <jiaqiyan@google.com>, "Liam R. Howlett" <Liam.Howlett@oracle.com>, Lorenzo Stoakes <lorenzo.stoakes@oracle.com>, "Matthew Wilcox (Oracle)" <willy@infradead.org>, Michal Hocko <mhocko@suse.com>, Mike Rapoport <rppt@kernel.org>, Muchun Song <muchun.song@linux.dev>, Naoya Horiguchi <nao.horiguchi@gmail.com>, Oscar Salvador <osalvador@suse.de>, Suren Baghdasaryan <surenb@google.com>, William Roche <william.roche@oracle.com>, Andrew Morton <akpm@linux-foundation.org>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260615153903.2214102-4-sashal@kernel.org>
+
+From: Jane Chu <jane.chu@oracle.com>
+
+[ Upstream commit a148a2040191b12b45b82cb29c281cb3036baf90 ]
+
+When a newly poisoned subpage ends up in an already poisoned hugetlb
+folio, 'num_poisoned_pages' is incremented, but the per node ->mf_stats is
+not. Fix the inconsistency by designating action_result() to update them
+both.
+
+While at it, define __get_huge_page_for_hwpoison() return values in terms
+of symbol names for better readibility. Also rename
+folio_set_hugetlb_hwpoison() to hugetlb_update_hwpoison() since the
+function does more than the conventional bit setting and the fact three
+possible return values are expected.
+
+Link: https://lkml.kernel.org/r/20260120232234.3462258-1-jane.chu@oracle.com
+Fixes: 18f41fa616ee ("mm: memory-failure: bump memory failure stats to pglist_data")
+Signed-off-by: Jane Chu <jane.chu@oracle.com>
+Acked-by: Miaohe Lin <linmiaohe@huawei.com>
+Cc: Chris Mason <clm@meta.com>
+Cc: David Hildenbrand <david@kernel.org>
+Cc: David Rientjes <rientjes@google.com>
+Cc: Jiaqi Yan <jiaqiyan@google.com>
+Cc: Liam R. Howlett <Liam.Howlett@oracle.com>
+Cc: Lorenzo Stoakes <lorenzo.stoakes@oracle.com>
+Cc: Matthew Wilcox (Oracle) <willy@infradead.org>
+Cc: Michal Hocko <mhocko@suse.com>
+Cc: Mike Rapoport <rppt@kernel.org>
+Cc: Muchun Song <muchun.song@linux.dev>
+Cc: Naoya Horiguchi <nao.horiguchi@gmail.com>
+Cc: Oscar Salvador <osalvador@suse.de>
+Cc: Suren Baghdasaryan <surenb@google.com>
+Cc: William Roche <william.roche@oracle.com>
+Cc: <stable@vger.kernel.org>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Stable-dep-of: 3c2d42b8ee34 ("mm/memory-failure: fix hugetlb_lock AA deadlock in get_huge_page_for_hwpoison")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ mm/memory-failure.c | 73 ++++++++++++++++++++++++++++++++--------------------
+ 1 file changed, 46 insertions(+), 27 deletions(-)
+
+--- a/mm/memory-failure.c
++++ b/mm/memory-failure.c
+@@ -1912,12 +1912,22 @@ static unsigned long __folio_free_raw_hw
+ return count;
+ }
+
+-static int folio_set_hugetlb_hwpoison(struct folio *folio, struct page *page)
++#define MF_HUGETLB_FREED 0 /* freed hugepage */
++#define MF_HUGETLB_IN_USED 1 /* in-use hugepage */
++#define MF_HUGETLB_NON_HUGEPAGE 2 /* not a hugepage */
++#define MF_HUGETLB_FOLIO_PRE_POISONED 3 /* folio already poisoned */
++#define MF_HUGETLB_PAGE_PRE_POISONED 4 /* exact page already poisoned */
++#define MF_HUGETLB_RETRY 5 /* hugepage is busy, retry */
++/*
++ * Set hugetlb folio as hwpoisoned, update folio private raw hwpoison list
++ * to keep track of the poisoned pages.
++ */
++static int hugetlb_update_hwpoison(struct folio *folio, struct page *page)
+ {
+ struct llist_head *head;
+ struct raw_hwp_page *raw_hwp;
+ struct raw_hwp_page *p, *next;
+- int ret = folio_test_set_hwpoison(folio) ? -EHWPOISON : 0;
++ int ret = folio_test_set_hwpoison(folio) ? MF_HUGETLB_FOLIO_PRE_POISONED : 0;
+
+ /*
+ * Once the hwpoison hugepage has lost reliable raw error info,
+@@ -1925,11 +1935,11 @@ static int folio_set_hugetlb_hwpoison(st
+ * so skip to add additional raw error info.
+ */
+ if (folio_test_hugetlb_raw_hwp_unreliable(folio))
+- return -EHWPOISON;
++ return MF_HUGETLB_FOLIO_PRE_POISONED;
+ head = raw_hwp_list_head(folio);
+ llist_for_each_entry_safe(p, next, head->first, node) {
+ if (p->page == page)
+- return -EHWPOISON;
++ return MF_HUGETLB_PAGE_PRE_POISONED;
+ }
+
+ raw_hwp = kmalloc(sizeof(struct raw_hwp_page), GFP_ATOMIC);
+@@ -1986,42 +1996,39 @@ void folio_clear_hugetlb_hwpoison(struct
+
+ /*
+ * Called from hugetlb code with hugetlb_lock held.
+- *
+- * Return values:
+- * 0 - free hugepage
+- * 1 - in-use hugepage
+- * 2 - not a hugepage
+- * -EBUSY - the hugepage is busy (try to retry)
+- * -EHWPOISON - the hugepage is already hwpoisoned
+ */
+ int __get_huge_page_for_hwpoison(unsigned long pfn, int flags,
+ bool *migratable_cleared)
+ {
+ struct page *page = pfn_to_page(pfn);
+ struct folio *folio = page_folio(page);
+- int ret = 2; /* fallback to normal page handling */
+ bool count_increased = false;
++ int ret, rc;
+
+- if (!folio_test_hugetlb(folio))
++ if (!folio_test_hugetlb(folio)) {
++ ret = MF_HUGETLB_NON_HUGEPAGE;
+ goto out;
+-
+- if (flags & MF_COUNT_INCREASED) {
+- ret = 1;
++ } else if (flags & MF_COUNT_INCREASED) {
++ ret = MF_HUGETLB_IN_USED;
+ count_increased = true;
+ } else if (folio_test_hugetlb_freed(folio)) {
+- ret = 0;
++ ret = MF_HUGETLB_FREED;
+ } else if (folio_test_hugetlb_migratable(folio)) {
+- ret = folio_try_get(folio);
+- if (ret)
++ if (folio_try_get(folio)) {
++ ret = MF_HUGETLB_IN_USED;
+ count_increased = true;
++ } else {
++ ret = MF_HUGETLB_FREED;
++ }
+ } else {
+- ret = -EBUSY;
++ ret = MF_HUGETLB_RETRY;
+ if (!(flags & MF_NO_RETRY))
+ goto out;
+ }
+
+- if (folio_set_hugetlb_hwpoison(folio, page)) {
+- ret = -EHWPOISON;
++ rc = hugetlb_update_hwpoison(folio, page);
++ if (rc >= MF_HUGETLB_FOLIO_PRE_POISONED) {
++ ret = rc;
+ goto out;
+ }
+
+@@ -2046,6 +2053,12 @@ out:
+ * with basic operations like hugepage allocation/free/demotion.
+ * So some of prechecks for hwpoison (pinning, and testing/setting
+ * PageHWPoison) should be done in single hugetlb_lock range.
++ * Returns:
++ * 0 - not hugetlb, or recovered
++ * -EBUSY - not recovered
++ * -EOPNOTSUPP - hwpoison_filter'ed
++ * -EHWPOISON - folio or exact page already poisoned
++ * -EFAULT - kill_accessing_process finds current->mm null
+ */
+ static int try_memory_failure_hugetlb(unsigned long pfn, int flags, int *hugetlb)
+ {
+@@ -2058,22 +2071,28 @@ static int try_memory_failure_hugetlb(un
+ *hugetlb = 1;
+ retry:
+ res = get_huge_page_for_hwpoison(pfn, flags, &migratable_cleared);
+- if (res == 2) { /* fallback to normal page handling */
++ switch (res) {
++ case MF_HUGETLB_NON_HUGEPAGE: /* fallback to normal page handling */
+ *hugetlb = 0;
+ return 0;
+- } else if (res == -EHWPOISON) {
++ case MF_HUGETLB_FOLIO_PRE_POISONED:
++ case MF_HUGETLB_PAGE_PRE_POISONED:
+ pr_err("%#lx: already hardware poisoned\n", pfn);
++ res = -EHWPOISON;
+ if (flags & MF_ACTION_REQUIRED) {
+ folio = page_folio(p);
+ res = kill_accessing_process(current, folio_pfn(folio), flags);
+ }
+ return res;
+- } else if (res == -EBUSY) {
++ case MF_HUGETLB_RETRY:
+ if (!(flags & MF_NO_RETRY)) {
+ flags |= MF_NO_RETRY;
+ goto retry;
+ }
+ return action_result(pfn, MF_MSG_UNKNOWN, MF_IGNORED);
++ default:
++ WARN_ON((res != MF_HUGETLB_FREED) && (res != MF_HUGETLB_IN_USED));
++ break;
+ }
+
+ folio = page_folio(p);
+@@ -2084,7 +2103,7 @@ retry:
+ if (migratable_cleared)
+ folio_set_hugetlb_migratable(folio);
+ folio_unlock(folio);
+- if (res == 1)
++ if (res == MF_HUGETLB_IN_USED)
+ folio_put(folio);
+ return -EOPNOTSUPP;
+ }
+@@ -2093,7 +2112,7 @@ retry:
+ * Handling free hugepage. The possible race with hugepage allocation
+ * or demotion can be prevented by PageHWPoison flag.
+ */
+- if (res == 0) {
++ if (res == MF_HUGETLB_FREED) {
+ folio_unlock(folio);
+ if (__page_handle_poison(p) > 0) {
+ page_ref_inc(p);
--- /dev/null
+From stable+bounces-263329-greg=kroah.com@vger.kernel.org Mon Jun 15 21:12:46 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 15 Jun 2026 11:39:00 -0400
+Subject: mm/migrate: don't call folio_putback_active_hugetlb() on dst hugetlb folio
+To: stable@vger.kernel.org
+Cc: David Hildenbrand <david@redhat.com>, Baolin Wang <baolin.wang@linux.alibaba.com>, "Matthew Wilcox (Oracle)" <willy@infradead.org>, Muchun Song <muchun.song@linux.dev>, Sidhartha Kumar <sidhartha.kumar@oracle.com>, Andrew Morton <akpm@linux-foundation.org>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260615153903.2214102-2-sashal@kernel.org>
+
+From: David Hildenbrand <david@redhat.com>
+
+[ Upstream commit ba23f58de896842028b4b33b95530f08288396fe ]
+
+We replaced a simple put_page() by a putback_active_hugepage() call in
+commit 3aaa76e125c1 ("mm: migrate: hugetlb: putback destination hugepage
+to active list"), to set the "active" flag on the dst hugetlb folio.
+
+Nowadays, we decoupled the "active" list from the flag, by calling the
+flag "migratable".
+
+Calling "putback" on something that wasn't allocated is weird and not
+future proof, especially if we might reach that path when migration failed
+and we just want to free the freshly allocated hugetlb folio.
+
+Let's simply handle the migratable flag and the active list flag in
+move_hugetlb_state(), where we know that allocation succeeded and already
+handle the temporary flag; use a simple folio_put() to return our
+reference.
+
+Link: https://lkml.kernel.org/r/20250113131611.2554758-4-david@redhat.com
+Signed-off-by: David Hildenbrand <david@redhat.com>
+Reviewed-by: Baolin Wang <baolin.wang@linux.alibaba.com>
+Cc: Matthew Wilcox (Oracle) <willy@infradead.org>
+Cc: Muchun Song <muchun.song@linux.dev>
+Cc: Sidhartha Kumar <sidhartha.kumar@oracle.com>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Stable-dep-of: 3c2d42b8ee34 ("mm/memory-failure: fix hugetlb_lock AA deadlock in get_huge_page_for_hwpoison")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ mm/hugetlb.c | 10 ++++++++++
+ mm/migrate.c | 8 ++++----
+ 2 files changed, 14 insertions(+), 4 deletions(-)
+
+--- a/mm/hugetlb.c
++++ b/mm/hugetlb.c
+@@ -7358,6 +7358,16 @@ void move_hugetlb_state(struct folio *ol
+ }
+ spin_unlock_irq(&hugetlb_lock);
+ }
++
++ /*
++ * Our old folio is isolated and has "migratable" cleared until it
++ * is putback. As migration succeeded, set the new folio "migratable"
++ * and add it to the active list.
++ */
++ spin_lock_irq(&hugetlb_lock);
++ folio_set_hugetlb_migratable(new_folio);
++ list_move_tail(&new_folio->lru, &(folio_hstate(new_folio))->hugepage_activelist);
++ spin_unlock_irq(&hugetlb_lock);
+ }
+
+ /*
+--- a/mm/migrate.c
++++ b/mm/migrate.c
+@@ -1461,14 +1461,14 @@ out:
+ list_move_tail(&src->lru, ret);
+
+ /*
+- * If migration was not successful and there's a freeing callback, use
+- * it. Otherwise, put_page() will drop the reference grabbed during
+- * isolation.
++ * If migration was not successful and there's a freeing callback,
++ * return the folio to that special allocator. Otherwise, simply drop
++ * our additional reference.
+ */
+ if (put_new_folio)
+ put_new_folio(dst, private);
+ else
+- folio_putback_active_hugetlb(dst);
++ folio_put(dst);
+
+ return rc;
+ }
--- /dev/null
+From stable+bounces-263293-greg=kroah.com@vger.kernel.org Mon Jun 15 20:52:22 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 15 Jun 2026 11:16:35 -0400
+Subject: netfilter: nft_fib: fix stale stack leak via the OIFNAME register
+To: stable@vger.kernel.org
+Cc: Davide Ornaghi <d.ornaghi97@gmail.com>, Florian Westphal <fw@strlen.de>, Pablo Neira Ayuso <pablo@netfilter.org>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260615151635.2204309-1-sashal@kernel.org>
+
+From: Davide Ornaghi <d.ornaghi97@gmail.com>
+
+[ Upstream commit ab185e0c4fb82dfba6fb86f8271e06f931d9c64c ]
+
+For NFT_FIB_RESULT_OIFNAME the destination register is declared with
+len = IFNAMSIZ (four 32-bit registers), but on the lookup-fail,
+RTN_LOCAL and oif-mismatch paths nft_fib{4,6}_eval() only writes one
+register via "*dest = 0". The remaining three registers are left as
+whatever was on the stack in nft_do_chain()'s struct nft_regs, and a
+downstream expression that loads the register span can leak that
+uninitialised kernel stack to userspace.
+
+The NFTA_FIB_F_PRESENT existence check has the same shape: it is only
+meaningful for NFT_FIB_RESULT_OIF, yet it was accepted for any result type
+while the eval stores a single byte via nft_reg_store8(), leaving the rest
+of the declared span stale.
+
+Fix both:
+
+ - replace the bare "*dest = 0" in the eval with nft_fib_store_result(),
+ which strscpy_pad()s the whole IFNAMSIZ for OIFNAME (and is already
+ used on the other early-return path), and
+
+ - restrict NFTA_FIB_F_PRESENT to NFT_FIB_RESULT_OIF and declare its
+ destination as a single u8, so the marked span matches the one byte
+ the eval writes.
+
+Fixes: f6d0cbcf09c5 ("netfilter: nf_tables: add fib expression")
+Suggested-by: Florian Westphal <fw@strlen.de>
+Cc: stable@vger.kernel.org
+Signed-off-by: Davide Ornaghi <d.ornaghi97@gmail.com>
+Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
+[ kept the tree's existing `ip6_route_lookup`/`rt6_info` machinery (missing `fib6_lookup` refactor) and changed only `*dest = 0;` to `nft_fib_store_result(dest, priv, NULL)` ]
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/ipv4/netfilter/nft_fib_ipv4.c | 2 +-
+ net/ipv6/netfilter/nft_fib_ipv6.c | 2 +-
+ net/netfilter/nft_fib.c | 6 ++++++
+ 3 files changed, 8 insertions(+), 2 deletions(-)
+
+--- a/net/ipv4/netfilter/nft_fib_ipv4.c
++++ b/net/ipv4/netfilter/nft_fib_ipv4.c
+@@ -122,7 +122,7 @@ void nft_fib4_eval(const struct nft_expr
+ fl4.saddr = get_saddr(iph->daddr);
+ }
+
+- *dest = 0;
++ nft_fib_store_result(dest, priv, NULL);
+
+ if (fib_lookup(nft_net(pkt), &fl4, &res, FIB_LOOKUP_IGNORE_LINKSTATE))
+ return;
+--- a/net/ipv6/netfilter/nft_fib_ipv6.c
++++ b/net/ipv6/netfilter/nft_fib_ipv6.c
+@@ -193,7 +193,7 @@ void nft_fib6_eval(const struct nft_expr
+ }
+ }
+
+- *dest = 0;
++ nft_fib_store_result(dest, priv, NULL);
+ rt = (void *)ip6_route_lookup(nft_net(pkt), &fl6, pkt->skb,
+ lookup_flags);
+ if (rt->dst.error)
+--- a/net/netfilter/nft_fib.c
++++ b/net/netfilter/nft_fib.c
+@@ -107,6 +107,12 @@ int nft_fib_init(const struct nft_ctx *c
+ return -EINVAL;
+ }
+
++ if (priv->flags & NFTA_FIB_F_PRESENT) {
++ if (priv->result != NFT_FIB_RESULT_OIF)
++ return -EINVAL;
++ len = sizeof(u8);
++ }
++
+ err = nft_parse_register_store(ctx, tb[NFTA_FIB_DREG], &priv->dreg,
+ NULL, NFT_DATA_VALUE, len);
+ if (err < 0)
--- /dev/null
+From stable+bounces-263480-greg=kroah.com@vger.kernel.org Tue Jun 16 04:24:12 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 15 Jun 2026 18:52:07 -0400
+Subject: RDMA: During rereg_mr ensure that REREG_ACCESS is compatible
+To: stable@vger.kernel.org
+Cc: Jason Gunthorpe <jgg@nvidia.com>, Philip Tsukerman <philiptsukerman@gmail.com>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260615225207.2520056-1-sashal@kernel.org>
+
+From: Jason Gunthorpe <jgg@nvidia.com>
+
+[ Upstream commit badad6fad60def1b9805559dd81dbab3d97b82aa ]
+
+If IB_MR_REREG_ACCESS changes from RO to RW then the umem has to be
+re-evaluated to ensure it is properly pinned as RW. Since the umem is
+hidden inside each driver's mr struct add a ib_umem_check_rereg() function
+that each driver has to call before processing IB_MR_REREG_ACCESS.
+
+mlx4 has to retain its duplicate ib_access_writable check because it
+implements IB_MR_REREG_ACCESS | IB_MR_REREG_TRANS by changing both items
+in place sequentially while the MR is live, so it will continue to not
+support this combination.
+
+Cc: stable@vger.kernel.org
+Fixes: b40656aa7d55 ("RDMA/umem: remove FOLL_FORCE usage")
+Link: https://patch.msgid.link/r/0-v1-06fb1a2d6cf5+107-rereg_access_jgg@nvidia.com
+Reported-by: Philip Tsukerman <philiptsukerman@gmail.com>
+Signed-off-by: Jason Gunthorpe <jgg@nvidia.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/infiniband/core/umem.c | 16 ++++++++++++++++
+ drivers/infiniband/hw/hns/hns_roce_mr.c | 4 ++++
+ drivers/infiniband/hw/irdma/verbs.c | 4 ++++
+ drivers/infiniband/hw/mlx4/mr.c | 4 ++++
+ drivers/infiniband/hw/mlx5/mr.c | 4 ++++
+ drivers/infiniband/sw/rxe/rxe_verbs.c | 5 +++++
+ include/rdma/ib_umem.h | 8 ++++++++
+ 7 files changed, 45 insertions(+)
+
+--- a/drivers/infiniband/core/umem.c
++++ b/drivers/infiniband/core/umem.c
+@@ -326,3 +326,19 @@ int ib_umem_copy_from(void *dst, struct
+ return 0;
+ }
+ EXPORT_SYMBOL(ib_umem_copy_from);
++
++/*
++ * Called during rereg mr if the driver is able to re-use a umem for
++ * IB_MR_REREG_ACCESS.
++ */
++int ib_umem_check_rereg(struct ib_umem *umem, int flags, int new_access_flags)
++{
++ if (!umem)
++ return 0;
++
++ if ((flags & IB_MR_REREG_ACCESS) && !(flags & IB_MR_REREG_TRANS))
++ if (ib_access_writable(new_access_flags) && !umem->writable)
++ return -EACCES;
++ return 0;
++}
++EXPORT_SYMBOL(ib_umem_check_rereg);
+--- a/drivers/infiniband/hw/hns/hns_roce_mr.c
++++ b/drivers/infiniband/hw/hns/hns_roce_mr.c
+@@ -277,6 +277,10 @@ struct ib_mr *hns_roce_rereg_user_mr(str
+ if (!mr->enabled)
+ return ERR_PTR(-EINVAL);
+
++ ret = ib_umem_check_rereg(mr->pbl_mtr.umem, flags, mr_access_flags);
++ if (ret)
++ return ERR_PTR(ret);
++
+ mailbox = hns_roce_alloc_cmd_mailbox(hr_dev);
+ if (IS_ERR(mailbox))
+ return ERR_CAST(mailbox);
+--- a/drivers/infiniband/hw/irdma/verbs.c
++++ b/drivers/infiniband/hw/irdma/verbs.c
+@@ -3244,6 +3244,10 @@ static struct ib_mr *irdma_rereg_user_mr
+ if (flags & ~(IB_MR_REREG_TRANS | IB_MR_REREG_PD | IB_MR_REREG_ACCESS))
+ return ERR_PTR(-EOPNOTSUPP);
+
++ ret = ib_umem_check_rereg(iwmr->region, flags, new_access);
++ if (ret)
++ return ERR_PTR(ret);
++
+ ret = irdma_hwdereg_mr(ib_mr);
+ if (ret)
+ return ERR_PTR(ret);
+--- a/drivers/infiniband/hw/mlx4/mr.c
++++ b/drivers/infiniband/hw/mlx4/mr.c
+@@ -466,6 +466,10 @@ struct ib_mr *mlx4_ib_rereg_user_mr(stru
+ struct mlx4_mpt_entry **pmpt_entry = &mpt_entry;
+ int err;
+
++ err = ib_umem_check_rereg(mmr->umem, flags, mr_access_flags);
++ if (err)
++ return ERR_PTR(err);
++
+ /* Since we synchronize this call and mlx4_ib_dereg_mr via uverbs,
+ * we assume that the calls can't run concurrently. Otherwise, a
+ * race exists.
+--- a/drivers/infiniband/hw/mlx5/mr.c
++++ b/drivers/infiniband/hw/mlx5/mr.c
+@@ -1698,6 +1698,10 @@ struct ib_mr *mlx5_ib_rereg_user_mr(stru
+ if (flags & ~(IB_MR_REREG_TRANS | IB_MR_REREG_PD | IB_MR_REREG_ACCESS))
+ return ERR_PTR(-EOPNOTSUPP);
+
++ err = ib_umem_check_rereg(mr->umem, flags, new_access_flags);
++ if (err)
++ return ERR_PTR(err);
++
+ if (!(flags & IB_MR_REREG_ACCESS))
+ new_access_flags = mr->access_flags;
+ if (!(flags & IB_MR_REREG_PD))
+--- a/drivers/infiniband/sw/rxe/rxe_verbs.c
++++ b/drivers/infiniband/sw/rxe/rxe_verbs.c
+@@ -1316,6 +1316,7 @@ static struct ib_mr *rxe_rereg_user_mr(s
+ struct rxe_mr *mr = to_rmr(ibmr);
+ struct rxe_pd *old_pd = to_rpd(ibmr->pd);
+ struct rxe_pd *pd = to_rpd(ibpd);
++ int err;
+
+ /* for now only support the two easy cases:
+ * rereg_pd and rereg_access
+@@ -1325,6 +1326,10 @@ static struct ib_mr *rxe_rereg_user_mr(s
+ return ERR_PTR(-EOPNOTSUPP);
+ }
+
++ err = ib_umem_check_rereg(mr->umem, flags, access);
++ if (err)
++ return ERR_PTR(err);
++
+ if (flags & IB_MR_REREG_PD) {
+ rxe_put(old_pd);
+ rxe_get(pd);
+--- a/include/rdma/ib_umem.h
++++ b/include/rdma/ib_umem.h
+@@ -154,6 +154,8 @@ int ib_umem_dmabuf_map_pages(struct ib_u
+ void ib_umem_dmabuf_unmap_pages(struct ib_umem_dmabuf *umem_dmabuf);
+ void ib_umem_dmabuf_release(struct ib_umem_dmabuf *umem_dmabuf);
+
++int ib_umem_check_rereg(struct ib_umem *umem, int flags, int new_access_flags);
++
+ #else /* CONFIG_INFINIBAND_USER_MEM */
+
+ #include <linux/err.h>
+@@ -203,5 +205,11 @@ static inline int ib_umem_dmabuf_map_pag
+ static inline void ib_umem_dmabuf_unmap_pages(struct ib_umem_dmabuf *umem_dmabuf) { }
+ static inline void ib_umem_dmabuf_release(struct ib_umem_dmabuf *umem_dmabuf) { }
+
++static inline int ib_umem_check_rereg(struct ib_umem *umem, int flags,
++ int new_access_flags)
++{
++ return -EOPNOTSUPP;
++}
++
+ #endif /* CONFIG_INFINIBAND_USER_MEM */
+ #endif /* IB_UMEM_H */
--- /dev/null
+From stable+bounces-263489-greg=kroah.com@vger.kernel.org Tue Jun 16 05:29:08 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 15 Jun 2026 19:58:47 -0400
+Subject: RDMA: Move DMA block iterator logic into dedicated files
+To: stable@vger.kernel.org
+Cc: Leon Romanovsky <leonro@nvidia.com>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260615235848.2562462-2-sashal@kernel.org>
+
+From: Leon Romanovsky <leonro@nvidia.com>
+
+[ Upstream commit 6094ea64c69520ed1e770e7c79c43412de202bfa ]
+
+The DMA iterator logic was mixed into verbs and umem-specific code,
+forcing all users to include rdma/ib_umem.h. Move the block iterator
+logic into iter.c and rdma/iter.h so that rdma/ib_umem.h and
+rdma/ib_verbs.h can be separated in a follow-up patch.
+
+Link: https://patch.msgid.link/20260213-refactor-umem-v1-1-f3be85847922@nvidia.com
+Signed-off-by: Leon Romanovsky <leonro@nvidia.com>
+Stable-dep-of: 15fe76e23615 ("RDMA/umem: Fix truncation for block sizes >= 4G")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/infiniband/core/Makefile | 2
+ drivers/infiniband/core/iter.c | 43 +++++++++++++
+ drivers/infiniband/core/verbs.c | 38 -----------
+ drivers/infiniband/hw/bnxt_re/qplib_res.c | 2
+ drivers/infiniband/hw/cxgb4/mem.c | 2
+ drivers/infiniband/hw/efa/efa_verbs.c | 2
+ drivers/infiniband/hw/erdma/erdma_verbs.c | 2
+ drivers/infiniband/hw/hns/hns_roce_alloc.c | 2
+ drivers/infiniband/hw/irdma/main.h | 2
+ drivers/infiniband/hw/mana/mana_ib.h | 2
+ drivers/infiniband/hw/mlx4/mr.c | 1
+ drivers/infiniband/hw/mlx5/mem.c | 1
+ drivers/infiniband/hw/mlx5/umr.c | 1
+ drivers/infiniband/hw/mthca/mthca_provider.c | 2
+ drivers/infiniband/hw/ocrdma/ocrdma_verbs.c | 2
+ drivers/infiniband/hw/qedr/verbs.c | 2
+ drivers/infiniband/hw/vmw_pvrdma/pvrdma.h | 2
+ include/rdma/ib_umem.h | 32 ---------
+ include/rdma/ib_verbs.h | 48 --------------
+ include/rdma/iter.h | 88 +++++++++++++++++++++++++++
+ 20 files changed, 146 insertions(+), 130 deletions(-)
+ create mode 100644 drivers/infiniband/core/iter.c
+ create mode 100644 include/rdma/iter.h
+
+--- a/drivers/infiniband/core/Makefile
++++ b/drivers/infiniband/core/Makefile
+@@ -12,7 +12,7 @@ ib_core-y := packer.o ud_header.o verb
+ roce_gid_mgmt.o mr_pool.o addr.o sa_query.o \
+ multicast.o mad.o smi.o agent.o mad_rmpp.o \
+ nldev.o restrack.o counters.o ib_core_uverbs.o \
+- trace.o lag.o
++ trace.o lag.o iter.o
+
+ ib_core-$(CONFIG_SECURITY_INFINIBAND) += security.o
+ ib_core-$(CONFIG_CGROUP_RDMA) += cgroup.o
+--- /dev/null
++++ b/drivers/infiniband/core/iter.c
+@@ -0,0 +1,43 @@
++// SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
++/* Copyright (c) 2026, NVIDIA CORPORATION & AFFILIATES. */
++
++#include <linux/export.h>
++#include <rdma/iter.h>
++
++void __rdma_block_iter_start(struct ib_block_iter *biter,
++ struct scatterlist *sglist, unsigned int nents,
++ unsigned long pgsz)
++{
++ memset(biter, 0, sizeof(struct ib_block_iter));
++ biter->__sg = sglist;
++ biter->__sg_nents = nents;
++
++ /* Driver provides best block size to use */
++ biter->__pg_bit = __fls(pgsz);
++}
++EXPORT_SYMBOL(__rdma_block_iter_start);
++
++bool __rdma_block_iter_next(struct ib_block_iter *biter)
++{
++ unsigned int block_offset;
++ unsigned int delta;
++
++ if (!biter->__sg_nents || !biter->__sg)
++ return false;
++
++ biter->__dma_addr = sg_dma_address(biter->__sg) + biter->__sg_advance;
++ block_offset = biter->__dma_addr & (BIT_ULL(biter->__pg_bit) - 1);
++ delta = BIT_ULL(biter->__pg_bit) - block_offset;
++
++ while (biter->__sg_nents && biter->__sg &&
++ sg_dma_len(biter->__sg) - biter->__sg_advance <= delta) {
++ delta -= sg_dma_len(biter->__sg) - biter->__sg_advance;
++ biter->__sg_advance = 0;
++ biter->__sg = sg_next(biter->__sg);
++ biter->__sg_nents--;
++ }
++ biter->__sg_advance += delta;
++
++ return true;
++}
++EXPORT_SYMBOL(__rdma_block_iter_next);
+--- a/drivers/infiniband/core/verbs.c
++++ b/drivers/infiniband/core/verbs.c
+@@ -3013,44 +3013,6 @@ int rdma_init_netdev(struct ib_device *d
+ }
+ EXPORT_SYMBOL(rdma_init_netdev);
+
+-void __rdma_block_iter_start(struct ib_block_iter *biter,
+- struct scatterlist *sglist, unsigned int nents,
+- unsigned long pgsz)
+-{
+- memset(biter, 0, sizeof(struct ib_block_iter));
+- biter->__sg = sglist;
+- biter->__sg_nents = nents;
+-
+- /* Driver provides best block size to use */
+- biter->__pg_bit = __fls(pgsz);
+-}
+-EXPORT_SYMBOL(__rdma_block_iter_start);
+-
+-bool __rdma_block_iter_next(struct ib_block_iter *biter)
+-{
+- unsigned int block_offset;
+- unsigned int delta;
+-
+- if (!biter->__sg_nents || !biter->__sg)
+- return false;
+-
+- biter->__dma_addr = sg_dma_address(biter->__sg) + biter->__sg_advance;
+- block_offset = biter->__dma_addr & (BIT_ULL(biter->__pg_bit) - 1);
+- delta = BIT_ULL(biter->__pg_bit) - block_offset;
+-
+- while (biter->__sg_nents && biter->__sg &&
+- sg_dma_len(biter->__sg) - biter->__sg_advance <= delta) {
+- delta -= sg_dma_len(biter->__sg) - biter->__sg_advance;
+- biter->__sg_advance = 0;
+- biter->__sg = sg_next(biter->__sg);
+- biter->__sg_nents--;
+- }
+- biter->__sg_advance += delta;
+-
+- return true;
+-}
+-EXPORT_SYMBOL(__rdma_block_iter_next);
+-
+ /**
+ * rdma_alloc_hw_stats_struct - Helper function to allocate dynamic struct
+ * for the drivers.
+--- a/drivers/infiniband/hw/bnxt_re/qplib_res.c
++++ b/drivers/infiniband/hw/bnxt_re/qplib_res.c
+@@ -46,7 +46,7 @@
+ #include <linux/if_vlan.h>
+ #include <linux/vmalloc.h>
+ #include <rdma/ib_verbs.h>
+-#include <rdma/ib_umem.h>
++#include <rdma/iter.h>
+
+ #include "roce_hsi.h"
+ #include "qplib_res.h"
+--- a/drivers/infiniband/hw/cxgb4/mem.c
++++ b/drivers/infiniband/hw/cxgb4/mem.c
+@@ -32,9 +32,9 @@
+
+ #include <linux/module.h>
+ #include <linux/moduleparam.h>
+-#include <rdma/ib_umem.h>
+ #include <linux/atomic.h>
+ #include <rdma/ib_user_verbs.h>
++#include <rdma/iter.h>
+
+ #include "iw_cxgb4.h"
+
+--- a/drivers/infiniband/hw/efa/efa_verbs.c
++++ b/drivers/infiniband/hw/efa/efa_verbs.c
+@@ -9,9 +9,9 @@
+ #include <linux/log2.h>
+
+ #include <rdma/ib_addr.h>
+-#include <rdma/ib_umem.h>
+ #include <rdma/ib_user_verbs.h>
+ #include <rdma/ib_verbs.h>
++#include <rdma/iter.h>
+ #include <rdma/uverbs_ioctl.h>
+
+ #include "efa.h"
+--- a/drivers/infiniband/hw/erdma/erdma_verbs.c
++++ b/drivers/infiniband/hw/erdma/erdma_verbs.c
+@@ -12,7 +12,7 @@
+ #include <linux/vmalloc.h>
+ #include <net/addrconf.h>
+ #include <rdma/erdma-abi.h>
+-#include <rdma/ib_umem.h>
++#include <rdma/iter.h>
+ #include <rdma/uverbs_ioctl.h>
+
+ #include "erdma.h"
+--- a/drivers/infiniband/hw/hns/hns_roce_alloc.c
++++ b/drivers/infiniband/hw/hns/hns_roce_alloc.c
+@@ -32,7 +32,7 @@
+ */
+
+ #include <linux/vmalloc.h>
+-#include <rdma/ib_umem.h>
++#include <rdma/iter.h>
+ #include "hns_roce_device.h"
+
+ void hns_roce_buf_free(struct hns_roce_dev *hr_dev, struct hns_roce_buf *buf)
+--- a/drivers/infiniband/hw/irdma/main.h
++++ b/drivers/infiniband/hw/irdma/main.h
+@@ -37,8 +37,8 @@
+ #include <rdma/rdma_cm.h>
+ #include <rdma/iw_cm.h>
+ #include <rdma/ib_user_verbs.h>
+-#include <rdma/ib_umem.h>
+ #include <rdma/ib_cache.h>
++#include <rdma/iter.h>
+ #include <rdma/uverbs_ioctl.h>
+ #include "osdep.h"
+ #include "defs.h"
+--- a/drivers/infiniband/hw/mana/mana_ib.h
++++ b/drivers/infiniband/hw/mana/mana_ib.h
+@@ -8,7 +8,7 @@
+
+ #include <rdma/ib_verbs.h>
+ #include <rdma/ib_mad.h>
+-#include <rdma/ib_umem.h>
++#include <rdma/iter.h>
+ #include <rdma/mana-abi.h>
+ #include <rdma/uverbs_ioctl.h>
+
+--- a/drivers/infiniband/hw/mlx4/mr.c
++++ b/drivers/infiniband/hw/mlx4/mr.c
+@@ -33,6 +33,7 @@
+
+ #include <linux/slab.h>
+ #include <rdma/ib_user_verbs.h>
++#include <rdma/iter.h>
+
+ #include "mlx4_ib.h"
+
+--- a/drivers/infiniband/hw/mlx5/mem.c
++++ b/drivers/infiniband/hw/mlx5/mem.c
+@@ -32,6 +32,7 @@
+
+ #include <linux/io.h>
+ #include <rdma/ib_umem_odp.h>
++#include <rdma/iter.h>
+ #include "mlx5_ib.h"
+ #include <linux/jiffies.h>
+
+--- a/drivers/infiniband/hw/mlx5/umr.c
++++ b/drivers/infiniband/hw/mlx5/umr.c
+@@ -2,6 +2,7 @@
+ /* Copyright (c) 2022, NVIDIA CORPORATION & AFFILIATES. */
+
+ #include <rdma/ib_umem_odp.h>
++#include <rdma/iter.h>
+ #include "mlx5_ib.h"
+ #include "umr.h"
+ #include "wr.h"
+--- a/drivers/infiniband/hw/mthca/mthca_provider.c
++++ b/drivers/infiniband/hw/mthca/mthca_provider.c
+@@ -35,8 +35,8 @@
+ */
+
+ #include <rdma/ib_smi.h>
+-#include <rdma/ib_umem.h>
+ #include <rdma/ib_user_verbs.h>
++#include <rdma/iter.h>
+ #include <rdma/uverbs_ioctl.h>
+
+ #include <linux/sched.h>
+--- a/drivers/infiniband/hw/ocrdma/ocrdma_verbs.c
++++ b/drivers/infiniband/hw/ocrdma/ocrdma_verbs.c
+@@ -45,9 +45,9 @@
+ #include <rdma/ib_verbs.h>
+ #include <rdma/ib_user_verbs.h>
+ #include <rdma/iw_cm.h>
+-#include <rdma/ib_umem.h>
+ #include <rdma/ib_addr.h>
+ #include <rdma/ib_cache.h>
++#include <rdma/iter.h>
+ #include <rdma/uverbs_ioctl.h>
+
+ #include "ocrdma.h"
+--- a/drivers/infiniband/hw/qedr/verbs.c
++++ b/drivers/infiniband/hw/qedr/verbs.c
+@@ -39,9 +39,9 @@
+ #include <rdma/ib_verbs.h>
+ #include <rdma/ib_user_verbs.h>
+ #include <rdma/iw_cm.h>
+-#include <rdma/ib_umem.h>
+ #include <rdma/ib_addr.h>
+ #include <rdma/ib_cache.h>
++#include <rdma/iter.h>
+ #include <rdma/uverbs_ioctl.h>
+
+ #include <linux/qed/common_hsi.h>
+--- a/drivers/infiniband/hw/vmw_pvrdma/pvrdma.h
++++ b/drivers/infiniband/hw/vmw_pvrdma/pvrdma.h
+@@ -53,8 +53,8 @@
+ #include <linux/pci.h>
+ #include <linux/semaphore.h>
+ #include <linux/workqueue.h>
+-#include <rdma/ib_umem.h>
+ #include <rdma/ib_verbs.h>
++#include <rdma/iter.h>
+ #include <rdma/vmw_pvrdma-abi.h>
+
+ #include "pvrdma_ring.h"
+--- a/include/rdma/ib_umem.h
++++ b/include/rdma/ib_umem.h
+@@ -70,38 +70,6 @@ static inline size_t ib_umem_num_pages(s
+ {
+ return ib_umem_num_dma_blocks(umem, PAGE_SIZE);
+ }
+-
+-static inline void __rdma_umem_block_iter_start(struct ib_block_iter *biter,
+- struct ib_umem *umem,
+- unsigned long pgsz)
+-{
+- __rdma_block_iter_start(biter, umem->sgt_append.sgt.sgl,
+- umem->sgt_append.sgt.nents, pgsz);
+- biter->__sg_advance = ib_umem_offset(umem) & ~(pgsz - 1);
+- biter->__sg_numblocks = ib_umem_num_dma_blocks(umem, pgsz);
+-}
+-
+-static inline bool __rdma_umem_block_iter_next(struct ib_block_iter *biter)
+-{
+- return __rdma_block_iter_next(biter) && biter->__sg_numblocks--;
+-}
+-
+-/**
+- * rdma_umem_for_each_dma_block - iterate over contiguous DMA blocks of the umem
+- * @umem: umem to iterate over
+- * @biter: block iterator variable
+- * @pgsz: Page size to split the list into
+- *
+- * pgsz must be <= PAGE_SIZE or computed by ib_umem_find_best_pgsz(). The
+- * returned DMA blocks will be aligned to pgsz and span the range:
+- * ALIGN_DOWN(umem->address, pgsz) to ALIGN(umem->address + umem->length, pgsz)
+- *
+- * Performs exactly ib_umem_num_dma_blocks() iterations.
+- */
+-#define rdma_umem_for_each_dma_block(umem, biter, pgsz) \
+- for (__rdma_umem_block_iter_start(biter, umem, pgsz); \
+- __rdma_umem_block_iter_next(biter);)
+-
+ #ifdef CONFIG_INFINIBAND_USER_MEM
+
+ struct ib_umem *ib_umem_get(struct ib_device *device, unsigned long addr,
+--- a/include/rdma/ib_verbs.h
++++ b/include/rdma/ib_verbs.h
+@@ -2839,22 +2839,6 @@ struct ib_client {
+ u8 no_kverbs_req:1;
+ };
+
+-/*
+- * IB block DMA iterator
+- *
+- * Iterates the DMA-mapped SGL in contiguous memory blocks aligned
+- * to a HW supported page size.
+- */
+-struct ib_block_iter {
+- /* internal states */
+- struct scatterlist *__sg; /* sg holding the current aligned block */
+- dma_addr_t __dma_addr; /* unaligned DMA address of this block */
+- size_t __sg_numblocks; /* ib_umem_num_dma_blocks() */
+- unsigned int __sg_nents; /* number of SG entries */
+- unsigned int __sg_advance; /* number of bytes to advance in sg in next step */
+- unsigned int __pg_bit; /* alignment of current block */
+-};
+-
+ struct ib_device *_ib_alloc_device(size_t size);
+ #define ib_alloc_device(drv_struct, member) \
+ container_of(_ib_alloc_device(sizeof(struct drv_struct) + \
+@@ -2876,38 +2860,6 @@ void ib_unregister_device_queued(struct
+ int ib_register_client (struct ib_client *client);
+ void ib_unregister_client(struct ib_client *client);
+
+-void __rdma_block_iter_start(struct ib_block_iter *biter,
+- struct scatterlist *sglist,
+- unsigned int nents,
+- unsigned long pgsz);
+-bool __rdma_block_iter_next(struct ib_block_iter *biter);
+-
+-/**
+- * rdma_block_iter_dma_address - get the aligned dma address of the current
+- * block held by the block iterator.
+- * @biter: block iterator holding the memory block
+- */
+-static inline dma_addr_t
+-rdma_block_iter_dma_address(struct ib_block_iter *biter)
+-{
+- return biter->__dma_addr & ~(BIT_ULL(biter->__pg_bit) - 1);
+-}
+-
+-/**
+- * rdma_for_each_block - iterate over contiguous memory blocks of the sg list
+- * @sglist: sglist to iterate over
+- * @biter: block iterator holding the memory block
+- * @nents: maximum number of sg entries to iterate over
+- * @pgsz: best HW supported page size to use
+- *
+- * Callers may use rdma_block_iter_dma_address() to get each
+- * blocks aligned DMA address.
+- */
+-#define rdma_for_each_block(sglist, biter, nents, pgsz) \
+- for (__rdma_block_iter_start(biter, sglist, nents, \
+- pgsz); \
+- __rdma_block_iter_next(biter);)
+-
+ /**
+ * ib_get_client_data - Get IB client context
+ * @device:Device to get context for
+--- /dev/null
++++ b/include/rdma/iter.h
+@@ -0,0 +1,88 @@
++/* SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB */
++/* Copyright (c) 2026, NVIDIA CORPORATION & AFFILIATES. */
++
++#ifndef _RDMA_ITER_H_
++#define _RDMA_ITER_H_
++
++#include <linux/scatterlist.h>
++#include <rdma/ib_umem.h>
++
++/**
++ * IB block DMA iterator
++ *
++ * Iterates the DMA-mapped SGL in contiguous memory blocks aligned
++ * to a HW supported page size.
++ */
++struct ib_block_iter {
++ /* internal states */
++ struct scatterlist *__sg; /* sg holding the current aligned block */
++ dma_addr_t __dma_addr; /* unaligned DMA address of this block */
++ size_t __sg_numblocks; /* ib_umem_num_dma_blocks() */
++ unsigned int __sg_nents; /* number of SG entries */
++ unsigned int __sg_advance; /* number of bytes to advance in sg in next step */
++ unsigned int __pg_bit; /* alignment of current block */
++};
++
++void __rdma_block_iter_start(struct ib_block_iter *biter,
++ struct scatterlist *sglist,
++ unsigned int nents,
++ unsigned long pgsz);
++bool __rdma_block_iter_next(struct ib_block_iter *biter);
++
++/**
++ * rdma_block_iter_dma_address - get the aligned dma address of the current
++ * block held by the block iterator.
++ * @biter: block iterator holding the memory block
++ */
++static inline dma_addr_t
++rdma_block_iter_dma_address(struct ib_block_iter *biter)
++{
++ return biter->__dma_addr & ~(BIT_ULL(biter->__pg_bit) - 1);
++}
++
++/**
++ * rdma_for_each_block - iterate over contiguous memory blocks of the sg list
++ * @sglist: sglist to iterate over
++ * @biter: block iterator holding the memory block
++ * @nents: maximum number of sg entries to iterate over
++ * @pgsz: best HW supported page size to use
++ *
++ * Callers may use rdma_block_iter_dma_address() to get each
++ * blocks aligned DMA address.
++ */
++#define rdma_for_each_block(sglist, biter, nents, pgsz) \
++ for (__rdma_block_iter_start(biter, sglist, nents, \
++ pgsz); \
++ __rdma_block_iter_next(biter);)
++
++static inline void __rdma_umem_block_iter_start(struct ib_block_iter *biter,
++ struct ib_umem *umem,
++ unsigned long pgsz)
++{
++ __rdma_block_iter_start(biter, umem->sgt_append.sgt.sgl,
++ umem->sgt_append.sgt.nents, pgsz);
++ biter->__sg_advance = ib_umem_offset(umem) & ~(pgsz - 1);
++ biter->__sg_numblocks = ib_umem_num_dma_blocks(umem, pgsz);
++}
++
++static inline bool __rdma_umem_block_iter_next(struct ib_block_iter *biter)
++{
++ return __rdma_block_iter_next(biter) && biter->__sg_numblocks--;
++}
++
++/**
++ * rdma_umem_for_each_dma_block - iterate over contiguous DMA blocks of the umem
++ * @umem: umem to iterate over
++ * @pgsz: Page size to split the list into
++ *
++ * pgsz must be <= PAGE_SIZE or computed by ib_umem_find_best_pgsz(). The
++ * returned DMA blocks will be aligned to pgsz and span the range:
++ * ALIGN_DOWN(umem->address, pgsz) to ALIGN(umem->address + umem->length, pgsz)
++ *
++ * Performs exactly ib_umem_num_dma_blocks() iterations.
++ */
++#define rdma_umem_for_each_dma_block(umem, biter, pgsz) \
++ for (__rdma_umem_block_iter_start(biter, umem, pgsz); \
++ __rdma_umem_block_iter_next(biter);)
++
++#endif /* _RDMA_ITER_H_ */
--- /dev/null
+From stable+bounces-263488-greg=kroah.com@vger.kernel.org Tue Jun 16 05:30:22 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 15 Jun 2026 19:58:46 -0400
+Subject: RDMA/umem: fix kernel-doc warnings
+To: stable@vger.kernel.org
+Cc: Randy Dunlap <rdunlap@infradead.org>, Leon Romanovsky <leon@kernel.org>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260615235848.2562462-1-sashal@kernel.org>
+
+From: Randy Dunlap <rdunlap@infradead.org>
+
+[ Upstream commit ff46d1392750444fab5ae5a0194764ffdc4ac0d2 ]
+
+Add or correct kernel-doc comments to eliminate warnings:
+
+Warning: include/rdma/ib_umem.h:104 function parameter 'biter' not
+ described in 'rdma_umem_for_each_dma_block'
+Warning: include/rdma/ib_umem.h:140 function parameter 'pgsz_bitmap' not
+ described in 'ib_umem_find_best_pgoff'
+Warning: include/rdma/ib_umem.h:141 No description found for return
+ value of 'ib_umem_find_best_pgoff'
+
+Signed-off-by: Randy Dunlap <rdunlap@infradead.org>
+Link: https://patch.msgid.link/20260224003120.3173892-1-rdunlap@infradead.org
+Signed-off-by: Leon Romanovsky <leon@kernel.org>
+Stable-dep-of: 15fe76e23615 ("RDMA/umem: Fix truncation for block sizes >= 4G")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ include/rdma/ib_umem.h | 6 +++++-
+ 1 file changed, 5 insertions(+), 1 deletion(-)
+
+--- a/include/rdma/ib_umem.h
++++ b/include/rdma/ib_umem.h
+@@ -89,6 +89,7 @@ static inline bool __rdma_umem_block_ite
+ /**
+ * rdma_umem_for_each_dma_block - iterate over contiguous DMA blocks of the umem
+ * @umem: umem to iterate over
++ * @biter: block iterator variable
+ * @pgsz: Page size to split the list into
+ *
+ * pgsz must be <= PAGE_SIZE or computed by ib_umem_find_best_pgsz(). The
+@@ -116,7 +117,7 @@ unsigned long ib_umem_find_best_pgsz(str
+ * ib_umem_find_best_pgoff - Find best HW page size
+ *
+ * @umem: umem struct
+- * @pgsz_bitmap bitmap of HW supported page sizes
++ * @pgsz_bitmap: bitmap of HW supported page sizes
+ * @pgoff_bitmask: Mask of bits that can be represented with an offset
+ *
+ * This is very similar to ib_umem_find_best_pgsz() except instead of accepting
+@@ -129,6 +130,9 @@ unsigned long ib_umem_find_best_pgsz(str
+ *
+ * If the pgoff_bitmask requires either alignment in the low bit or an
+ * unavailable page size for the high bits, this function returns 0.
++ *
++ * Returns: best HW page size for the parameters or 0 if none available
++ * for the given parameters.
+ */
+ static inline unsigned long ib_umem_find_best_pgoff(struct ib_umem *umem,
+ unsigned long pgsz_bitmap,
--- /dev/null
+From stable+bounces-263490-greg=kroah.com@vger.kernel.org Tue Jun 16 05:29:08 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 15 Jun 2026 19:58:48 -0400
+Subject: RDMA/umem: Fix truncation for block sizes >= 4G
+To: stable@vger.kernel.org
+Cc: Jason Gunthorpe <jgg@nvidia.com>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260615235848.2562462-3-sashal@kernel.org>
+
+From: Jason Gunthorpe <jgg@nvidia.com>
+
+[ Upstream commit 15fe76e23615f502d051ef0768f86babaf08746c ]
+
+When the iommu is used the linearization of the mapping can give a single
+block that is very large split across multiple SG entries.
+
+When __rdma_block_iter_next() reassembles the split SG entries it is
+overflowing the 32 bit stack values and computed the wrong DMA addresses
+for blocks after the truncation.
+
+Use the right types to hold DMA addresses.
+
+Link: https://patch.msgid.link/r/1-v1-88303e9e509f+f7-ib_umem_types_jgg@nvidia.com
+Cc: stable@vger.kernel.org
+Fixes: a808273a495c ("RDMA/verbs: Add a DMA iterator to return aligned contiguous memory blocks")
+Signed-off-by: Jason Gunthorpe <jgg@nvidia.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/infiniband/core/iter.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+--- a/drivers/infiniband/core/iter.c
++++ b/drivers/infiniband/core/iter.c
+@@ -19,8 +19,8 @@ EXPORT_SYMBOL(__rdma_block_iter_start);
+
+ bool __rdma_block_iter_next(struct ib_block_iter *biter)
+ {
+- unsigned int block_offset;
+- unsigned int delta;
++ dma_addr_t block_offset;
++ dma_addr_t delta;
+
+ if (!biter->__sg_nents || !biter->__sg)
+ return false;
--- /dev/null
+From stable+bounces-260871-greg=kroah.com@vger.kernel.org Sat Jun 6 17:50:24 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 6 Jun 2026 08:19:09 -0400
+Subject: scsi: target: iscsi: Fix CRC overread and double-free in iscsit_handle_text_cmd()
+To: stable@vger.kernel.org
+Cc: Michael Bommarito <michael.bommarito@gmail.com>, John Garry <john.g.garry@oracle.com>, "Martin K. Petersen" <martin.petersen@oracle.com>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260606121909.2851630-1-sashal@kernel.org>
+
+From: Michael Bommarito <michael.bommarito@gmail.com>
+
+[ Upstream commit 778c2ab142c625a8a8afa570e0f9b7873f445d99 ]
+
+Two latent bugs in the Text-phase handler, both present since the
+original LIO integration in commit e48354ce078c ("iscsi-target: Add
+iSCSI fabric support for target v4.1"):
+
+1) DataDigest CRC buffer overread (4 bytes past text_in).
+
+ text_in is kzalloc()'d at ALIGN(payload_length, 4). rx_size is then
+ incremented by ISCSI_CRC_LEN to make room for the received DataDigest
+ in the iovec, but the same (now-bumped) rx_size is passed as the
+ buffer length to iscsit_crc_buf():
+
+ if (conn->conn_ops->DataDigest) {
+ ...
+ rx_size += ISCSI_CRC_LEN;
+ }
+ ...
+ if (conn->conn_ops->DataDigest) {
+ data_crc = iscsit_crc_buf(text_in, rx_size, 0, NULL);
+
+ iscsit_crc_buf() walks rx_size bytes of text_in with crc32c(), so
+ when DataDigest is negotiated it reads 4 bytes past the end of the
+ text_in allocation. KASAN reproduces this directly on the unpatched
+ mainline tree as slab-out-of-bounds in crc32c() called from the Text
+ PDU path. The OOB bytes feed crc32c() and are then compared against
+ the initiator-supplied checksum, so the value does not flow back to
+ the attacker, but the kernel does read past the buffer on every Text
+ PDU with DataDigest=CRC32C.
+
+ Fix by passing the actual padded payload length
+ (ALIGN(payload_length, 4)) that was used for the kzalloc().
+
+2) Stale cmd->text_in_ptr re-free (double-free) on ERL>0 bad DataDigest
+ drop.
+
+ On DataDigest mismatch with ErrorRecoveryLevel > 0 the handler
+ silently drops the PDU and lets the initiator plug the CmdSN gap:
+
+ kfree(text_in);
+ return 0;
+
+ cmd->text_in_ptr still points at the freed buffer. The next Text
+ Request on the same ITT re-enters iscsit_setup_text_cmd(), which
+ unconditionally does
+
+ kfree(cmd->text_in_ptr);
+ cmd->text_in_ptr = NULL;
+
+ freeing the same pointer a second time. Session teardown via
+ iscsit_release_cmd() has the same shape and hits the same double-free
+ if the connection is dropped before a second Text Request arrives.
+
+ On an unmodified mainline tree the bug-1 CRC overread fires first on
+ the initial valid Text Request and perturbs the subsequent state, so
+ #4 was isolated by building a kernel with only the bug-1 hunk of this
+ patch applied plus temporary printk() observability around the three
+ relevant kfree() sites. The observability prints are not part of
+ this patch. On that build, a three-PDU Text Request sequence after
+ login produces two back-to-back splats:
+
+ BUG: KASAN: double-free in iscsit_setup_text_cmd+0x??
+ BUG: KASAN: double-free in iscsit_release_cmd+0x??
+
+ showing the same pointer freed in the ERL>0 drop path and again in
+ iscsit_setup_text_cmd() (next Text Request on the same ITT) and once
+ more in iscsit_release_cmd() (session teardown). On distro kernels
+ with CONFIG_SLAB_FREELIST_HARDENED=y (default) the double-free
+ becomes a remote kernel BUG(); on non-hardened kernels it corrupts
+ the slab freelist.
+
+ Fix by clearing cmd->text_in_ptr after the kfree() in the ERL>0 drop
+ path. With both hunks applied #4 is directly observable on the stock
+ tree without observability printks; fixing bug-1 alone would mask #4
+ less, not more, so the hunks are submitted together.
+
+Both fixes are one-liners. The Text PDU state machine is unchanged and
+the wire protocol is unaffected.
+
+Fixes: e48354ce078c ("iscsi-target: Add iSCSI fabric support for target v4.1")
+Cc: stable@vger.kernel.org
+Assisted-by: Claude:claude-opus-4-7
+Signed-off-by: Michael Bommarito <michael.bommarito@gmail.com>
+Tested-by: John Garry <john.g.garry@oracle.com>
+Reviewed-by: John Garry <john.g.garry@oracle.com>
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/target/iscsi/iscsi_target.c | 6 ++++--
+ 1 file changed, 4 insertions(+), 2 deletions(-)
+
+--- a/drivers/target/iscsi/iscsi_target.c
++++ b/drivers/target/iscsi/iscsi_target.c
+@@ -2335,8 +2335,9 @@ iscsit_handle_text_cmd(struct iscsit_con
+
+ if (conn->conn_ops->DataDigest) {
+ iscsit_do_crypto_hash_buf(conn->conn_rx_hash,
+- text_in, rx_size, 0, NULL,
+- &data_crc);
++ text_in,
++ ALIGN(payload_length, 4),
++ 0, NULL, &data_crc);
+
+ if (checksum != data_crc) {
+ pr_err("Text data CRC32C DataDigest"
+@@ -2356,6 +2357,7 @@ iscsit_handle_text_cmd(struct iscsit_con
+ " Command CmdSN: 0x%08x due to"
+ " DataCRC error.\n", hdr->cmdsn);
+ kfree(text_in);
++ cmd->text_in_ptr = NULL;
+ return 0;
+ }
+ } else {
--- /dev/null
+From stable+bounces-260880-greg=kroah.com@vger.kernel.org Sat Jun 6 18:19:51 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 6 Jun 2026 08:49:44 -0400
+Subject: serial: qcom_geni: fix kfifo underflow when flush precedes DMA completion IRQ
+To: stable@vger.kernel.org
+Cc: Viken Dadhaniya <viken.dadhaniya@oss.qualcomm.com>, stable <stable@kernel.org>, Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>, Greg Kroah-Hartman <gregkh@linuxfoundation.org>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260606124944.2878832-1-sashal@kernel.org>
+
+From: Viken Dadhaniya <viken.dadhaniya@oss.qualcomm.com>
+
+[ Upstream commit 452d6fa37ae9b021f4f6d397dbae077f7296f6f4 ]
+
+When uart_flush_buffer() runs before the DMA completion IRQ is delivered,
+the following race can occur (all steps serialized by uart_port_lock):
+
+ 1. DMA starts: tx_remaining = N, kfifo contains N bytes
+ 2. DMA completes in hardware; IRQ is pending but not yet delivered
+ 3. uart_flush_buffer() acquires the port lock and calls kfifo_reset(),
+ making kfifo_len() = 0 while tx_remaining remains N
+ 4. uart_flush_buffer() releases the port lock
+ 5. DMA IRQ fires; handle_tx_dma() acquires the port lock and calls
+ uart_xmit_advance(uport, tx_remaining) on an empty kfifo
+
+uart_xmit_advance() increments kfifo->out by tx_remaining. Since
+kfifo_reset() already set both in and out to 0, out wraps past in,
+causing kfifo_len() to return UART_XMIT_SIZE - tx_remaining. The next
+start_tx_dma() call then submits a DMA transfer of stale buffer data.
+
+Fix this by snapshotting kfifo_len() at the start of handle_tx_dma()
+and skipping uart_xmit_advance() when fifo_len < tx_remaining, which
+indicates the kfifo was reset by a preceding flush.
+
+Fixes: 2aaa43c70778 ("tty: serial: qcom-geni-serial: add support for serial engine DMA")
+Cc: stable <stable@kernel.org>
+Signed-off-by: Viken Dadhaniya <viken.dadhaniya@oss.qualcomm.com>
+Reviewed-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
+Link: https://patch.msgid.link/20260506-serial-dma-stale-tx-buf-v1-1-e3ccb360d719@oss.qualcomm.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/tty/serial/qcom_geni_serial.c | 15 ++++++++++++++-
+ 1 file changed, 14 insertions(+), 1 deletion(-)
+
+--- a/drivers/tty/serial/qcom_geni_serial.c
++++ b/drivers/tty/serial/qcom_geni_serial.c
+@@ -962,8 +962,21 @@ static void qcom_geni_serial_handle_tx_d
+ {
+ struct qcom_geni_serial_port *port = to_dev_port(uport);
+ struct circ_buf *xmit = &uport->state->xmit;
++ unsigned int chars_pending = uart_circ_chars_pending(xmit);
++
++ /*
++ * Only advance the buffer if it still contains the bytes that were
++ * transferred. uart_flush_buffer() may have run before this IRQ
++ * fired: it clears the circular buffer under the port lock, making
++ * chars_pending = 0 while tx_remaining remains non-zero. Calling
++ * uart_xmit_advance() in that case would advance xmit->tail past
++ * xmit->head, making uart_circ_chars_pending() wrap to
++ * UART_XMIT_SIZE - tx_remaining and triggering a spurious large DMA
++ * transfer of stale data.
++ */
++ if (chars_pending >= port->tx_remaining)
++ uart_xmit_advance(uport, port->tx_remaining);
+
+- uart_xmit_advance(uport, port->tx_remaining);
+ geni_se_tx_dma_unprep(&port->se, port->tx_dma_addr, port->tx_remaining);
+ port->tx_dma_addr = 0;
+ port->tx_remaining = 0;
--- /dev/null
+From stable+bounces-260700-greg=kroah.com@vger.kernel.org Fri Jun 5 19:23:32 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 5 Jun 2026 09:53:22 -0400
+Subject: serial: samsung_tty: Use port lock wrappers
+To: stable@vger.kernel.org
+Cc: Thomas Gleixner <tglx@linutronix.de>, John Ogness <john.ogness@linutronix.de>, Greg Kroah-Hartman <gregkh@linuxfoundation.org>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260605135324.928676-1-sashal@kernel.org>
+
+From: Thomas Gleixner <tglx@linutronix.de>
+
+[ Upstream commit 97d7a9aeba1d424c2359f1686d02c75d798ad184 ]
+
+When a serial port is used for kernel console output, then all
+modifications to the UART registers which are done from other contexts,
+e.g. getty, termios, are interference points for the kernel console.
+
+So far this has been ignored and the printk output is based on the
+principle of hope. The rework of the console infrastructure which aims to
+support threaded and atomic consoles, requires to mark sections which
+modify the UART registers as unsafe. This allows the atomic write function
+to make informed decisions and eventually to restore operational state. It
+also allows to prevent the regular UART code from modifying UART registers
+while printk output is in progress.
+
+All modifications of UART registers are guarded by the UART port lock,
+which provides an obvious synchronization point with the console
+infrastructure.
+
+To avoid adding this functionality to all UART drivers, wrap the
+spin_[un]lock*() invocations for uart_port::lock into helper functions
+which just contain the spin_[un]lock*() invocations for now. In a
+subsequent step these helpers will gain the console synchronization
+mechanisms.
+
+Converted with coccinelle. No functional change.
+
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Signed-off-by: John Ogness <john.ogness@linutronix.de>
+Link: https://lore.kernel.org/r/20230914183831.587273-54-john.ogness@linutronix.de
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Stable-dep-of: a3bb136bff5e ("tty: serial: samsung: Remove redundant port lock acquisition in rx helpers")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/tty/serial/samsung_tty.c | 50 +++++++++++++++++++--------------------
+ 1 file changed, 25 insertions(+), 25 deletions(-)
+
+--- a/drivers/tty/serial/samsung_tty.c
++++ b/drivers/tty/serial/samsung_tty.c
+@@ -248,7 +248,7 @@ static void s3c24xx_serial_rx_enable(str
+ unsigned int ucon, ufcon;
+ int count = 10000;
+
+- spin_lock_irqsave(&port->lock, flags);
++ uart_port_lock_irqsave(port, &flags);
+
+ while (--count && !s3c24xx_serial_txempty_nofifo(port))
+ udelay(100);
+@@ -262,7 +262,7 @@ static void s3c24xx_serial_rx_enable(str
+ wr_regl(port, S3C2410_UCON, ucon);
+
+ ourport->rx_enabled = 1;
+- spin_unlock_irqrestore(&port->lock, flags);
++ uart_port_unlock_irqrestore(port, flags);
+ }
+
+ static void s3c24xx_serial_rx_disable(struct uart_port *port)
+@@ -271,14 +271,14 @@ static void s3c24xx_serial_rx_disable(st
+ unsigned long flags;
+ unsigned int ucon;
+
+- spin_lock_irqsave(&port->lock, flags);
++ uart_port_lock_irqsave(port, &flags);
+
+ ucon = rd_regl(port, S3C2410_UCON);
+ ucon &= ~S3C2410_UCON_RXIRQMODE;
+ wr_regl(port, S3C2410_UCON, ucon);
+
+ ourport->rx_enabled = 0;
+- spin_unlock_irqrestore(&port->lock, flags);
++ uart_port_unlock_irqrestore(port, flags);
+ }
+
+ static void s3c24xx_serial_stop_tx(struct uart_port *port)
+@@ -344,7 +344,7 @@ static void s3c24xx_serial_tx_dma_comple
+ dma->tx_transfer_addr, dma->tx_size,
+ DMA_TO_DEVICE);
+
+- spin_lock_irqsave(&port->lock, flags);
++ uart_port_lock_irqsave(port, &flags);
+
+ uart_xmit_advance(port, count);
+ ourport->tx_in_progress = 0;
+@@ -353,7 +353,7 @@ static void s3c24xx_serial_tx_dma_comple
+ uart_write_wakeup(port);
+
+ s3c24xx_serial_start_next_tx(ourport);
+- spin_unlock_irqrestore(&port->lock, flags);
++ uart_port_unlock_irqrestore(port, flags);
+ }
+
+ static void enable_tx_dma(struct s3c24xx_uart_port *ourport)
+@@ -619,7 +619,7 @@ static void s3c24xx_serial_rx_dma_comple
+ received = dma->rx_bytes_requested - state.residue;
+ async_tx_ack(dma->rx_desc);
+
+- spin_lock_irqsave(&port->lock, flags);
++ uart_port_lock_irqsave(port, &flags);
+
+ if (received)
+ s3c24xx_uart_copy_rx_to_tty(ourport, t, received);
+@@ -631,7 +631,7 @@ static void s3c24xx_serial_rx_dma_comple
+
+ s3c64xx_start_rx_dma(ourport);
+
+- spin_unlock_irqrestore(&port->lock, flags);
++ uart_port_unlock_irqrestore(port, flags);
+ }
+
+ static void s3c64xx_start_rx_dma(struct s3c24xx_uart_port *ourport)
+@@ -722,7 +722,7 @@ static irqreturn_t s3c24xx_serial_rx_cha
+ utrstat = rd_regl(port, S3C2410_UTRSTAT);
+ rd_regl(port, S3C2410_UFSTAT);
+
+- spin_lock(&port->lock);
++ uart_port_lock(port);
+
+ if (!(utrstat & S3C2410_UTRSTAT_TIMEOUT)) {
+ s3c64xx_start_rx_dma(ourport);
+@@ -751,7 +751,7 @@ static irqreturn_t s3c24xx_serial_rx_cha
+ wr_regl(port, S3C2410_UTRSTAT, S3C2410_UTRSTAT_TIMEOUT);
+
+ finish:
+- spin_unlock(&port->lock);
++ uart_port_unlock(port);
+
+ return IRQ_HANDLED;
+ }
+@@ -849,9 +849,9 @@ static irqreturn_t s3c24xx_serial_rx_cha
+ struct s3c24xx_uart_port *ourport = dev_id;
+ struct uart_port *port = &ourport->port;
+
+- spin_lock(&port->lock);
++ uart_port_lock(port);
+ s3c24xx_serial_rx_drain_fifo(ourport);
+- spin_unlock(&port->lock);
++ uart_port_unlock(port);
+
+ return IRQ_HANDLED;
+ }
+@@ -932,11 +932,11 @@ static irqreturn_t s3c24xx_serial_tx_irq
+ struct s3c24xx_uart_port *ourport = id;
+ struct uart_port *port = &ourport->port;
+
+- spin_lock(&port->lock);
++ uart_port_lock(port);
+
+ s3c24xx_serial_tx_chars(ourport);
+
+- spin_unlock(&port->lock);
++ uart_port_unlock(port);
+ return IRQ_HANDLED;
+ }
+
+@@ -1032,7 +1032,7 @@ static void s3c24xx_serial_break_ctl(str
+ unsigned long flags;
+ unsigned int ucon;
+
+- spin_lock_irqsave(&port->lock, flags);
++ uart_port_lock_irqsave(port, &flags);
+
+ ucon = rd_regl(port, S3C2410_UCON);
+
+@@ -1043,7 +1043,7 @@ static void s3c24xx_serial_break_ctl(str
+
+ wr_regl(port, S3C2410_UCON, ucon);
+
+- spin_unlock_irqrestore(&port->lock, flags);
++ uart_port_unlock_irqrestore(port, flags);
+ }
+
+ static int s3c24xx_serial_request_dma(struct s3c24xx_uart_port *p)
+@@ -1302,7 +1302,7 @@ static int s3c64xx_serial_startup(struct
+ ourport->rx_enabled = 1;
+ ourport->tx_enabled = 0;
+
+- spin_lock_irqsave(&port->lock, flags);
++ uart_port_lock_irqsave(port, &flags);
+
+ ufcon = rd_regl(port, S3C2410_UFCON);
+ ufcon |= S3C2410_UFCON_RESETRX | S5PV210_UFCON_RXTRIG8;
+@@ -1312,7 +1312,7 @@ static int s3c64xx_serial_startup(struct
+
+ enable_rx_pio(ourport);
+
+- spin_unlock_irqrestore(&port->lock, flags);
++ uart_port_unlock_irqrestore(port, flags);
+
+ /* Enable Rx Interrupt */
+ s3c24xx_clear_bit(port, S3C64XX_UINTM_RXD, S3C64XX_UINTM);
+@@ -1340,7 +1340,7 @@ static int apple_s5l_serial_startup(stru
+ ourport->rx_enabled = 1;
+ ourport->tx_enabled = 0;
+
+- spin_lock_irqsave(&port->lock, flags);
++ uart_port_lock_irqsave(port, &flags);
+
+ ufcon = rd_regl(port, S3C2410_UFCON);
+ ufcon |= S3C2410_UFCON_RESETRX | S5PV210_UFCON_RXTRIG8;
+@@ -1350,7 +1350,7 @@ static int apple_s5l_serial_startup(stru
+
+ enable_rx_pio(ourport);
+
+- spin_unlock_irqrestore(&port->lock, flags);
++ uart_port_unlock_irqrestore(port, flags);
+
+ /* Enable Rx Interrupt */
+ s3c24xx_set_bit(port, APPLE_S5L_UCON_RXTHRESH_ENA, S3C2410_UCON);
+@@ -1625,7 +1625,7 @@ static void s3c24xx_serial_set_termios(s
+ ulcon |= S3C2410_LCON_PNONE;
+ }
+
+- spin_lock_irqsave(&port->lock, flags);
++ uart_port_lock_irqsave(port, &flags);
+
+ dev_dbg(port->dev,
+ "setting ulcon to %08x, brddiv to %d, udivslot %08x\n",
+@@ -1683,7 +1683,7 @@ static void s3c24xx_serial_set_termios(s
+ if ((termios->c_cflag & CREAD) == 0)
+ port->ignore_status_mask |= RXSTAT_DUMMY_READ;
+
+- spin_unlock_irqrestore(&port->lock, flags);
++ uart_port_unlock_irqrestore(port, flags);
+ }
+
+ static const char *s3c24xx_serial_type(struct uart_port *port)
+@@ -2375,14 +2375,14 @@ s3c24xx_serial_console_write(struct cons
+ if (cons_uart->sysrq)
+ locked = false;
+ else if (oops_in_progress)
+- locked = spin_trylock_irqsave(&cons_uart->lock, flags);
++ locked = uart_port_trylock_irqsave(cons_uart, &flags);
+ else
+- spin_lock_irqsave(&cons_uart->lock, flags);
++ uart_port_lock_irqsave(cons_uart, &flags);
+
+ uart_console_write(cons_uart, s, count, s3c24xx_serial_console_putchar);
+
+ if (locked)
+- spin_unlock_irqrestore(&cons_uart->lock, flags);
++ uart_port_unlock_irqrestore(cons_uart, flags);
+ }
+
+ /* Shouldn't be __init, as it can be instantiated from other module */
bluetooth-hci_qca-migrate-to-serdev-specific-shutdown-function.patch
bluetooth-hci_qca-convert-timeout-from-jiffies-to-ms.patch
mptcp-handle-first-subflow-closing-consistently.patch
+iio-gyro-adis16260-fix-division-by-zero-in-write_raw.patch
+iio-chemical-scd30-use-guard-mutex-to-allow-early-returns.patch
+iio-chemical-scd30-fix-division-by-zero-in-write_raw.patch
+usb-cdns3-plat-fix-leaked-usb2_phy-initialization-on-usb3_phy-acquisition-failure.patch
+iio-dac-ad5686-fix-ref-bit-initialization-for-single-channel-parts.patch
+memfd-deny-writeable-mappings-when-implying-seal_write.patch
+alsa-firewire-motu-protect-register-dsp-event-queue-positions.patch
+serial-samsung_tty-use-port-lock-wrappers.patch
+tty-serial-samsung-use-u32-for-register-interactions.patch
+tty-serial-samsung-remove-redundant-port-lock-acquisition-in-rx-helpers.patch
+usb-musb-omap2430-fix-use-after-free-in-omap2430_probe.patch
+usb-dwc3-xilinx-fix-error-handling-in-zynqmp-init-error-paths.patch
+usb-gadget-uvc-hold-opts-lock-across-xu-walks-in-uvc_function_bind.patch
+usb-typec-ucsi-check-if-power-role-change-actually-happened-before-handling.patch
+thunderbolt-property-cap-recursion-depth-in-__tb_property_parse_dir.patch
+scsi-target-iscsi-fix-crc-overread-and-double-free-in-iscsit_handle_text_cmd.patch
+serial-qcom_geni-fix-kfifo-underflow-when-flush-precedes-dma-completion-irq.patch
+usb-typec-ucsi-don-t-update-power_supply-on-power-role-change-if-not-connected.patch
+netfilter-nft_fib-fix-stale-stack-leak-via-the-oifname-register.patch
+mm-hugetlb-rename-isolate_hugetlb-to-folio_isolate_hugetlb.patch
+mm-migrate-don-t-call-folio_putback_active_hugetlb-on-dst-hugetlb-folio.patch
+mm-hugetlb-rename-folio_putback_active_hugetlb-to-folio_putback_hugetlb.patch
+mm-memory-failure-fix-missing-mf_stats-count-in-hugetlb-poison.patch
+mm-memory-failure-fix-hugetlb_lock-aa-deadlock-in-get_huge_page_for_hwpoison.patch
+hv_netvsc-use-kmap_local_page-in-netvsc_copy_to_send_buf.patch
+rdma-during-rereg_mr-ensure-that-rereg_access-is-compatible.patch
+rdma-umem-fix-kernel-doc-warnings.patch
+rdma-move-dma-block-iterator-logic-into-dedicated-files.patch
+rdma-umem-fix-truncation-for-block-sizes-4g.patch
--- /dev/null
+From stable+bounces-260811-greg=kroah.com@vger.kernel.org Sat Jun 6 01:17:55 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 5 Jun 2026 15:42:47 -0400
+Subject: thunderbolt: property: Cap recursion depth in __tb_property_parse_dir()
+To: stable@vger.kernel.org
+Cc: Michael Bommarito <michael.bommarito@gmail.com>, Mika Westerberg <mika.westerberg@linux.intel.com>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260605194247.2177334-1-sashal@kernel.org>
+
+From: Michael Bommarito <michael.bommarito@gmail.com>
+
+[ Upstream commit 928abe19fbf0127003abcb1ea69cabc1c897d0ab ]
+
+A DIRECTORY entry's value field is used as the dir_offset for a
+recursive call into __tb_property_parse_dir() with no depth counter.
+A crafted peer that chains DIRECTORY entries into a back-reference
+loop drives the parser until the kernel stack is exhausted and the
+guard page fires. Any untrusted XDomain peer (cable, dock, in-line
+inspector, adjacent host) that reaches the PROPERTIES_REQUEST
+control-plane exchange can trigger this without authentication.
+
+Thread a depth counter through tb_property_parse() and
+__tb_property_parse_dir(), and reject blocks that exceed
+TB_PROPERTY_MAX_DEPTH = 8. That is comfortably larger than any
+observed legitimate XDomain layout.
+
+Operators who do not need XDomain host-to-host discovery can disable
+the path entirely with thunderbolt.xdomain=0 on the kernel command
+line.
+
+Fixes: cdae7c07e3e3 ("thunderbolt: Add support for XDomain properties")
+Cc: stable@vger.kernel.org
+Assisted-by: Claude:claude-opus-4-6
+Assisted-by: Codex:gpt-5-4
+Signed-off-by: Michael Bommarito <michael.bommarito@gmail.com>
+Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/thunderbolt/property.c | 18 ++++++++++++------
+ 1 file changed, 12 insertions(+), 6 deletions(-)
+
+--- a/drivers/thunderbolt/property.c
++++ b/drivers/thunderbolt/property.c
+@@ -35,10 +35,11 @@ struct tb_property_dir_entry {
+ };
+
+ #define TB_PROPERTY_ROOTDIR_MAGIC 0x55584401
++#define TB_PROPERTY_MAX_DEPTH 8
+
+ static struct tb_property_dir *__tb_property_parse_dir(const u32 *block,
+ size_t block_len, unsigned int dir_offset, size_t dir_len,
+- bool is_root);
++ bool is_root, unsigned int depth);
+
+ static inline void parse_dwdata(void *dst, const void *src, size_t dwords)
+ {
+@@ -99,7 +100,8 @@ tb_property_alloc(const char *key, enum
+ }
+
+ static struct tb_property *tb_property_parse(const u32 *block, size_t block_len,
+- const struct tb_property_entry *entry)
++ const struct tb_property_entry *entry,
++ unsigned int depth)
+ {
+ char key[TB_PROPERTY_KEY_SIZE + 1];
+ struct tb_property *property;
+@@ -120,7 +122,7 @@ static struct tb_property *tb_property_p
+ switch (property->type) {
+ case TB_PROPERTY_TYPE_DIRECTORY:
+ dir = __tb_property_parse_dir(block, block_len, entry->value,
+- entry->length, false);
++ entry->length, false, depth + 1);
+ if (!dir) {
+ kfree(property);
+ return NULL;
+@@ -165,13 +167,17 @@ static struct tb_property *tb_property_p
+ }
+
+ static struct tb_property_dir *__tb_property_parse_dir(const u32 *block,
+- size_t block_len, unsigned int dir_offset, size_t dir_len, bool is_root)
++ size_t block_len, unsigned int dir_offset, size_t dir_len, bool is_root,
++ unsigned int depth)
+ {
+ const struct tb_property_entry *entries;
+ size_t i, content_len, nentries;
+ unsigned int content_offset;
+ struct tb_property_dir *dir;
+
++ if (depth > TB_PROPERTY_MAX_DEPTH)
++ return NULL;
++
+ dir = kzalloc(sizeof(*dir), GFP_KERNEL);
+ if (!dir)
+ return NULL;
+@@ -206,7 +212,7 @@ static struct tb_property_dir *__tb_prop
+ for (i = 0; i < nentries; i++) {
+ struct tb_property *property;
+
+- property = tb_property_parse(block, block_len, &entries[i]);
++ property = tb_property_parse(block, block_len, &entries[i], depth);
+ if (!property) {
+ tb_property_free_dir(dir);
+ return NULL;
+@@ -243,7 +249,7 @@ struct tb_property_dir *tb_property_pars
+ return NULL;
+
+ return __tb_property_parse_dir(block, block_len, 0, rootdir->length,
+- true);
++ true, 0);
+ }
+
+ /**
--- /dev/null
+From sashal@kernel.org Fri Jun 5 19:23:29 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 5 Jun 2026 09:53:24 -0400
+Subject: tty: serial: samsung: Remove redundant port lock acquisition in rx helpers
+To: stable@vger.kernel.org
+Cc: Tudor Ambarus <tudor.ambarus@linaro.org>, stable <stable@kernel.org>, John Ogness <john.ogness@linutronix.de>, Greg Kroah-Hartman <gregkh@linuxfoundation.org>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260605135324.928676-3-sashal@kernel.org>
+
+From: Tudor Ambarus <tudor.ambarus@linaro.org>
+
+[ Upstream commit a3bb136bff5e6a5e48cdd813246c9c4686feaaa9 ]
+
+Sashiko identified a deadlock when the console flow is engaged [1].
+
+When console flow control is enabled (UPF_CONS_FLOW),
+s3c24xx_serial_stop_tx() calls s3c24xx_serial_rx_enable() and
+s3c24xx_serial_start_tx() calls s3c24xx_serial_rx_disable().
+
+The serial core framework invokes the .stop_tx() and .start_tx()
+callbacks with the port->lock spinlock already held. Furthermore, all
+internal driver paths that invoke stop_tx (such as the DMA TX
+completion handler s3c24xx_serial_tx_dma_complete() or the PIO TX IRQ
+handler s3c24xx_serial_tx_irq()) also acquire port->lock prior to
+calling it. (Note that s3c24xx_serial_start_tx() is only invoked by the
+serial core).
+
+However, s3c24xx_serial_rx_enable() and s3c24xx_serial_rx_disable()
+unconditionally attempt to acquire port->lock again using
+uart_port_lock_irqsave(). Since spinlocks are not recursive, this
+causes a deadlock on the same CPU when console flow control is engaged.
+
+Remove the redundant lock acquisition from both rx helper functions.
+
+Cc: stable <stable@kernel.org>
+Fixes: b497549a035c ("[ARM] S3C24XX: Split serial driver into core and per-cpu drivers")
+Reported-by: John Ogness <john.ogness@linutronix.de>
+Closes: https://sashiko.dev/#/patchset/20260506121606.5805-1-john.ogness%40linutronix.de [1]
+Signed-off-by: Tudor Ambarus <tudor.ambarus@linaro.org>
+Link: https://patch.msgid.link/20260515-samsung-tty-flow-control-deadlock-v1-1-93255edbc9bc@linaro.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/tty/serial/samsung_tty.c | 8 --------
+ 1 file changed, 8 deletions(-)
+
+--- a/drivers/tty/serial/samsung_tty.c
++++ b/drivers/tty/serial/samsung_tty.c
+@@ -244,12 +244,9 @@ static int s3c24xx_serial_txempty_nofifo
+ static void s3c24xx_serial_rx_enable(struct uart_port *port)
+ {
+ struct s3c24xx_uart_port *ourport = to_ourport(port);
+- unsigned long flags;
+ int count = 10000;
+ u32 ucon, ufcon;
+
+- uart_port_lock_irqsave(port, &flags);
+-
+ while (--count && !s3c24xx_serial_txempty_nofifo(port))
+ udelay(100);
+
+@@ -262,23 +259,18 @@ static void s3c24xx_serial_rx_enable(str
+ wr_regl(port, S3C2410_UCON, ucon);
+
+ ourport->rx_enabled = 1;
+- uart_port_unlock_irqrestore(port, flags);
+ }
+
+ static void s3c24xx_serial_rx_disable(struct uart_port *port)
+ {
+ struct s3c24xx_uart_port *ourport = to_ourport(port);
+- unsigned long flags;
+ u32 ucon;
+
+- uart_port_lock_irqsave(port, &flags);
+-
+ ucon = rd_regl(port, S3C2410_UCON);
+ ucon &= ~S3C2410_UCON_RXIRQMODE;
+ wr_regl(port, S3C2410_UCON, ucon);
+
+ ourport->rx_enabled = 0;
+- uart_port_unlock_irqrestore(port, flags);
+ }
+
+ static void s3c24xx_serial_stop_tx(struct uart_port *port)
--- /dev/null
+From sashal@kernel.org Fri Jun 5 19:23:29 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 5 Jun 2026 09:53:23 -0400
+Subject: tty: serial: samsung: use u32 for register interactions
+To: stable@vger.kernel.org
+Cc: Tudor Ambarus <tudor.ambarus@linaro.org>, Sam Protsenko <semen.protsenko@linaro.org>, Greg Kroah-Hartman <gregkh@linuxfoundation.org>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260605135324.928676-2-sashal@kernel.org>
+
+From: Tudor Ambarus <tudor.ambarus@linaro.org>
+
+[ Upstream commit 032a725c16add79332d774348d7ad7d0d4b86479 ]
+
+All registers of the IP have 32 bits. Use u32 variables when reading
+or writing from/to the registers. The purpose of those variables becomes
+clearer.
+
+Reviewed-by: Sam Protsenko <semen.protsenko@linaro.org>
+Signed-off-by: Tudor Ambarus <tudor.ambarus@linaro.org>
+Link: https://lore.kernel.org/r/20240119104526.1221243-9-tudor.ambarus@linaro.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Stable-dep-of: a3bb136bff5e ("tty: serial: samsung: Remove redundant port lock acquisition in rx helpers")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/tty/serial/samsung_tty.c | 79 +++++++++++++++++++--------------------
+ 1 file changed, 39 insertions(+), 40 deletions(-)
+
+--- a/drivers/tty/serial/samsung_tty.c
++++ b/drivers/tty/serial/samsung_tty.c
+@@ -199,7 +199,7 @@ static void wr_reg(const struct uart_por
+ /* Byte-order aware bit setting/clearing functions. */
+
+ static inline void s3c24xx_set_bit(const struct uart_port *port, int idx,
+- unsigned int reg)
++ u32 reg)
+ {
+ unsigned long flags;
+ u32 val;
+@@ -212,7 +212,7 @@ static inline void s3c24xx_set_bit(const
+ }
+
+ static inline void s3c24xx_clear_bit(const struct uart_port *port, int idx,
+- unsigned int reg)
++ u32 reg)
+ {
+ unsigned long flags;
+ u32 val;
+@@ -245,8 +245,8 @@ static void s3c24xx_serial_rx_enable(str
+ {
+ struct s3c24xx_uart_port *ourport = to_ourport(port);
+ unsigned long flags;
+- unsigned int ucon, ufcon;
+ int count = 10000;
++ u32 ucon, ufcon;
+
+ uart_port_lock_irqsave(port, &flags);
+
+@@ -269,7 +269,7 @@ static void s3c24xx_serial_rx_disable(st
+ {
+ struct s3c24xx_uart_port *ourport = to_ourport(port);
+ unsigned long flags;
+- unsigned int ucon;
++ u32 ucon;
+
+ uart_port_lock_irqsave(port, &flags);
+
+@@ -591,7 +591,7 @@ static inline const struct s3c2410_uartc
+ }
+
+ static int s3c24xx_serial_rx_fifocnt(const struct s3c24xx_uart_port *ourport,
+- unsigned long ufstat)
++ u32 ufstat)
+ {
+ const struct s3c24xx_uart_info *info = ourport->info;
+
+@@ -663,7 +663,7 @@ static void s3c64xx_start_rx_dma(struct
+ static void enable_rx_dma(struct s3c24xx_uart_port *ourport)
+ {
+ struct uart_port *port = &ourport->port;
+- unsigned int ucon;
++ u32 ucon;
+
+ /* set Rx mode to DMA mode */
+ ucon = rd_regl(port, S3C2410_UCON);
+@@ -686,7 +686,7 @@ static void enable_rx_dma(struct s3c24xx
+ static void enable_rx_pio(struct s3c24xx_uart_port *ourport)
+ {
+ struct uart_port *port = &ourport->port;
+- unsigned int ucon;
++ u32 ucon;
+
+ /* set Rx mode to DMA mode */
+ ucon = rd_regl(port, S3C2410_UCON);
+@@ -711,13 +711,14 @@ static void s3c24xx_serial_rx_drain_fifo
+
+ static irqreturn_t s3c24xx_serial_rx_chars_dma(void *dev_id)
+ {
+- unsigned int utrstat, received;
+ struct s3c24xx_uart_port *ourport = dev_id;
+ struct uart_port *port = &ourport->port;
+ struct s3c24xx_uart_dma *dma = ourport->dma;
+ struct tty_struct *tty = tty_port_tty_get(&ourport->port.state->port);
+ struct tty_port *t = &port->state->port;
+ struct dma_tx_state state;
++ unsigned int received;
++ u32 utrstat;
+
+ utrstat = rd_regl(port, S3C2410_UTRSTAT);
+ rd_regl(port, S3C2410_UFSTAT);
+@@ -759,9 +760,9 @@ finish:
+ static void s3c24xx_serial_rx_drain_fifo(struct s3c24xx_uart_port *ourport)
+ {
+ struct uart_port *port = &ourport->port;
+- unsigned int ufcon, ufstat, uerstat;
+ unsigned int fifocnt = 0;
+ int max_count = port->fifosize;
++ u32 ufcon, ufstat, uerstat;
+ u8 ch, flag;
+
+ while (max_count-- > 0) {
+@@ -945,7 +946,7 @@ static irqreturn_t s3c64xx_serial_handle
+ {
+ const struct s3c24xx_uart_port *ourport = id;
+ const struct uart_port *port = &ourport->port;
+- unsigned int pend = rd_regl(port, S3C64XX_UINTP);
++ u32 pend = rd_regl(port, S3C64XX_UINTP);
+ irqreturn_t ret = IRQ_HANDLED;
+
+ if (pend & S3C64XX_UINTM_RXD_MSK) {
+@@ -964,7 +965,7 @@ static irqreturn_t apple_serial_handle_i
+ {
+ const struct s3c24xx_uart_port *ourport = id;
+ const struct uart_port *port = &ourport->port;
+- unsigned int pend = rd_regl(port, S3C2410_UTRSTAT);
++ u32 pend = rd_regl(port, S3C2410_UTRSTAT);
+ irqreturn_t ret = IRQ_NONE;
+
+ if (pend & (APPLE_S5L_UTRSTAT_RXTHRESH | APPLE_S5L_UTRSTAT_RXTO)) {
+@@ -983,8 +984,8 @@ static irqreturn_t apple_serial_handle_i
+ static unsigned int s3c24xx_serial_tx_empty(struct uart_port *port)
+ {
+ const struct s3c24xx_uart_info *info = s3c24xx_port_to_info(port);
+- unsigned long ufstat = rd_regl(port, S3C2410_UFSTAT);
+- unsigned long ufcon = rd_regl(port, S3C2410_UFCON);
++ u32 ufstat = rd_regl(port, S3C2410_UFSTAT);
++ u32 ufcon = rd_regl(port, S3C2410_UFCON);
+
+ if (ufcon & S3C2410_UFCON_FIFOMODE) {
+ if ((ufstat & info->tx_fifomask) != 0 ||
+@@ -999,7 +1000,7 @@ static unsigned int s3c24xx_serial_tx_em
+ /* no modem control lines */
+ static unsigned int s3c24xx_serial_get_mctrl(struct uart_port *port)
+ {
+- unsigned int umstat = rd_reg(port, S3C2410_UMSTAT);
++ u32 umstat = rd_reg(port, S3C2410_UMSTAT);
+
+ if (umstat & S3C2410_UMSTAT_CTS)
+ return TIOCM_CAR | TIOCM_DSR | TIOCM_CTS;
+@@ -1009,8 +1010,8 @@ static unsigned int s3c24xx_serial_get_m
+
+ static void s3c24xx_serial_set_mctrl(struct uart_port *port, unsigned int mctrl)
+ {
+- unsigned int umcon = rd_regl(port, S3C2410_UMCON);
+- unsigned int ucon = rd_regl(port, S3C2410_UCON);
++ u32 umcon = rd_regl(port, S3C2410_UMCON);
++ u32 ucon = rd_regl(port, S3C2410_UCON);
+
+ if (mctrl & TIOCM_RTS)
+ umcon |= S3C2410_UMCOM_RTS_LOW;
+@@ -1030,7 +1031,7 @@ static void s3c24xx_serial_set_mctrl(str
+ static void s3c24xx_serial_break_ctl(struct uart_port *port, int break_state)
+ {
+ unsigned long flags;
+- unsigned int ucon;
++ u32 ucon;
+
+ uart_port_lock_irqsave(port, &flags);
+
+@@ -1211,7 +1212,7 @@ static void apple_s5l_serial_shutdown(st
+ {
+ struct s3c24xx_uart_port *ourport = to_ourport(port);
+
+- unsigned int ucon;
++ u32 ucon;
+
+ ucon = rd_regl(port, S3C2410_UCON);
+ ucon &= ~(APPLE_S5L_UCON_TXTHRESH_ENA_MSK |
+@@ -1279,7 +1280,7 @@ static int s3c64xx_serial_startup(struct
+ {
+ struct s3c24xx_uart_port *ourport = to_ourport(port);
+ unsigned long flags;
+- unsigned int ufcon;
++ u32 ufcon;
+ int ret;
+
+ wr_regl(port, S3C64XX_UINTM, 0xf);
+@@ -1324,7 +1325,7 @@ static int apple_s5l_serial_startup(stru
+ {
+ struct s3c24xx_uart_port *ourport = to_ourport(port);
+ unsigned long flags;
+- unsigned int ufcon;
++ u32 ufcon;
+ int ret;
+
+ wr_regl(port, S3C2410_UTRSTAT, APPLE_S5L_UTRSTAT_ALL_FLAGS);
+@@ -1409,7 +1410,7 @@ static void s3c24xx_serial_pm(struct uar
+ static inline int s3c24xx_serial_getsource(struct uart_port *port)
+ {
+ const struct s3c24xx_uart_info *info = s3c24xx_port_to_info(port);
+- unsigned int ucon;
++ u32 ucon;
+
+ if (info->num_clks == 1)
+ return 0;
+@@ -1423,7 +1424,7 @@ static void s3c24xx_serial_setsource(str
+ unsigned int clk_sel)
+ {
+ const struct s3c24xx_uart_info *info = s3c24xx_port_to_info(port);
+- unsigned int ucon;
++ u32 ucon;
+
+ if (info->num_clks == 1)
+ return;
+@@ -1540,9 +1541,8 @@ static void s3c24xx_serial_set_termios(s
+ struct clk *clk = ERR_PTR(-EINVAL);
+ unsigned long flags;
+ unsigned int baud, quot, clk_sel = 0;
+- unsigned int ulcon;
+- unsigned int umcon;
+ unsigned int udivslot = 0;
++ u32 ulcon, umcon;
+
+ /*
+ * We don't support modem control lines.
+@@ -1849,7 +1849,7 @@ static void s3c24xx_serial_resetport(str
+ const struct s3c2410_uartcfg *cfg)
+ {
+ const struct s3c24xx_uart_info *info = s3c24xx_port_to_info(port);
+- unsigned long ucon = rd_regl(port, S3C2410_UCON);
++ u32 ucon = rd_regl(port, S3C2410_UCON);
+
+ ucon &= (info->clksel_mask | info->ucon_mask);
+ wr_regl(port, S3C2410_UCON, ucon | cfg->ucon);
+@@ -2005,7 +2005,7 @@ static int s3c24xx_serial_init_port(stru
+ wr_regl(port, S3C64XX_UINTSP, 0xf);
+ break;
+ case TYPE_APPLE_S5L: {
+- unsigned int ucon;
++ u32 ucon;
+
+ ucon = rd_regl(port, S3C2410_UCON);
+ ucon &= ~(APPLE_S5L_UCON_TXTHRESH_ENA_MSK |
+@@ -2212,7 +2212,7 @@ static int s3c24xx_serial_resume_noirq(s
+ /* restore IRQ mask */
+ switch (ourport->info->type) {
+ case TYPE_S3C6400: {
+- unsigned int uintm = 0xf;
++ u32 uintm = 0xf;
+
+ if (ourport->tx_enabled)
+ uintm &= ~S3C64XX_UINTM_TXD_MSK;
+@@ -2228,7 +2228,7 @@ static int s3c24xx_serial_resume_noirq(s
+ break;
+ }
+ case TYPE_APPLE_S5L: {
+- unsigned int ucon;
++ u32 ucon;
+ int ret;
+
+ ret = clk_prepare_enable(ourport->clk);
+@@ -2290,10 +2290,10 @@ static const struct dev_pm_ops s3c24xx_s
+ static struct uart_port *cons_uart;
+
+ static int
+-s3c24xx_serial_console_txrdy(struct uart_port *port, unsigned int ufcon)
++s3c24xx_serial_console_txrdy(struct uart_port *port, u32 ufcon)
+ {
+ const struct s3c24xx_uart_info *info = s3c24xx_port_to_info(port);
+- unsigned long ufstat, utrstat;
++ u32 ufstat, utrstat;
+
+ if (ufcon & S3C2410_UFCON_FIFOMODE) {
+ /* fifo mode - check amount of data in fifo registers... */
+@@ -2309,7 +2309,7 @@ s3c24xx_serial_console_txrdy(struct uart
+ }
+
+ static bool
+-s3c24xx_port_configured(unsigned int ucon)
++s3c24xx_port_configured(u32 ucon)
+ {
+ /* consider the serial port configured if the tx/rx mode set */
+ return (ucon & 0xf) != 0;
+@@ -2324,7 +2324,7 @@ s3c24xx_port_configured(unsigned int uco
+ static int s3c24xx_serial_get_poll_char(struct uart_port *port)
+ {
+ const struct s3c24xx_uart_port *ourport = to_ourport(port);
+- unsigned int ufstat;
++ u32 ufstat;
+
+ ufstat = rd_regl(port, S3C2410_UFSTAT);
+ if (s3c24xx_serial_rx_fifocnt(ourport, ufstat) == 0)
+@@ -2336,8 +2336,8 @@ static int s3c24xx_serial_get_poll_char(
+ static void s3c24xx_serial_put_poll_char(struct uart_port *port,
+ unsigned char c)
+ {
+- unsigned int ufcon = rd_regl(port, S3C2410_UFCON);
+- unsigned int ucon = rd_regl(port, S3C2410_UCON);
++ u32 ufcon = rd_regl(port, S3C2410_UFCON);
++ u32 ucon = rd_regl(port, S3C2410_UCON);
+
+ /* not possible to xmit on unconfigured port */
+ if (!s3c24xx_port_configured(ucon))
+@@ -2353,7 +2353,7 @@ static void s3c24xx_serial_put_poll_char
+ static void
+ s3c24xx_serial_console_putchar(struct uart_port *port, unsigned char ch)
+ {
+- unsigned int ufcon = rd_regl(port, S3C2410_UFCON);
++ u32 ufcon = rd_regl(port, S3C2410_UFCON);
+
+ while (!s3c24xx_serial_console_txrdy(port, ufcon))
+ cpu_relax();
+@@ -2364,7 +2364,7 @@ static void
+ s3c24xx_serial_console_write(struct console *co, const char *s,
+ unsigned int count)
+ {
+- unsigned int ucon = rd_regl(cons_uart, S3C2410_UCON);
++ u32 ucon = rd_regl(cons_uart, S3C2410_UCON);
+ unsigned long flags;
+ bool locked = true;
+
+@@ -2391,11 +2391,9 @@ s3c24xx_serial_get_options(struct uart_p
+ int *parity, int *bits)
+ {
+ struct clk *clk;
+- unsigned int ulcon;
+- unsigned int ucon;
+- unsigned int ubrdiv;
+ unsigned long rate;
+ unsigned int clk_sel;
++ u32 ulcon, ucon, ubrdiv;
+ char clk_name[MAX_CLK_NAME_LENGTH];
+
+ ulcon = rd_regl(port, S3C2410_ULCON);
+@@ -2806,7 +2804,8 @@ static int samsung_early_read(struct con
+ {
+ struct earlycon_device *dev = con->data;
+ const struct samsung_early_console_data *data = dev->port.private_data;
+- int ch, ufstat, num_read = 0;
++ int num_read = 0;
++ u32 ch, ufstat;
+
+ while (num_read < n) {
+ ufstat = rd_regl(&dev->port, S3C2410_UFSTAT);
--- /dev/null
+From stable+bounces-260588-greg=kroah.com@vger.kernel.org Fri Jun 5 05:19:24 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 4 Jun 2026 19:49:13 -0400
+Subject: usb: cdns3: plat: fix leaked usb2_phy initialization on usb3_phy acquisition failure
+To: stable@vger.kernel.org
+Cc: Peter Chen <peter.chen@cixtech.com>, stable <stable@kernel.org>, sashiko-bot <sashiko-bot@kernel.org>, Greg Kroah-Hartman <gregkh@linuxfoundation.org>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260604234913.2468901-1-sashal@kernel.org>
+
+From: Peter Chen <peter.chen@cixtech.com>
+
+[ Upstream commit e6970cda63fd4b4546aeed9d0e2f53a7c95cd09c ]
+
+Move usb2_phy initialization after usb3_phy acquisition.
+
+Fixes: f738957277ba ("usb: cdns3: Split core.c into cdns3-plat and core.c file")
+Cc: stable <stable@kernel.org>
+Reported-by: sashiko-bot <sashiko-bot@kernel.org>
+Closes: https://lore.kernel.org/linux-devicetree/agKaEePSFknhDBg2@nchen-desktop/T/#m21e1d9c1574eb127ce03c0c2a1a49002ce435b52
+Signed-off-by: Peter Chen <peter.chen@cixtech.com>
+Link: https://patch.msgid.link/20260513085310.2217547-2-peter.chen@cixtech.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/usb/cdns3/cdns3-plat.c | 8 ++++----
+ 1 file changed, 4 insertions(+), 4 deletions(-)
+
+--- a/drivers/usb/cdns3/cdns3-plat.c
++++ b/drivers/usb/cdns3/cdns3-plat.c
+@@ -121,14 +121,14 @@ static int cdns3_plat_probe(struct platf
+ if (IS_ERR(cdns->usb2_phy))
+ return PTR_ERR(cdns->usb2_phy);
+
+- ret = phy_init(cdns->usb2_phy);
+- if (ret)
+- return ret;
+-
+ cdns->usb3_phy = devm_phy_optional_get(dev, "cdns3,usb3-phy");
+ if (IS_ERR(cdns->usb3_phy))
+ return PTR_ERR(cdns->usb3_phy);
+
++ ret = phy_init(cdns->usb2_phy);
++ if (ret)
++ return ret;
++
+ ret = phy_init(cdns->usb3_phy);
+ if (ret)
+ goto err_phy3_init;
--- /dev/null
+From sashal@kernel.org Fri Jun 5 21:01:14 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 5 Jun 2026 11:31:11 -0400
+Subject: usb: dwc3: xilinx: fix error handling in zynqmp init error paths
+To: stable@vger.kernel.org
+Cc: Radhey Shyam Pandey <radhey.shyam.pandey@amd.com>, Thinh Nguyen <Thinh.Nguyen@synopsys.com>, Greg Kroah-Hartman <gregkh@linuxfoundation.org>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260605153111.1929312-1-sashal@kernel.org>
+
+From: Radhey Shyam Pandey <radhey.shyam.pandey@amd.com>
+
+[ Upstream commit c1a0ecbf32c4b397353204e2ec94c5bb9f3300ed ]
+
+Fix error handling and resource cleanup i.e remove invalid
+phy_exit() after failed phy_init(), route failures through
+proper cleanup paths and return 0 explicitly on success.
+
+Fixes: 84770f028fab ("usb: dwc3: Add driver for Xilinx platforms")
+Cc: stable@vger.kernel.org
+Acked-by: Thinh Nguyen <Thinh.Nguyen@synopsys.com>
+Signed-off-by: Radhey Shyam Pandey <radhey.shyam.pandey@amd.com>
+Link: https://patch.msgid.link/20260519115529.2980421-1-radhey.shyam.pandey@amd.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/usb/dwc3/dwc3-xilinx.c | 26 ++++++++++++++------------
+ 1 file changed, 14 insertions(+), 12 deletions(-)
+
+--- a/drivers/usb/dwc3/dwc3-xilinx.c
++++ b/drivers/usb/dwc3/dwc3-xilinx.c
+@@ -170,15 +170,13 @@ static int dwc3_xlnx_init_zynqmp(struct
+ }
+
+ ret = phy_init(priv_data->usb3_phy);
+- if (ret < 0) {
+- phy_exit(priv_data->usb3_phy);
++ if (ret < 0)
+ goto err;
+- }
+
+ ret = reset_control_deassert(apbrst);
+ if (ret < 0) {
+ dev_err(dev, "Failed to release APB reset\n");
+- goto err;
++ goto err_phy_exit;
+ }
+
+ /* Set PIPE Power Present signal in FPD Power Present Register*/
+@@ -190,27 +188,25 @@ static int dwc3_xlnx_init_zynqmp(struct
+ ret = reset_control_deassert(crst);
+ if (ret < 0) {
+ dev_err(dev, "Failed to release core reset\n");
+- goto err;
++ goto err_phy_exit;
+ }
+
+ ret = reset_control_deassert(hibrst);
+ if (ret < 0) {
+ dev_err(dev, "Failed to release hibernation reset\n");
+- goto err;
++ goto err_phy_exit;
+ }
+
+ ret = phy_power_on(priv_data->usb3_phy);
+- if (ret < 0) {
+- phy_exit(priv_data->usb3_phy);
+- goto err;
+- }
++ if (ret < 0)
++ goto err_phy_exit;
+
+ skip_usb3_phy:
+ /* ulpi reset via gpio-modepin or gpio-framework driver */
+ reset_gpio = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_HIGH);
+ if (IS_ERR(reset_gpio)) {
+- return dev_err_probe(dev, PTR_ERR(reset_gpio),
+- "Failed to request reset GPIO\n");
++ ret = PTR_ERR(reset_gpio);
++ goto err_phy_power_off;
+ }
+
+ if (reset_gpio) {
+@@ -230,6 +226,12 @@ skip_usb3_phy:
+ writel(reg, priv_data->regs + XLNX_USB_TRAFFIC_ROUTE_CONFIG);
+ }
+
++ return 0;
++
++err_phy_power_off:
++ phy_power_off(priv_data->usb3_phy);
++err_phy_exit:
++ phy_exit(priv_data->usb3_phy);
+ err:
+ return ret;
+ }
--- /dev/null
+From sashal@kernel.org Sat Jun 6 00:01:30 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 5 Jun 2026 14:31:27 -0400
+Subject: usb: gadget: uvc: hold opts->lock across XU walks in uvc_function_bind
+To: stable@vger.kernel.org
+Cc: Kai Aizen <kai.aizen.dev@gmail.com>, stable <stable@kernel.org>, Greg Kroah-Hartman <gregkh@linuxfoundation.org>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260605183127.2055332-1-sashal@kernel.org>
+
+From: Kai Aizen <kai.aizen.dev@gmail.com>
+
+[ Upstream commit 68aa70648b625fa684bc0b71bbfd905f4943ca20 ]
+
+uvc_function_bind() walks &opts->extension_units twice without holding
+opts->lock:
+
+ - directly, for the iExtension string-descriptor fixup loop;
+ - indirectly, four times via uvc_copy_descriptors() (once per speed),
+ where the helper iterates uvc->desc.extension_units (which aliases
+ &opts->extension_units) to size and emit XU descriptors.
+
+The configfs side (uvcg_extension_make / uvcg_extension_drop, in
+drivers/usb/gadget/function/uvc_configfs.c) takes opts->lock around its
+list_add_tail / list_del operations. A privileged userspace process
+that holds the configfs subtree open and writes the gadget UDC name
+to bind the function while concurrently rmdir()'ing an extensions
+subdir can race uvcg_extension_drop() against the bind-time list walks
+and dereference a freed struct uvcg_extension.
+
+Hold opts->lock from the start of the XU string-descriptor fixup
+through the last uvc_copy_descriptors() call, releasing on the
+descriptor-error path via a new error_unlock label that drops the
+lock before falling through to the existing error label. This
+matches the locking discipline of the configfs callbacks and removes
+the only remaining unsynchronised reader of the XU list during bind.
+
+Reachability: only privileged processes that can mount configfs and
+write to gadget UDC files can trigger the race, so this is a
+correctness fix rather than a security boundary.
+
+Fixes: 0525210c9840 ("usb: gadget: uvc: Allow definition of XUs in configfs")
+Cc: stable <stable@kernel.org>
+Signed-off-by: Kai Aizen <kai.aizen.dev@gmail.com>
+Link: https://patch.msgid.link/20260430175643.67120-1-kai.aizen.dev@gmail.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/usb/gadget/function/f_uvc.c | 26 ++++++++++++++++++++------
+ 1 file changed, 20 insertions(+), 6 deletions(-)
+
+--- a/drivers/usb/gadget/function/f_uvc.c
++++ b/drivers/usb/gadget/function/f_uvc.c
+@@ -763,6 +763,16 @@ uvc_function_bind(struct usb_configurati
+ uvc_ss_streaming_ep.bEndpointAddress = uvc->video.ep->address;
+
+ /*
++ * Hold opts->lock across both the XU string-descriptor fixup below and
++ * the descriptor-copy block further down. Without this, configfs
++ * uvcg_extension_drop() (which takes opts->lock) can race with the
++ * list_for_each_entry() walks here and inside uvc_copy_descriptors(),
++ * leading to a UAF on a freed struct uvcg_extension. See
++ * drivers/usb/gadget/function/uvc_configfs.c::uvcg_extension_drop().
++ */
++ mutex_lock(&opts->lock);
++
++ /*
+ * XUs can have an arbitrary string descriptor describing them. If they
+ * have one pick up the ID.
+ */
+@@ -779,7 +789,7 @@ uvc_function_bind(struct usb_configurati
+ ARRAY_SIZE(uvc_en_us_strings));
+ if (IS_ERR(us)) {
+ ret = PTR_ERR(us);
+- goto error;
++ goto error_unlock;
+ }
+
+ uvc_iad.iFunction = opts->iad_index ? cdev->usb_strings[opts->iad_index].id :
+@@ -793,14 +803,14 @@ uvc_function_bind(struct usb_configurati
+
+ /* Allocate interface IDs. */
+ if ((ret = usb_interface_id(c, f)) < 0)
+- goto error;
++ goto error_unlock;
+ uvc_iad.bFirstInterface = ret;
+ uvc_control_intf.bInterfaceNumber = ret;
+ uvc->control_intf = ret;
+ opts->control_interface = ret;
+
+ if ((ret = usb_interface_id(c, f)) < 0)
+- goto error;
++ goto error_unlock;
+ uvc_streaming_intf_alt0.bInterfaceNumber = ret;
+ uvc_streaming_intf_alt1.bInterfaceNumber = ret;
+ uvc->streaming_intf = ret;
+@@ -811,23 +821,25 @@ uvc_function_bind(struct usb_configurati
+ if (IS_ERR(f->fs_descriptors)) {
+ ret = PTR_ERR(f->fs_descriptors);
+ f->fs_descriptors = NULL;
+- goto error;
++ goto error_unlock;
+ }
+
+ f->hs_descriptors = uvc_copy_descriptors(uvc, USB_SPEED_HIGH);
+ if (IS_ERR(f->hs_descriptors)) {
+ ret = PTR_ERR(f->hs_descriptors);
+ f->hs_descriptors = NULL;
+- goto error;
++ goto error_unlock;
+ }
+
+ f->ss_descriptors = uvc_copy_descriptors(uvc, USB_SPEED_SUPER);
+ if (IS_ERR(f->ss_descriptors)) {
+ ret = PTR_ERR(f->ss_descriptors);
+ f->ss_descriptors = NULL;
+- goto error;
++ goto error_unlock;
+ }
+
++ mutex_unlock(&opts->lock);
++
+ /* Preallocate control endpoint request. */
+ uvc->control_req = usb_ep_alloc_request(cdev->gadget->ep0, GFP_KERNEL);
+ uvc->control_buf = kmalloc(UVC_MAX_REQUEST_SIZE, GFP_KERNEL);
+@@ -859,6 +871,8 @@ uvc_function_bind(struct usb_configurati
+
+ return 0;
+
++error_unlock:
++ mutex_unlock(&opts->lock);
+ v4l2_error:
+ v4l2_device_unregister(&uvc->v4l2_dev);
+ error:
--- /dev/null
+From sashal@kernel.org Fri Jun 5 21:01:10 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 5 Jun 2026 11:31:07 -0400
+Subject: usb: musb: omap2430: Fix use-after-free in omap2430_probe()
+To: stable@vger.kernel.org
+Cc: Wentao Liang <vulab@iscas.ac.cn>, stable <stable@kernel.org>, Greg Kroah-Hartman <gregkh@linuxfoundation.org>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260605153108.1929169-1-sashal@kernel.org>
+
+From: Wentao Liang <vulab@iscas.ac.cn>
+
+[ Upstream commit e194ce048f5a6c549b3a23a8c568c6470f40f772 ]
+
+In omap2430_probe(), of_node_put(np) is called prematurely before the
+last access to np, leading to a use-after-free if the node's reference
+count drops to zero. Move the of_node_put() calls after the last use of
+np in both the success and error paths.
+
+Fixes: ffbe2feac59b ("usb: musb: omap2430: Fix probe regression for missing resources")
+Cc: stable <stable@kernel.org>
+Signed-off-by: Wentao Liang <vulab@iscas.ac.cn>
+Link: https://patch.msgid.link/20260409101104.480623-1-vulab@iscas.ac.cn
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/usb/musb/omap2430.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+--- a/drivers/usb/musb/omap2430.c
++++ b/drivers/usb/musb/omap2430.c
+@@ -340,7 +340,6 @@ static int omap2430_probe(struct platfor
+ } else {
+ device_set_of_node_from_dev(&musb->dev, &pdev->dev);
+ }
+- of_node_put(np);
+
+ glue->dev = &pdev->dev;
+ glue->musb = musb;
+@@ -458,6 +457,7 @@ static int omap2430_probe(struct platfor
+ dev_err(&pdev->dev, "failed to register musb device\n");
+ goto err3;
+ }
++ of_node_put(np);
+
+ return 0;
+
+@@ -467,6 +467,7 @@ err_put_control_otghs:
+ if (!IS_ERR(glue->control_otghs))
+ put_device(glue->control_otghs);
+ err2:
++ of_node_put(np);
+ platform_device_put(musb);
+
+ err0:
--- /dev/null
+From sashal@kernel.org Sat Jun 6 00:47:19 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 5 Jun 2026 15:17:16 -0400
+Subject: usb: typec: ucsi: Check if power role change actually happened before handling
+To: stable@vger.kernel.org
+Cc: Myrrh Periwinkle <myrrhperiwinkle@qtmlabs.xyz>, stable <stable@kernel.org>, Sergey Senozhatsky <senozhatsky@chromium.org>, Heikki Krogerus <heikki.krogerus@linux.intel.com>, Greg Kroah-Hartman <gregkh@linuxfoundation.org>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260605191716.2134705-1-sashal@kernel.org>
+
+From: Myrrh Periwinkle <myrrhperiwinkle@qtmlabs.xyz>
+
+[ Upstream commit b80e7d34c7ea6a564525119d6138fbb577a23dba ]
+
+The CrOS EC may send a connector status change event with the power
+direction changed flag set even if the power direction hasn't actually
+changed after initiating a SET_PDR command internally [1]. In practice
+this happens on every system suspend due to other changes performed by
+the EC [2][3][4], causing suspend to fail.
+
+Fix this by checking if the power role change actually happened before
+handling it.
+
+[1]: https://source.chromium.org/chromiumos/chromiumos/codesearch/+/main:src/platform/ec/zephyr/subsys/pd_controller/pdc_power_mgmt.c;l=1689;drc=2d5a1cffce4e5ac8a39442cb3b764d2d5e1cf794
+[2]: https://source.chromium.org/chromiumos/chromiumos/codesearch/+/main:src/platform/ec/zephyr/subsys/pd_controller/pdc_power_mgmt.c;l=3923;drc=2d5a1cffce4e5ac8a39442cb3b764d2d5e1cf794
+[3]: https://source.chromium.org/chromiumos/chromiumos/codesearch/+/main:src/platform/ec/zephyr/subsys/pd_controller/pdc_power_mgmt.c;l=5094;drc=2d5a1cffce4e5ac8a39442cb3b764d2d5e1cf794
+[4]: https://source.chromium.org/chromiumos/chromiumos/codesearch/+/main:src/platform/ec/zephyr/subsys/pd_controller/pdc_power_mgmt.c;l=2229;drc=2d5a1cffce4e5ac8a39442cb3b764d2d5e1cf794
+
+Cc: stable <stable@kernel.org>
+Fixes: 7616f006db07 ("usb: typec: ucsi: Update power_supply on power role change")
+Signed-off-by: Myrrh Periwinkle <myrrhperiwinkle@qtmlabs.xyz>
+Reported-and-tested-by: Sergey Senozhatsky <senozhatsky@chromium.org>
+Reviewed-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>
+Link: https://patch.msgid.link/20260519-ucsi-fix-2-v1-1-6f1239535187@qtmlabs.xyz
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/usb/typec/ucsi/ucsi.c | 6 ++++--
+ 1 file changed, 4 insertions(+), 2 deletions(-)
+
+--- a/drivers/usb/typec/ucsi/ucsi.c
++++ b/drivers/usb/typec/ucsi/ucsi.c
+@@ -884,7 +884,7 @@ static void ucsi_handle_connector_change
+ struct ucsi_connector *con = container_of(work, struct ucsi_connector,
+ work);
+ struct ucsi *ucsi = con->ucsi;
+- enum typec_role role;
++ enum typec_role role, prev_role;
+ u64 command;
+ int ret;
+
+@@ -892,6 +892,8 @@ static void ucsi_handle_connector_change
+
+ command = UCSI_GET_CONNECTOR_STATUS | UCSI_CONNECTOR_NUMBER(con->num);
+
++ prev_role = !!(con->status.flags & UCSI_CONSTAT_PWR_DIR);
++
+ ret = ucsi_send_command_common(ucsi, command, &con->status,
+ sizeof(con->status), true);
+ if (ret < 0) {
+@@ -908,7 +910,7 @@ static void ucsi_handle_connector_change
+
+ role = !!(con->status.flags & UCSI_CONSTAT_PWR_DIR);
+
+- if (con->status.change & UCSI_CONSTAT_POWER_DIR_CHANGE) {
++ if ((con->status.change & UCSI_CONSTAT_POWER_DIR_CHANGE) && role != prev_role) {
+ typec_set_pwr_role(con->port, role);
+ ucsi_port_psy_changed(con);
+
--- /dev/null
+From stable+bounces-260881-greg=kroah.com@vger.kernel.org Sat Jun 6 18:37:00 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 6 Jun 2026 09:05:38 -0400
+Subject: usb: typec: ucsi: Don't update power_supply on power role change if not connected
+To: stable@vger.kernel.org
+Cc: Myrrh Periwinkle <myrrhperiwinkle@qtmlabs.xyz>, stable <stable@kernel.org>, Sergey Senozhatsky <senozhatsky@chromium.org>, Greg Kroah-Hartman <gregkh@linuxfoundation.org>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260606130538.2924564-1-sashal@kernel.org>
+
+From: Myrrh Periwinkle <myrrhperiwinkle@qtmlabs.xyz>
+
+[ Upstream commit d98d413ca65d0790a8f3695d0a5845538958ab84 ]
+
+We only need to update the power_supply on power role change if the port
+is connected, because otherwise the online status should be the same for
+both cases.
+
+Cc: stable <stable@kernel.org>
+Fixes: 7616f006db07 ("usb: typec: ucsi: Update power_supply on power role change")
+Signed-off-by: Myrrh Periwinkle <myrrhperiwinkle@qtmlabs.xyz>
+Reported-and-tested-by: Sergey Senozhatsky <senozhatsky@chromium.org>
+Link: https://patch.msgid.link/20260519-ucsi-fix-2-v1-2-6f1239535187@qtmlabs.xyz
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+[ changed `UCSI_CONSTAT(con, CONNECTED)` accessor macro to `con->status.flags & UCSI_CONSTAT_CONNECTED` ]
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/usb/typec/ucsi/ucsi.c | 7 ++++++-
+ 1 file changed, 6 insertions(+), 1 deletion(-)
+
+--- a/drivers/usb/typec/ucsi/ucsi.c
++++ b/drivers/usb/typec/ucsi/ucsi.c
+@@ -912,7 +912,12 @@ static void ucsi_handle_connector_change
+
+ if ((con->status.change & UCSI_CONSTAT_POWER_DIR_CHANGE) && role != prev_role) {
+ typec_set_pwr_role(con->port, role);
+- ucsi_port_psy_changed(con);
++
++ /* Some power_supply properties vary depending on the power direction when
++ * connected
++ */
++ if (con->status.flags & UCSI_CONSTAT_CONNECTED)
++ ucsi_port_psy_changed(con);
+
+ /* Complete pending power role swap */
+ if (!completion_done(&con->complete))