--- /dev/null
+From stable+bounces-211905-greg=kroah.com@vger.kernel.org Wed Jan 28 01:56:49 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 27 Jan 2026 19:56:42 -0500
+Subject: ALSA: scarlett2: Fix buffer overflow in config retrieval
+To: stable@vger.kernel.org
+Cc: Samasth Norway Ananda <samasth.norway.ananda@oracle.com>, Takashi Iwai <tiwai@suse.de>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260128005642.2300891-1-sashal@kernel.org>
+
+From: Samasth Norway Ananda <samasth.norway.ananda@oracle.com>
+
+[ Upstream commit 6f5c69f72e50d51be3a8c028ae7eda42c82902cb ]
+
+The scarlett2_usb_get_config() function has a logic error in the
+endianness conversion code that can cause buffer overflows when
+count > 1.
+
+The code checks `if (size == 2)` where `size` is the total buffer size in
+bytes, then loops `count` times treating each element as u16 (2 bytes).
+This causes the loop to access `count * 2` bytes when the buffer only
+has `size` bytes allocated.
+
+Fix by checking the element size (config_item->size) instead of the
+total buffer size. This ensures the endianness conversion matches the
+actual element type.
+
+Fixes: ac34df733d2d ("ALSA: usb-audio: scarlett2: Update get_config to do endian conversion")
+Cc: stable@vger.kernel.org
+Signed-off-by: Samasth Norway Ananda <samasth.norway.ananda@oracle.com>
+Link: https://patch.msgid.link/20260117012706.1715574-1-samasth.norway.ananda@oracle.com
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+[ add 32-bit handling block ]
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ sound/usb/mixer_scarlett2.c | 7 ++++++-
+ 1 file changed, 6 insertions(+), 1 deletion(-)
+
+--- a/sound/usb/mixer_scarlett2.c
++++ b/sound/usb/mixer_scarlett2.c
+@@ -1408,11 +1408,16 @@ static int scarlett2_usb_get_config(
+ err = scarlett2_usb_get(mixer, config_item->offset, buf, size);
+ if (err < 0)
+ return err;
+- if (size == 2) {
++ if (config_item->size == 16) {
+ u16 *buf_16 = buf;
+
+ for (i = 0; i < count; i++, buf_16++)
+ *buf_16 = le16_to_cpu(*(__le16 *)buf_16);
++ } else if (config_item->size == 32) {
++ u32 *buf_32 = (u32 *)buf;
++
++ for (i = 0; i < count; i++, buf_32++)
++ *buf_32 = le32_to_cpu(*(__le32 *)buf_32);
+ }
+ return 0;
+ }
--- /dev/null
+From stable+bounces-211649-greg=kroah.com@vger.kernel.org Mon Jan 26 17:22:23 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 26 Jan 2026 11:21:33 -0500
+Subject: arm64: dts: rockchip: remove redundant max-link-speed from nanopi-r4s
+To: stable@vger.kernel.org
+Cc: Geraldo Nascimento <geraldogabriel@gmail.com>, Dragan Simic <dsimic@manjaro.org>, Shawn Lin <shawn.lin@rock-chips.com>, Heiko Stuebner <heiko@sntech.de>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260126162133.3376453-1-sashal@kernel.org>
+
+From: Geraldo Nascimento <geraldogabriel@gmail.com>
+
+[ Upstream commit ce652c98a7bfa0b7c675ef5cd85c44c186db96af ]
+
+This is already the default in rk3399-base.dtsi, remove redundant
+declaration from rk3399-nanopi-r4s.dtsi.
+
+Fixes: db792e9adbf8 ("rockchip: rk3399: Add support for FriendlyARM NanoPi R4S")
+Cc: stable@vger.kernel.org
+Reported-by: Dragan Simic <dsimic@manjaro.org>
+Reviewed-by: Dragan Simic <dsimic@manjaro.org>
+Signed-off-by: Geraldo Nascimento <geraldogabriel@gmail.com>
+Acked-by: Shawn Lin <shawn.lin@rock-chips.com>
+Link: https://patch.msgid.link/6694456a735844177c897581f785cc00c064c7d1.1763415706.git.geraldogabriel@gmail.com
+Signed-off-by: Heiko Stuebner <heiko@sntech.de>
+[ adapted file path from rk3399-nanopi-r4s.dtsi to rk3399-nanopi-r4s.dts ]
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/arm64/boot/dts/rockchip/rk3399-nanopi-r4s.dts | 1 -
+ 1 file changed, 1 deletion(-)
+
+--- a/arch/arm64/boot/dts/rockchip/rk3399-nanopi-r4s.dts
++++ b/arch/arm64/boot/dts/rockchip/rk3399-nanopi-r4s.dts
+@@ -73,7 +73,6 @@
+ };
+
+ &pcie0 {
+- max-link-speed = <1>;
+ num-lanes = <1>;
+ vpcie3v3-supply = <&vcc3v3_sys>;
+ };
--- /dev/null
+From stable+bounces-212680-greg=kroah.com@vger.kernel.org Wed Jan 28 22:37:23 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 28 Jan 2026 16:37:16 -0500
+Subject: arm64/fpsimd: signal: Fix restoration of SVE context
+To: stable@vger.kernel.org
+Cc: Mark Rutland <mark.rutland@arm.com>, Mark Brown <broonie@kernel.org>, Will Deacon <will@kernel.org>, Catalin Marinas <catalin.marinas@arm.com>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260128213716.2763076-1-sashal@kernel.org>
+
+From: Mark Rutland <mark.rutland@arm.com>
+
+[ Upstream commit d2907cbe9ea0a54cbe078076f9d089240ee1e2d9 ]
+
+When SME is supported, Restoring SVE signal context can go wrong in a
+few ways, including placing the task into an invalid state where the
+kernel may read from out-of-bounds memory (and may potentially take a
+fatal fault) and/or may kill the task with a SIGKILL.
+
+(1) Restoring a context with SVE_SIG_FLAG_SM set can place the task into
+ an invalid state where SVCR.SM is set (and sve_state is non-NULL)
+ but TIF_SME is clear, consequently resuting in out-of-bounds memory
+ reads and/or killing the task with SIGKILL.
+
+ This can only occur in unusual (but legitimate) cases where the SVE
+ signal context has either been modified by userspace or was saved in
+ the context of another task (e.g. as with CRIU), as otherwise the
+ presence of an SVE signal context with SVE_SIG_FLAG_SM implies that
+ TIF_SME is already set.
+
+ While in this state, task_fpsimd_load() will NOT configure SMCR_ELx
+ (leaving some arbitrary value configured in hardware) before
+ restoring SVCR and attempting to restore the streaming mode SVE
+ registers from memory via sve_load_state(). As the value of
+ SMCR_ELx.LEN may be larger than the task's streaming SVE vector
+ length, this may read memory outside of the task's allocated
+ sve_state, reading unrelated data and/or triggering a fault.
+
+ While this can result in secrets being loaded into streaming SVE
+ registers, these values are never exposed. As TIF_SME is clear,
+ fpsimd_bind_task_to_cpu() will configure CPACR_ELx.SMEN to trap EL0
+ accesses to streaming mode SVE registers, so these cannot be
+ accessed directly at EL0. As fpsimd_save_user_state() verifies the
+ live vector length before saving (S)SVE state to memory, no secret
+ values can be saved back to memory (and hence cannot be observed via
+ ptrace, signals, etc).
+
+ When the live vector length doesn't match the expected vector length
+ for the task, fpsimd_save_user_state() will send a fatal SIGKILL
+ signal to the task. Hence the task may be killed after executing
+ userspace for some period of time.
+
+(2) Restoring a context with SVE_SIG_FLAG_SM clear does not clear the
+ task's SVCR.SM. If SVCR.SM was set prior to restoring the context,
+ then the task will be left in streaming mode unexpectedly, and some
+ register state will be combined inconsistently, though the task will
+ be left in legitimate state from the kernel's PoV.
+
+ This can only occur in unusual (but legitimate) cases where ptrace
+ has been used to set SVCR.SM after entry to the sigreturn syscall,
+ as syscall entry clears SVCR.SM.
+
+ In these cases, the the provided SVE register data will be loaded
+ into the task's sve_state using the non-streaming SVE vector length
+ and the FPSIMD registers will be merged into this using the
+ streaming SVE vector length.
+
+Fix (1) by setting TIF_SME when setting SVCR.SM. This also requires
+ensuring that the task's sme_state has been allocated, but as this could
+contain live ZA state, it should not be zeroed. Fix (2) by clearing
+SVCR.SM when restoring a SVE signal context with SVE_SIG_FLAG_SM clear.
+
+For consistency, I've pulled the manipulation of SVCR, TIF_SVE, TIF_SME,
+and fp_type earlier, immediately after the allocation of
+sve_state/sme_state, before the restore of the actual register state.
+This makes it easier to ensure that these are always modified
+consistently, even if a fault is taken while reading the register data
+from the signal context. I do not expect any software to depend on the
+exact state restored when a fault is taken while reading the context.
+
+Fixes: 85ed24dad290 ("arm64/sme: Implement streaming SVE signal handling")
+Signed-off-by: Mark Rutland <mark.rutland@arm.com>
+Cc: <stable@vger.kernel.org>
+Cc: Mark Brown <broonie@kernel.org>
+Cc: Will Deacon <will@kernel.org>
+Reviewed-by: Mark Brown <broonie@kernel.org>
+Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
+[ adapted sme_state to za_state ]
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/arm64/kernel/signal.c | 22 ++++++++++++++++------
+ 1 file changed, 16 insertions(+), 6 deletions(-)
+
+--- a/arch/arm64/kernel/signal.c
++++ b/arch/arm64/kernel/signal.c
+@@ -317,12 +317,28 @@ static int restore_sve_fpsimd_context(st
+ fpsimd_flush_task_state(current);
+ /* From now, fpsimd_thread_switch() won't touch thread.sve_state */
+
++ if (sve.flags & SVE_SIG_FLAG_SM) {
++ sme_alloc(current, false);
++ if (!current->thread.za_state)
++ return -ENOMEM;
++ }
++
+ sve_alloc(current, true);
+ if (!current->thread.sve_state) {
+ clear_thread_flag(TIF_SVE);
+ return -ENOMEM;
+ }
+
++ if (sve.flags & SVE_SIG_FLAG_SM) {
++ current->thread.svcr |= SVCR_SM_MASK;
++ set_thread_flag(TIF_SME);
++ } else {
++ current->thread.svcr &= ~SVCR_SM_MASK;
++ set_thread_flag(TIF_SVE);
++ }
++
++ current->thread.fp_type = FP_STATE_SVE;
++
+ err = __copy_from_user(current->thread.sve_state,
+ (char __user const *)user->sve +
+ SVE_SIG_REGS_OFFSET,
+@@ -330,12 +346,6 @@ static int restore_sve_fpsimd_context(st
+ if (err)
+ return -EFAULT;
+
+- if (sve.flags & SVE_SIG_FLAG_SM)
+- current->thread.svcr |= SVCR_SM_MASK;
+- else
+- set_thread_flag(TIF_SVE);
+- current->thread.fp_type = FP_STATE_SVE;
+-
+ fpsimd_only:
+ /* copy the FP and status/control registers */
+ /* restore_sigframe() already checked that user->fpsimd != NULL. */
--- /dev/null
+From stable+bounces-210643-greg=kroah.com@vger.kernel.org Wed Jan 21 03:05:09 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 20 Jan 2026 21:04:23 -0500
+Subject: ASoC: codecs: wsa881x: Drop unused version readout
+To: stable@vger.kernel.org
+Cc: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>, Mark Brown <broonie@kernel.org>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260121020424.1123218-3-sashal@kernel.org>
+
+From: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
+
+[ Upstream commit 3d2a69eb503d15171a7ba51cf0b562728ac396b7 ]
+
+Driver does not use the device version after reading it from the
+registers, so simplify by dropping unneeded code.
+
+Signed-off-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
+Link: https://patch.msgid.link/20240710-asoc-wsa88xx-version-v1-1-f1c54966ccde@linaro.org
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Stable-dep-of: 29d71b8a5a40 ("ASoC: codecs: wsa881x: fix unnecessary initialisation")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ sound/soc/codecs/wsa881x.c | 2 --
+ 1 file changed, 2 deletions(-)
+
+--- a/sound/soc/codecs/wsa881x.c
++++ b/sound/soc/codecs/wsa881x.c
+@@ -683,7 +683,6 @@ struct wsa881x_priv {
+ * For backwards compatibility.
+ */
+ unsigned int sd_n_val;
+- int version;
+ int active_ports;
+ bool port_prepared[WSA881X_MAX_SWR_PORTS];
+ bool port_enable[WSA881X_MAX_SWR_PORTS];
+@@ -694,7 +693,6 @@ static void wsa881x_init(struct wsa881x_
+ struct regmap *rm = wsa881x->regmap;
+ unsigned int val = 0;
+
+- regmap_read(rm, WSA881X_CHIP_ID1, &wsa881x->version);
+ regmap_register_patch(wsa881x->regmap, wsa881x_rev_2_0,
+ ARRAY_SIZE(wsa881x_rev_2_0));
+
--- /dev/null
+From stable+bounces-210644-greg=kroah.com@vger.kernel.org Wed Jan 21 03:05:07 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 20 Jan 2026 21:04:24 -0500
+Subject: ASoC: codecs: wsa881x: fix unnecessary initialisation
+To: stable@vger.kernel.org
+Cc: Johan Hovold <johan@kernel.org>, Srinivas Kandagatla <srini@kernel.org>, Krzysztof Kozlowski <krzysztof.kozlowski@oss.qualcomm.com>, Srinivas Kandagatla <srinivas.kandagatla@oss.qualcomm.com>, Mark Brown <broonie@kernel.org>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260121020424.1123218-4-sashal@kernel.org>
+
+From: Johan Hovold <johan@kernel.org>
+
+[ Upstream commit 29d71b8a5a40708b3eed9ba4953bfc2312c9c776 ]
+
+The soundwire update_status() callback may be called multiple times with
+the same ATTACHED status but initialisation should only be done when
+transitioning from UNATTACHED to ATTACHED.
+
+Fixes: a0aab9e1404a ("ASoC: codecs: add wsa881x amplifier support")
+Cc: stable@vger.kernel.org # 5.6
+Cc: Srinivas Kandagatla <srini@kernel.org>
+Signed-off-by: Johan Hovold <johan@kernel.org>
+Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski@oss.qualcomm.com>
+Reviewed-by: Srinivas Kandagatla <srinivas.kandagatla@oss.qualcomm.com>
+Link: https://patch.msgid.link/20260102111413.9605-3-johan@kernel.org
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ sound/soc/codecs/wsa881x.c | 9 +++++++++
+ 1 file changed, 9 insertions(+)
+
+--- a/sound/soc/codecs/wsa881x.c
++++ b/sound/soc/codecs/wsa881x.c
+@@ -684,6 +684,7 @@ struct wsa881x_priv {
+ */
+ unsigned int sd_n_val;
+ int active_ports;
++ bool hw_init;
+ bool port_prepared[WSA881X_MAX_SWR_PORTS];
+ bool port_enable[WSA881X_MAX_SWR_PORTS];
+ };
+@@ -693,6 +694,9 @@ static void wsa881x_init(struct wsa881x_
+ struct regmap *rm = wsa881x->regmap;
+ unsigned int val = 0;
+
++ if (wsa881x->hw_init)
++ return;
++
+ regmap_register_patch(wsa881x->regmap, wsa881x_rev_2_0,
+ ARRAY_SIZE(wsa881x_rev_2_0));
+
+@@ -730,6 +734,8 @@ static void wsa881x_init(struct wsa881x_
+ regmap_update_bits(rm, WSA881X_OTP_REG_28, 0x3F, 0x3A);
+ regmap_update_bits(rm, WSA881X_BONGO_RESRV_REG1, 0xFF, 0xB2);
+ regmap_update_bits(rm, WSA881X_BONGO_RESRV_REG2, 0xFF, 0x05);
++
++ wsa881x->hw_init = true;
+ }
+
+ static int wsa881x_component_probe(struct snd_soc_component *comp)
+@@ -1074,6 +1080,9 @@ static int wsa881x_update_status(struct
+ {
+ struct wsa881x_priv *wsa881x = dev_get_drvdata(&slave->dev);
+
++ if (status == SDW_SLAVE_UNATTACHED)
++ wsa881x->hw_init = false;
++
+ if (status == SDW_SLAVE_ATTACHED && slave->dev_num > 0)
+ wsa881x_init(wsa881x);
+
--- /dev/null
+From stable+bounces-210641-greg=kroah.com@vger.kernel.org Wed Jan 21 03:07:04 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 20 Jan 2026 21:04:21 -0500
+Subject: ASoC: codecs: wsa881x: Simplify &pdev->dev in probe
+To: stable@vger.kernel.org
+Cc: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>, Mark Brown <broonie@kernel.org>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260121020424.1123218-1-sashal@kernel.org>
+
+From: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
+
+[ Upstream commit c617c9e7024d152426acf9f1aaf01070b6852f13 ]
+
+The probe already stores pointer to &pdev->dev, so use it to make the
+code a bit easier to read.
+
+Signed-off-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
+Link: https://lore.kernel.org/r/20230102114152.297305-2-krzysztof.kozlowski@linaro.org
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Stable-dep-of: 29d71b8a5a40 ("ASoC: codecs: wsa881x: fix unnecessary initialisation")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ sound/soc/codecs/wsa881x.c | 10 +++++-----
+ 1 file changed, 5 insertions(+), 5 deletions(-)
+
+--- a/sound/soc/codecs/wsa881x.c
++++ b/sound/soc/codecs/wsa881x.c
+@@ -1112,20 +1112,20 @@ static int wsa881x_probe(struct sdw_slav
+ struct wsa881x_priv *wsa881x;
+ struct device *dev = &pdev->dev;
+
+- wsa881x = devm_kzalloc(&pdev->dev, sizeof(*wsa881x), GFP_KERNEL);
++ wsa881x = devm_kzalloc(dev, sizeof(*wsa881x), GFP_KERNEL);
+ if (!wsa881x)
+ return -ENOMEM;
+
+- wsa881x->sd_n = devm_gpiod_get_optional(&pdev->dev, "powerdown",
++ wsa881x->sd_n = devm_gpiod_get_optional(dev, "powerdown",
+ GPIOD_FLAGS_BIT_NONEXCLUSIVE);
+ if (IS_ERR(wsa881x->sd_n)) {
+ dev_err(&pdev->dev, "Shutdown Control GPIO not found\n");
+ return PTR_ERR(wsa881x->sd_n);
+ }
+
+- dev_set_drvdata(&pdev->dev, wsa881x);
++ dev_set_drvdata(dev, wsa881x);
+ wsa881x->slave = pdev;
+- wsa881x->dev = &pdev->dev;
++ wsa881x->dev = dev;
+ wsa881x->sconfig.ch_count = 1;
+ wsa881x->sconfig.bps = 1;
+ wsa881x->sconfig.frame_rate = 48000;
+@@ -1148,7 +1148,7 @@ static int wsa881x_probe(struct sdw_slav
+ pm_runtime_set_active(dev);
+ pm_runtime_enable(dev);
+
+- return devm_snd_soc_register_component(&pdev->dev,
++ return devm_snd_soc_register_component(dev,
+ &wsa881x_component_drv,
+ wsa881x_dais,
+ ARRAY_SIZE(wsa881x_dais));
--- /dev/null
+From stable+bounces-210642-greg=kroah.com@vger.kernel.org Wed Jan 21 03:07:16 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 20 Jan 2026 21:04:22 -0500
+Subject: ASoC: codecs: wsa881x: Use proper shutdown GPIO polarity
+To: stable@vger.kernel.org
+Cc: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>, Mark Brown <broonie@kernel.org>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260121020424.1123218-2-sashal@kernel.org>
+
+From: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
+
+[ Upstream commit 738455858a2d21b769f673892546cf8300c9fd78 ]
+
+The shutdown GPIO is active low (SD_N), but this depends on actual board
+layout. Linux drivers should only care about logical state, where high
+(1) means shutdown and low (0) means do not shutdown.
+
+Invert the GPIO to match logical value while preserving backwards DTB
+compatibility. It is not possible to detect whether ACTIVE_HIGH flag in
+DTB is because it is an old DTB (using incorrect flag) or it is a new
+DTB with a correct hardware pin polarity description. Therefore the
+solution prioritizes backwards compatibility while relying on relevant
+DTS being upstreamed.
+
+Signed-off-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
+Link: https://lore.kernel.org/r/20230102114152.297305-4-krzysztof.kozlowski@linaro.org
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Stable-dep-of: 29d71b8a5a40 ("ASoC: codecs: wsa881x: fix unnecessary initialisation")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ sound/soc/codecs/wsa881x.c | 33 +++++++++++++++++++++++++++++----
+ 1 file changed, 29 insertions(+), 4 deletions(-)
+
+--- a/sound/soc/codecs/wsa881x.c
++++ b/sound/soc/codecs/wsa881x.c
+@@ -678,6 +678,11 @@ struct wsa881x_priv {
+ struct sdw_stream_runtime *sruntime;
+ struct sdw_port_config port_config[WSA881X_MAX_SWR_PORTS];
+ struct gpio_desc *sd_n;
++ /*
++ * Logical state for SD_N GPIO: high for shutdown, low for enable.
++ * For backwards compatibility.
++ */
++ unsigned int sd_n_val;
+ int version;
+ int active_ports;
+ bool port_prepared[WSA881X_MAX_SWR_PORTS];
+@@ -1123,6 +1128,26 @@ static int wsa881x_probe(struct sdw_slav
+ return PTR_ERR(wsa881x->sd_n);
+ }
+
++ /*
++ * Backwards compatibility work-around.
++ *
++ * The SD_N GPIO is active low, however upstream DTS used always active
++ * high. Changing the flag in driver and DTS will break backwards
++ * compatibility, so add a simple value inversion to work with both old
++ * and new DTS.
++ *
++ * This won't work properly with DTS using the flags properly in cases:
++ * 1. Old DTS with proper ACTIVE_LOW, however such case was broken
++ * before as the driver required the active high.
++ * 2. New DTS with proper ACTIVE_HIGH (intended), which is rare case
++ * (not existing upstream) but possible. This is the price of
++ * backwards compatibility, therefore this hack should be removed at
++ * some point.
++ */
++ wsa881x->sd_n_val = gpiod_is_active_low(wsa881x->sd_n);
++ if (!wsa881x->sd_n_val)
++ dev_warn(dev, "Using ACTIVE_HIGH for shutdown GPIO. Your DTB might be outdated or you use unsupported configuration for the GPIO.");
++
+ dev_set_drvdata(dev, wsa881x);
+ wsa881x->slave = pdev;
+ wsa881x->dev = dev;
+@@ -1134,7 +1159,7 @@ static int wsa881x_probe(struct sdw_slav
+ pdev->prop.sink_ports = GENMASK(WSA881X_MAX_SWR_PORTS - 1, 0);
+ pdev->prop.sink_dpn_prop = wsa_sink_dpn_prop;
+ pdev->prop.scp_int1_mask = SDW_SCP_INT1_BUS_CLASH | SDW_SCP_INT1_PARITY;
+- gpiod_direction_output(wsa881x->sd_n, 1);
++ gpiod_direction_output(wsa881x->sd_n, !wsa881x->sd_n_val);
+
+ wsa881x->regmap = devm_regmap_init_sdw(pdev, &wsa881x_regmap_config);
+ if (IS_ERR(wsa881x->regmap)) {
+@@ -1159,7 +1184,7 @@ static int __maybe_unused wsa881x_runtim
+ struct regmap *regmap = dev_get_regmap(dev, NULL);
+ struct wsa881x_priv *wsa881x = dev_get_drvdata(dev);
+
+- gpiod_direction_output(wsa881x->sd_n, 0);
++ gpiod_direction_output(wsa881x->sd_n, wsa881x->sd_n_val);
+
+ regcache_cache_only(regmap, true);
+ regcache_mark_dirty(regmap);
+@@ -1174,13 +1199,13 @@ static int __maybe_unused wsa881x_runtim
+ struct wsa881x_priv *wsa881x = dev_get_drvdata(dev);
+ unsigned long time;
+
+- gpiod_direction_output(wsa881x->sd_n, 1);
++ gpiod_direction_output(wsa881x->sd_n, !wsa881x->sd_n_val);
+
+ time = wait_for_completion_timeout(&slave->initialization_complete,
+ msecs_to_jiffies(WSA881X_PROBE_TIMEOUT));
+ if (!time) {
+ dev_err(dev, "Initialization not complete, timed out\n");
+- gpiod_direction_output(wsa881x->sd_n, 0);
++ gpiod_direction_output(wsa881x->sd_n, wsa881x->sd_n_val);
+ return -ETIMEDOUT;
+ }
+
--- /dev/null
+From stable+bounces-210386-greg=kroah.com@vger.kernel.org Mon Jan 19 18:44:24 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 19 Jan 2026 12:20:22 -0500
+Subject: ASoC: codecs: wsa883x: fix unnecessary initialisation
+To: stable@vger.kernel.org
+Cc: Johan Hovold <johan@kernel.org>, Srinivas Kandagatla <srini@kernel.org>, Krzysztof Kozlowski <krzysztof.kozlowski@oss.qualcomm.com>, Srinivas Kandagatla <srinivas.kandagatla@oss.qualcomm.com>, Mark Brown <broonie@kernel.org>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260119172022.3580065-1-sashal@kernel.org>
+
+From: Johan Hovold <johan@kernel.org>
+
+[ Upstream commit 49aadf830eb048134d33ad7329d92ecff45d8dbb ]
+
+The soundwire update_status() callback may be called multiple times with
+the same ATTACHED status but initialisation should only be done when
+transitioning from UNATTACHED to ATTACHED.
+
+This avoids repeated initialisation of the codecs during boot of
+machines like the Lenovo ThinkPad X13s:
+
+[ 11.614523] wsa883x-codec sdw:1:0:0217:0202:00:1: WSA883X Version 1_1, Variant: WSA8835_V2
+[ 11.618022] wsa883x-codec sdw:1:0:0217:0202:00:1: WSA883X Version 1_1, Variant: WSA8835_V2
+[ 11.621377] wsa883x-codec sdw:1:0:0217:0202:00:1: WSA883X Version 1_1, Variant: WSA8835_V2
+[ 11.624065] wsa883x-codec sdw:1:0:0217:0202:00:1: WSA883X Version 1_1, Variant: WSA8835_V2
+[ 11.631382] wsa883x-codec sdw:1:0:0217:0202:00:2: WSA883X Version 1_1, Variant: WSA8835_V2
+[ 11.634424] wsa883x-codec sdw:1:0:0217:0202:00:2: WSA883X Version 1_1, Variant: WSA8835_V2
+
+Fixes: 43b8c7dc85a1 ("ASoC: codecs: add wsa883x amplifier support")
+Cc: stable@vger.kernel.org # 6.0
+Cc: Srinivas Kandagatla <srini@kernel.org>
+Signed-off-by: Johan Hovold <johan@kernel.org>
+Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski@oss.qualcomm.com>
+Reviewed-by: Srinivas Kandagatla <srinivas.kandagatla@oss.qualcomm.com>
+Link: https://patch.msgid.link/20260102111413.9605-2-johan@kernel.org
+Signed-off-by: Mark Brown <broonie@kernel.org>
+[ Adjust context ]
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ sound/soc/codecs/wsa883x.c | 9 +++++++++
+ 1 file changed, 9 insertions(+)
+
+--- a/sound/soc/codecs/wsa883x.c
++++ b/sound/soc/codecs/wsa883x.c
+@@ -448,6 +448,7 @@ struct wsa883x_priv {
+ int active_ports;
+ int dev_mode;
+ int comp_offset;
++ bool hw_init;
+ };
+
+ enum {
+@@ -1007,6 +1008,9 @@ static int wsa883x_init(struct wsa883x_p
+ struct regmap *regmap = wsa883x->regmap;
+ int variant, version, ret;
+
++ if (wsa883x->hw_init)
++ return 0;
++
+ ret = regmap_read(regmap, WSA883X_OTP_REG_0, &variant);
+ if (ret)
+ return ret;
+@@ -1050,6 +1054,8 @@ static int wsa883x_init(struct wsa883x_p
+ wsa883x->comp_offset);
+ }
+
++ wsa883x->hw_init = true;
++
+ return 0;
+ }
+
+@@ -1058,6 +1064,9 @@ static int wsa883x_update_status(struct
+ {
+ struct wsa883x_priv *wsa883x = dev_get_drvdata(&slave->dev);
+
++ if (status == SDW_SLAVE_UNATTACHED)
++ wsa883x->hw_init = false;
++
+ if (status == SDW_SLAVE_ATTACHED && slave->dev_num > 0)
+ return wsa883x_init(wsa883x);
+
--- /dev/null
+From stable+bounces-210739-greg=kroah.com@vger.kernel.org Wed Jan 21 13:23:28 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 21 Jan 2026 07:20:38 -0500
+Subject: dmaengine: stm32: dmamux: fix device leak on route allocation
+To: stable@vger.kernel.org
+Cc: Johan Hovold <johan@kernel.org>, Pierre-Yves MORDRET <pierre-yves.mordret@foss.st.com>, Amelie Delaunay <amelie.delaunay@foss.st.com>, Vinod Koul <vkoul@kernel.org>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260121122038.1526229-1-sashal@kernel.org>
+
+From: Johan Hovold <johan@kernel.org>
+
+[ Upstream commit dd6e4943889fb354efa3f700e42739da9bddb6ef ]
+
+Make sure to drop the reference taken when looking up the DMA mux
+platform device during route allocation.
+
+Note that holding a reference to a device does not prevent its driver
+data from going away so there is no point in keeping the reference.
+
+Fixes: df7e762db5f6 ("dmaengine: Add STM32 DMAMUX driver")
+Cc: stable@vger.kernel.org # 4.15
+Cc: Pierre-Yves MORDRET <pierre-yves.mordret@foss.st.com>
+Signed-off-by: Johan Hovold <johan@kernel.org>
+Reviewed-by: Amelie Delaunay <amelie.delaunay@foss.st.com>
+Link: https://patch.msgid.link/20251117161258.10679-11-johan@kernel.org
+Signed-off-by: Vinod Koul <vkoul@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/dma/stm32-dmamux.c | 18 ++++++++++++------
+ 1 file changed, 12 insertions(+), 6 deletions(-)
+
+--- a/drivers/dma/stm32-dmamux.c
++++ b/drivers/dma/stm32-dmamux.c
+@@ -88,23 +88,25 @@ static void *stm32_dmamux_route_allocate
+ struct stm32_dmamux_data *dmamux = platform_get_drvdata(pdev);
+ struct stm32_dmamux *mux;
+ u32 i, min, max;
+- int ret;
++ int ret = -EINVAL;
+ unsigned long flags;
+
+ if (dma_spec->args_count != 3) {
+ dev_err(&pdev->dev, "invalid number of dma mux args\n");
+- return ERR_PTR(-EINVAL);
++ goto err_put_pdev;
+ }
+
+ if (dma_spec->args[0] > dmamux->dmamux_requests) {
+ dev_err(&pdev->dev, "invalid mux request number: %d\n",
+ dma_spec->args[0]);
+- return ERR_PTR(-EINVAL);
++ goto err_put_pdev;
+ }
+
+ mux = kzalloc(sizeof(*mux), GFP_KERNEL);
+- if (!mux)
+- return ERR_PTR(-ENOMEM);
++ if (!mux) {
++ ret = -ENOMEM;
++ goto err_put_pdev;
++ }
+
+ spin_lock_irqsave(&dmamux->lock, flags);
+ mux->chan_id = find_first_zero_bit(dmamux->dma_inuse,
+@@ -131,7 +133,6 @@ static void *stm32_dmamux_route_allocate
+ dma_spec->np = of_parse_phandle(ofdma->of_node, "dma-masters", i - 1);
+ if (!dma_spec->np) {
+ dev_err(&pdev->dev, "can't get dma master\n");
+- ret = -EINVAL;
+ goto error;
+ }
+
+@@ -158,6 +159,8 @@ static void *stm32_dmamux_route_allocate
+ dev_dbg(&pdev->dev, "Mapping DMAMUX(%u) to DMA%u(%u)\n",
+ mux->request, mux->master, mux->chan_id);
+
++ put_device(&pdev->dev);
++
+ return mux;
+
+ err_put_dma_spec_np:
+@@ -167,6 +170,9 @@ error:
+
+ error_chan_id:
+ kfree(mux);
++err_put_pdev:
++ put_device(&pdev->dev);
++
+ return ERR_PTR(ret);
+ }
+
--- /dev/null
+From stable+bounces-210742-greg=kroah.com@vger.kernel.org Wed Jan 21 13:30:52 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 21 Jan 2026 07:24:45 -0500
+Subject: dmaengine: stm32: dmamux: fix OF node leak on route allocation failure
+To: stable@vger.kernel.org
+Cc: Johan Hovold <johan@kernel.org>, Pierre-Yves MORDRET <pierre-yves.mordret@foss.st.com>, Amelie Delaunay <amelie.delaunay@foss.st.com>, Vinod Koul <vkoul@kernel.org>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260121122445.1527855-1-sashal@kernel.org>
+
+From: Johan Hovold <johan@kernel.org>
+
+[ Upstream commit b1b590a590af13ded598e70f0b72bc1e515787a1 ]
+
+Make sure to drop the reference taken to the DMA master OF node also on
+late route allocation failures.
+
+Fixes: df7e762db5f6 ("dmaengine: Add STM32 DMAMUX driver")
+Cc: stable@vger.kernel.org # 4.15
+Cc: Pierre-Yves MORDRET <pierre-yves.mordret@foss.st.com>
+Signed-off-by: Johan Hovold <johan@kernel.org>
+Reviewed-by: Amelie Delaunay <amelie.delaunay@foss.st.com>
+Link: https://patch.msgid.link/20251117161258.10679-12-johan@kernel.org
+Signed-off-by: Vinod Koul <vkoul@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/dma/stm32-dmamux.c | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+--- a/drivers/dma/stm32-dmamux.c
++++ b/drivers/dma/stm32-dmamux.c
+@@ -140,7 +140,7 @@ static void *stm32_dmamux_route_allocate
+ ret = pm_runtime_resume_and_get(&pdev->dev);
+ if (ret < 0) {
+ spin_unlock_irqrestore(&dmamux->lock, flags);
+- goto error;
++ goto err_put_dma_spec_np;
+ }
+ spin_unlock_irqrestore(&dmamux->lock, flags);
+
+@@ -160,6 +160,8 @@ static void *stm32_dmamux_route_allocate
+
+ return mux;
+
++err_put_dma_spec_np:
++ of_node_put(dma_spec->np);
+ error:
+ clear_bit(mux->chan_id, dmamux->dma_inuse);
+
--- /dev/null
+From black.hawk@163.com Mon Feb 2 09:28:18 2026
+From: Rahul Sharma <black.hawk@163.com>
+Date: Mon, 2 Feb 2026 16:27:28 +0800
+Subject: genirq/irq_sim: Initialize work context pointers properly
+To: gregkh@linuxfoundation.org, stable@vger.kernel.org
+Cc: linux-kernel@vger.kernel.org, Gyeyoung Baek <gye976@gmail.com>, Thomas Gleixner <tglx@linutronix.de>, Rahul Sharma <black.hawk@163.com>
+Message-ID: <20260202082728.975184-1-black.hawk@163.com>
+
+From: Gyeyoung Baek <gye976@gmail.com>
+
+[ Upstream commit 8a2277a3c9e4cc5398f80821afe7ecbe9bdf2819 ]
+
+Initialize `ops` member's pointers properly by using kzalloc() instead of
+kmalloc() when allocating the simulation work context. Otherwise the
+pointers contain random content leading to invalid dereferencing.
+
+Signed-off-by: Gyeyoung Baek <gye976@gmail.com>
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Link: https://lore.kernel.org/all/20250612124827.63259-1-gye976@gmail.com
+[ The context change is due to the commit 011f583781fa
+("genirq/irq_sim: add an extended irq_sim initializer")
+which is irrelevant to the logic of this patch. ]
+Signed-off-by: Rahul Sharma <black.hawk@163.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ kernel/irq/irq_sim.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/kernel/irq/irq_sim.c
++++ b/kernel/irq/irq_sim.c
+@@ -166,7 +166,7 @@ struct irq_domain *irq_domain_create_sim
+ {
+ struct irq_sim_work_ctx *work_ctx;
+
+- work_ctx = kmalloc(sizeof(*work_ctx), GFP_KERNEL);
++ work_ctx = kzalloc(sizeof(*work_ctx), GFP_KERNEL);
+ if (!work_ctx)
+ goto err_out;
+
--- /dev/null
+From stable+bounces-211892-greg=kroah.com@vger.kernel.org Tue Jan 27 22:09:48 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 27 Jan 2026 16:07:04 -0500
+Subject: iio: adc: exynos_adc: fix OF populate on driver rebind
+To: stable@vger.kernel.org
+Cc: Johan Hovold <johan@kernel.org>, Krzysztof Kozlowski <krzysztof.kozlowski@oss.qualcomm.com>, Jonathan Cameron <Jonathan.Cameron@huawei.com>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260127210704.2163667-1-sashal@kernel.org>
+
+From: Johan Hovold <johan@kernel.org>
+
+[ Upstream commit ea6b4feba85e996e840e0b661bc42793df6eb701 ]
+
+Since commit c6e126de43e7 ("of: Keep track of populated platform
+devices") child devices will not be created by of_platform_populate()
+if the devices had previously been deregistered individually so that the
+OF_POPULATED flag is still set in the corresponding OF nodes.
+
+Switch to using of_platform_depopulate() instead of open coding so that
+the child devices are created if the driver is rebound.
+
+Fixes: c6e126de43e7 ("of: Keep track of populated platform devices")
+Cc: stable@vger.kernel.org # 3.16
+Signed-off-by: Johan Hovold <johan@kernel.org>
+Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski@oss.qualcomm.com>
+Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
+[ Adjust context ]
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/iio/adc/exynos_adc.c | 13 ++-----------
+ 1 file changed, 2 insertions(+), 11 deletions(-)
+
+--- a/drivers/iio/adc/exynos_adc.c
++++ b/drivers/iio/adc/exynos_adc.c
+@@ -721,14 +721,7 @@ static const struct iio_chan_spec exynos
+ ADC_CHANNEL(9, "adc9"),
+ };
+
+-static int exynos_adc_remove_devices(struct device *dev, void *c)
+-{
+- struct platform_device *pdev = to_platform_device(dev);
+-
+- platform_device_unregister(pdev);
+
+- return 0;
+-}
+
+ static int exynos_adc_ts_open(struct input_dev *dev)
+ {
+@@ -929,8 +922,7 @@ static int exynos_adc_probe(struct platf
+ return 0;
+
+ err_of_populate:
+- device_for_each_child(&indio_dev->dev, NULL,
+- exynos_adc_remove_devices);
++ of_platform_depopulate(&indio_dev->dev);
+ if (has_ts) {
+ input_unregister_device(info->input);
+ free_irq(info->tsirq, info);
+@@ -959,8 +951,7 @@ static int exynos_adc_remove(struct plat
+ free_irq(info->tsirq, info);
+ input_unregister_device(info->input);
+ }
+- device_for_each_child(&indio_dev->dev, NULL,
+- exynos_adc_remove_devices);
++ of_platform_depopulate(&indio_dev->dev);
+ iio_device_unregister(indio_dev);
+ free_irq(info->irq, info);
+ if (info->data->exit_hw)
--- /dev/null
+From stable+bounces-211851-greg=kroah.com@vger.kernel.org Tue Jan 27 16:52:08 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 27 Jan 2026 10:52:02 -0500
+Subject: iio: chemical: scd4x: fix reported channel endianness
+To: stable@vger.kernel.org
+Cc: Fiona Klute <fiona.klute@gmx.de>, David Lechner <dlechner@baylibre.com>, Jonathan Cameron <Jonathan.Cameron@huawei.com>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260127155202.1927098-1-sashal@kernel.org>
+
+From: Fiona Klute <fiona.klute@gmx.de>
+
+[ Upstream commit 81d5a5366d3c20203fb9d7345e1aa46d668445a2 ]
+
+The driver converts values read from the sensor from BE to CPU
+endianness in scd4x_read_meas(). The result is then pushed into the
+buffer in scd4x_trigger_handler(), so on LE architectures parsing the
+buffer using the reported BE type gave wrong results.
+
+scd4x_read_raw() which provides sysfs *_raw values is not affected, it
+used the values returned by scd4x_read_meas() without further
+conversion.
+
+Fixes: 49d22b695cbb6 ("drivers: iio: chemical: Add support for Sensirion SCD4x CO2 sensor")
+Signed-off-by: Fiona Klute <fiona.klute@gmx.de>
+Reviewed-by: David Lechner <dlechner@baylibre.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/chemical/scd4x.c | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+--- a/drivers/iio/chemical/scd4x.c
++++ b/drivers/iio/chemical/scd4x.c
+@@ -518,7 +518,7 @@ static const struct iio_chan_spec scd4x_
+ .sign = 'u',
+ .realbits = 16,
+ .storagebits = 16,
+- .endianness = IIO_BE,
++ .endianness = IIO_CPU,
+ },
+ },
+ {
+@@ -533,7 +533,7 @@ static const struct iio_chan_spec scd4x_
+ .sign = 'u',
+ .realbits = 16,
+ .storagebits = 16,
+- .endianness = IIO_BE,
++ .endianness = IIO_CPU,
+ },
+ },
+ {
+@@ -546,7 +546,7 @@ static const struct iio_chan_spec scd4x_
+ .sign = 'u',
+ .realbits = 16,
+ .storagebits = 16,
+- .endianness = IIO_BE,
++ .endianness = IIO_CPU,
+ },
+ },
+ };
--- /dev/null
+From stable+bounces-212683-greg=kroah.com@vger.kernel.org Wed Jan 28 23:21:36 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 28 Jan 2026 17:20:21 -0500
+Subject: ksmbd: smbd: fix dma_unmap_sg() nents
+To: stable@vger.kernel.org
+Cc: Thomas Fourier <fourier.thomas@gmail.com>, Namjae Jeon <linkinjeon@kernel.org>, Steve French <stfrench@microsoft.com>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260128222021.2800060-1-sashal@kernel.org>
+
+From: Thomas Fourier <fourier.thomas@gmail.com>
+
+[ Upstream commit 98e3e2b561bc88f4dd218d1c05890672874692f6 ]
+
+The dma_unmap_sg() functions should be called with the same nents as the
+dma_map_sg(), not the value the map function returned.
+
+Fixes: 0626e6641f6b ("cifsd: add server handler for central processing and tranport layers")
+Cc: <stable@vger.kernel.org>
+Signed-off-by: Thomas Fourier <fourier.thomas@gmail.com>
+Acked-by: Namjae Jeon <linkinjeon@kernel.org>
+Signed-off-by: Steve French <stfrench@microsoft.com>
+[ Context ]
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/smb/server/transport_rdma.c | 15 +++++++--------
+ 1 file changed, 7 insertions(+), 8 deletions(-)
+
+--- a/fs/smb/server/transport_rdma.c
++++ b/fs/smb/server/transport_rdma.c
+@@ -1103,14 +1103,12 @@ static int get_sg_list(void *buf, int si
+
+ static int get_mapped_sg_list(struct ib_device *device, void *buf, int size,
+ struct scatterlist *sg_list, int nentries,
+- enum dma_data_direction dir)
++ enum dma_data_direction dir, int *npages)
+ {
+- int npages;
+-
+- npages = get_sg_list(buf, size, sg_list, nentries);
+- if (npages < 0)
++ *npages = get_sg_list(buf, size, sg_list, nentries);
++ if (*npages < 0)
+ return -EINVAL;
+- return ib_dma_map_sg(device, sg_list, npages, dir);
++ return ib_dma_map_sg(device, sg_list, *npages, dir);
+ }
+
+ static int post_sendmsg(struct smb_direct_transport *t,
+@@ -1179,12 +1177,13 @@ static int smb_direct_post_send_data(str
+ for (i = 0; i < niov; i++) {
+ struct ib_sge *sge;
+ int sg_cnt;
++ int npages;
+
+ sg_init_table(sg, SMB_DIRECT_MAX_SEND_SGES - 1);
+ sg_cnt = get_mapped_sg_list(t->cm_id->device,
+ iov[i].iov_base, iov[i].iov_len,
+ sg, SMB_DIRECT_MAX_SEND_SGES - 1,
+- DMA_TO_DEVICE);
++ DMA_TO_DEVICE, &npages);
+ if (sg_cnt <= 0) {
+ pr_err("failed to map buffer\n");
+ ret = -ENOMEM;
+@@ -1192,7 +1191,7 @@ static int smb_direct_post_send_data(str
+ } else if (sg_cnt + msg->num_sge > SMB_DIRECT_MAX_SEND_SGES) {
+ pr_err("buffer not fitted into sges\n");
+ ret = -E2BIG;
+- ib_dma_unmap_sg(t->cm_id->device, sg, sg_cnt,
++ ib_dma_unmap_sg(t->cm_id->device, sg, npages,
+ DMA_TO_DEVICE);
+ goto err;
+ }
--- /dev/null
+From stable+bounces-212682-greg=kroah.com@vger.kernel.org Wed Jan 28 23:21:34 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 28 Jan 2026 17:20:19 -0500
+Subject: mei: trace: treat reg parameter as string
+To: stable@vger.kernel.org
+Cc: Alexander Usyskin <alexander.usyskin@intel.com>, Greg Kroah-Hartman <gregkh@linuxfoundation.org>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260128222019.2800019-1-sashal@kernel.org>
+
+From: Alexander Usyskin <alexander.usyskin@intel.com>
+
+[ Upstream commit 06d5a7afe1d0b47102936d8fba568572c2b4b941 ]
+
+The commit
+afd2627f727b ("tracing: Check "%s" dereference via the field and not the TP_printk format")
+forbids to emit event with a plain char* without a wrapper.
+
+The reg parameter always passed as static string and wrapper
+is not strictly required, contrary to dev parameter.
+Use the string wrapper anyway to check sanity of the reg parameters,
+store it value independently and prevent internal kernel data leaks.
+
+Since some code refactoring has taken place, explicit backporting may
+be needed for kernels older than 6.10.
+
+Cc: stable@vger.kernel.org # v6.11+
+Fixes: a0a927d06d79 ("mei: me: add io register tracing")
+Signed-off-by: Alexander Usyskin <alexander.usyskin@intel.com>
+Link: https://patch.msgid.link/20260111145125.1754912-1-alexander.usyskin@intel.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+[ adapted __assign_str() calls to use two arguments ]
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/misc/mei/mei-trace.h | 18 +++++++++---------
+ 1 file changed, 9 insertions(+), 9 deletions(-)
+
+--- a/drivers/misc/mei/mei-trace.h
++++ b/drivers/misc/mei/mei-trace.h
+@@ -21,18 +21,18 @@ TRACE_EVENT(mei_reg_read,
+ TP_ARGS(dev, reg, offs, val),
+ TP_STRUCT__entry(
+ __string(dev, dev_name(dev))
+- __field(const char *, reg)
++ __string(reg, reg)
+ __field(u32, offs)
+ __field(u32, val)
+ ),
+ TP_fast_assign(
+ __assign_str(dev, dev_name(dev));
+- __entry->reg = reg;
++ __assign_str(reg, reg);
+ __entry->offs = offs;
+ __entry->val = val;
+ ),
+ TP_printk("[%s] read %s:[%#x] = %#x",
+- __get_str(dev), __entry->reg, __entry->offs, __entry->val)
++ __get_str(dev), __get_str(reg), __entry->offs, __entry->val)
+ );
+
+ TRACE_EVENT(mei_reg_write,
+@@ -40,18 +40,18 @@ TRACE_EVENT(mei_reg_write,
+ TP_ARGS(dev, reg, offs, val),
+ TP_STRUCT__entry(
+ __string(dev, dev_name(dev))
+- __field(const char *, reg)
++ __string(reg, reg)
+ __field(u32, offs)
+ __field(u32, val)
+ ),
+ TP_fast_assign(
+ __assign_str(dev, dev_name(dev));
+- __entry->reg = reg;
++ __assign_str(reg, reg);
+ __entry->offs = offs;
+ __entry->val = val;
+ ),
+ TP_printk("[%s] write %s[%#x] = %#x",
+- __get_str(dev), __entry->reg, __entry->offs, __entry->val)
++ __get_str(dev), __get_str(reg), __entry->offs, __entry->val)
+ );
+
+ TRACE_EVENT(mei_pci_cfg_read,
+@@ -59,18 +59,18 @@ TRACE_EVENT(mei_pci_cfg_read,
+ TP_ARGS(dev, reg, offs, val),
+ TP_STRUCT__entry(
+ __string(dev, dev_name(dev))
+- __field(const char *, reg)
++ __string(reg, reg)
+ __field(u32, offs)
+ __field(u32, val)
+ ),
+ TP_fast_assign(
+ __assign_str(dev, dev_name(dev));
+- __entry->reg = reg;
++ __assign_str(reg, reg);
+ __entry->offs = offs;
+ __entry->val = val;
+ ),
+ TP_printk("[%s] pci cfg read %s:[%#x] = %#x",
+- __get_str(dev), __entry->reg, __entry->offs, __entry->val)
++ __get_str(dev), __get_str(reg), __entry->offs, __entry->val)
+ );
+
+ #endif /* _MEI_TRACE_H_ */
--- /dev/null
+From stable+bounces-210736-greg=kroah.com@vger.kernel.org Wed Jan 21 13:12:30 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 21 Jan 2026 07:05:13 -0500
+Subject: mm: kmsan: fix poisoning of high-order non-compound pages
+To: stable@vger.kernel.org
+Cc: Ryan Roberts <ryan.roberts@arm.com>, Alexander Potapenko <glider@google.com>, Dmitriy Vyukov <dvyukov@google.com>, Marco Elver <elver@google.com>, Andrew Morton <akpm@linux-foundation.org>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260121120513.1505706-1-sashal@kernel.org>
+
+From: Ryan Roberts <ryan.roberts@arm.com>
+
+[ Upstream commit 4795d205d78690a46b60164f44b8bb7b3e800865 ]
+
+kmsan_free_page() is called by the page allocator's free_pages_prepare()
+during page freeing. Its job is to poison all the memory covered by the
+page. It can be called with an order-0 page, a compound high-order page
+or a non-compound high-order page. But page_size() only works for order-0
+and compound pages. For a non-compound high-order page it will
+incorrectly return PAGE_SIZE.
+
+The implication is that the tail pages of a high-order non-compound page
+do not get poisoned at free, so any invalid access while they are free
+could go unnoticed. It looks like the pages will be poisoned again at
+allocation time, so that would bookend the window.
+
+Fix this by using the order parameter to calculate the size.
+
+Link: https://lkml.kernel.org/r/20260104134348.3544298-1-ryan.roberts@arm.com
+Fixes: b073d7f8aee4 ("mm: kmsan: maintain KMSAN metadata for page operations")
+Signed-off-by: Ryan Roberts <ryan.roberts@arm.com>
+Reviewed-by: Alexander Potapenko <glider@google.com>
+Tested-by: Alexander Potapenko <glider@google.com>
+Cc: Dmitriy Vyukov <dvyukov@google.com>
+Cc: Dmitry Vyukov <dvyukov@google.com>
+Cc: Marco Elver <elver@google.com>
+Cc: Ryan Roberts <ryan.roberts@arm.com>
+Cc: <stable@vger.kernel.org>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ mm/kmsan/shadow.c | 3 +--
+ 1 file changed, 1 insertion(+), 2 deletions(-)
+
+--- a/mm/kmsan/shadow.c
++++ b/mm/kmsan/shadow.c
+@@ -209,8 +209,7 @@ void kmsan_free_page(struct page *page,
+ if (!kmsan_enabled || kmsan_in_runtime())
+ return;
+ kmsan_enter_runtime();
+- kmsan_internal_poison_memory(page_address(page),
+- PAGE_SIZE << compound_order(page),
++ kmsan_internal_poison_memory(page_address(page), PAGE_SIZE << order,
+ GFP_KERNEL,
+ KMSAN_POISON_CHECK | KMSAN_POISON_FREE);
+ kmsan_leave_runtime();
--- /dev/null
+From stable+bounces-210738-greg=kroah.com@vger.kernel.org Wed Jan 21 13:25:40 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 21 Jan 2026 07:15:54 -0500
+Subject: mm/page_alloc: prevent pcp corruption with SMP=n
+To: stable@vger.kernel.org
+Cc: Vlastimil Babka <vbabka@suse.cz>, kernel test robot <oliver.sang@intel.com>, Matthew Wilcox <willy@infradead.org>, Mel Gorman <mgorman@techsingularity.net>, Brendan Jackman <jackmanb@google.com>, Johannes Weiner <hannes@cmpxchg.org>, Michal Hocko <mhocko@suse.com>, Sebastian Andrzej Siewior <bigeasy@linutronix.de>, Steven Rostedt <rostedt@goodmis.org>, Suren Baghdasaryan <surenb@google.com>, Zi Yan <ziy@nvidia.com>, Andrew Morton <akpm@linux-foundation.org>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260121121554.1523263-1-sashal@kernel.org>
+
+From: Vlastimil Babka <vbabka@suse.cz>
+
+[ Upstream commit 038a102535eb49e10e93eafac54352fcc5d78847 ]
+
+The kernel test robot has reported:
+
+ BUG: spinlock trylock failure on UP on CPU#0, kcompactd0/28
+ lock: 0xffff888807e35ef0, .magic: dead4ead, .owner: kcompactd0/28, .owner_cpu: 0
+ CPU: 0 UID: 0 PID: 28 Comm: kcompactd0 Not tainted 6.18.0-rc5-00127-ga06157804399 #1 PREEMPT 8cc09ef94dcec767faa911515ce9e609c45db470
+ Call Trace:
+ <IRQ>
+ __dump_stack (lib/dump_stack.c:95)
+ dump_stack_lvl (lib/dump_stack.c:123)
+ dump_stack (lib/dump_stack.c:130)
+ spin_dump (kernel/locking/spinlock_debug.c:71)
+ do_raw_spin_trylock (kernel/locking/spinlock_debug.c:?)
+ _raw_spin_trylock (include/linux/spinlock_api_smp.h:89 kernel/locking/spinlock.c:138)
+ __free_frozen_pages (mm/page_alloc.c:2973)
+ ___free_pages (mm/page_alloc.c:5295)
+ __free_pages (mm/page_alloc.c:5334)
+ tlb_remove_table_rcu (include/linux/mm.h:? include/linux/mm.h:3122 include/asm-generic/tlb.h:220 mm/mmu_gather.c:227 mm/mmu_gather.c:290)
+ ? __cfi_tlb_remove_table_rcu (mm/mmu_gather.c:289)
+ ? rcu_core (kernel/rcu/tree.c:?)
+ rcu_core (include/linux/rcupdate.h:341 kernel/rcu/tree.c:2607 kernel/rcu/tree.c:2861)
+ rcu_core_si (kernel/rcu/tree.c:2879)
+ handle_softirqs (arch/x86/include/asm/jump_label.h:36 include/trace/events/irq.h:142 kernel/softirq.c:623)
+ __irq_exit_rcu (arch/x86/include/asm/jump_label.h:36 kernel/softirq.c:725)
+ irq_exit_rcu (kernel/softirq.c:741)
+ sysvec_apic_timer_interrupt (arch/x86/kernel/apic/apic.c:1052)
+ </IRQ>
+ <TASK>
+ RIP: 0010:_raw_spin_unlock_irqrestore (arch/x86/include/asm/preempt.h:95 include/linux/spinlock_api_smp.h:152 kernel/locking/spinlock.c:194)
+ free_pcppages_bulk (mm/page_alloc.c:1494)
+ drain_pages_zone (include/linux/spinlock.h:391 mm/page_alloc.c:2632)
+ __drain_all_pages (mm/page_alloc.c:2731)
+ drain_all_pages (mm/page_alloc.c:2747)
+ kcompactd (mm/compaction.c:3115)
+ kthread (kernel/kthread.c:465)
+ ? __cfi_kcompactd (mm/compaction.c:3166)
+ ? __cfi_kthread (kernel/kthread.c:412)
+ ret_from_fork (arch/x86/kernel/process.c:164)
+ ? __cfi_kthread (kernel/kthread.c:412)
+ ret_from_fork_asm (arch/x86/entry/entry_64.S:255)
+ </TASK>
+
+Matthew has analyzed the report and identified that in drain_page_zone()
+we are in a section protected by spin_lock(&pcp->lock) and then get an
+interrupt that attempts spin_trylock() on the same lock. The code is
+designed to work this way without disabling IRQs and occasionally fail the
+trylock with a fallback. However, the SMP=n spinlock implementation
+assumes spin_trylock() will always succeed, and thus it's normally a
+no-op. Here the enabled lock debugging catches the problem, but otherwise
+it could cause a corruption of the pcp structure.
+
+The problem has been introduced by commit 574907741599 ("mm/page_alloc:
+leave IRQs enabled for per-cpu page allocations"). The pcp locking scheme
+recognizes the need for disabling IRQs to prevent nesting spin_trylock()
+sections on SMP=n, but the need to prevent the nesting in spin_lock() has
+not been recognized. Fix it by introducing local wrappers that change the
+spin_lock() to spin_lock_iqsave() with SMP=n and use them in all places
+that do spin_lock(&pcp->lock).
+
+[vbabka@suse.cz: add pcp_ prefix to the spin_lock_irqsave wrappers, per Steven]
+Link: https://lkml.kernel.org/r/20260105-fix-pcp-up-v1-1-5579662d2071@suse.cz
+Fixes: 574907741599 ("mm/page_alloc: leave IRQs enabled for per-cpu page allocations")
+Signed-off-by: Vlastimil Babka <vbabka@suse.cz>
+Reported-by: kernel test robot <oliver.sang@intel.com>
+Closes: https://lore.kernel.org/oe-lkp/202512101320.e2f2dd6f-lkp@intel.com
+Analyzed-by: Matthew Wilcox <willy@infradead.org>
+Link: https://lore.kernel.org/all/aUW05pyc9nZkvY-1@casper.infradead.org/
+Acked-by: Mel Gorman <mgorman@techsingularity.net>
+Cc: Brendan Jackman <jackmanb@google.com>
+Cc: Johannes Weiner <hannes@cmpxchg.org>
+Cc: Michal Hocko <mhocko@suse.com>
+Cc: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+Cc: Steven Rostedt <rostedt@goodmis.org>
+Cc: Suren Baghdasaryan <surenb@google.com>
+Cc: Zi Yan <ziy@nvidia.com>
+Cc: <stable@vger.kernel.org>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+[ drop changes to decay_pcp_high() and zone_pcp_update_cacheinfo() ]
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ mm/page_alloc.c | 37 +++++++++++++++++++++++++++++++++----
+ 1 file changed, 33 insertions(+), 4 deletions(-)
+
+--- a/mm/page_alloc.c
++++ b/mm/page_alloc.c
+@@ -198,6 +198,33 @@ static DEFINE_MUTEX(pcp_batch_high_lock)
+ #define pcp_spin_unlock(ptr) \
+ pcpu_spin_unlock(lock, ptr)
+
++/*
++ * With the UP spinlock implementation, when we spin_lock(&pcp->lock) (for i.e.
++ * a potentially remote cpu drain) and get interrupted by an operation that
++ * attempts pcp_spin_trylock(), we can't rely on the trylock failure due to UP
++ * spinlock assumptions making the trylock a no-op. So we have to turn that
++ * spin_lock() to a spin_lock_irqsave(). This works because on UP there are no
++ * remote cpu's so we can only be locking the only existing local one.
++ */
++#if defined(CONFIG_SMP) || defined(CONFIG_PREEMPT_RT)
++static inline void __flags_noop(unsigned long *flags) { }
++#define pcp_spin_lock_maybe_irqsave(ptr, flags) \
++({ \
++ __flags_noop(&(flags)); \
++ spin_lock(&(ptr)->lock); \
++})
++#define pcp_spin_unlock_maybe_irqrestore(ptr, flags) \
++({ \
++ spin_unlock(&(ptr)->lock); \
++ __flags_noop(&(flags)); \
++})
++#else
++#define pcp_spin_lock_maybe_irqsave(ptr, flags) \
++ spin_lock_irqsave(&(ptr)->lock, flags)
++#define pcp_spin_unlock_maybe_irqrestore(ptr, flags) \
++ spin_unlock_irqrestore(&(ptr)->lock, flags)
++#endif
++
+ #ifdef CONFIG_USE_PERCPU_NUMA_NODE_ID
+ DEFINE_PER_CPU(int, numa_node);
+ EXPORT_PER_CPU_SYMBOL(numa_node);
+@@ -3174,14 +3201,15 @@ static int rmqueue_bulk(struct zone *zon
+ */
+ void drain_zone_pages(struct zone *zone, struct per_cpu_pages *pcp)
+ {
++ unsigned long UP_flags;
+ int to_drain, batch;
+
+ batch = READ_ONCE(pcp->batch);
+ to_drain = min(pcp->count, batch);
+ if (to_drain > 0) {
+- spin_lock(&pcp->lock);
++ pcp_spin_lock_maybe_irqsave(pcp, UP_flags);
+ free_pcppages_bulk(zone, to_drain, pcp, 0);
+- spin_unlock(&pcp->lock);
++ pcp_spin_unlock_maybe_irqrestore(pcp, UP_flags);
+ }
+ }
+ #endif
+@@ -3192,10 +3220,11 @@ void drain_zone_pages(struct zone *zone,
+ static void drain_pages_zone(unsigned int cpu, struct zone *zone)
+ {
+ struct per_cpu_pages *pcp = per_cpu_ptr(zone->per_cpu_pageset, cpu);
++ unsigned long UP_flags;
+ int count;
+
+ do {
+- spin_lock(&pcp->lock);
++ pcp_spin_lock_maybe_irqsave(pcp, UP_flags);
+ count = pcp->count;
+ if (count) {
+ int to_drain = min(count,
+@@ -3204,7 +3233,7 @@ static void drain_pages_zone(unsigned in
+ free_pcppages_bulk(zone, to_drain, pcp, 0);
+ count -= to_drain;
+ }
+- spin_unlock(&pcp->lock);
++ pcp_spin_unlock_maybe_irqrestore(pcp, UP_flags);
+ } while (count);
+ }
+
--- /dev/null
+From stable+bounces-211671-greg=kroah.com@vger.kernel.org Mon Jan 26 19:02:25 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 26 Jan 2026 13:02:11 -0500
+Subject: mm/rmap: fix two comments related to huge_pmd_unshare()
+To: stable@vger.kernel.org
+Cc: "David Hildenbrand (Red Hat)" <david@kernel.org>, Rik van Riel <riel@surriel.com>, Laurence Oberman <loberman@redhat.com>, Lorenzo Stoakes <lorenzo.stoakes@oracle.com>, Oscar Salvador <osalvador@suse.de>, Liu Shixin <liushixin2@huawei.com>, Harry Yoo <harry.yoo@oracle.com>, Lance Yang <lance.yang@linux.dev>, "Uschakow, Stanislav" <suschako@amazon.de>, Andrew Morton <akpm@linux-foundation.org>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260126180211.3511367-1-sashal@kernel.org>
+
+From: "David Hildenbrand (Red Hat)" <david@kernel.org>
+
+[ Upstream commit a8682d500f691b6dfaa16ae1502d990aeb86e8be ]
+
+PMD page table unsharing no longer touches the refcount of a PMD page
+table. Also, it is not about dropping the refcount of a "PMD page" but
+the "PMD page table".
+
+Let's just simplify by saying that the PMD page table was unmapped,
+consequently also unmapping the folio that was mapped into this page.
+
+This code should be deduplicated in the future.
+
+Link: https://lkml.kernel.org/r/20251223214037.580860-4-david@kernel.org
+Fixes: 59d9094df3d7 ("mm: hugetlb: independent PMD page table shared count")
+Signed-off-by: David Hildenbrand (Red Hat) <david@kernel.org>
+Reviewed-by: Rik van Riel <riel@surriel.com>
+Tested-by: Laurence Oberman <loberman@redhat.com>
+Reviewed-by: Lorenzo Stoakes <lorenzo.stoakes@oracle.com>
+Acked-by: Oscar Salvador <osalvador@suse.de>
+Cc: Liu Shixin <liushixin2@huawei.com>
+Cc: Harry Yoo <harry.yoo@oracle.com>
+Cc: Lance Yang <lance.yang@linux.dev>
+Cc: "Uschakow, Stanislav" <suschako@amazon.de>
+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/rmap.c | 20 ++++----------------
+ 1 file changed, 4 insertions(+), 16 deletions(-)
+
+--- a/mm/rmap.c
++++ b/mm/rmap.c
+@@ -1574,14 +1574,8 @@ static bool try_to_unmap_one(struct foli
+ mmu_notifier_invalidate_range(mm,
+ range.start, range.end);
+ /*
+- * The ref count of the PMD page was
+- * dropped which is part of the way map
+- * counting is done for shared PMDs.
+- * Return 'true' here. When there is
+- * no other sharing, huge_pmd_unshare
+- * returns false and we will unmap the
+- * actual page and drop map count
+- * to zero.
++ * The PMD table was unmapped,
++ * consequently unmapping the folio.
+ */
+ page_vma_mapped_walk_done(&pvmw);
+ break;
+@@ -1965,14 +1959,8 @@ static bool try_to_migrate_one(struct fo
+ range.start, range.end);
+
+ /*
+- * The ref count of the PMD page was
+- * dropped which is part of the way map
+- * counting is done for shared PMDs.
+- * Return 'true' here. When there is
+- * no other sharing, huge_pmd_unshare
+- * returns false and we will unmap the
+- * actual page and drop map count
+- * to zero.
++ * The PMD table was unmapped,
++ * consequently unmapping the folio.
+ */
+ page_vma_mapped_walk_done(&pvmw);
+ break;
--- /dev/null
+From stable+bounces-212658-greg=kroah.com@vger.kernel.org Wed Jan 28 19:26:23 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 28 Jan 2026 13:26:15 -0500
+Subject: mmc: sdhci-of-dwcmshc: Prevent illegal clock reduction in HS200/HS400 mode
+To: stable@vger.kernel.org
+Cc: Shawn Lin <shawn.lin@rock-chips.com>, Sebastian Reichel <sebastian.reichel@collabora.com>, Yifeng Zhao <yifeng.zhao@rock-chips.com>, Ulf Hansson <ulf.hansson@linaro.org>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260128182615.2660161-2-sashal@kernel.org>
+
+From: Shawn Lin <shawn.lin@rock-chips.com>
+
+[ Upstream commit 3009738a855cf938bbfc9078bec725031ae623a4 ]
+
+When operating in HS200 or HS400 timing modes, reducing the clock frequency
+below 52MHz will lead to link broken as the Rockchip DWC MSHC controller
+requires maintaining a minimum clock of 52MHz in these modes.
+
+Add a check to prevent illegal clock reduction through debugfs:
+
+root@debian:/# echo 50000000 > /sys/kernel/debug/mmc0/clock
+root@debian:/# [ 30.090146] mmc0: running CQE recovery
+mmc0: cqhci: Failed to halt
+mmc0: cqhci: spurious TCN for tag 0
+WARNING: drivers/mmc/host/cqhci-core.c:797 at cqhci_irq+0x254/0x818, CPU#1: kworker/1:0H/24
+Modules linked in:
+CPU: 1 UID: 0 PID: 24 Comm: kworker/1:0H Not tainted 6.19.0-rc1-00001-g09db0998649d-dirty #204 PREEMPT
+Hardware name: Rockchip RK3588 EVB1 V10 Board (DT)
+Workqueue: kblockd blk_mq_run_work_fn
+pstate: 604000c9 (nZCv daIF +PAN -UAO -TCO -DIT -SSBS BTYPE=--)
+pc : cqhci_irq+0x254/0x818
+lr : cqhci_irq+0x254/0x818
+...
+
+Fixes: c6f361cba51c ("mmc: sdhci-of-dwcmshc: add support for rk3588")
+Cc: Sebastian Reichel <sebastian.reichel@collabora.com>
+Cc: Yifeng Zhao <yifeng.zhao@rock-chips.com>
+Signed-off-by: Shawn Lin <shawn.lin@rock-chips.com>
+Cc: stable@vger.kernel.org
+Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/mmc/host/sdhci-of-dwcmshc.c | 7 +++++++
+ 1 file changed, 7 insertions(+)
+
+--- a/drivers/mmc/host/sdhci-of-dwcmshc.c
++++ b/drivers/mmc/host/sdhci-of-dwcmshc.c
+@@ -236,6 +236,13 @@ static void dwcmshc_rk3568_set_clock(str
+ sdhci_writel(host, extra, reg);
+
+ if (clock <= 52000000) {
++ if (host->mmc->ios.timing == MMC_TIMING_MMC_HS200 ||
++ host->mmc->ios.timing == MMC_TIMING_MMC_HS400) {
++ dev_err(mmc_dev(host->mmc),
++ "Can't reduce the clock below 52MHz in HS200/HS400 mode");
++ return;
++ }
++
+ /*
+ * Disable DLL and reset both of sample and drive clock.
+ * The bypass bit and start bit need to be set if DLL is not locked.
--- /dev/null
+From stable+bounces-212657-greg=kroah.com@vger.kernel.org Wed Jan 28 19:29:28 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 28 Jan 2026 13:26:14 -0500
+Subject: mmc: sdhci-of-dwcmshc: Update DLL and pre-change delay for rockchip platform
+To: stable@vger.kernel.org
+Cc: Shawn Lin <shawn.lin@rock-chips.com>, Ulf Hansson <ulf.hansson@linaro.org>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260128182615.2660161-1-sashal@kernel.org>
+
+From: Shawn Lin <shawn.lin@rock-chips.com>
+
+[ Upstream commit b75a52b0dda353aeefb4830a320589a363f49579 ]
+
+For Rockchip platform, DLL bypass bit and start bit need to be set if
+DLL is not locked. And adjust pre-change delay to 0x3 for better signal
+test result.
+
+Signed-off-by: Shawn Lin <shawn.lin@rock-chips.com>
+Link: https://lore.kernel.org/r/1675298118-64243-2-git-send-email-shawn.lin@rock-chips.com
+Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
+Stable-dep-of: 3009738a855c ("mmc: sdhci-of-dwcmshc: Prevent illegal clock reduction in HS200/HS400 mode")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/mmc/host/sdhci-of-dwcmshc.c | 13 +++++++++----
+ 1 file changed, 9 insertions(+), 4 deletions(-)
+
+--- a/drivers/mmc/host/sdhci-of-dwcmshc.c
++++ b/drivers/mmc/host/sdhci-of-dwcmshc.c
+@@ -48,6 +48,7 @@
+ #define DWCMSHC_EMMC_DLL_RXCLK_SRCSEL 29
+ #define DWCMSHC_EMMC_DLL_START_POINT 16
+ #define DWCMSHC_EMMC_DLL_INC 8
++#define DWCMSHC_EMMC_DLL_BYPASS BIT(24)
+ #define DWCMSHC_EMMC_DLL_DLYENA BIT(27)
+ #define DLL_TXCLK_TAPNUM_DEFAULT 0x10
+ #define DLL_TXCLK_TAPNUM_90_DEGREES 0xA
+@@ -60,6 +61,7 @@
+ #define DLL_RXCLK_NO_INVERTER 1
+ #define DLL_RXCLK_INVERTER 0
+ #define DLL_CMDOUT_TAPNUM_90_DEGREES 0x8
++#define DLL_RXCLK_ORI_GATE BIT(31)
+ #define DLL_CMDOUT_TAPNUM_FROM_SW BIT(24)
+ #define DLL_CMDOUT_SRC_CLK_NEG BIT(28)
+ #define DLL_CMDOUT_EN_SRC_CLK_NEG BIT(29)
+@@ -234,9 +236,12 @@ static void dwcmshc_rk3568_set_clock(str
+ sdhci_writel(host, extra, reg);
+
+ if (clock <= 52000000) {
+- /* Disable DLL and reset both of sample and drive clock */
+- sdhci_writel(host, 0, DWCMSHC_EMMC_DLL_CTRL);
+- sdhci_writel(host, 0, DWCMSHC_EMMC_DLL_RXCLK);
++ /*
++ * Disable DLL and reset both of sample and drive clock.
++ * The bypass bit and start bit need to be set if DLL is not locked.
++ */
++ sdhci_writel(host, DWCMSHC_EMMC_DLL_BYPASS | DWCMSHC_EMMC_DLL_START, DWCMSHC_EMMC_DLL_CTRL);
++ sdhci_writel(host, DLL_RXCLK_ORI_GATE, DWCMSHC_EMMC_DLL_RXCLK);
+ sdhci_writel(host, 0, DWCMSHC_EMMC_DLL_TXCLK);
+ sdhci_writel(host, 0, DECMSHC_EMMC_DLL_CMDOUT);
+ /*
+@@ -279,7 +284,7 @@ static void dwcmshc_rk3568_set_clock(str
+ }
+
+ extra = 0x1 << 16 | /* tune clock stop en */
+- 0x2 << 17 | /* pre-change delay */
++ 0x3 << 17 | /* pre-change delay */
+ 0x3 << 19; /* post-change delay */
+ sdhci_writel(host, extra, dwc_priv->vendor_specific_area1 + DWCMSHC_EMMC_ATCTRL);
+
--- /dev/null
+From stable+bounces-210661-greg=kroah.com@vger.kernel.org Wed Jan 21 03:57:09 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 20 Jan 2026 21:56:57 -0500
+Subject: nvme-fc: rename free_ctrl callback to match name pattern
+To: stable@vger.kernel.org
+Cc: Daniel Wagner <dwagner@suse.de>, Christoph Hellwig <hch@lst.de>, Sagi Grimberg <sagi@grimberg.me>, Hannes Reinecke <hare@suse.de>, Keith Busch <kbusch@kernel.org>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260121025659.1157002-1-sashal@kernel.org>
+
+From: Daniel Wagner <dwagner@suse.de>
+
+[ Upstream commit 205fb5fa6fde1b5b426015eb1ff69f2ff25ef5bb ]
+
+Rename nvme_fc_nvme_ctrl_freed to nvme_fc_free_ctrl to match the name
+pattern for the callback.
+
+Reviewed-by: Christoph Hellwig <hch@lst.de>
+Reviewed-by: Sagi Grimberg <sagi@grimberg.me>
+Reviewed-by: Hannes Reinecke <hare@suse.de>
+Signed-off-by: Daniel Wagner <dwagner@suse.de>
+Signed-off-by: Keith Busch <kbusch@kernel.org>
+Stable-dep-of: 0edb475ac0a7 ("nvme: fix PCIe subsystem reset controller state transition")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/nvme/host/fc.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+--- a/drivers/nvme/host/fc.c
++++ b/drivers/nvme/host/fc.c
+@@ -2417,7 +2417,7 @@ nvme_fc_ctrl_get(struct nvme_fc_ctrl *ct
+ * controller. Called after last nvme_put_ctrl() call
+ */
+ static void
+-nvme_fc_nvme_ctrl_freed(struct nvme_ctrl *nctrl)
++nvme_fc_free_ctrl(struct nvme_ctrl *nctrl)
+ {
+ struct nvme_fc_ctrl *ctrl = to_fc_ctrl(nctrl);
+
+@@ -3362,7 +3362,7 @@ static const struct nvme_ctrl_ops nvme_f
+ .reg_read32 = nvmf_reg_read32,
+ .reg_read64 = nvmf_reg_read64,
+ .reg_write32 = nvmf_reg_write32,
+- .free_ctrl = nvme_fc_nvme_ctrl_freed,
++ .free_ctrl = nvme_fc_free_ctrl,
+ .submit_async_event = nvme_fc_submit_async_event,
+ .delete_ctrl = nvme_fc_delete_ctrl,
+ .get_address = nvmf_get_address,
--- /dev/null
+From stable+bounces-210663-greg=kroah.com@vger.kernel.org Wed Jan 21 03:57:51 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 20 Jan 2026 21:56:59 -0500
+Subject: nvme: fix PCIe subsystem reset controller state transition
+To: stable@vger.kernel.org
+Cc: Nilay Shroff <nilay@linux.ibm.com>, Daniel Wagner <dwagner@suse.de>, Keith Busch <kbusch@kernel.org>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260121025659.1157002-3-sashal@kernel.org>
+
+From: Nilay Shroff <nilay@linux.ibm.com>
+
+[ Upstream commit 0edb475ac0a7d153318a24d4dca175a270a5cc4f ]
+
+The commit d2fe192348f9 (“nvme: only allow entering LIVE from CONNECTING
+state”) disallows controller state transitions directly from RESETTING
+to LIVE. However, the NVMe PCIe subsystem reset path relies on this
+transition to recover the controller on PowerPC (PPC) systems.
+
+On PPC systems, issuing a subsystem reset causes a temporary loss of
+communication with the NVMe adapter. A subsequent PCIe MMIO read then
+triggers EEH recovery, which restores the PCIe link and brings the
+controller back online. For EEH recovery to proceed correctly, the
+controller must transition back to the LIVE state.
+
+Due to the changes introduced by commit d2fe192348f9 (“nvme: only allow
+entering LIVE from CONNECTING state”), the controller can no longer
+transition directly from RESETTING to LIVE. As a result, EEH recovery
+exits prematurely, leaving the controller stuck in the RESETTING state.
+
+Fix this by explicitly transitioning the controller state from RESETTING
+to CONNECTING and then to LIVE. This satisfies the updated state
+transition rules and allows the controller to be successfully recovered
+on PPC systems following a PCIe subsystem reset.
+
+Cc: stable@vger.kernel.org
+Fixes: d2fe192348f9 ("nvme: only allow entering LIVE from CONNECTING state")
+Reviewed-by: Daniel Wagner <dwagner@suse.de>
+Signed-off-by: Nilay Shroff <nilay@linux.ibm.com>
+Signed-off-by: Keith Busch <kbusch@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/nvme/host/pci.c | 5 ++++-
+ 1 file changed, 4 insertions(+), 1 deletion(-)
+
+--- a/drivers/nvme/host/pci.c
++++ b/drivers/nvme/host/pci.c
+@@ -1213,7 +1213,10 @@ static int nvme_pci_subsystem_reset(stru
+ }
+
+ writel(NVME_SUBSYS_RESET, dev->bar + NVME_REG_NSSR);
+- nvme_change_ctrl_state(ctrl, NVME_CTRL_LIVE);
++
++ if (!nvme_change_ctrl_state(ctrl, NVME_CTRL_CONNECTING) ||
++ !nvme_change_ctrl_state(ctrl, NVME_CTRL_LIVE))
++ goto unlock;
+
+ /*
+ * Read controller status to flush the previous write and trigger a
--- /dev/null
+From stable+bounces-210662-greg=kroah.com@vger.kernel.org Wed Jan 21 03:57:48 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 20 Jan 2026 21:56:58 -0500
+Subject: nvme-pci: do not directly handle subsys reset fallout
+To: stable@vger.kernel.org
+Cc: Keith Busch <kbusch@kernel.org>, Nilay Shroff <nilay@linux.ibm.com>, Christoph Hellwig <hch@lst.de>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260121025659.1157002-2-sashal@kernel.org>
+
+From: Keith Busch <kbusch@kernel.org>
+
+[ Upstream commit 210b1f6576e8b367907e7ff51ef425062e1468e4 ]
+
+Scheduling reset_work after a nvme subsystem reset is expected to fail
+on pcie, but this also prevents potential handling the platform's pcie
+services may provide that might successfully recovering the link without
+re-enumeration. Such examples include AER, DPC, and power's EEH.
+
+Provide a pci specific operation that safely initiates a subsystem
+reset, and instead of scheduling reset work, read back the status
+register to trigger a pcie read error.
+
+Since this only affects pci, the other fabrics drivers subscribe to a
+generic nvmf subsystem reset that is exactly the same as before. The
+loop fabric doesn't use it because nvmet doesn't support setting that
+property anyway.
+
+And since we're using the magic NSSR value in two places now, provide a
+symbolic define for it.
+
+Reported-by: Nilay Shroff <nilay@linux.ibm.com>
+Reviewed-by: Christoph Hellwig <hch@lst.de>
+Signed-off-by: Keith Busch <kbusch@kernel.org>
+Stable-dep-of: 0edb475ac0a7 ("nvme: fix PCIe subsystem reset controller state transition")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/nvme/host/fabrics.c | 15 +++++++++++++++
+ drivers/nvme/host/fabrics.h | 1 +
+ drivers/nvme/host/fc.c | 1 +
+ drivers/nvme/host/nvme.h | 14 +++-----------
+ drivers/nvme/host/pci.c | 36 ++++++++++++++++++++++++++++++++++++
+ drivers/nvme/host/rdma.c | 1 +
+ drivers/nvme/host/tcp.c | 1 +
+ include/linux/nvme.h | 3 +++
+ 8 files changed, 61 insertions(+), 11 deletions(-)
+
+--- a/drivers/nvme/host/fabrics.c
++++ b/drivers/nvme/host/fabrics.c
+@@ -253,6 +253,21 @@ int nvmf_reg_write32(struct nvme_ctrl *c
+ }
+ EXPORT_SYMBOL_GPL(nvmf_reg_write32);
+
++int nvmf_subsystem_reset(struct nvme_ctrl *ctrl)
++{
++ int ret;
++
++ if (!nvme_wait_reset(ctrl))
++ return -EBUSY;
++
++ ret = ctrl->ops->reg_write32(ctrl, NVME_REG_NSSR, NVME_SUBSYS_RESET);
++ if (ret)
++ return ret;
++
++ return nvme_try_sched_reset(ctrl);
++}
++EXPORT_SYMBOL_GPL(nvmf_subsystem_reset);
++
+ /**
+ * nvmf_log_connect_error() - Error-parsing-diagnostic print out function for
+ * connect() errors.
+--- a/drivers/nvme/host/fabrics.h
++++ b/drivers/nvme/host/fabrics.h
+@@ -199,6 +199,7 @@ static inline void nvmf_complete_timed_o
+ int nvmf_reg_read32(struct nvme_ctrl *ctrl, u32 off, u32 *val);
+ int nvmf_reg_read64(struct nvme_ctrl *ctrl, u32 off, u64 *val);
+ int nvmf_reg_write32(struct nvme_ctrl *ctrl, u32 off, u32 val);
++int nvmf_subsystem_reset(struct nvme_ctrl *ctrl);
+ int nvmf_connect_admin_queue(struct nvme_ctrl *ctrl);
+ int nvmf_connect_io_queue(struct nvme_ctrl *ctrl, u16 qid);
+ int nvmf_register_transport(struct nvmf_transport_ops *ops);
+--- a/drivers/nvme/host/fc.c
++++ b/drivers/nvme/host/fc.c
+@@ -3362,6 +3362,7 @@ static const struct nvme_ctrl_ops nvme_f
+ .reg_read32 = nvmf_reg_read32,
+ .reg_read64 = nvmf_reg_read64,
+ .reg_write32 = nvmf_reg_write32,
++ .subsystem_reset = nvmf_subsystem_reset,
+ .free_ctrl = nvme_fc_free_ctrl,
+ .submit_async_event = nvme_fc_submit_async_event,
+ .delete_ctrl = nvme_fc_delete_ctrl,
+--- a/drivers/nvme/host/nvme.h
++++ b/drivers/nvme/host/nvme.h
+@@ -538,6 +538,7 @@ struct nvme_ctrl_ops {
+ int (*reg_read64)(struct nvme_ctrl *ctrl, u32 off, u64 *val);
+ void (*free_ctrl)(struct nvme_ctrl *ctrl);
+ void (*submit_async_event)(struct nvme_ctrl *ctrl);
++ int (*subsystem_reset)(struct nvme_ctrl *ctrl);
+ void (*delete_ctrl)(struct nvme_ctrl *ctrl);
+ void (*stop_ctrl)(struct nvme_ctrl *ctrl);
+ int (*get_address)(struct nvme_ctrl *ctrl, char *buf, int size);
+@@ -636,18 +637,9 @@ int nvme_try_sched_reset(struct nvme_ctr
+
+ static inline int nvme_reset_subsystem(struct nvme_ctrl *ctrl)
+ {
+- int ret;
+-
+- if (!ctrl->subsystem)
++ if (!ctrl->subsystem || !ctrl->ops->subsystem_reset)
+ return -ENOTTY;
+- if (!nvme_wait_reset(ctrl))
+- return -EBUSY;
+-
+- ret = ctrl->ops->reg_write32(ctrl, NVME_REG_NSSR, 0x4E564D65);
+- if (ret)
+- return ret;
+-
+- return nvme_try_sched_reset(ctrl);
++ return ctrl->ops->subsystem_reset(ctrl);
+ }
+
+ /*
+--- a/drivers/nvme/host/pci.c
++++ b/drivers/nvme/host/pci.c
+@@ -1190,6 +1190,41 @@ static void nvme_pci_submit_async_event(
+ spin_unlock(&nvmeq->sq_lock);
+ }
+
++static int nvme_pci_subsystem_reset(struct nvme_ctrl *ctrl)
++{
++ struct nvme_dev *dev = to_nvme_dev(ctrl);
++ int ret = 0;
++
++ /*
++ * Taking the shutdown_lock ensures the BAR mapping is not being
++ * altered by reset_work. Holding this lock before the RESETTING state
++ * change, if successful, also ensures nvme_remove won't be able to
++ * proceed to iounmap until we're done.
++ */
++ mutex_lock(&dev->shutdown_lock);
++ if (!dev->bar_mapped_size) {
++ ret = -ENODEV;
++ goto unlock;
++ }
++
++ if (!nvme_change_ctrl_state(ctrl, NVME_CTRL_RESETTING)) {
++ ret = -EBUSY;
++ goto unlock;
++ }
++
++ writel(NVME_SUBSYS_RESET, dev->bar + NVME_REG_NSSR);
++ nvme_change_ctrl_state(ctrl, NVME_CTRL_LIVE);
++
++ /*
++ * Read controller status to flush the previous write and trigger a
++ * pcie read error.
++ */
++ readl(dev->bar + NVME_REG_CSTS);
++unlock:
++ mutex_unlock(&dev->shutdown_lock);
++ return ret;
++}
++
+ static int adapter_delete_queue(struct nvme_dev *dev, u8 opcode, u16 id)
+ {
+ struct nvme_command c = { };
+@@ -3033,6 +3068,7 @@ static const struct nvme_ctrl_ops nvme_p
+ .reg_read64 = nvme_pci_reg_read64,
+ .free_ctrl = nvme_pci_free_ctrl,
+ .submit_async_event = nvme_pci_submit_async_event,
++ .subsystem_reset = nvme_pci_subsystem_reset,
+ .get_address = nvme_pci_get_address,
+ .print_device_info = nvme_pci_print_device_info,
+ .supports_pci_p2pdma = nvme_pci_supports_pci_p2pdma,
+--- a/drivers/nvme/host/rdma.c
++++ b/drivers/nvme/host/rdma.c
+@@ -2256,6 +2256,7 @@ static const struct nvme_ctrl_ops nvme_r
+ .reg_read32 = nvmf_reg_read32,
+ .reg_read64 = nvmf_reg_read64,
+ .reg_write32 = nvmf_reg_write32,
++ .subsystem_reset = nvmf_subsystem_reset,
+ .free_ctrl = nvme_rdma_free_ctrl,
+ .submit_async_event = nvme_rdma_submit_async_event,
+ .delete_ctrl = nvme_rdma_delete_ctrl,
+--- a/drivers/nvme/host/tcp.c
++++ b/drivers/nvme/host/tcp.c
+@@ -2612,6 +2612,7 @@ static const struct nvme_ctrl_ops nvme_t
+ .reg_read32 = nvmf_reg_read32,
+ .reg_read64 = nvmf_reg_read64,
+ .reg_write32 = nvmf_reg_write32,
++ .subsystem_reset = nvmf_subsystem_reset,
+ .free_ctrl = nvme_tcp_free_ctrl,
+ .submit_async_event = nvme_tcp_submit_async_event,
+ .delete_ctrl = nvme_tcp_delete_ctrl,
+--- a/include/linux/nvme.h
++++ b/include/linux/nvme.h
+@@ -28,6 +28,9 @@
+
+ #define NVME_NSID_ALL 0xffffffff
+
++/* Special NSSR value, 'NVMe' */
++#define NVME_SUBSYS_RESET 0x4E564D65
++
+ enum nvme_subsys_type {
+ /* Referral to another discovery type target subsystem */
+ NVME_NQN_DISC = 1,
--- /dev/null
+From stable+bounces-210647-greg=kroah.com@vger.kernel.org Wed Jan 21 03:13:38 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 20 Jan 2026 21:13:31 -0500
+Subject: phy: phy-rockchip-inno-usb2: simplify phy clock handling
+To: stable@vger.kernel.org
+Cc: Sebastian Reichel <sebastian.reichel@collabora.com>, Vinod Koul <vkoul@kernel.org>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260121021333.1126769-1-sashal@kernel.org>
+
+From: Sebastian Reichel <sebastian.reichel@collabora.com>
+
+[ Upstream commit b43511233c6e34b9c0d9a55e41b078d10e7d9ea6 ]
+
+Simplify phyclk handling by using devm_clk_get_optional_enabled to
+acquire and enable the optional clock. This also fixes a resource
+leak in driver remove path and adds proper error handling.
+
+Signed-off-by: Sebastian Reichel <sebastian.reichel@collabora.com>
+Link: https://lore.kernel.org/r/20230522170324.61349-6-sebastian.reichel@collabora.com
+Signed-off-by: Vinod Koul <vkoul@kernel.org>
+Stable-dep-of: e07dea3de508 ("phy: rockchip: inno-usb2: Fix a double free bug in rockchip_usb2phy_probe()")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/phy/rockchip/phy-rockchip-inno-usb2.c | 17 +++++------------
+ 1 file changed, 5 insertions(+), 12 deletions(-)
+
+--- a/drivers/phy/rockchip/phy-rockchip-inno-usb2.c
++++ b/drivers/phy/rockchip/phy-rockchip-inno-usb2.c
+@@ -1273,18 +1273,16 @@ static int rockchip_usb2phy_probe(struct
+ return -EINVAL;
+ }
+
+- rphy->clk = of_clk_get_by_name(np, "phyclk");
+- if (!IS_ERR(rphy->clk)) {
+- clk_prepare_enable(rphy->clk);
+- } else {
+- dev_info(&pdev->dev, "no phyclk specified\n");
+- rphy->clk = NULL;
++ rphy->clk = devm_clk_get_optional_enabled(dev, "phyclk");
++ if (IS_ERR(rphy->clk)) {
++ return dev_err_probe(&pdev->dev, PTR_ERR(rphy->clk),
++ "failed to get phyclk\n");
+ }
+
+ ret = rockchip_usb2phy_clk480m_register(rphy);
+ if (ret) {
+ dev_err(dev, "failed to register 480m output clock\n");
+- goto disable_clks;
++ return ret;
+ }
+
+ index = 0;
+@@ -1347,11 +1345,6 @@ next_child:
+
+ put_child:
+ of_node_put(child_np);
+-disable_clks:
+- if (rphy->clk) {
+- clk_disable_unprepare(rphy->clk);
+- clk_put(rphy->clk);
+- }
+ return ret;
+ }
+
--- /dev/null
+From stable+bounces-210648-greg=kroah.com@vger.kernel.org Wed Jan 21 03:14:14 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 20 Jan 2026 21:13:32 -0500
+Subject: phy: phy-rockchip-inno-usb2: Use dev_err_probe() in the probe path
+To: stable@vger.kernel.org
+Cc: Dragan Simic <dsimic@manjaro.org>, Heiko Stuebner <heiko@sntech.de>, Vinod Koul <vkoul@kernel.org>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260121021333.1126769-2-sashal@kernel.org>
+
+From: Dragan Simic <dsimic@manjaro.org>
+
+[ Upstream commit 40452520850683f6771094ca218ff206d1fcb022 ]
+
+Improve error handling in the probe path by using function dev_err_probe()
+instead of function dev_err(), where appropriate.
+
+Signed-off-by: Dragan Simic <dsimic@manjaro.org>
+Reviewed-by: Heiko Stuebner <heiko@sntech.de>
+Link: https://lore.kernel.org/r/d4ccd9fc278fb46ea868406bf77811ee507f0e4e.1725524803.git.dsimic@manjaro.org
+Signed-off-by: Vinod Koul <vkoul@kernel.org>
+Stable-dep-of: e07dea3de508 ("phy: rockchip: inno-usb2: Fix a double free bug in rockchip_usb2phy_probe()")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/phy/rockchip/phy-rockchip-inno-usb2.c | 27 +++++++++-----------------
+ 1 file changed, 10 insertions(+), 17 deletions(-)
+
+--- a/drivers/phy/rockchip/phy-rockchip-inno-usb2.c
++++ b/drivers/phy/rockchip/phy-rockchip-inno-usb2.c
+@@ -380,11 +380,9 @@ static int rockchip_usb2phy_extcon_regis
+
+ if (of_property_read_bool(node, "extcon")) {
+ edev = extcon_get_edev_by_phandle(rphy->dev, 0);
+- if (IS_ERR(edev)) {
+- if (PTR_ERR(edev) != -EPROBE_DEFER)
+- dev_err(rphy->dev, "Invalid or missing extcon\n");
+- return PTR_ERR(edev);
+- }
++ if (IS_ERR(edev))
++ return dev_err_probe(rphy->dev, PTR_ERR(edev),
++ "invalid or missing extcon\n");
+ } else {
+ /* Initialize extcon device */
+ edev = devm_extcon_dev_allocate(rphy->dev,
+@@ -394,10 +392,9 @@ static int rockchip_usb2phy_extcon_regis
+ return -ENOMEM;
+
+ ret = devm_extcon_dev_register(rphy->dev, edev);
+- if (ret) {
+- dev_err(rphy->dev, "failed to register extcon device\n");
+- return ret;
+- }
++ if (ret)
++ return dev_err_probe(rphy->dev, ret,
++ "failed to register extcon device\n");
+ }
+
+ rphy->edev = edev;
+@@ -1280,10 +1277,8 @@ static int rockchip_usb2phy_probe(struct
+ }
+
+ ret = rockchip_usb2phy_clk480m_register(rphy);
+- if (ret) {
+- dev_err(dev, "failed to register 480m output clock\n");
+- return ret;
+- }
++ if (ret)
++ return dev_err_probe(dev, ret, "failed to register 480m output clock\n");
+
+ index = 0;
+ for_each_available_child_of_node(np, child_np) {
+@@ -1297,8 +1292,7 @@ static int rockchip_usb2phy_probe(struct
+
+ phy = devm_phy_create(dev, child_np, &rockchip_usb2phy_ops);
+ if (IS_ERR(phy)) {
+- dev_err_probe(dev, PTR_ERR(phy), "failed to create phy\n");
+- ret = PTR_ERR(phy);
++ ret = dev_err_probe(dev, PTR_ERR(phy), "failed to create phy\n");
+ goto put_child;
+ }
+
+@@ -1335,8 +1329,7 @@ next_child:
+ "rockchip_usb2phy",
+ rphy);
+ if (ret) {
+- dev_err(rphy->dev,
+- "failed to request usb2phy irq handle\n");
++ dev_err_probe(rphy->dev, ret, "failed to request usb2phy irq handle\n");
+ goto put_child;
+ }
+ }
--- /dev/null
+From stable+bounces-210649-greg=kroah.com@vger.kernel.org Wed Jan 21 03:13:42 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 20 Jan 2026 21:13:33 -0500
+Subject: phy: rockchip: inno-usb2: Fix a double free bug in rockchip_usb2phy_probe()
+To: stable@vger.kernel.org
+Cc: Wentao Liang <vulab@iscas.ac.cn>, Neil Armstrong <neil.armstrong@linaro.org>, Vinod Koul <vkoul@kernel.org>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260121021333.1126769-3-sashal@kernel.org>
+
+From: Wentao Liang <vulab@iscas.ac.cn>
+
+[ Upstream commit e07dea3de508cd6950c937cec42de7603190e1ca ]
+
+The for_each_available_child_of_node() calls of_node_put() to
+release child_np in each success loop. After breaking from the
+loop with the child_np has been released, the code will jump to
+the put_child label and will call the of_node_put() again if the
+devm_request_threaded_irq() fails. These cause a double free bug.
+
+Fix by returning directly to avoid the duplicate of_node_put().
+
+Fixes: ed2b5a8e6b98 ("phy: phy-rockchip-inno-usb2: support muxed interrupts")
+Cc: stable@vger.kernel.org
+Signed-off-by: Wentao Liang <vulab@iscas.ac.cn>
+Reviewed-by: Neil Armstrong <neil.armstrong@linaro.org>
+Link: https://patch.msgid.link/20260109154626.2452034-1-vulab@iscas.ac.cn
+Signed-off-by: Vinod Koul <vkoul@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/phy/rockchip/phy-rockchip-inno-usb2.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/phy/rockchip/phy-rockchip-inno-usb2.c
++++ b/drivers/phy/rockchip/phy-rockchip-inno-usb2.c
+@@ -1330,7 +1330,7 @@ next_child:
+ rphy);
+ if (ret) {
+ dev_err_probe(rphy->dev, ret, "failed to request usb2phy irq handle\n");
+- goto put_child;
++ return ret;
+ }
+ }
+
--- /dev/null
+From stable+bounces-212684-greg=kroah.com@vger.kernel.org Wed Jan 28 23:21:38 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 28 Jan 2026 17:20:33 -0500
+Subject: pmdomain: imx8m-blk-ctrl: Remove separate rst and clk mask for 8mq vpu
+To: stable@vger.kernel.org
+Cc: Ming Qian <ming.qian@oss.nxp.com>, Benjamin Gaignard <benjamin.gaignard@collabora.com>, Peng Fan <peng.fan@nxp.com>, Frank Li <Frank.Li@nxp.com>, Ulf Hansson <ulf.hansson@linaro.org>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260128222033.2800495-1-sashal@kernel.org>
+
+From: Ming Qian <ming.qian@oss.nxp.com>
+
+[ Upstream commit 3de49966499634454fd59e0e6fecd50baab7febd ]
+
+For i.MX8MQ platform, the ADB in the VPUMIX domain has no separate reset
+and clock enable bits, but is ungated and reset together with the VPUs.
+So we can't reset G1 or G2 separately, it may led to the system hang.
+Remove rst_mask and clk_mask of imx8mq_vpu_blk_ctl_domain_data.
+Let imx8mq_vpu_power_notifier() do really vpu reset.
+
+Fixes: 608d7c325e85 ("soc: imx: imx8m-blk-ctrl: add i.MX8MQ VPU blk-ctrl")
+Signed-off-by: Ming Qian <ming.qian@oss.nxp.com>
+Reviewed-by: Benjamin Gaignard <benjamin.gaignard@collabora.com>
+Reviewed-by: Peng Fan <peng.fan@nxp.com>
+Reviewed-by: Frank Li <Frank.Li@nxp.com>
+Cc: stable@vger.kernel.org
+Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/soc/imx/imx8m-blk-ctrl.c | 11 +++++++----
+ 1 file changed, 7 insertions(+), 4 deletions(-)
+
+--- a/drivers/soc/imx/imx8m-blk-ctrl.c
++++ b/drivers/soc/imx/imx8m-blk-ctrl.c
+@@ -810,22 +810,25 @@ static int imx8mq_vpu_power_notifier(str
+ return NOTIFY_OK;
+ }
+
++/*
++ * For i.MX8MQ, the ADB in the VPUMIX domain has no separate reset and clock
++ * enable bits, but is ungated and reset together with the VPUs.
++ * Resetting G1 or G2 separately may led to system hang.
++ * Remove the rst_mask and clk_mask from the domain data of G1 and G2,
++ * Let imx8mq_vpu_power_notifier() do really vpu reset.
++ */
+ static const struct imx8m_blk_ctrl_domain_data imx8mq_vpu_blk_ctl_domain_data[] = {
+ [IMX8MQ_VPUBLK_PD_G1] = {
+ .name = "vpublk-g1",
+ .clk_names = (const char *[]){ "g1", },
+ .num_clks = 1,
+ .gpc_name = "g1",
+- .rst_mask = BIT(1),
+- .clk_mask = BIT(1),
+ },
+ [IMX8MQ_VPUBLK_PD_G2] = {
+ .name = "vpublk-g2",
+ .clk_names = (const char *[]){ "g2", },
+ .num_clks = 1,
+ .gpc_name = "g2",
+- .rst_mask = BIT(0),
+- .clk_mask = BIT(0),
+ },
+ };
+
--- /dev/null
+From stable+bounces-211642-greg=kroah.com@vger.kernel.org Mon Jan 26 16:51:27 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 26 Jan 2026 10:51:19 -0500
+Subject: scsi: xen: scsiback: Fix potential memory leak in scsiback_remove()
+To: stable@vger.kernel.org
+Cc: Abdun Nihaal <nihaal@cse.iitm.ac.in>, Juergen Gross <jgross@suse.com>, "Martin K. Petersen" <martin.petersen@oracle.com>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260126155119.3323199-2-sashal@kernel.org>
+
+From: Abdun Nihaal <nihaal@cse.iitm.ac.in>
+
+[ Upstream commit 901a5f309daba412e2a30364d7ec1492fa11c32c ]
+
+Memory allocated for struct vscsiblk_info in scsiback_probe() is not
+freed in scsiback_remove() leading to potential memory leaks on remove,
+as well as in the scsiback_probe() error paths. Fix that by freeing it
+in scsiback_remove().
+
+Cc: stable@vger.kernel.org
+Fixes: d9d660f6e562 ("xen-scsiback: Add Xen PV SCSI backend driver")
+Signed-off-by: Abdun Nihaal <nihaal@cse.iitm.ac.in>
+Reviewed-by: Juergen Gross <jgross@suse.com>
+Link: https://patch.msgid.link/20251223063012.119035-1-nihaal@cse.iitm.ac.in
+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/xen/xen-scsiback.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/drivers/xen/xen-scsiback.c
++++ b/drivers/xen/xen-scsiback.c
+@@ -1261,6 +1261,7 @@ static void scsiback_remove(struct xenbu
+ gnttab_page_cache_shrink(&info->free_pages, 0);
+
+ dev_set_drvdata(&dev->dev, NULL);
++ kfree(info);
+ }
+
+ static int scsiback_probe(struct xenbus_device *dev,
drm-amdgpu-gfx10-fix-wptr-reset-in-kgq-init.patch
drm-amdgpu-gfx11-fix-wptr-reset-in-kgq-init.patch
gpio-rockchip-stop-calling-pinctrl-for-set_direction.patch
+mm-rmap-fix-two-comments-related-to-huge_pmd_unshare.patch
+arm64-dts-rockchip-remove-redundant-max-link-speed-from-nanopi-r4s.patch
+xen-make-remove-callback-of-xen-driver-void-returned.patch
+scsi-xen-scsiback-fix-potential-memory-leak-in-scsiback_remove.patch
+dmaengine-stm32-dmamux-fix-of-node-leak-on-route-allocation-failure.patch
+mm-page_alloc-prevent-pcp-corruption-with-smp-n.patch
+dmaengine-stm32-dmamux-fix-device-leak-on-route-allocation.patch
+mm-kmsan-fix-poisoning-of-high-order-non-compound-pages.patch
+xfs-set-max_agbno-to-allow-sparse-alloc-of-last-full-inode-chunk.patch
+pmdomain-imx8m-blk-ctrl-remove-separate-rst-and-clk-mask-for-8mq-vpu.patch
+ksmbd-smbd-fix-dma_unmap_sg-nents.patch
+mei-trace-treat-reg-parameter-as-string.patch
+arm64-fpsimd-signal-fix-restoration-of-sve-context.patch
+mmc-sdhci-of-dwcmshc-update-dll-and-pre-change-delay-for-rockchip-platform.patch
+mmc-sdhci-of-dwcmshc-prevent-illegal-clock-reduction-in-hs200-hs400-mode.patch
+alsa-scarlett2-fix-buffer-overflow-in-config-retrieval.patch
+iio-adc-exynos_adc-fix-of-populate-on-driver-rebind.patch
+iio-chemical-scd4x-fix-reported-channel-endianness.patch
+nvme-fc-rename-free_ctrl-callback-to-match-name-pattern.patch
+nvme-pci-do-not-directly-handle-subsys-reset-fallout.patch
+nvme-fix-pcie-subsystem-reset-controller-state-transition.patch
+phy-phy-rockchip-inno-usb2-simplify-phy-clock-handling.patch
+phy-phy-rockchip-inno-usb2-use-dev_err_probe-in-the-probe-path.patch
+phy-rockchip-inno-usb2-fix-a-double-free-bug-in-rockchip_usb2phy_probe.patch
+asoc-codecs-wsa881x-simplify-pdev-dev-in-probe.patch
+asoc-codecs-wsa881x-use-proper-shutdown-gpio-polarity.patch
+asoc-codecs-wsa881x-drop-unused-version-readout.patch
+asoc-codecs-wsa881x-fix-unnecessary-initialisation.patch
+asoc-codecs-wsa883x-fix-unnecessary-initialisation.patch
+x86-fpu-clear-xstate_bv-in-guest-xsave-state-whenever-xfd-1.patch
+team-move-team-device-type-change-at-the-end-of-team_port_add.patch
+wifi-mac80211-use-wiphy-work-for-sdata-work.patch
+wifi-mac80211-move-tdls-work-to-wiphy-work.patch
+genirq-irq_sim-initialize-work-context-pointers-properly.patch
--- /dev/null
+From black.hawk@163.com Tue Feb 3 07:09:19 2026
+From: Rahul Sharma <black.hawk@163.com>
+Date: Tue, 3 Feb 2026 14:08:48 +0800
+Subject: team: Move team device type change at the end of team_port_add
+To: gregkh@linuxfoundation.org, stable@vger.kernel.org
+Cc: linux-kernel@vger.kernel.org, "Nikola Z. Ivanov" <zlatistiv@gmail.com>, syzbot+a2a3b519de727b0f7903@syzkaller.appspotmail.com, Jiri Pirko <jiri@nvidia.com>, Jakub Kicinski <kuba@kernel.org>, Rahul Sharma <black.hawk@163.com>
+Message-ID: <20260203060848.1805797-1-black.hawk@163.com>
+
+From: "Nikola Z. Ivanov" <zlatistiv@gmail.com>
+
+[ Upstream commit 0ae9cfc454ea5ead5f3ddbdfe2e70270d8e2c8ef ]
+
+Attempting to add a port device that is already up will expectedly fail,
+but not before modifying the team device header_ops.
+
+In the case of the syzbot reproducer the gre0 device is
+already in state UP when it attempts to add it as a
+port device of team0, this fails but before that
+header_ops->create of team0 is changed from eth_header to ipgre_header
+in the call to team_dev_type_check_change.
+
+Later when we end up in ipgre_header() struct ip_tunnel* points to nonsense
+as the private data of the device still holds a struct team.
+
+Example sequence of iproute2 commands to reproduce the hang/BUG():
+ip link add dev team0 type team
+ip link add dev gre0 type gre
+ip link set dev gre0 up
+ip link set dev gre0 master team0
+ip link set dev team0 up
+ping -I team0 1.1.1.1
+
+Move team_dev_type_check_change down where all other checks have passed
+as it changes the dev type with no way to restore it in case
+one of the checks that follow it fail.
+
+Also make sure to preserve the origial mtu assignment:
+ - If port_dev is not the same type as dev, dev takes mtu from port_dev
+ - If port_dev is the same type as dev, port_dev takes mtu from dev
+
+This is done by adding a conditional before the call to dev_set_mtu
+to prevent it from assigning port_dev->mtu = dev->mtu and instead
+letting team_dev_type_check_change assign dev->mtu = port_dev->mtu.
+The conditional is needed because the patch moves the call to
+team_dev_type_check_change past dev_set_mtu.
+
+Testing:
+ - team device driver in-tree selftests
+ - Add/remove various devices as slaves of team device
+ - syzbot
+
+Reported-by: syzbot+a2a3b519de727b0f7903@syzkaller.appspotmail.com
+Closes: https://syzkaller.appspot.com/bug?extid=a2a3b519de727b0f7903
+Fixes: 1d76efe1577b ("team: add support for non-ethernet devices")
+Signed-off-by: Nikola Z. Ivanov <zlatistiv@gmail.com>
+Reviewed-by: Jiri Pirko <jiri@nvidia.com>
+Link: https://patch.msgid.link/20251122002027.695151-1-zlatistiv@gmail.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Rahul Sharma <black.hawk@163.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/net/team/team.c | 23 +++++++++++++++--------
+ 1 file changed, 15 insertions(+), 8 deletions(-)
+
+--- a/drivers/net/team/team.c
++++ b/drivers/net/team/team.c
+@@ -1186,10 +1186,6 @@ static int team_port_add(struct team *te
+ return -EPERM;
+ }
+
+- err = team_dev_type_check_change(dev, port_dev);
+- if (err)
+- return err;
+-
+ if (port_dev->flags & IFF_UP) {
+ NL_SET_ERR_MSG(extack, "Device is up. Set it down before adding it as a team port");
+ netdev_err(dev, "Device %s is up. Set it down before adding it as a team port\n",
+@@ -1207,10 +1203,16 @@ static int team_port_add(struct team *te
+ INIT_LIST_HEAD(&port->qom_list);
+
+ port->orig.mtu = port_dev->mtu;
+- err = dev_set_mtu(port_dev, dev->mtu);
+- if (err) {
+- netdev_dbg(dev, "Error %d calling dev_set_mtu\n", err);
+- goto err_set_mtu;
++ /*
++ * MTU assignment will be handled in team_dev_type_check_change
++ * if dev and port_dev are of different types
++ */
++ if (dev->type == port_dev->type) {
++ err = dev_set_mtu(port_dev, dev->mtu);
++ if (err) {
++ netdev_dbg(dev, "Error %d calling dev_set_mtu\n", err);
++ goto err_set_mtu;
++ }
+ }
+
+ memcpy(port->orig.dev_addr, port_dev->dev_addr, port_dev->addr_len);
+@@ -1285,6 +1287,10 @@ static int team_port_add(struct team *te
+ }
+ }
+
++ err = team_dev_type_check_change(dev, port_dev);
++ if (err)
++ goto err_set_dev_type;
++
+ if (dev->flags & IFF_UP) {
+ netif_addr_lock_bh(dev);
+ dev_uc_sync_multiple(port_dev, dev);
+@@ -1303,6 +1309,7 @@ static int team_port_add(struct team *te
+
+ return 0;
+
++err_set_dev_type:
+ err_set_slave_promisc:
+ __team_option_inst_del_port(team, port);
+
--- /dev/null
+From stable+bounces-213087-greg=kroah.com@vger.kernel.org Mon Feb 2 17:54:07 2026
+From: "Hanne-Lotta Mäenpää" <hannelotta@gmail.com>
+Date: Mon, 2 Feb 2026 18:49:24 +0200
+Subject: wifi: mac80211: move TDLS work to wiphy work
+To: stable@vger.kernel.org
+Cc: johannes@sipsolutions.net, linux-wireless@vger.kernel.org, linux-kernel@vger.kernel.org, "Johannes Berg" <johannes.berg@intel.com>, "Emmanuel Grumbach" <emmanuel.grumbach@intel.com>, "Hanne-Lotta Mäenpää" <hannelotta@gmail.com>
+Message-ID: <20260202164924.215621-2-hannelotta@gmail.com>
+
+From: Johannes Berg <johannes.berg@intel.com>
+
+[ Upstream commit 777b26002b73127e81643d9286fadf3d41e0e477 ]
+
+Again, to have the wiphy locked for it.
+
+Reviewed-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
+Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+[ Summary of conflict resolutions:
+ - In mlme.c, move only tdls_peer_del_work
+ to wiphy work, and none the other works ]
+Signed-off-by: Hanne-Lotta Mäenpää <hannelotta@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/mac80211/ieee80211_i.h | 4 ++--
+ net/mac80211/mlme.c | 7 ++++---
+ net/mac80211/tdls.c | 11 ++++++-----
+ 3 files changed, 12 insertions(+), 10 deletions(-)
+
+--- a/net/mac80211/ieee80211_i.h
++++ b/net/mac80211/ieee80211_i.h
+@@ -531,7 +531,7 @@ struct ieee80211_if_managed {
+
+ /* TDLS support */
+ u8 tdls_peer[ETH_ALEN] __aligned(2);
+- struct delayed_work tdls_peer_del_work;
++ struct wiphy_delayed_work tdls_peer_del_work;
+ struct sk_buff *orig_teardown_skb; /* The original teardown skb */
+ struct sk_buff *teardown_skb; /* A copy to send through the AP */
+ spinlock_t teardown_lock; /* To lock changing teardown_skb */
+@@ -2525,7 +2525,7 @@ int ieee80211_tdls_mgmt(struct wiphy *wi
+ size_t extra_ies_len);
+ int ieee80211_tdls_oper(struct wiphy *wiphy, struct net_device *dev,
+ const u8 *peer, enum nl80211_tdls_operation oper);
+-void ieee80211_tdls_peer_del_work(struct work_struct *wk);
++void ieee80211_tdls_peer_del_work(struct wiphy *wiphy, struct wiphy_work *wk);
+ int ieee80211_tdls_channel_switch(struct wiphy *wiphy, struct net_device *dev,
+ const u8 *addr, u8 oper_class,
+ struct cfg80211_chan_def *chandef);
+--- a/net/mac80211/mlme.c
++++ b/net/mac80211/mlme.c
+@@ -6517,8 +6517,8 @@ void ieee80211_sta_setup_sdata(struct ie
+ ieee80211_beacon_connection_loss_work);
+ INIT_WORK(&ifmgd->csa_connection_drop_work,
+ ieee80211_csa_connection_drop_work);
+- INIT_DELAYED_WORK(&ifmgd->tdls_peer_del_work,
+- ieee80211_tdls_peer_del_work);
++ wiphy_delayed_work_init(&ifmgd->tdls_peer_del_work,
++ ieee80211_tdls_peer_del_work);
+ timer_setup(&ifmgd->timer, ieee80211_sta_timer, 0);
+ timer_setup(&ifmgd->bcn_mon_timer, ieee80211_sta_bcn_mon_timer, 0);
+ timer_setup(&ifmgd->conn_mon_timer, ieee80211_sta_conn_mon_timer, 0);
+@@ -7524,7 +7524,8 @@ void ieee80211_mgd_stop(struct ieee80211
+ cancel_work_sync(&ifmgd->monitor_work);
+ cancel_work_sync(&ifmgd->beacon_connection_loss_work);
+ cancel_work_sync(&ifmgd->csa_connection_drop_work);
+- cancel_delayed_work_sync(&ifmgd->tdls_peer_del_work);
++ wiphy_delayed_work_cancel(sdata->local->hw.wiphy,
++ &ifmgd->tdls_peer_del_work);
+
+ sdata_lock(sdata);
+ if (ifmgd->assoc_data)
+--- a/net/mac80211/tdls.c
++++ b/net/mac80211/tdls.c
+@@ -21,7 +21,7 @@
+ /* give usermode some time for retries in setting up the TDLS session */
+ #define TDLS_PEER_SETUP_TIMEOUT (15 * HZ)
+
+-void ieee80211_tdls_peer_del_work(struct work_struct *wk)
++void ieee80211_tdls_peer_del_work(struct wiphy *wiphy, struct wiphy_work *wk)
+ {
+ struct ieee80211_sub_if_data *sdata;
+ struct ieee80211_local *local;
+@@ -1128,9 +1128,9 @@ ieee80211_tdls_mgmt_setup(struct wiphy *
+ return ret;
+ }
+
+- ieee80211_queue_delayed_work(&sdata->local->hw,
+- &sdata->u.mgd.tdls_peer_del_work,
+- TDLS_PEER_SETUP_TIMEOUT);
++ wiphy_delayed_work_queue(sdata->local->hw.wiphy,
++ &sdata->u.mgd.tdls_peer_del_work,
++ TDLS_PEER_SETUP_TIMEOUT);
+ return 0;
+
+ out_unlock:
+@@ -1427,7 +1427,8 @@ int ieee80211_tdls_oper(struct wiphy *wi
+ }
+
+ if (ret == 0 && ether_addr_equal(sdata->u.mgd.tdls_peer, peer)) {
+- cancel_delayed_work(&sdata->u.mgd.tdls_peer_del_work);
++ wiphy_delayed_work_cancel(sdata->local->hw.wiphy,
++ &sdata->u.mgd.tdls_peer_del_work);
+ eth_zero_addr(sdata->u.mgd.tdls_peer);
+ }
+
--- /dev/null
+From stable+bounces-213086-greg=kroah.com@vger.kernel.org Mon Feb 2 17:52:48 2026
+From: "Hanne-Lotta Mäenpää" <hannelotta@gmail.com>
+Date: Mon, 2 Feb 2026 18:49:23 +0200
+Subject: wifi: mac80211: use wiphy work for sdata->work
+To: stable@vger.kernel.org
+Cc: johannes@sipsolutions.net, linux-wireless@vger.kernel.org, linux-kernel@vger.kernel.org, "Johannes Berg" <johannes.berg@intel.com>, "Hanne-Lotta Mäenpää" <hannelotta@gmail.com>
+Message-ID: <20260202164924.215621-1-hannelotta@gmail.com>
+
+From: Johannes Berg <johannes.berg@intel.com>
+
+[ Upstream commit 16114496d684a3df4ce09f7c6b7557a8b2922795 ]
+
+We'll need this later to convert other works that might
+be cancelled from here, so convert this one first.
+
+Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+(cherry picked from commit 16114496d684a3df4ce09f7c6b7557a8b2922795)
+Signed-off-by: Hanne-Lotta Mäenpää <hannelotta@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/mac80211/ibss.c | 8 ++++----
+ net/mac80211/ieee80211_i.h | 2 +-
+ net/mac80211/iface.c | 10 +++++-----
+ net/mac80211/mesh.c | 10 +++++-----
+ net/mac80211/mesh_hwmp.c | 6 +++---
+ net/mac80211/mlme.c | 6 +++---
+ net/mac80211/ocb.c | 6 +++---
+ net/mac80211/rx.c | 2 +-
+ net/mac80211/scan.c | 2 +-
+ net/mac80211/status.c | 6 +++---
+ net/mac80211/util.c | 2 +-
+ 11 files changed, 30 insertions(+), 30 deletions(-)
+
+--- a/net/mac80211/ibss.c
++++ b/net/mac80211/ibss.c
+@@ -741,7 +741,7 @@ static void ieee80211_csa_connection_dro
+ skb_queue_purge(&sdata->skb_queue);
+
+ /* trigger a scan to find another IBSS network to join */
+- ieee80211_queue_work(&sdata->local->hw, &sdata->work);
++ wiphy_work_queue(sdata->local->hw.wiphy, &sdata->work);
+
+ sdata_unlock(sdata);
+ }
+@@ -1242,7 +1242,7 @@ void ieee80211_ibss_rx_no_sta(struct iee
+ spin_lock(&ifibss->incomplete_lock);
+ list_add(&sta->list, &ifibss->incomplete_stations);
+ spin_unlock(&ifibss->incomplete_lock);
+- ieee80211_queue_work(&local->hw, &sdata->work);
++ wiphy_work_queue(local->hw.wiphy, &sdata->work);
+ }
+
+ static void ieee80211_ibss_sta_expire(struct ieee80211_sub_if_data *sdata)
+@@ -1721,7 +1721,7 @@ static void ieee80211_ibss_timer(struct
+ struct ieee80211_sub_if_data *sdata =
+ from_timer(sdata, t, u.ibss.timer);
+
+- ieee80211_queue_work(&sdata->local->hw, &sdata->work);
++ wiphy_work_queue(sdata->local->hw.wiphy, &sdata->work);
+ }
+
+ void ieee80211_ibss_setup_sdata(struct ieee80211_sub_if_data *sdata)
+@@ -1856,7 +1856,7 @@ int ieee80211_ibss_join(struct ieee80211
+ sdata->deflink.needed_rx_chains = local->rx_chains;
+ sdata->control_port_over_nl80211 = params->control_port_over_nl80211;
+
+- ieee80211_queue_work(&local->hw, &sdata->work);
++ wiphy_work_queue(local->hw.wiphy, &sdata->work);
+
+ return 0;
+ }
+--- a/net/mac80211/ieee80211_i.h
++++ b/net/mac80211/ieee80211_i.h
+@@ -1046,7 +1046,7 @@ struct ieee80211_sub_if_data {
+ /* used to reconfigure hardware SM PS */
+ struct work_struct recalc_smps;
+
+- struct work_struct work;
++ struct wiphy_work work;
+ struct sk_buff_head skb_queue;
+ struct sk_buff_head status_queue;
+
+--- a/net/mac80211/iface.c
++++ b/net/mac80211/iface.c
+@@ -43,7 +43,7 @@
+ * by either the RTNL, the iflist_mtx or RCU.
+ */
+
+-static void ieee80211_iface_work(struct work_struct *work);
++static void ieee80211_iface_work(struct wiphy *wiphy, struct wiphy_work *work);
+
+ bool __ieee80211_recalc_txpower(struct ieee80211_sub_if_data *sdata)
+ {
+@@ -650,7 +650,7 @@ static void ieee80211_do_stop(struct iee
+ RCU_INIT_POINTER(local->p2p_sdata, NULL);
+ fallthrough;
+ default:
+- cancel_work_sync(&sdata->work);
++ wiphy_work_cancel(sdata->local->hw.wiphy, &sdata->work);
+ /*
+ * When we get here, the interface is marked down.
+ * Free the remaining keys, if there are any
+@@ -1224,7 +1224,7 @@ int ieee80211_add_virtual_monitor(struct
+
+ skb_queue_head_init(&sdata->skb_queue);
+ skb_queue_head_init(&sdata->status_queue);
+- INIT_WORK(&sdata->work, ieee80211_iface_work);
++ wiphy_work_init(&sdata->work, ieee80211_iface_work);
+
+ return 0;
+ }
+@@ -1707,7 +1707,7 @@ static void ieee80211_iface_process_stat
+ }
+ }
+
+-static void ieee80211_iface_work(struct work_struct *work)
++static void ieee80211_iface_work(struct wiphy *wiphy, struct wiphy_work *work)
+ {
+ struct ieee80211_sub_if_data *sdata =
+ container_of(work, struct ieee80211_sub_if_data, work);
+@@ -1819,7 +1819,7 @@ static void ieee80211_setup_sdata(struct
+
+ skb_queue_head_init(&sdata->skb_queue);
+ skb_queue_head_init(&sdata->status_queue);
+- INIT_WORK(&sdata->work, ieee80211_iface_work);
++ wiphy_work_init(&sdata->work, ieee80211_iface_work);
+ INIT_WORK(&sdata->recalc_smps, ieee80211_recalc_smps_work);
+ INIT_WORK(&sdata->activate_links_work, ieee80211_activate_links_work);
+
+--- a/net/mac80211/mesh.c
++++ b/net/mac80211/mesh.c
+@@ -44,7 +44,7 @@ static void ieee80211_mesh_housekeeping_
+
+ set_bit(MESH_WORK_HOUSEKEEPING, &ifmsh->wrkq_flags);
+
+- ieee80211_queue_work(&local->hw, &sdata->work);
++ wiphy_work_queue(local->hw.wiphy, &sdata->work);
+ }
+
+ /**
+@@ -643,7 +643,7 @@ static void ieee80211_mesh_path_timer(st
+ struct ieee80211_sub_if_data *sdata =
+ from_timer(sdata, t, u.mesh.mesh_path_timer);
+
+- ieee80211_queue_work(&sdata->local->hw, &sdata->work);
++ wiphy_work_queue(sdata->local->hw.wiphy, &sdata->work);
+ }
+
+ static void ieee80211_mesh_path_root_timer(struct timer_list *t)
+@@ -654,7 +654,7 @@ static void ieee80211_mesh_path_root_tim
+
+ set_bit(MESH_WORK_ROOT, &ifmsh->wrkq_flags);
+
+- ieee80211_queue_work(&sdata->local->hw, &sdata->work);
++ wiphy_work_queue(sdata->local->hw.wiphy, &sdata->work);
+ }
+
+ void ieee80211_mesh_root_setup(struct ieee80211_if_mesh *ifmsh)
+@@ -1018,7 +1018,7 @@ void ieee80211_mbss_info_change_notify(s
+ for_each_set_bit(bit, &bits, sizeof(changed) * BITS_PER_BYTE)
+ set_bit(bit, &ifmsh->mbss_changed);
+ set_bit(MESH_WORK_MBSS_CHANGED, &ifmsh->wrkq_flags);
+- ieee80211_queue_work(&sdata->local->hw, &sdata->work);
++ wiphy_work_queue(sdata->local->hw.wiphy, &sdata->work);
+ }
+
+ int ieee80211_start_mesh(struct ieee80211_sub_if_data *sdata)
+@@ -1043,7 +1043,7 @@ int ieee80211_start_mesh(struct ieee8021
+ ifmsh->sync_offset_clockdrift_max = 0;
+ set_bit(MESH_WORK_HOUSEKEEPING, &ifmsh->wrkq_flags);
+ ieee80211_mesh_root_setup(ifmsh);
+- ieee80211_queue_work(&local->hw, &sdata->work);
++ wiphy_work_queue(local->hw.wiphy, &sdata->work);
+ sdata->vif.bss_conf.ht_operation_mode =
+ ifmsh->mshcfg.ht_opmode;
+ sdata->vif.bss_conf.enable_beacon = true;
+--- a/net/mac80211/mesh_hwmp.c
++++ b/net/mac80211/mesh_hwmp.c
+@@ -1,7 +1,7 @@
+ // SPDX-License-Identifier: GPL-2.0-only
+ /*
+ * Copyright (c) 2008, 2009 open80211s Ltd.
+- * Copyright (C) 2019, 2021-2022 Intel Corporation
++ * Copyright (C) 2019, 2021-2023 Intel Corporation
+ * Author: Luis Carlos Cobo <luisca@cozybit.com>
+ */
+
+@@ -1025,14 +1025,14 @@ static void mesh_queue_preq(struct mesh_
+ spin_unlock_bh(&ifmsh->mesh_preq_queue_lock);
+
+ if (time_after(jiffies, ifmsh->last_preq + min_preq_int_jiff(sdata)))
+- ieee80211_queue_work(&sdata->local->hw, &sdata->work);
++ wiphy_work_queue(sdata->local->hw.wiphy, &sdata->work);
+
+ else if (time_before(jiffies, ifmsh->last_preq)) {
+ /* avoid long wait if did not send preqs for a long time
+ * and jiffies wrapped around
+ */
+ ifmsh->last_preq = jiffies - min_preq_int_jiff(sdata) - 1;
+- ieee80211_queue_work(&sdata->local->hw, &sdata->work);
++ wiphy_work_queue(sdata->local->hw.wiphy, &sdata->work);
+ } else
+ mod_timer(&ifmsh->mesh_path_timer, ifmsh->last_preq +
+ min_preq_int_jiff(sdata));
+--- a/net/mac80211/mlme.c
++++ b/net/mac80211/mlme.c
+@@ -3168,7 +3168,7 @@ void ieee80211_sta_tx_notify(struct ieee
+ sdata->u.mgd.probe_send_count = 0;
+ else
+ sdata->u.mgd.nullfunc_failed = true;
+- ieee80211_queue_work(&sdata->local->hw, &sdata->work);
++ wiphy_work_queue(sdata->local->hw.wiphy, &sdata->work);
+ }
+
+ static void ieee80211_mlme_send_probe_req(struct ieee80211_sub_if_data *sdata,
+@@ -6031,7 +6031,7 @@ static void ieee80211_sta_timer(struct t
+ struct ieee80211_sub_if_data *sdata =
+ from_timer(sdata, t, u.mgd.timer);
+
+- ieee80211_queue_work(&sdata->local->hw, &sdata->work);
++ wiphy_work_queue(sdata->local->hw.wiphy, &sdata->work);
+ }
+
+ void ieee80211_sta_connection_lost(struct ieee80211_sub_if_data *sdata,
+@@ -6175,7 +6175,7 @@ void ieee80211_mgd_conn_tx_status(struct
+ sdata->u.mgd.status_acked = acked;
+ sdata->u.mgd.status_received = true;
+
+- ieee80211_queue_work(&local->hw, &sdata->work);
++ wiphy_work_queue(local->hw.wiphy, &sdata->work);
+ }
+
+ void ieee80211_sta_work(struct ieee80211_sub_if_data *sdata)
+--- a/net/mac80211/ocb.c
++++ b/net/mac80211/ocb.c
+@@ -81,7 +81,7 @@ void ieee80211_ocb_rx_no_sta(struct ieee
+ spin_lock(&ifocb->incomplete_lock);
+ list_add(&sta->list, &ifocb->incomplete_stations);
+ spin_unlock(&ifocb->incomplete_lock);
+- ieee80211_queue_work(&local->hw, &sdata->work);
++ wiphy_work_queue(local->hw.wiphy, &sdata->work);
+ }
+
+ static struct sta_info *ieee80211_ocb_finish_sta(struct sta_info *sta)
+@@ -157,7 +157,7 @@ static void ieee80211_ocb_housekeeping_t
+
+ set_bit(OCB_WORK_HOUSEKEEPING, &ifocb->wrkq_flags);
+
+- ieee80211_queue_work(&local->hw, &sdata->work);
++ wiphy_work_queue(local->hw.wiphy, &sdata->work);
+ }
+
+ void ieee80211_ocb_setup_sdata(struct ieee80211_sub_if_data *sdata)
+@@ -197,7 +197,7 @@ int ieee80211_ocb_join(struct ieee80211_
+ ifocb->joined = true;
+
+ set_bit(OCB_WORK_HOUSEKEEPING, &ifocb->wrkq_flags);
+- ieee80211_queue_work(&local->hw, &sdata->work);
++ wiphy_work_queue(local->hw.wiphy, &sdata->work);
+
+ netif_carrier_on(sdata->dev);
+ return 0;
+--- a/net/mac80211/rx.c
++++ b/net/mac80211/rx.c
+@@ -229,7 +229,7 @@ static void __ieee80211_queue_skb_to_ifa
+ }
+
+ skb_queue_tail(&sdata->skb_queue, skb);
+- ieee80211_queue_work(&sdata->local->hw, &sdata->work);
++ wiphy_work_queue(sdata->local->hw.wiphy, &sdata->work);
+ if (sta)
+ sta->deflink.rx_stats.packets++;
+ }
+--- a/net/mac80211/scan.c
++++ b/net/mac80211/scan.c
+@@ -503,7 +503,7 @@ static void __ieee80211_scan_completed(s
+ */
+ list_for_each_entry_rcu(sdata, &local->interfaces, list) {
+ if (ieee80211_sdata_running(sdata))
+- ieee80211_queue_work(&sdata->local->hw, &sdata->work);
++ wiphy_work_queue(sdata->local->hw.wiphy, &sdata->work);
+ }
+
+ if (was_scanning)
+--- a/net/mac80211/status.c
++++ b/net/mac80211/status.c
+@@ -5,7 +5,7 @@
+ * Copyright 2006-2007 Jiri Benc <jbenc@suse.cz>
+ * Copyright 2008-2010 Johannes Berg <johannes@sipsolutions.net>
+ * Copyright 2013-2014 Intel Mobile Communications GmbH
+- * Copyright 2021-2022 Intel Corporation
++ * Copyright 2021-2023 Intel Corporation
+ */
+
+ #include <linux/export.h>
+@@ -747,8 +747,8 @@ static void ieee80211_report_used_skb(st
+ if (qskb) {
+ skb_queue_tail(&sdata->status_queue,
+ qskb);
+- ieee80211_queue_work(&local->hw,
+- &sdata->work);
++ wiphy_work_queue(local->hw.wiphy,
++ &sdata->work);
+ }
+ }
+ } else {
+--- a/net/mac80211/util.c
++++ b/net/mac80211/util.c
+@@ -2751,7 +2751,7 @@ int ieee80211_reconfig(struct ieee80211_
+
+ /* Requeue all works */
+ list_for_each_entry(sdata, &local->interfaces, list)
+- ieee80211_queue_work(&local->hw, &sdata->work);
++ wiphy_work_queue(local->hw.wiphy, &sdata->work);
+ }
+
+ ieee80211_wake_queues_by_reason(hw, IEEE80211_MAX_QUEUE_MAP,
--- /dev/null
+From stable+bounces-210370-greg=kroah.com@vger.kernel.org Mon Jan 19 17:01:11 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 19 Jan 2026 11:00:09 -0500
+Subject: x86/fpu: Clear XSTATE_BV[i] in guest XSAVE state whenever XFD[i]=1
+To: stable@vger.kernel.org
+Cc: Sean Christopherson <seanjc@google.com>, Paolo Bonzini <pbonzini@redhat.com>, Binbin Wu <binbin.wu@linux.intel.com>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260119160009.3069587-1-sashal@kernel.org>
+
+From: Sean Christopherson <seanjc@google.com>
+
+[ Upstream commit b45f721775947a84996deb5c661602254ce25ce6 ]
+
+When loading guest XSAVE state via KVM_SET_XSAVE, and when updating XFD in
+response to a guest WRMSR, clear XFD-disabled features in the saved (or to
+be restored) XSTATE_BV to ensure KVM doesn't attempt to load state for
+features that are disabled via the guest's XFD. Because the kernel
+executes XRSTOR with the guest's XFD, saving XSTATE_BV[i]=1 with XFD[i]=1
+will cause XRSTOR to #NM and panic the kernel.
+
+E.g. if fpu_update_guest_xfd() sets XFD without clearing XSTATE_BV:
+
+ ------------[ cut here ]------------
+ WARNING: arch/x86/kernel/traps.c:1524 at exc_device_not_available+0x101/0x110, CPU#29: amx_test/848
+ Modules linked in: kvm_intel kvm irqbypass
+ CPU: 29 UID: 1000 PID: 848 Comm: amx_test Not tainted 6.19.0-rc2-ffa07f7fd437-x86_amx_nm_xfd_non_init-vm #171 NONE
+ Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 0.0.0 02/06/2015
+ RIP: 0010:exc_device_not_available+0x101/0x110
+ Call Trace:
+ <TASK>
+ asm_exc_device_not_available+0x1a/0x20
+ RIP: 0010:restore_fpregs_from_fpstate+0x36/0x90
+ switch_fpu_return+0x4a/0xb0
+ kvm_arch_vcpu_ioctl_run+0x1245/0x1e40 [kvm]
+ kvm_vcpu_ioctl+0x2c3/0x8f0 [kvm]
+ __x64_sys_ioctl+0x8f/0xd0
+ do_syscall_64+0x62/0x940
+ entry_SYSCALL_64_after_hwframe+0x4b/0x53
+ </TASK>
+ ---[ end trace 0000000000000000 ]---
+
+This can happen if the guest executes WRMSR(MSR_IA32_XFD) to set XFD[18] = 1,
+and a host IRQ triggers kernel_fpu_begin() prior to the vmexit handler's
+call to fpu_update_guest_xfd().
+
+and if userspace stuffs XSTATE_BV[i]=1 via KVM_SET_XSAVE:
+
+ ------------[ cut here ]------------
+ WARNING: arch/x86/kernel/traps.c:1524 at exc_device_not_available+0x101/0x110, CPU#14: amx_test/867
+ Modules linked in: kvm_intel kvm irqbypass
+ CPU: 14 UID: 1000 PID: 867 Comm: amx_test Not tainted 6.19.0-rc2-2dace9faccd6-x86_amx_nm_xfd_non_init-vm #168 NONE
+ Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 0.0.0 02/06/2015
+ RIP: 0010:exc_device_not_available+0x101/0x110
+ Call Trace:
+ <TASK>
+ asm_exc_device_not_available+0x1a/0x20
+ RIP: 0010:restore_fpregs_from_fpstate+0x36/0x90
+ fpu_swap_kvm_fpstate+0x6b/0x120
+ kvm_load_guest_fpu+0x30/0x80 [kvm]
+ kvm_arch_vcpu_ioctl_run+0x85/0x1e40 [kvm]
+ kvm_vcpu_ioctl+0x2c3/0x8f0 [kvm]
+ __x64_sys_ioctl+0x8f/0xd0
+ do_syscall_64+0x62/0x940
+ entry_SYSCALL_64_after_hwframe+0x4b/0x53
+ </TASK>
+ ---[ end trace 0000000000000000 ]---
+
+The new behavior is consistent with the AMX architecture. Per Intel's SDM,
+XSAVE saves XSTATE_BV as '0' for components that are disabled via XFD
+(and non-compacted XSAVE saves the initial configuration of the state
+component):
+
+ If XSAVE, XSAVEC, XSAVEOPT, or XSAVES is saving the state component i,
+ the instruction does not generate #NM when XCR0[i] = IA32_XFD[i] = 1;
+ instead, it operates as if XINUSE[i] = 0 (and the state component was
+ in its initial state): it saves bit i of XSTATE_BV field of the XSAVE
+ header as 0; in addition, XSAVE saves the initial configuration of the
+ state component (the other instructions do not save state component i).
+
+Alternatively, KVM could always do XRSTOR with XFD=0, e.g. by using
+a constant XFD based on the set of enabled features when XSAVEing for
+a struct fpu_guest. However, having XSTATE_BV[i]=1 for XFD-disabled
+features can only happen in the above interrupt case, or in similar
+scenarios involving preemption on preemptible kernels, because
+fpu_swap_kvm_fpstate()'s call to save_fpregs_to_fpstate() saves the
+outgoing FPU state with the current XFD; and that is (on all but the
+first WRMSR to XFD) the guest XFD.
+
+Therefore, XFD can only go out of sync with XSTATE_BV in the above
+interrupt case, or in similar scenarios involving preemption on
+preemptible kernels, and it we can consider it (de facto) part of KVM
+ABI that KVM_GET_XSAVE returns XSTATE_BV[i]=0 for XFD-disabled features.
+
+Reported-by: Paolo Bonzini <pbonzini@redhat.com>
+Cc: stable@vger.kernel.org
+Fixes: 820a6ee944e7 ("kvm: x86: Add emulation for IA32_XFD", 2022-01-14)
+Signed-off-by: Sean Christopherson <seanjc@google.com>
+[Move clearing of XSTATE_BV from fpu_copy_uabi_to_guest_fpstate
+ to kvm_vcpu_ioctl_x86_set_xsave. - Paolo]
+Reviewed-by: Binbin Wu <binbin.wu@linux.intel.com>
+Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/x86/kernel/fpu/core.c | 32 +++++++++++++++++++++++++++++---
+ arch/x86/kvm/x86.c | 9 +++++++++
+ 2 files changed, 38 insertions(+), 3 deletions(-)
+
+--- a/arch/x86/kernel/fpu/core.c
++++ b/arch/x86/kernel/fpu/core.c
+@@ -294,10 +294,29 @@ EXPORT_SYMBOL_GPL(fpu_enable_guest_xfd_f
+ #ifdef CONFIG_X86_64
+ void fpu_update_guest_xfd(struct fpu_guest *guest_fpu, u64 xfd)
+ {
++ struct fpstate *fpstate = guest_fpu->fpstate;
++
+ fpregs_lock();
+- guest_fpu->fpstate->xfd = xfd;
+- if (guest_fpu->fpstate->in_use)
+- xfd_update_state(guest_fpu->fpstate);
++
++ /*
++ * KVM's guest ABI is that setting XFD[i]=1 *can* immediately revert the
++ * save state to its initial configuration. Likewise, KVM_GET_XSAVE does
++ * the same as XSAVE and returns XSTATE_BV[i]=0 whenever XFD[i]=1.
++ *
++ * If the guest's FPU state is in hardware, just update XFD: the XSAVE
++ * in fpu_swap_kvm_fpstate will clear XSTATE_BV[i] whenever XFD[i]=1.
++ *
++ * If however the guest's FPU state is NOT resident in hardware, clear
++ * disabled components in XSTATE_BV now, or a subsequent XRSTOR will
++ * attempt to load disabled components and generate #NM _in the host_.
++ */
++ if (xfd && test_thread_flag(TIF_NEED_FPU_LOAD))
++ fpstate->regs.xsave.header.xfeatures &= ~xfd;
++
++ fpstate->xfd = xfd;
++ if (fpstate->in_use)
++ xfd_update_state(fpstate);
++
+ fpregs_unlock();
+ }
+ EXPORT_SYMBOL_GPL(fpu_update_guest_xfd);
+@@ -406,6 +425,13 @@ int fpu_copy_uabi_to_guest_fpstate(struc
+ return -EINVAL;
+
+ /*
++ * Disabled features must be in their initial state, otherwise XRSTOR
++ * causes an exception.
++ */
++ if (WARN_ON_ONCE(ustate->xsave.header.xfeatures & kstate->xfd))
++ return -EINVAL;
++
++ /*
+ * Nullify @vpkru to preserve its current value if PKRU's bit isn't set
+ * in the header. KVM's odd ABI is to leave PKRU untouched in this
+ * case (all other components are eventually re-initialized).
+--- a/arch/x86/kvm/x86.c
++++ b/arch/x86/kvm/x86.c
+@@ -5341,9 +5341,18 @@ static void kvm_vcpu_ioctl_x86_get_xsave
+ static int kvm_vcpu_ioctl_x86_set_xsave(struct kvm_vcpu *vcpu,
+ struct kvm_xsave *guest_xsave)
+ {
++ union fpregs_state *xstate = (union fpregs_state *)guest_xsave->region;
++
+ if (fpstate_is_confidential(&vcpu->arch.guest_fpu))
+ return 0;
+
++ /*
++ * For backwards compatibility, do not expect disabled features to be in
++ * their initial state. XSTATE_BV[i] must still be cleared whenever
++ * XFD[i]=1, or XRSTOR would cause a #NM.
++ */
++ xstate->xsave.header.xfeatures &= ~vcpu->arch.guest_fpu.fpstate->xfd;
++
+ return fpu_copy_uabi_to_guest_fpstate(&vcpu->arch.guest_fpu,
+ guest_xsave->region,
+ kvm_caps.supported_xcr0,
--- /dev/null
+From stable+bounces-211641-greg=kroah.com@vger.kernel.org Mon Jan 26 16:51:25 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 26 Jan 2026 10:51:18 -0500
+Subject: xen: make remove callback of xen driver void returned
+To: stable@vger.kernel.org
+Cc: Dawei Li <set_pte_at@outlook.com>, Juergen Gross <jgross@suse.com>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260126155119.3323199-1-sashal@kernel.org>
+
+From: Dawei Li <set_pte_at@outlook.com>
+
+[ Upstream commit 7cffcade57a429667447c4f41d8414bbcf1b3aaa ]
+
+Since commit fc7a6209d571 ("bus: Make remove callback return void")
+forces bus_type::remove be void-returned, it doesn't make much sense for
+any bus based driver implementing remove callbalk to return non-void to
+its caller.
+
+This change is for xen bus based drivers.
+
+Acked-by: Juergen Gross <jgross@suse.com>
+Signed-off-by: Dawei Li <set_pte_at@outlook.com>
+Link: https://lore.kernel.org/r/TYCP286MB23238119AB4DF190997075C9CAE39@TYCP286MB2323.JPNP286.PROD.OUTLOOK.COM
+Signed-off-by: Juergen Gross <jgross@suse.com>
+Stable-dep-of: 901a5f309dab ("scsi: xen: scsiback: Fix potential memory leak in scsiback_remove()")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/block/xen-blkback/xenbus.c | 4 +---
+ drivers/block/xen-blkfront.c | 3 +--
+ drivers/char/tpm/xen-tpmfront.c | 3 +--
+ drivers/gpu/drm/xen/xen_drm_front.c | 3 +--
+ drivers/input/misc/xen-kbdfront.c | 5 ++---
+ drivers/net/xen-netback/xenbus.c | 3 +--
+ drivers/net/xen-netfront.c | 4 +---
+ drivers/pci/xen-pcifront.c | 4 +---
+ drivers/scsi/xen-scsifront.c | 4 +---
+ drivers/tty/hvc/hvc_xen.c | 4 ++--
+ drivers/usb/host/xen-hcd.c | 4 +---
+ drivers/video/fbdev/xen-fbfront.c | 6 ++----
+ drivers/xen/pvcalls-back.c | 3 +--
+ drivers/xen/pvcalls-front.c | 3 +--
+ drivers/xen/xen-pciback/xenbus.c | 4 +---
+ drivers/xen/xen-scsiback.c | 4 +---
+ include/xen/xenbus.h | 2 +-
+ net/9p/trans_xen.c | 3 +--
+ sound/xen/xen_snd_front.c | 3 +--
+ 19 files changed, 22 insertions(+), 47 deletions(-)
+
+--- a/drivers/block/xen-blkback/xenbus.c
++++ b/drivers/block/xen-blkback/xenbus.c
+@@ -524,7 +524,7 @@ static int xen_vbd_create(struct xen_blk
+ return 0;
+ }
+
+-static int xen_blkbk_remove(struct xenbus_device *dev)
++static void xen_blkbk_remove(struct xenbus_device *dev)
+ {
+ struct backend_info *be = dev_get_drvdata(&dev->dev);
+
+@@ -547,8 +547,6 @@ static int xen_blkbk_remove(struct xenbu
+ /* Put the reference we set in xen_blkif_alloc(). */
+ xen_blkif_put(be->blkif);
+ }
+-
+- return 0;
+ }
+
+ int xen_blkbk_flush_diskcache(struct xenbus_transaction xbt,
+--- a/drivers/block/xen-blkfront.c
++++ b/drivers/block/xen-blkfront.c
+@@ -2469,7 +2469,7 @@ static void blkback_changed(struct xenbu
+ }
+ }
+
+-static int blkfront_remove(struct xenbus_device *xbdev)
++static void blkfront_remove(struct xenbus_device *xbdev)
+ {
+ struct blkfront_info *info = dev_get_drvdata(&xbdev->dev);
+
+@@ -2490,7 +2490,6 @@ static int blkfront_remove(struct xenbus
+ }
+
+ kfree(info);
+- return 0;
+ }
+
+ static int blkfront_is_ready(struct xenbus_device *dev)
+--- a/drivers/char/tpm/xen-tpmfront.c
++++ b/drivers/char/tpm/xen-tpmfront.c
+@@ -360,14 +360,13 @@ static int tpmfront_probe(struct xenbus_
+ return tpm_chip_register(priv->chip);
+ }
+
+-static int tpmfront_remove(struct xenbus_device *dev)
++static void tpmfront_remove(struct xenbus_device *dev)
+ {
+ struct tpm_chip *chip = dev_get_drvdata(&dev->dev);
+ struct tpm_private *priv = dev_get_drvdata(&chip->dev);
+ tpm_chip_unregister(chip);
+ ring_free(priv);
+ dev_set_drvdata(&chip->dev, NULL);
+- return 0;
+ }
+
+ static int tpmfront_resume(struct xenbus_device *dev)
+--- a/drivers/gpu/drm/xen/xen_drm_front.c
++++ b/drivers/gpu/drm/xen/xen_drm_front.c
+@@ -717,7 +717,7 @@ static int xen_drv_probe(struct xenbus_d
+ return xenbus_switch_state(xb_dev, XenbusStateInitialising);
+ }
+
+-static int xen_drv_remove(struct xenbus_device *dev)
++static void xen_drv_remove(struct xenbus_device *dev)
+ {
+ struct xen_drm_front_info *front_info = dev_get_drvdata(&dev->dev);
+ int to = 100;
+@@ -751,7 +751,6 @@ static int xen_drv_remove(struct xenbus_
+
+ xen_drm_drv_fini(front_info);
+ xenbus_frontend_closed(dev);
+- return 0;
+ }
+
+ static const struct xenbus_device_id xen_driver_ids[] = {
+--- a/drivers/input/misc/xen-kbdfront.c
++++ b/drivers/input/misc/xen-kbdfront.c
+@@ -51,7 +51,7 @@ module_param_array(ptr_size, int, NULL,
+ MODULE_PARM_DESC(ptr_size,
+ "Pointing device width, height in pixels (default 800,600)");
+
+-static int xenkbd_remove(struct xenbus_device *);
++static void xenkbd_remove(struct xenbus_device *);
+ static int xenkbd_connect_backend(struct xenbus_device *, struct xenkbd_info *);
+ static void xenkbd_disconnect_backend(struct xenkbd_info *);
+
+@@ -404,7 +404,7 @@ static int xenkbd_resume(struct xenbus_d
+ return xenkbd_connect_backend(dev, info);
+ }
+
+-static int xenkbd_remove(struct xenbus_device *dev)
++static void xenkbd_remove(struct xenbus_device *dev)
+ {
+ struct xenkbd_info *info = dev_get_drvdata(&dev->dev);
+
+@@ -417,7 +417,6 @@ static int xenkbd_remove(struct xenbus_d
+ input_unregister_device(info->mtouch);
+ free_page((unsigned long)info->page);
+ kfree(info);
+- return 0;
+ }
+
+ static int xenkbd_connect_backend(struct xenbus_device *dev,
+--- a/drivers/net/xen-netback/xenbus.c
++++ b/drivers/net/xen-netback/xenbus.c
+@@ -977,7 +977,7 @@ static int read_xenbus_vif_flags(struct
+ return 0;
+ }
+
+-static int netback_remove(struct xenbus_device *dev)
++static void netback_remove(struct xenbus_device *dev)
+ {
+ struct backend_info *be = dev_get_drvdata(&dev->dev);
+
+@@ -992,7 +992,6 @@ static int netback_remove(struct xenbus_
+ kfree(be->hotplug_script);
+ kfree(be);
+ dev_set_drvdata(&dev->dev, NULL);
+- return 0;
+ }
+
+ /*
+--- a/drivers/net/xen-netfront.c
++++ b/drivers/net/xen-netfront.c
+@@ -2652,7 +2652,7 @@ static void xennet_bus_close(struct xenb
+ } while (!ret);
+ }
+
+-static int xennet_remove(struct xenbus_device *dev)
++static void xennet_remove(struct xenbus_device *dev)
+ {
+ struct netfront_info *info = dev_get_drvdata(&dev->dev);
+
+@@ -2668,8 +2668,6 @@ static int xennet_remove(struct xenbus_d
+ rtnl_unlock();
+ }
+ xennet_free_netdev(info->netdev);
+-
+- return 0;
+ }
+
+ static const struct xenbus_device_id netfront_ids[] = {
+--- a/drivers/pci/xen-pcifront.c
++++ b/drivers/pci/xen-pcifront.c
+@@ -1055,14 +1055,12 @@ out:
+ return err;
+ }
+
+-static int pcifront_xenbus_remove(struct xenbus_device *xdev)
++static void pcifront_xenbus_remove(struct xenbus_device *xdev)
+ {
+ struct pcifront_device *pdev = dev_get_drvdata(&xdev->dev);
+
+ if (pdev)
+ free_pdev(pdev);
+-
+- return 0;
+ }
+
+ static const struct xenbus_device_id xenpci_ids[] = {
+--- a/drivers/scsi/xen-scsifront.c
++++ b/drivers/scsi/xen-scsifront.c
+@@ -995,7 +995,7 @@ static int scsifront_suspend(struct xenb
+ return err;
+ }
+
+-static int scsifront_remove(struct xenbus_device *dev)
++static void scsifront_remove(struct xenbus_device *dev)
+ {
+ struct vscsifrnt_info *info = dev_get_drvdata(&dev->dev);
+
+@@ -1011,8 +1011,6 @@ static int scsifront_remove(struct xenbu
+
+ scsifront_free_ring(info);
+ scsi_host_put(info->host);
+-
+- return 0;
+ }
+
+ static void scsifront_disconnect(struct vscsifrnt_info *info)
+--- a/drivers/tty/hvc/hvc_xen.c
++++ b/drivers/tty/hvc/hvc_xen.c
+@@ -420,9 +420,9 @@ static int xen_console_remove(struct xen
+ return 0;
+ }
+
+-static int xencons_remove(struct xenbus_device *dev)
++static void xencons_remove(struct xenbus_device *dev)
+ {
+- return xen_console_remove(dev_get_drvdata(&dev->dev));
++ xen_console_remove(dev_get_drvdata(&dev->dev));
+ }
+
+ static int xencons_connect_backend(struct xenbus_device *dev,
+--- a/drivers/usb/host/xen-hcd.c
++++ b/drivers/usb/host/xen-hcd.c
+@@ -1530,15 +1530,13 @@ static void xenhcd_backend_changed(struc
+ }
+ }
+
+-static int xenhcd_remove(struct xenbus_device *dev)
++static void xenhcd_remove(struct xenbus_device *dev)
+ {
+ struct xenhcd_info *info = dev_get_drvdata(&dev->dev);
+ struct usb_hcd *hcd = xenhcd_info_to_hcd(info);
+
+ xenhcd_destroy_rings(info);
+ usb_put_hcd(hcd);
+-
+- return 0;
+ }
+
+ static int xenhcd_probe(struct xenbus_device *dev,
+--- a/drivers/video/fbdev/xen-fbfront.c
++++ b/drivers/video/fbdev/xen-fbfront.c
+@@ -67,7 +67,7 @@ MODULE_PARM_DESC(video,
+ "Video memory size in MB, width, height in pixels (default 2,800,600)");
+
+ static void xenfb_make_preferred_console(void);
+-static int xenfb_remove(struct xenbus_device *);
++static void xenfb_remove(struct xenbus_device *);
+ static void xenfb_init_shared_page(struct xenfb_info *, struct fb_info *);
+ static int xenfb_connect_backend(struct xenbus_device *, struct xenfb_info *);
+ static void xenfb_disconnect_backend(struct xenfb_info *);
+@@ -527,7 +527,7 @@ static int xenfb_resume(struct xenbus_de
+ return xenfb_connect_backend(dev, info);
+ }
+
+-static int xenfb_remove(struct xenbus_device *dev)
++static void xenfb_remove(struct xenbus_device *dev)
+ {
+ struct xenfb_info *info = dev_get_drvdata(&dev->dev);
+
+@@ -542,8 +542,6 @@ static int xenfb_remove(struct xenbus_de
+ vfree(info->gfns);
+ vfree(info->fb);
+ kfree(info);
+-
+- return 0;
+ }
+
+ static unsigned long vmalloc_to_gfn(void *address)
+--- a/drivers/xen/pvcalls-back.c
++++ b/drivers/xen/pvcalls-back.c
+@@ -1180,9 +1180,8 @@ static void pvcalls_back_changed(struct
+ }
+ }
+
+-static int pvcalls_back_remove(struct xenbus_device *dev)
++static void pvcalls_back_remove(struct xenbus_device *dev)
+ {
+- return 0;
+ }
+
+ static int pvcalls_back_uevent(struct xenbus_device *xdev,
+--- a/drivers/xen/pvcalls-front.c
++++ b/drivers/xen/pvcalls-front.c
+@@ -1087,7 +1087,7 @@ static const struct xenbus_device_id pvc
+ { "" }
+ };
+
+-static int pvcalls_front_remove(struct xenbus_device *dev)
++static void pvcalls_front_remove(struct xenbus_device *dev)
+ {
+ struct pvcalls_bedata *bedata;
+ struct sock_mapping *map = NULL, *n;
+@@ -1123,7 +1123,6 @@ static int pvcalls_front_remove(struct x
+ kfree(bedata->ring.sring);
+ kfree(bedata);
+ xenbus_switch_state(dev, XenbusStateClosed);
+- return 0;
+ }
+
+ static int pvcalls_front_probe(struct xenbus_device *dev,
+--- a/drivers/xen/xen-pciback/xenbus.c
++++ b/drivers/xen/xen-pciback/xenbus.c
+@@ -716,14 +716,12 @@ out:
+ return err;
+ }
+
+-static int xen_pcibk_xenbus_remove(struct xenbus_device *dev)
++static void xen_pcibk_xenbus_remove(struct xenbus_device *dev)
+ {
+ struct xen_pcibk_device *pdev = dev_get_drvdata(&dev->dev);
+
+ if (pdev != NULL)
+ free_pdev(pdev);
+-
+- return 0;
+ }
+
+ static const struct xenbus_device_id xen_pcibk_ids[] = {
+--- a/drivers/xen/xen-scsiback.c
++++ b/drivers/xen/xen-scsiback.c
+@@ -1249,7 +1249,7 @@ static void scsiback_release_translation
+ spin_unlock_irqrestore(&info->v2p_lock, flags);
+ }
+
+-static int scsiback_remove(struct xenbus_device *dev)
++static void scsiback_remove(struct xenbus_device *dev)
+ {
+ struct vscsibk_info *info = dev_get_drvdata(&dev->dev);
+
+@@ -1261,8 +1261,6 @@ static int scsiback_remove(struct xenbus
+ gnttab_page_cache_shrink(&info->free_pages, 0);
+
+ dev_set_drvdata(&dev->dev, NULL);
+-
+- return 0;
+ }
+
+ static int scsiback_probe(struct xenbus_device *dev,
+--- a/include/xen/xenbus.h
++++ b/include/xen/xenbus.h
+@@ -117,7 +117,7 @@ struct xenbus_driver {
+ const struct xenbus_device_id *id);
+ void (*otherend_changed)(struct xenbus_device *dev,
+ enum xenbus_state backend_state);
+- int (*remove)(struct xenbus_device *dev);
++ void (*remove)(struct xenbus_device *dev);
+ int (*suspend)(struct xenbus_device *dev);
+ int (*resume)(struct xenbus_device *dev);
+ int (*uevent)(struct xenbus_device *, struct kobj_uevent_env *);
+--- a/net/9p/trans_xen.c
++++ b/net/9p/trans_xen.c
+@@ -307,13 +307,12 @@ static void xen_9pfs_front_free(struct x
+ kfree(priv);
+ }
+
+-static int xen_9pfs_front_remove(struct xenbus_device *dev)
++static void xen_9pfs_front_remove(struct xenbus_device *dev)
+ {
+ struct xen_9pfs_front_priv *priv = dev_get_drvdata(&dev->dev);
+
+ dev_set_drvdata(&dev->dev, NULL);
+ xen_9pfs_front_free(priv);
+- return 0;
+ }
+
+ static int xen_9pfs_front_alloc_dataring(struct xenbus_device *dev,
+--- a/sound/xen/xen_snd_front.c
++++ b/sound/xen/xen_snd_front.c
+@@ -311,7 +311,7 @@ static int xen_drv_probe(struct xenbus_d
+ return xenbus_switch_state(xb_dev, XenbusStateInitialising);
+ }
+
+-static int xen_drv_remove(struct xenbus_device *dev)
++static void xen_drv_remove(struct xenbus_device *dev)
+ {
+ struct xen_snd_front_info *front_info = dev_get_drvdata(&dev->dev);
+ int to = 100;
+@@ -345,7 +345,6 @@ static int xen_drv_remove(struct xenbus_
+
+ xen_snd_drv_fini(front_info);
+ xenbus_frontend_closed(dev);
+- return 0;
+ }
+
+ static const struct xenbus_device_id xen_drv_ids[] = {
--- /dev/null
+From stable+bounces-210650-greg=kroah.com@vger.kernel.org Wed Jan 21 03:21:51 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 20 Jan 2026 21:19:53 -0500
+Subject: xfs: set max_agbno to allow sparse alloc of last full inode chunk
+To: stable@vger.kernel.org
+Cc: Brian Foster <bfoster@redhat.com>, "Darrick J. Wong" <djwong@kernel.org>, Carlos Maiolino <cem@kernel.org>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260121021953.1128404-1-sashal@kernel.org>
+
+From: Brian Foster <bfoster@redhat.com>
+
+[ Upstream commit c360004c0160dbe345870f59f24595519008926f ]
+
+Sparse inode cluster allocation sets min/max agbno values to avoid
+allocating an inode cluster that might map to an invalid inode
+chunk. For example, we can't have an inode record mapped to agbno 0
+or that extends past the end of a runt AG of misaligned size.
+
+The initial calculation of max_agbno is unnecessarily conservative,
+however. This has triggered a corner case allocation failure where a
+small runt AG (i.e. 2063 blocks) is mostly full save for an extent
+to the EOFS boundary: [2050,13]. max_agbno is set to 2048 in this
+case, which happens to be the offset of the last possible valid
+inode chunk in the AG. In practice, we should be able to allocate
+the 4-block cluster at agbno 2052 to map to the parent inode record
+at agbno 2048, but the max_agbno value precludes it.
+
+Note that this can result in filesystem shutdown via dirty trans
+cancel on stable kernels prior to commit 9eb775968b68 ("xfs: walk
+all AGs if TRYLOCK passed to xfs_alloc_vextent_iterate_ags") because
+the tail AG selection by the allocator sets t_highest_agno on the
+transaction. If the inode allocator spins around and finds an inode
+chunk with free inodes in an earlier AG, the subsequent dir name
+creation path may still fail to allocate due to the AG restriction
+and cancel.
+
+To avoid this problem, update the max_agbno calculation to the agbno
+prior to the last chunk aligned agbno in the AG. This is not
+necessarily the last valid allocation target for a sparse chunk, but
+since inode chunks (i.e. records) are chunk aligned and sparse
+allocs are cluster sized/aligned, this allows the sb_spino_align
+alignment restriction to take over and round down the max effective
+agbno to within the last valid inode chunk in the AG.
+
+Note that even though the allocator improvements in the
+aforementioned commit seem to avoid this particular dirty trans
+cancel situation, the max_agbno logic improvement still applies as
+we should be able to allocate from an AG that has been appropriately
+selected. The more important target for this patch however are
+older/stable kernels prior to this allocator rework/improvement.
+
+Cc: stable@vger.kernel.org # v4.2
+Fixes: 56d1115c9bc7 ("xfs: allocate sparse inode chunks on full chunk allocation failure")
+Signed-off-by: Brian Foster <bfoster@redhat.com>
+Reviewed-by: Darrick J. Wong <djwong@kernel.org>
+Signed-off-by: Carlos Maiolino <cem@kernel.org>
+[ xfs_ag_block_count(args.mp, pag_agno(pag)) => args.mp->m_sb.sb_agblocks ]
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/xfs/libxfs/xfs_ialloc.c | 11 ++++++-----
+ 1 file changed, 6 insertions(+), 5 deletions(-)
+
+--- a/fs/xfs/libxfs/xfs_ialloc.c
++++ b/fs/xfs/libxfs/xfs_ialloc.c
+@@ -772,14 +772,15 @@ sparse_alloc:
+ * invalid inode records, such as records that start at agbno 0
+ * or extend beyond the AG.
+ *
+- * Set min agbno to the first aligned, non-zero agbno and max to
+- * the last aligned agbno that is at least one full chunk from
+- * the end of the AG.
++ * Set min agbno to the first chunk aligned, non-zero agbno and
++ * max to one less than the last chunk aligned agbno from the
++ * end of the AG. We subtract 1 from max so that the cluster
++ * allocation alignment takes over and allows allocation within
++ * the last full inode chunk in the AG.
+ */
+ args.min_agbno = args.mp->m_sb.sb_inoalignmt;
+ args.max_agbno = round_down(args.mp->m_sb.sb_agblocks,
+- args.mp->m_sb.sb_inoalignmt) -
+- igeo->ialloc_blks;
++ args.mp->m_sb.sb_inoalignmt) - 1;
+
+ error = xfs_alloc_vextent(&args);
+ if (error)